diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index 0feda605ea66b..50ff149e38776 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -529,24 +529,8 @@ runClangTidy(clang::tidy::ClangTidyContext &Context, return AdjustedArgs; }; - // Remove plugins arguments. - ArgumentsAdjuster PluginArgumentsRemover = - [](const CommandLineArguments &Args, StringRef Filename) { - CommandLineArguments AdjustedArgs; - for (size_t I = 0, E = Args.size(); I < E; ++I) { - if (I + 4 < Args.size() && Args[I] == "-Xclang" && - (Args[I + 1] == "-load" || Args[I + 1] == "-add-plugin" || - StringRef(Args[I + 1]).startswith("-plugin-arg-")) && - Args[I + 2] == "-Xclang") { - I += 3; - } else - AdjustedArgs.push_back(Args[I]); - } - return AdjustedArgs; - }; - Tool.appendArgumentsAdjuster(PerFileExtraArgumentsInserter); - Tool.appendArgumentsAdjuster(PluginArgumentsRemover); + Tool.appendArgumentsAdjuster(getStripPluginsAdjuster()); Context.setEnableProfiling(EnableCheckProfile); Context.setProfileStoragePrefix(StoreCheckProfile); diff --git a/clang-tools-extra/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.cpp b/clang-tools-extra/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.cpp index c0bdbfbfe0424..bac7f898785a0 100644 --- a/clang-tools-extra/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/NonPrivateMemberVariablesInClassesCheck.cpp @@ -23,8 +23,8 @@ AST_MATCHER(CXXRecordDecl, hasMethods) { return std::distance(Node.method_begin(), Node.method_end()) != 0; } -AST_MATCHER(CXXRecordDecl, hasNonStaticMethod) { - return hasMethod(unless(isStaticStorageClass())) +AST_MATCHER(CXXRecordDecl, hasNonStaticNonImplicitMethod) { + return hasMethod(unless(anyOf(isStaticStorageClass(), isImplicit()))) .matches(Node, Finder, Builder); } @@ -67,10 +67,11 @@ void NonPrivateMemberVariablesInClassesCheck::registerMatchers( IgnorePublicMemberVariables ? isProtected() : unless(isPrivate())); // We only want the records that not only contain the mutable data (non-static - // member variables), but also have some logic (non-static member functions). - // We may optionally ignore records where all the member variables are public. + // member variables), but also have some logic (non-static, non-implicit + // member functions). We may optionally ignore records where all the member + // variables are public. Finder->addMatcher(cxxRecordDecl(anyOf(isStruct(), isClass()), hasMethods(), - hasNonStaticMethod(), + hasNonStaticNonImplicitMethod(), unless(ShouldIgnoreRecord), forEach(InterestingField.bind("field"))) .bind("record"), diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp index dd19483295e8d..6ef45ee855244 100644 --- a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp @@ -31,6 +31,12 @@ AST_MATCHER(clang::RecordDecl, isExternCContext) { return Node.isExternCContext(); } +AST_MATCHER(clang::ParmVarDecl, isArgvOfMain) { + const clang::DeclContext *DC = Node.getDeclContext(); + const auto *FD = llvm::dyn_cast(DC); + return FD ? FD->isMain() : false; +} + } // namespace namespace clang { @@ -44,7 +50,8 @@ void AvoidCArraysCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( typeLoc(hasValidBeginLoc(), hasType(arrayType()), - unless(anyOf(hasParent(varDecl(isExternC())), + unless(anyOf(hasParent(parmVarDecl(isArgvOfMain())), + hasParent(varDecl(isExternC())), hasParent(fieldDecl( hasParent(recordDecl(isExternCContext())))), hasAncestor(functionDecl(isExternC()))))) diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index 80792eddc69a9..97a5e89c47837 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -290,7 +290,8 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params, if (UseDirBasedCDB) BaseCDB = llvm::make_unique( CompileCommandsDir); - CDB.emplace(BaseCDB.get(), Params.initializationOptions.fallbackFlags); + CDB.emplace(BaseCDB.get(), Params.initializationOptions.fallbackFlags, + ClangdServerOpts.ResourceDir); Server.emplace(*CDB, FSProvider, static_cast(*this), ClangdServerOpts); applyConfiguration(Params.initializationOptions.ConfigSettings); diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index 53a27bdb91d5f..a4ab622e101ed 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -38,11 +38,6 @@ namespace clang { namespace clangd { namespace { -std::string getStandardResourceDir() { - static int Dummy; // Just an address in this process. - return CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy); -} - class RefactoringResultCollector final : public tooling::RefactoringResultConsumer { public: @@ -108,8 +103,6 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB, DiagnosticsConsumer &DiagConsumer, const Options &Opts) : CDB(CDB), FSProvider(FSProvider), - ResourceDir(Opts.ResourceDir ? *Opts.ResourceDir - : getStandardResourceDir()), DynamicIdx(Opts.BuildDynamicSymbolIndex ? new FileIndex(Opts.HeavyweightDynamicSymbolIndex) : nullptr), @@ -137,7 +130,7 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB, AddIndex(Opts.StaticIndex); if (Opts.BackgroundIndex) { BackgroundIdx = llvm::make_unique( - Context::current().clone(), ResourceDir, FSProvider, CDB, + Context::current().clone(), FSProvider, CDB, BackgroundIndexStorage::createDiskBackedStorageFactory(), Opts.BackgroundIndexRebuildPeriodMs); AddIndex(BackgroundIdx.get()); @@ -462,10 +455,6 @@ tooling::CompileCommand ClangdServer::getCompileCommand(PathRef File) { llvm::Optional C = CDB.getCompileCommand(File); if (!C) // FIXME: Suppress diagnostics? Let the user know? C = CDB.getFallbackCommand(File); - - // Inject the resource dir. - // FIXME: Don't overwrite it if it's already there. - C->CommandLine.push_back("-resource-dir=" + ResourceDir); return std::move(*C); } diff --git a/clang-tools-extra/clangd/ExpectedTypes.cpp b/clang-tools-extra/clangd/ExpectedTypes.cpp index 4bbf0651260b6..59d9e149162a6 100644 --- a/clang-tools-extra/clangd/ExpectedTypes.cpp +++ b/clang-tools-extra/clangd/ExpectedTypes.cpp @@ -35,8 +35,10 @@ static llvm::Optional typeOfCompletion(const CodeCompletionResult &R) { auto *VD = dyn_cast_or_null(R.Declaration); if (!VD) - return None; // We handle only variables and functions below. + return llvm::None; // We handle only variables and functions below. auto T = VD->getType(); + if (T.isNull()) + return llvm::None; if (auto FuncT = T->getAs()) { // Functions are a special case. They are completed as 'foo()' and we want // to match their return type rather than the function type itself. diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp index c2fff7b20f37b..8c7aa194a1f8e 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -9,12 +9,36 @@ #include "GlobalCompilationDatabase.h" #include "Logger.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/CompilationDatabase.h" +#include "llvm/ADT/Optional.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" namespace clang { namespace clangd { +namespace { + +void adjustArguments(tooling::CompileCommand &Cmd, + llvm::StringRef ResourceDir) { + // Strip plugin related command line arguments. Clangd does + // not support plugins currently. Therefore it breaks if + // compiler tries to load plugins. + Cmd.CommandLine = + tooling::getStripPluginsAdjuster()(Cmd.CommandLine, Cmd.Filename); + // Inject the resource dir. + // FIXME: Don't overwrite it if it's already there. + if (!ResourceDir.empty()) + Cmd.CommandLine.push_back(("-resource-dir=" + ResourceDir).str()); +} + +std::string getStandardResourceDir() { + static int Dummy; // Just an address in this process. + return CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy); +} + +} // namespace static std::string getFallbackClangPath() { static int Dummy; @@ -106,8 +130,11 @@ DirectoryBasedGlobalCompilationDatabase::getCDBForFile( } OverlayCDB::OverlayCDB(const GlobalCompilationDatabase *Base, - std::vector FallbackFlags) - : Base(Base), FallbackFlags(std::move(FallbackFlags)) { + std::vector FallbackFlags, + llvm::Optional ResourceDir) + : Base(Base), ResourceDir(ResourceDir ? std::move(*ResourceDir) + : getStandardResourceDir()), + FallbackFlags(std::move(FallbackFlags)) { if (Base) BaseChanged = Base->watch([this](const std::vector Changes) { OnCommandChanged.broadcast(Changes); @@ -116,16 +143,22 @@ OverlayCDB::OverlayCDB(const GlobalCompilationDatabase *Base, llvm::Optional OverlayCDB::getCompileCommand(PathRef File, ProjectInfo *Project) const { + llvm::Optional Cmd; { std::lock_guard Lock(Mutex); auto It = Commands.find(File); if (It != Commands.end()) { if (Project) Project->SourceRoot = ""; - return It->second; + Cmd = It->second; } } - return Base ? Base->getCompileCommand(File, Project) : None; + if (!Cmd && Base) + Cmd = Base->getCompileCommand(File, Project); + if (!Cmd) + return llvm::None; + adjustArguments(*Cmd, ResourceDir); + return Cmd; } tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const { diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h b/clang-tools-extra/clangd/GlobalCompilationDatabase.h index 181b1781f73b3..6411fd48ced00 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h @@ -12,6 +12,7 @@ #include "Function.h" #include "Path.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" #include #include @@ -98,7 +99,8 @@ class OverlayCDB : public GlobalCompilationDatabase { // Base may be null, in which case no entries are inherited. // FallbackFlags are added to the fallback compile command. OverlayCDB(const GlobalCompilationDatabase *Base, - std::vector FallbackFlags = {}); + std::vector FallbackFlags = {}, + llvm::Optional ResourceDir = llvm::None); llvm::Optional getCompileCommand(PathRef File, ProjectInfo * = nullptr) const override; @@ -113,6 +115,7 @@ class OverlayCDB : public GlobalCompilationDatabase { mutable std::mutex Mutex; llvm::StringMap Commands; /* GUARDED_BY(Mut) */ const GlobalCompilationDatabase *Base; + std::string ResourceDir; std::vector FallbackFlags; CommandChanged::Subscription BaseChanged; }; diff --git a/clang-tools-extra/clangd/Threading.cpp b/clang-tools-extra/clangd/Threading.cpp index 139fcc2f878d9..733267c0e706c 100644 --- a/clang-tools-extra/clangd/Threading.cpp +++ b/clang-tools-extra/clangd/Threading.cpp @@ -7,6 +7,10 @@ #include #ifdef __USE_POSIX #include +#elif defined(__APPLE__) +#include +#elif defined (_WIN32) +#include #endif namespace clang { @@ -121,6 +125,17 @@ void setCurrentThreadPriority(ThreadPriority Priority) { Priority == ThreadPriority::Low && !AvoidThreadStarvation ? SCHED_IDLE : SCHED_OTHER, &priority); +#elif defined(__APPLE__) + // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getpriority.2.html + setpriority(PRIO_DARWIN_THREAD, 0, + Priority == ThreadPriority::Low && !AvoidThreadStarvation + ? PRIO_DARWIN_BG + : 0); +#elif defined(_WIN32) + SetThreadPriority(GetCurrentThread(), + Priority == ThreadPriority::Low && !AvoidThreadStarvation + ? THREAD_MODE_BACKGROUND_BEGIN + : THREAD_MODE_BACKGROUND_END); #endif } diff --git a/clang-tools-extra/clangd/index/Background.cpp b/clang-tools-extra/clangd/index/Background.cpp index b9b945c52bdaf..752d5c2876e00 100644 --- a/clang-tools-extra/clangd/index/Background.cpp +++ b/clang-tools-extra/clangd/index/Background.cpp @@ -127,13 +127,12 @@ llvm::SmallString<128> getAbsolutePath(const tooling::CompileCommand &Cmd) { } // namespace BackgroundIndex::BackgroundIndex( - Context BackgroundContext, llvm::StringRef ResourceDir, - const FileSystemProvider &FSProvider, const GlobalCompilationDatabase &CDB, + Context BackgroundContext, const FileSystemProvider &FSProvider, + const GlobalCompilationDatabase &CDB, BackgroundIndexStorage::Factory IndexStorageFactory, size_t BuildIndexPeriodMs, size_t ThreadPoolSize) - : SwapIndex(llvm::make_unique()), ResourceDir(ResourceDir), - FSProvider(FSProvider), CDB(CDB), - BackgroundContext(std::move(BackgroundContext)), + : SwapIndex(llvm::make_unique()), FSProvider(FSProvider), + CDB(CDB), BackgroundContext(std::move(BackgroundContext)), BuildIndexPeriodMs(BuildIndexPeriodMs), SymbolsUpdatedSinceLastIndex(false), IndexStorageFactory(std::move(IndexStorageFactory)), @@ -230,7 +229,6 @@ void BackgroundIndex::enqueue(tooling::CompileCommand Cmd, BackgroundIndexStorage *Storage) { enqueueTask(Bind( [this, Storage](tooling::CompileCommand Cmd) { - Cmd.CommandLine.push_back("-resource-dir=" + ResourceDir); // We can't use llvm::StringRef here since we are going to // move from Cmd during the call below. const std::string FileName = Cmd.Filename; diff --git a/clang-tools-extra/clangd/index/Background.h b/clang-tools-extra/clangd/index/Background.h index 1a1fee68a571e..4978ccb77f521 100644 --- a/clang-tools-extra/clangd/index/Background.h +++ b/clang-tools-extra/clangd/index/Background.h @@ -55,7 +55,7 @@ class BackgroundIndexStorage { llvm::unique_function; // Creates an Index Storage that saves shards into disk. Index storage uses - // CDBDirectory + ".clangd-index/" as the folder to save shards. + // CDBDirectory + ".clangd/index/" as the folder to save shards. static Factory createDiskBackedStorageFactory(); }; @@ -68,13 +68,12 @@ class BackgroundIndex : public SwapIndex { /// If BuildIndexPeriodMs is greater than 0, the symbol index will only be /// rebuilt periodically (one per \p BuildIndexPeriodMs); otherwise, index is /// rebuilt for each indexed file. - // FIXME: resource-dir injection should be hoisted somewhere common. - BackgroundIndex(Context BackgroundContext, llvm::StringRef ResourceDir, - const FileSystemProvider &, - const GlobalCompilationDatabase &CDB, - BackgroundIndexStorage::Factory IndexStorageFactory, - size_t BuildIndexPeriodMs = 0, - size_t ThreadPoolSize = llvm::hardware_concurrency()); + BackgroundIndex( + Context BackgroundContext, const FileSystemProvider &, + const GlobalCompilationDatabase &CDB, + BackgroundIndexStorage::Factory IndexStorageFactory, + size_t BuildIndexPeriodMs = 0, + size_t ThreadPoolSize = llvm::heavyweight_hardware_concurrency()); ~BackgroundIndex(); // Blocks while the current task finishes. // Enqueue translation units for indexing. @@ -99,7 +98,6 @@ class BackgroundIndex : public SwapIndex { BackgroundIndexStorage *IndexStorage); // configuration - std::string ResourceDir; const FileSystemProvider &FSProvider; const GlobalCompilationDatabase &CDB; Context BackgroundContext; diff --git a/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp b/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp index a83bec6f27dbe..b75944785ee50 100644 --- a/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp +++ b/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp @@ -64,19 +64,19 @@ writeAtomically(llvm::StringRef OutPath, } // Uses disk as a storage for index shards. Creates a directory called -// ".clangd-index/" under the path provided during construction. +// ".clangd/index/" under the path provided during construction. class DiskBackedIndexStorage : public BackgroundIndexStorage { std::string DiskShardRoot; public: - // Sets DiskShardRoot to (Directory + ".clangd-index/") which is the base + // Sets DiskShardRoot to (Directory + ".clangd/index/") which is the base // directory for all shard files. DiskBackedIndexStorage(llvm::StringRef Directory) { llvm::SmallString<128> CDBDirectory(Directory); - llvm::sys::path::append(CDBDirectory, ".clangd-index/"); + llvm::sys::path::append(CDBDirectory, ".clangd", "index"); DiskShardRoot = CDBDirectory.str(); std::error_code OK; - std::error_code EC = llvm::sys::fs::create_directory(DiskShardRoot); + std::error_code EC = llvm::sys::fs::create_directories(DiskShardRoot); if (EC != OK) { elog("Failed to create directory {0} for index storage: {1}", DiskShardRoot, EC.message()); diff --git a/clang-tools-extra/docs/README.txt b/clang-tools-extra/docs/README.txt index 4b60777583017..cebbf63bcd6a7 100644 --- a/clang-tools-extra/docs/README.txt +++ b/clang-tools-extra/docs/README.txt @@ -1,11 +1,10 @@ -------------------------------------------------------------- -Documentation for the tools of clang-tools-extra repo project -------------------------------------------------------------- +---------------------------------- +Documentation in clang-tools-extra +---------------------------------- -Sphinx and doxygen documentation is generated by executing make. +To generate documentation in HTML format from files in clang-tools-extra/docs, +build the docs-clang-tools-html target. -Sphinx html files can be generated separately using make html. +To generate documentation from the source code using Doxygen, build the +doxygen-clang-tools target. -Doxygen html files can also be generated using make doxygen. - -The generated documentation will be placed in _build/html. diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 8731dc73c6487..7c24d28c99f86 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -1,6 +1,6 @@ -=================================================== -Extra Clang Tools 8.0.0 (In-Progress) Release Notes -=================================================== +===================================== +Extra Clang Tools 8.0.0 Release Notes +===================================== .. contents:: :local: @@ -8,30 +8,19 @@ Extra Clang Tools 8.0.0 (In-Progress) Release Notes Written by the `LLVM Team `_ -.. warning:: - - These are in-progress notes for the upcoming Extra Clang Tools 8 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ This document contains the release notes for the Extra Clang Tools, part of the Clang release 8.0.0. Here we describe the status of the Extra Clang Tools in some detail, including major improvements from the previous release and new -feature work. All LLVM releases may be downloaded from the `LLVM releases web -site `_. +feature work. All LLVM releases may be downloaded +from the `LLVM releases web site `_. For more information about Clang or LLVM, including information about the latest release, please see the `Clang Web Site `_ or the `LLVM Web Site `_. -Note that if you are reading this file from a Subversion checkout or the -main Clang web page, this document applies to the *next* release, not -the current one. To see the release notes for a specific release, please -see the `releases page `_. - What's New in Extra Clang Tools 8.0.0? ====================================== @@ -39,20 +28,62 @@ Some of the major new features and improvements to Extra Clang Tools are listed here. Generic improvements to Extra Clang Tools as a whole or to its underlying infrastructure are described first, followed by tool-specific sections. -Major New Features ------------------- - -... Improvements to clangd ---------------------- -The improvements are... +- clangd now adds namespace qualifiers in code completion, for example, if you + type "``vec``", the list of completions will include "``std::vector``". + + See also: `r343248 `__. + +- When a :ref:`global index ` is available, clangd will use it to augment the + results of "go to definition" and "find references" queries. Global index + also enables global code completion, which suggests symbols that are not + imported in the current file and automatically inserts the missing + ``#include`` directives. + +- clangd stores the symbol index on disk in a new compact binary serialization + format. It is 10x more compact than YAML and 40% more compact than gzipped + YAML. + + See also: `r341375 `__. + +- clangd has a new efficient symbol index suitable for complex and fuzzy + queries and large code bases (e.g., LLVM, Chromium). This index is used for + code completion, go to definition, and cross-references. The architecture of + the index allows for complex and fuzzy retrieval criteria and sophisticated + scoring. -Improvements to clang-doc -------------------------- + See also: `discussion on the mailing list + `__, `design + doc + `__. + +- clangd has a new LSP extension that communicates information about activity + on clangd's per-file worker thread. This information can be displayed to + users to let them know that the language server is busy with something. For + example, in clangd, building the AST blocks many other operations. + + More info: :ref:`lsp-extension-file-status`. + +- clangd has a new LSP extension that allows the client to supply the + compilation commands over LSP, instead of finding compile_commands.json on + disk. + + More info: :ref:`lsp-extension-compilation-commands`. + +- clangd has a new LSP extension that allows the client to request fixes to be + sent together with diagnostics, instead of asynchronously. + + More info: :ref:`lsp-extension-code-actions-in-diagnostics`. + +- clangd has a new LSP extension that allows the client to resolve a symbol in + a light-weight manner, without retrieving further information (like + definition location, which may require consulting an index). + + More info: :ref:`lsp-extension-symbol-info`. -The improvements are... Improvements to clang-query --------------------------- @@ -99,11 +130,6 @@ Improvements to clang-query disable output detailed-ast m functionDecl() -Improvements to clang-rename ----------------------------- - -The improvements are... - Improvements to clang-tidy -------------------------- @@ -226,18 +252,18 @@ Improvements to clang-tidy Adds ``[[nodiscard]]`` attributes (introduced in C++17) to member functions to highlight at compile time which return values should not be ignored. -- New :doc:`readability-isolate-decl - ` check. - - Detects local variable declarations declaring more than one variable and - tries to refactor the code to one statement per declaration. - - New :doc:`readability-const-return-type ` check. Checks for functions with a ``const``-qualified return type and recommends removal of the ``const`` keyword. +- New :doc:`readability-isolate-decl + ` check. + + Detects local variable declarations declaring more than one variable and + tries to refactor the code to one statement per declaration. + - New :doc:`readability-magic-numbers ` check. @@ -302,13 +328,3 @@ Improvements to clang-tidy - The :doc:`readability-uppercase-literal-suffix ` check does not warn about literal suffixes inside macros anymore by default. - -Improvements to include-fixer ------------------------------ - -The improvements are... - -Improvements to modularize --------------------------- - -The improvements are... diff --git a/clang-tools-extra/docs/_static/clang-tools-extra-styles.css b/clang-tools-extra/docs/_static/clang-tools-extra-styles.css new file mode 100644 index 0000000000000..1a6cd710e483a --- /dev/null +++ b/clang-tools-extra/docs/_static/clang-tools-extra-styles.css @@ -0,0 +1,23 @@ +details { + background-color: rgba(50, 150, 220, 0.08); + margin-bottom: 0.5em; + padding: 0 1em; + overflow-y: hidden; /* Suppress margin-collapsing */ +} +details[open] { + border-bottom: 1px solid rgba(0, 0, 128, 0.2); + margin-bottom: 1em; +} +details summary { + font-weight: bold; + background-color: rgba(50, 150, 220, 0.1); + border-color: rgba(0, 0, 128, 0.2); + border-width: 1px; + border-style: solid none; + padding: 0.2em; + margin: 0 -1em; +} +details summary:hover { + background-color: rgba(50, 150, 220, 0.2); + cursor: pointer; +} diff --git a/clang-tools-extra/docs/_templates/layout.html b/clang-tools-extra/docs/_templates/layout.html new file mode 100644 index 0000000000000..b4f5b4e1ebd0d --- /dev/null +++ b/clang-tools-extra/docs/_templates/layout.html @@ -0,0 +1,3 @@ +{% extends "!layout.html" %} + +{% set css_files = css_files + ['_static/clang-tools-extra-styles.css'] %} diff --git a/clang-tools-extra/docs/clang-tidy/Contributing.rst b/clang-tools-extra/docs/clang-tidy/Contributing.rst new file mode 100644 index 0000000000000..6d61809ecb337 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/Contributing.rst @@ -0,0 +1,512 @@ +================ +Getting Involved +================ + +:program:`clang-tidy` has several own checks and can run Clang static analyzer +checks, but its power is in the ability to easily write custom checks. + +Checks are organized in modules, which can be linked into :program:`clang-tidy` +with minimal or no code changes in :program:`clang-tidy`. + +Checks can plug into the analysis on the preprocessor level using `PPCallbacks`_ +or on the AST level using `AST Matchers`_. When an error is found, checks can +report them in a way similar to how Clang diagnostics work. A fix-it hint can be +attached to a diagnostic message. + +The interface provided by :program:`clang-tidy` makes it easy to write useful +and precise checks in just a few lines of code. If you have an idea for a good +check, the rest of this document explains how to do this. + +There are a few tools particularly useful when developing clang-tidy checks: + * ``add_new_check.py`` is a script to automate the process of adding a new + check, it will create the check, update the CMake file and create a test; + * ``rename_check.py`` does what the script name suggests, renames an existing + check; + * :program:`clang-query` is invaluable for interactive prototyping of AST + matchers and exploration of the Clang AST; + * `clang-check`_ with the ``-ast-dump`` (and optionally ``-ast-dump-filter``) + provides a convenient way to dump AST of a C++ program. + +If CMake is configured with ``CLANG_ENABLE_STATIC_ANALYZER``, +:program:`clang-tidy` will not be built with support for the +``clang-analyzer-*`` checks or the ``mpi-*`` checks. + + +.. _AST Matchers: https://clang.llvm.org/docs/LibASTMatchers.html +.. _PPCallbacks: https://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html +.. _clang-check: https://clang.llvm.org/docs/ClangCheck.html + + +Choosing the Right Place for your Check +--------------------------------------- + +If you have an idea of a check, you should decide whether it should be +implemented as a: + ++ *Clang diagnostic*: if the check is generic enough, targets code patterns that + most probably are bugs (rather than style or readability issues), can be + implemented effectively and with extremely low false positive rate, it may + make a good Clang diagnostic. + ++ *Clang static analyzer check*: if the check requires some sort of control flow + analysis, it should probably be implemented as a static analyzer check. + ++ *clang-tidy check* is a good choice for linter-style checks, checks that are + related to a certain coding style, checks that address code readability, etc. + + +Preparing your Workspace +------------------------ + +If you are new to LLVM development, you should read the `Getting Started with +the LLVM System`_, `Using Clang Tools`_ and `How To Setup Clang Tooling For +LLVM`_ documents to check out and build LLVM, Clang and Clang Extra Tools with +CMake. + +Once you are done, change to the ``llvm/tools/clang/tools/extra`` directory, and +let's start! + +.. _Getting Started with the LLVM System: https://llvm.org/docs/GettingStarted.html +.. _Using Clang Tools: https://clang.llvm.org/docs/ClangTools.html +.. _How To Setup Clang Tooling For LLVM: https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html + + +The Directory Structure +----------------------- + +:program:`clang-tidy` source code resides in the +``llvm/tools/clang/tools/extra`` directory and is structured as follows: + +:: + + clang-tidy/ # Clang-tidy core. + |-- ClangTidy.h # Interfaces for users and checks. + |-- ClangTidyModule.h # Interface for clang-tidy modules. + |-- ClangTidyModuleRegistry.h # Interface for registering of modules. + ... + |-- google/ # Google clang-tidy module. + |-+ + |-- GoogleTidyModule.cpp + |-- GoogleTidyModule.h + ... + |-- llvm/ # LLVM clang-tidy module. + |-+ + |-- LLVMTidyModule.cpp + |-- LLVMTidyModule.h + ... + |-- objc/ # Objective-C clang-tidy module. + |-+ + |-- ObjCTidyModule.cpp + |-- ObjCTidyModule.h + ... + |-- tool/ # Sources of the clang-tidy binary. + ... + test/clang-tidy/ # Integration tests. + ... + unittests/clang-tidy/ # Unit tests. + |-- ClangTidyTest.h + |-- GoogleModuleTest.cpp + |-- LLVMModuleTest.cpp + |-- ObjCModuleTest.cpp + ... + + +Writing a clang-tidy Check +-------------------------- + +So you have an idea of a useful check for :program:`clang-tidy`. + +First, if you're not familiar with LLVM development, read through the `Getting +Started with LLVM`_ document for instructions on setting up your workflow and +the `LLVM Coding Standards`_ document to familiarize yourself with the coding +style used in the project. For code reviews we mostly use `LLVM Phabricator`_. + +.. _Getting Started with LLVM: https://llvm.org/docs/GettingStarted.html +.. _LLVM Coding Standards: https://llvm.org/docs/CodingStandards.html +.. _LLVM Phabricator: https://llvm.org/docs/Phabricator.html + +Next, you need to decide which module the check belongs to. Modules +are located in subdirectories of `clang-tidy/ +`_ +and contain checks targeting a certain aspect of code quality (performance, +readability, etc.), certain coding style or standard (Google, LLVM, CERT, etc.) +or a widely used API (e.g. MPI). Their names are same as user-facing check +groups names described :ref:`above `. + +After choosing the module and the name for the check, run the +``clang-tidy/add_new_check.py`` script to create the skeleton of the check and +plug it to :program:`clang-tidy`. It's the recommended way of adding new checks. + +If we want to create a `readability-awesome-function-names`, we would run: + +.. code-block:: console + + $ clang-tidy/add_new_check.py readability awesome-function-names + + +The ``add_new_check.py`` script will: + * create the class for your check inside the specified module's directory and + register it in the module and in the build system; + * create a lit test file in the ``test/clang-tidy/`` directory; + * create a documentation file and include it into the + ``docs/clang-tidy/checks/list.rst``. + +Let's see in more detail at the check class definition: + +.. code-block:: c++ + + ... + + #include "../ClangTidy.h" + + namespace clang { + namespace tidy { + namespace readability { + + ... + class AwesomeFunctionNamesCheck : public ClangTidyCheck { + public: + AwesomeFunctionNamesCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + }; + + } // namespace readability + } // namespace tidy + } // namespace clang + + ... + +Constructor of the check receives the ``Name`` and ``Context`` parameters, and +must forward them to the ``ClangTidyCheck`` constructor. + +In our case the check needs to operate on the AST level and it overrides the +``registerMatchers`` and ``check`` methods. If we wanted to analyze code on the +preprocessor level, we'd need instead to override the ``registerPPCallbacks`` +method. + +In the ``registerMatchers`` method we create an AST Matcher (see `AST Matchers`_ +for more information) that will find the pattern in the AST that we want to +inspect. The results of the matching are passed to the ``check`` method, which +can further inspect them and report diagnostics. + +.. code-block:: c++ + + using namespace ast_matchers; + + void AwesomeFunctionNamesCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(functionDecl().bind("x"), this); + } + + void AwesomeFunctionNamesCheck::check(const MatchFinder::MatchResult &Result) { + const auto *MatchedDecl = Result.Nodes.getNodeAs("x"); + if (MatchedDecl->getName().startswith("awesome_")) + return; + diag(MatchedDecl->getLocation(), "function %0 is insufficiently awesome") + << MatchedDecl + << FixItHint::CreateInsertion(MatchedDecl->getLocation(), "awesome_"); + } + +(If you want to see an example of a useful check, look at +`clang-tidy/google/ExplicitConstructorCheck.h +`_ +and `clang-tidy/google/ExplicitConstructorCheck.cpp +`_). + + +Registering your Check +---------------------- + +(The ``add_new_check.py`` takes care of registering the check in an existing +module. If you want to create a new module or know the details, read on.) + +The check should be registered in the corresponding module with a distinct name: + +.. code-block:: c++ + + class MyModule : public ClangTidyModule { + public: + void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { + CheckFactories.registerCheck( + "my-explicit-constructor"); + } + }; + +Now we need to register the module in the ``ClangTidyModuleRegistry`` using a +statically initialized variable: + +.. code-block:: c++ + + static ClangTidyModuleRegistry::Add X("my-module", + "Adds my lint checks."); + + +When using LLVM build system, we need to use the following hack to ensure the +module is linked into the :program:`clang-tidy` binary: + +Add this near the ``ClangTidyModuleRegistry::Add`` variable: + +.. code-block:: c++ + + // This anchor is used to force the linker to link in the generated object file + // and thus register the MyModule. + volatile int MyModuleAnchorSource = 0; + +And this to the main translation unit of the :program:`clang-tidy` binary (or +the binary you link the ``clang-tidy`` library in) +``clang-tidy/tool/ClangTidyMain.cpp``: + +.. code-block:: c++ + + // This anchor is used to force the linker to link the MyModule. + extern volatile int MyModuleAnchorSource; + static int MyModuleAnchorDestination = MyModuleAnchorSource; + + +Configuring Checks +------------------ + +If a check needs configuration options, it can access check-specific options +using the ``Options.get("SomeOption", DefaultValue)`` call in the check +constructor. In this case the check should also override the +``ClangTidyCheck::storeOptions`` method to make the options provided by the +check discoverable. This method lets :program:`clang-tidy` know which options +the check implements and what the current values are (e.g. for the +``-dump-config`` command line option). + +.. code-block:: c++ + + class MyCheck : public ClangTidyCheck { + const unsigned SomeOption1; + const std::string SomeOption2; + + public: + MyCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + SomeOption(Options.get("SomeOption1", -1U)), + SomeOption(Options.get("SomeOption2", "some default")) {} + + void storeOptions(ClangTidyOptions::OptionMap &Opts) override { + Options.store(Opts, "SomeOption1", SomeOption1); + Options.store(Opts, "SomeOption2", SomeOption2); + } + ... + +Assuming the check is registered with the name "my-check", the option can then +be set in a ``.clang-tidy`` file in the following way: + +.. code-block:: yaml + + CheckOptions: + - key: my-check.SomeOption1 + value: 123 + - key: my-check.SomeOption2 + value: 'some other value' + +If you need to specify check options on a command line, you can use the inline +YAML format: + +.. code-block:: console + + $ clang-tidy -config="{CheckOptions: [{key: a, value: b}, {key: x, value: y}]}" ... + + +Testing Checks +-------------- + +To run tests for :program:`clang-tidy` use the command: + +.. code-block:: console + + $ ninja check-clang-tools + +:program:`clang-tidy` checks can be tested using either unit tests or +`lit`_ tests. Unit tests may be more convenient to test complex replacements +with strict checks. `Lit`_ tests allow using partial text matching and regular +expressions which makes them more suitable for writing compact tests for +diagnostic messages. + +The ``check_clang_tidy.py`` script provides an easy way to test both +diagnostic messages and fix-its. It filters out ``CHECK`` lines from the test +file, runs :program:`clang-tidy` and verifies messages and fixes with two +separate `FileCheck`_ invocations: once with FileCheck's directive +prefix set to ``CHECK-MESSAGES``, validating the diagnostic messages, +and once with the directive prefix set to ``CHECK-FIXES``, running +against the fixed code (i.e., the code after generated fix-its are +applied). In particular, ``CHECK-FIXES:`` can be used to check +that code was not modified by fix-its, by checking that it is present +unchanged in the fixed code. The full set of `FileCheck`_ directives +is available (e.g., ``CHECK-MESSAGES-SAME:``, ``CHECK-MESSAGES-NOT:``), though +typically the basic ``CHECK`` forms (``CHECK-MESSAGES`` and ``CHECK-FIXES``) +are sufficient for clang-tidy tests. Note that the `FileCheck`_ +documentation mostly assumes the default prefix (``CHECK``), and hence +describes the directive as ``CHECK:``, ``CHECK-SAME:``, ``CHECK-NOT:``, etc. +Replace ``CHECK`` by either ``CHECK-FIXES`` or ``CHECK-MESSAGES`` for +clang-tidy tests. + +An additional check enabled by ``check_clang_tidy.py`` ensures that +if `CHECK-MESSAGES:` is used in a file then every warning or error +must have an associated CHECK in that file. Or, you can use ``CHECK-NOTES:`` +instead, if you want to **also** ensure that all the notes are checked. + +To use the ``check_clang_tidy.py`` script, put a .cpp file with the +appropriate ``RUN`` line in the ``test/clang-tidy`` directory. Use +``CHECK-MESSAGES:`` and ``CHECK-FIXES:`` lines to write checks against +diagnostic messages and fixed code. + +It's advised to make the checks as specific as possible to avoid checks matching +to incorrect parts of the input. Use ``[[@LINE+X]]``/``[[@LINE-X]]`` +substitutions and distinct function and variable names in the test code. + +Here's an example of a test using the ``check_clang_tidy.py`` script (the full +source code is at `test/clang-tidy/google-readability-casting.cpp`_): + +.. code-block:: c++ + + // RUN: %check_clang_tidy %s google-readability-casting %t + + void f(int a) { + int b = (int)a; + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant cast to the same type [google-readability-casting] + // CHECK-FIXES: int b = a; + } + +To check more than one scenario in the same test file use +``-check-suffix=SUFFIX-NAME`` on ``check_clang_tidy.py`` command line or +``-check-suffixes=SUFFIX-NAME-1,SUFFIX-NAME-2,...``. +With ``-check-suffix[es]=SUFFIX-NAME`` you need to replace your ``CHECK-*`` +directives with ``CHECK-MESSAGES-SUFFIX-NAME`` and ``CHECK-FIXES-SUFFIX-NAME``. + +Here's an example: + +.. code-block:: c++ + + // RUN: %check_clang_tidy -check-suffix=USING-A %s misc-unused-using-decls %t -- -- -DUSING_A + // RUN: %check_clang_tidy -check-suffix=USING-B %s misc-unused-using-decls %t -- -- -DUSING_B + // RUN: %check_clang_tidy %s misc-unused-using-decls %t + ... + // CHECK-MESSAGES-USING-A: :[[@LINE-8]]:10: warning: using decl 'A' {{.*}} + // CHECK-MESSAGES-USING-B: :[[@LINE-7]]:10: warning: using decl 'B' {{.*}} + // CHECK-MESSAGES: :[[@LINE-6]]:10: warning: using decl 'C' {{.*}} + // CHECK-FIXES-USING-A-NOT: using a::A;$ + // CHECK-FIXES-USING-B-NOT: using a::B;$ + // CHECK-FIXES-NOT: using a::C;$ + + +There are many dark corners in the C++ language, and it may be difficult to make +your check work perfectly in all cases, especially if it issues fix-it hints. The +most frequent pitfalls are macros and templates: + +1. code written in a macro body/template definition may have a different meaning + depending on the macro expansion/template instantiation; +2. multiple macro expansions/template instantiations may result in the same code + being inspected by the check multiple times (possibly, with different + meanings, see 1), and the same warning (or a slightly different one) may be + issued by the check multiple times; :program:`clang-tidy` will deduplicate + _identical_ warnings, but if the warnings are slightly different, all of them + will be shown to the user (and used for applying fixes, if any); +3. making replacements to a macro body/template definition may be fine for some + macro expansions/template instantiations, but easily break some other + expansions/instantiations. + +.. _lit: https://llvm.org/docs/CommandGuide/lit.html +.. _FileCheck: https://llvm.org/docs/CommandGuide/FileCheck.html +.. _test/clang-tidy/google-readability-casting.cpp: https://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/test/clang-tidy/google-readability-casting.cpp + + +Running clang-tidy on LLVM +-------------------------- + +To test a check it's best to try it out on a larger code base. LLVM and Clang +are the natural targets as you already have the source code around. The most +convenient way to run :program:`clang-tidy` is with a compile command database; +CMake can automatically generate one, for a description of how to enable it see +`How To Setup Clang Tooling For LLVM`_. Once ``compile_commands.json`` is in +place and a working version of :program:`clang-tidy` is in ``PATH`` the entire +code base can be analyzed with ``clang-tidy/tool/run-clang-tidy.py``. The script +executes :program:`clang-tidy` with the default set of checks on every +translation unit in the compile command database and displays the resulting +warnings and errors. The script provides multiple configuration flags. + +.. _How To Setup Clang Tooling For LLVM: https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html + + +* The default set of checks can be overridden using the ``-checks`` argument, + taking the identical format as :program:`clang-tidy` does. For example + ``-checks=-*,modernize-use-override`` will run the ``modernize-use-override`` + check only. + +* To restrict the files examined you can provide one or more regex arguments + that the file names are matched against. + ``run-clang-tidy.py clang-tidy/.*Check\.cpp`` will only analyze clang-tidy + checks. It may also be necessary to restrict the header files warnings are + displayed from using the ``-header-filter`` flag. It has the same behavior + as the corresponding :program:`clang-tidy` flag. + +* To apply suggested fixes ``-fix`` can be passed as an argument. This gathers + all changes in a temporary directory and applies them. Passing ``-format`` + will run clang-format over changed lines. + + +On checks profiling +------------------- + +:program:`clang-tidy` can collect per-check profiling info, and output it +for each processed source file (translation unit). + +To enable profiling info collection, use the ``-enable-check-profile`` argument. +The timings will be output to ``stderr`` as a table. Example output: + +.. code-block:: console + + $ clang-tidy -enable-check-profile -checks=-*,readability-function-size source.cpp + ===-------------------------------------------------------------------------=== + clang-tidy checks profiling + ===-------------------------------------------------------------------------=== + Total Execution Time: 1.0282 seconds (1.0258 wall clock) + + ---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name --- + 0.9136 (100.0%) 0.1146 (100.0%) 1.0282 (100.0%) 1.0258 (100.0%) readability-function-size + 0.9136 (100.0%) 0.1146 (100.0%) 1.0282 (100.0%) 1.0258 (100.0%) Total + +It can also store that data as JSON files for further processing. Example output: + +.. code-block:: console + + $ clang-tidy -enable-check-profile -store-check-profile=. -checks=-*,readability-function-size source.cpp + $ # Note that there won't be timings table printed to the console. + $ ls /tmp/out/ + 20180516161318717446360-source.cpp.json + $ cat 20180516161318717446360-source.cpp.json + { + "file": "/path/to/source.cpp", + "timestamp": "2018-05-16 16:13:18.717446360", + "profile": { + "time.clang-tidy.readability-function-size.wall": 1.0421266555786133e+00, + "time.clang-tidy.readability-function-size.user": 9.2088400000005421e-01, + "time.clang-tidy.readability-function-size.sys": 1.2418899999999974e-01 + } + } + +There is only one argument that controls profile storage: + +* ``-store-check-profile=`` + + By default reports are printed in tabulated format to stderr. When this option + is passed, these per-TU profiles are instead stored as JSON. + If the prefix is not an absolute path, it is considered to be relative to the + directory from where you have run :program:`clang-tidy`. All ``.`` and ``..`` + patterns in the path are collapsed, and symlinks are resolved. + + Example: + Let's suppose you have a source file named ``example.cpp``, located in the + ``/source`` directory. Only the input filename is used, not the full path + to the source file. Additionally, it is prefixed with the current timestamp. + + * If you specify ``-store-check-profile=/tmp``, then the profile will be saved + to ``/tmp/-example.cpp.json`` + + * If you run :program:`clang-tidy` from within ``/foo`` directory, and specify + ``-store-check-profile=.``, then the profile will still be saved to + ``/foo/-example.cpp.json`` diff --git a/clang-tools-extra/docs/clang-tidy/Integrations.rst b/clang-tools-extra/docs/clang-tidy/Integrations.rst new file mode 100644 index 0000000000000..2d1e195645f5d --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/Integrations.rst @@ -0,0 +1,117 @@ +================================== +Clang-tidy IDE/Editor Integrations +================================== + +.. _Clangd: https://clang.llvm.org/extra/clangd.html + +Apart from being a standalone tool, :program:`clang-tidy` is integrated into +various IDEs, code analyzers, and editors. Besides, it is currently being +integrated into Clangd_. The following table shows the most +well-known :program:`clang-tidy` integrations in detail. + ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ +| | Feature | ++======================================+========================+=================================+==========================+=========================================+==========================+ +| **Tool** | On-the-fly inspection | Check list configuration (GUI) | Options to checks (GUI) | Configuration via ``.clang-tidy`` files | Custom clang-tidy binary | ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ +|A.L.E. for Vim | \+\ | \-\ | \-\ | \-\ | \+\ | ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ +|Clang Power Tools for Visual Studio | \-\ | \+\ | \-\ | \+\ | \-\ | ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ +|Clangd | \+\ | \-\ | \-\ | \-\ | \-\ | ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ +|CLion IDE | \+\ | \+\ | \+\ | \+\ | \+\ | ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ +|CodeChecker | \-\ | \-\ | \-\ | \-\ | \+\ | ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ +|CPPCheck | \-\ | \-\ | \-\ | \-\ | \-\ | ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ +|CPPDepend | \-\ | \-\ | \-\ | \-\ | \-\ | ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ +|Flycheck for Emacs | \+\ | \-\ | \-\ | \+\ | \+\ | ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ +|KDevelop IDE | \-\ | \+\ | \+\ | \+\ | \+\ | ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ +|Qt Creator IDE | \+\ | \+\ | \-\ | \-\ | \+\ | ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ +|ReSharper C++ for Visual Studio | \+\ | \+\ | \-\ | \+\ | \-\ | ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ +|Syntastic for Vim | \+\ | \-\ | \-\ | \-\ | \+\ | ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ +|Visual Assist for Visual Studio | \+\ | \+\ | \-\ | \-\ | \-\ | ++--------------------------------------+------------------------+---------------------------------+--------------------------+-----------------------------------------+--------------------------+ + +**IDEs** + +.. _CLion: https://www.jetbrains.com/clion/ +.. _integrates clang-tidy: https://www.jetbrains.com/help/clion/clang-tidy-checks-support.html + +CLion_ 2017.2 and later `integrates clang-tidy`_ as an extension to the +built-in code analyzer. Starting from 2018.2 EAP, CLion allows using +:program:`clang-tidy` via Clangd. Inspections and applicable quick-fixes are +performed on the fly, and checks can be configured in standard command line +format. In this integration, you can switch to the :program:`clang-tidy` +binary different from the bundled one, pass the configuration in +``.clang-tidy`` files instead of using the IDE settings, and configure +options for particular checks. + +.. _KDevelop: https://www.kdevelop.org/ +.. _kdev-clang-tidy: https://github.com/KDE/kdev-clang-tidy/ + +KDevelop_ with the kdev-clang-tidy_ plugin, starting from version 5.1, performs +static analysis using :program:`clang-tidy`. The plugin launches the +:program:`clang-tidy` binary from the specified location and parses its +output to provide a list of issues. + +.. _QtCreator: https://www.qt.io/ +.. _Clang Code Model: http://doc.qt.io/qtcreator/creator-clang-codemodel.html + +QtCreator_ 4.6 integrates :program:`clang-tidy` warnings into the editor +diagnostics under the `Clang Code Model`_. To employ :program:`clang-tidy` +inspection in QtCreator, you need to create a copy of one of the presets and +choose the checks to be performed in the Clang Code Model Warnings menu. + +.. _MS Visual Studio: https://visualstudio.microsoft.com/ +.. _ReSharper C++: https://www.jetbrains.com/help/resharper/Clang_Tidy_Integration.html +.. _Visual Assist: https://docs.wholetomato.com/default.asp?W761 +.. _Clang Power Tools: https://marketplace.visualstudio.com/items?itemName=caphyon.ClangPowerTools +.. _clang-tidy-vs: https://github.com/llvm-mirror/clang-tools-extra/tree/master/clang-tidy-vs + +`MS Visual Studio`_ has a native clang-tidy-vs_ plugin and also can integrate +:program:`clang-tidy` by means of three other tools. The `ReSharper C++`_ +extension, version 2017.3 and later, provides seamless :program:`clang-tidy` +integration: checks and quick-fixes run alongside native inspections. Apart +from that, ReSharper C++ incorporates :program:`clang-tidy` as a separate +step of its code clean-up process. `Visual Assist`_ build 2210 includes a +subset of :program:`clang-tidy` checklist to inspect the code as you edit. +Another way to bring :program:`clang-tidy` functionality to Visual Studio is +the `Clang Power Tools`_ plugin, which includes most of the +:program:`clang-tidy` checks and runs them during compilation or as a separate +step of code analysis. + +**Editors** + +.. _Flycheck: https://github.com/ch1bo/flycheck-clang-tidy +.. _Syntastic: https://github.com/vim-syntastic/syntastic +.. _A.L.E.: https://github.com/w0rp/ale +.. _Emacs24: https://www.gnu.org/s/emacs/ +.. _Vim: https://www.vim.org/ + +Emacs24_, when expanded with the Flycheck_ plugin, incorporates the +:program:`clang-tidy` inspection into the syntax analyzer. For Vim_, you can +use Syntastic_, which includes :program:`clang-tidy`, or `A.L.E.`_, +a lint engine that applies :program:`clang-tidy` along with other linters. + +**Analyzers** + +.. _CPPDepend: https://www.cppdepend.com/cppdependv2018 +.. _CPPCheck: https://sourceforge.net/p/cppcheck/news/ +.. _CodeChecker: https://github.com/Ericsson/codechecker +.. _plugin: https://github.com/Ericsson/CodeCheckerEclipsePlugin + +:program:`clang-tidy` is integrated in CPPDepend_ starting from version 2018.1 +and CPPCheck_ 1.82. CPPCheck integration lets you import Visual Studio +solutions and run the :program:`clang-tidy` inspection on them. The +CodeChecker_ application of version 5.3 or later, which also comes as a plugin_ +for Eclipse, supports :program:`clang-tidy` as a static analysis instrument and +allows to use a custom :program:`clang-tidy` binary. diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc-non-private-member-variables-in-classes.rst b/clang-tools-extra/docs/clang-tidy/checks/misc-non-private-member-variables-in-classes.rst index db88c9b1cffd8..57990622e60cd 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc-non-private-member-variables-in-classes.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc-non-private-member-variables-in-classes.rst @@ -6,11 +6,11 @@ misc-non-private-member-variables-in-classes `cppcoreguidelines-non-private-member-variables-in-classes` redirects here as an alias for this check. -Finds classes that contain non-static data members in addition to non-static -member functions and diagnose all data members declared with a non-``public`` -access specifier. The data members should be declared as ``private`` and -accessed through member functions instead of exposed to derived classes or -class consumers. +Finds classes that contain non-static data members in addition to user-declared +non-static member functions and diagnose all data members declared with a +non-``public`` access specifier. The data members should be declared as +``private`` and accessed through member functions instead of exposed to derived +classes or class consumers. Options ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-avoid-c-arrays.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-avoid-c-arrays.rst index 8f856a524b2d5..d7bc7474e27f8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-avoid-c-arrays.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-avoid-c-arrays.rst @@ -54,3 +54,7 @@ such headers between C code, and C++ code. } } + +Similarly, the ``main()`` function is ignored. Its second and third parameters +can be either ``char* argv[]`` or ``char** argv``, but can not be +``std::array<>``. diff --git a/clang-tools-extra/docs/clang-tidy/index.rst b/clang-tools-extra/docs/clang-tidy/index.rst index 20b18b4bf5989..4172d13487c53 100644 --- a/clang-tools-extra/docs/clang-tidy/index.rst +++ b/clang-tools-extra/docs/clang-tidy/index.rst @@ -10,6 +10,8 @@ See also: :maxdepth: 1 The list of clang-tidy checks + Clang-tidy IDE/Editor Integrations + Getting Involved :program:`clang-tidy` is a clang-based C++ "linter" tool. Its purpose is to provide an extensible framework for diagnosing and fixing typical programming @@ -310,511 +312,3 @@ the parenthesis) whitespaces can be used and will be ignored. .. _LibTooling: http://clang.llvm.org/docs/LibTooling.html .. _How To Setup Tooling For LLVM: http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html - - -Getting Involved -================ - -:program:`clang-tidy` has several own checks and can run Clang static analyzer -checks, but its power is in the ability to easily write custom checks. - -Checks are organized in modules, which can be linked into :program:`clang-tidy` -with minimal or no code changes in :program:`clang-tidy`. - -Checks can plug into the analysis on the preprocessor level using `PPCallbacks`_ -or on the AST level using `AST Matchers`_. When an error is found, checks can -report them in a way similar to how Clang diagnostics work. A fix-it hint can be -attached to a diagnostic message. - -The interface provided by :program:`clang-tidy` makes it easy to write useful -and precise checks in just a few lines of code. If you have an idea for a good -check, the rest of this document explains how to do this. - -There are a few tools particularly useful when developing clang-tidy checks: - * ``add_new_check.py`` is a script to automate the process of adding a new - check, it will create the check, update the CMake file and create a test; - * ``rename_check.py`` does what the script name suggests, renames an existing - check; - * :program:`clang-query` is invaluable for interactive prototyping of AST - matchers and exploration of the Clang AST; - * `clang-check`_ with the ``-ast-dump`` (and optionally ``-ast-dump-filter``) - provides a convenient way to dump AST of a C++ program. - -If CMake is configured with ``CLANG_ENABLE_STATIC_ANALYZER``, -:program:`clang-tidy` will not be built with support for the -``clang-analyzer-*`` checks or the ``mpi-*`` checks. - - -.. _AST Matchers: http://clang.llvm.org/docs/LibASTMatchers.html -.. _PPCallbacks: http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html -.. _clang-check: http://clang.llvm.org/docs/ClangCheck.html - - -Choosing the Right Place for your Check ---------------------------------------- - -If you have an idea of a check, you should decide whether it should be -implemented as a: - -+ *Clang diagnostic*: if the check is generic enough, targets code patterns that - most probably are bugs (rather than style or readability issues), can be - implemented effectively and with extremely low false positive rate, it may - make a good Clang diagnostic. - -+ *Clang static analyzer check*: if the check requires some sort of control flow - analysis, it should probably be implemented as a static analyzer check. - -+ *clang-tidy check* is a good choice for linter-style checks, checks that are - related to a certain coding style, checks that address code readability, etc. - - -Preparing your Workspace ------------------------- - -If you are new to LLVM development, you should read the `Getting Started with -the LLVM System`_, `Using Clang Tools`_ and `How To Setup Tooling For LLVM`_ -documents to check out and build LLVM, Clang and Clang Extra Tools with CMake. - -Once you are done, change to the ``llvm/tools/clang/tools/extra`` directory, and -let's start! - -.. _Getting Started with the LLVM System: http://llvm.org/docs/GettingStarted.html -.. _Using Clang Tools: http://clang.llvm.org/docs/ClangTools.html - - -The Directory Structure ------------------------ - -:program:`clang-tidy` source code resides in the -``llvm/tools/clang/tools/extra`` directory and is structured as follows: - -:: - - clang-tidy/ # Clang-tidy core. - |-- ClangTidy.h # Interfaces for users and checks. - |-- ClangTidyModule.h # Interface for clang-tidy modules. - |-- ClangTidyModuleRegistry.h # Interface for registering of modules. - ... - |-- google/ # Google clang-tidy module. - |-+ - |-- GoogleTidyModule.cpp - |-- GoogleTidyModule.h - ... - |-- llvm/ # LLVM clang-tidy module. - |-+ - |-- LLVMTidyModule.cpp - |-- LLVMTidyModule.h - ... - |-- objc/ # Objective-C clang-tidy module. - |-+ - |-- ObjCTidyModule.cpp - |-- ObjCTidyModule.h - ... - |-- tool/ # Sources of the clang-tidy binary. - ... - test/clang-tidy/ # Integration tests. - ... - unittests/clang-tidy/ # Unit tests. - |-- ClangTidyTest.h - |-- GoogleModuleTest.cpp - |-- LLVMModuleTest.cpp - |-- ObjCModuleTest.cpp - ... - - -Writing a clang-tidy Check --------------------------- - -So you have an idea of a useful check for :program:`clang-tidy`. - -First, if you're not familiar with LLVM development, read through the `Getting -Started with LLVM`_ document for instructions on setting up your workflow and -the `LLVM Coding Standards`_ document to familiarize yourself with the coding -style used in the project. For code reviews we mostly use `LLVM Phabricator`_. - -.. _Getting Started with LLVM: http://llvm.org/docs/GettingStarted.html -.. _LLVM Coding Standards: http://llvm.org/docs/CodingStandards.html -.. _LLVM Phabricator: http://llvm.org/docs/Phabricator.html - -Next, you need to decide which module the check belongs to. Modules -are located in subdirectories of `clang-tidy/ -`_ -and contain checks targeting a certain aspect of code quality (performance, -readability, etc.), certain coding style or standard (Google, LLVM, CERT, etc.) -or a widely used API (e.g. MPI). Their names are same as user-facing check -groups names described :ref:`above `. - -After choosing the module and the name for the check, run the -``clang-tidy/add_new_check.py`` script to create the skeleton of the check and -plug it to :program:`clang-tidy`. It's the recommended way of adding new checks. - -If we want to create a `readability-awesome-function-names`, we would run: - -.. code-block:: console - - $ clang-tidy/add_new_check.py readability awesome-function-names - - -The ``add_new_check.py`` script will: - * create the class for your check inside the specified module's directory and - register it in the module and in the build system; - * create a lit test file in the ``test/clang-tidy/`` directory; - * create a documentation file and include it into the - ``docs/clang-tidy/checks/list.rst``. - -Let's see in more detail at the check class definition: - -.. code-block:: c++ - - ... - - #include "../ClangTidy.h" - - namespace clang { - namespace tidy { - namespace readability { - - ... - class AwesomeFunctionNamesCheck : public ClangTidyCheck { - public: - AwesomeFunctionNamesCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} - void registerMatchers(ast_matchers::MatchFinder *Finder) override; - void check(const ast_matchers::MatchFinder::MatchResult &Result) override; - }; - - } // namespace readability - } // namespace tidy - } // namespace clang - - ... - -Constructor of the check receives the ``Name`` and ``Context`` parameters, and -must forward them to the ``ClangTidyCheck`` constructor. - -In our case the check needs to operate on the AST level and it overrides the -``registerMatchers`` and ``check`` methods. If we wanted to analyze code on the -preprocessor level, we'd need instead to override the ``registerPPCallbacks`` -method. - -In the ``registerMatchers`` method we create an AST Matcher (see `AST Matchers`_ -for more information) that will find the pattern in the AST that we want to -inspect. The results of the matching are passed to the ``check`` method, which -can further inspect them and report diagnostics. - -.. code-block:: c++ - - using namespace ast_matchers; - - void AwesomeFunctionNamesCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(functionDecl().bind("x"), this); - } - - void AwesomeFunctionNamesCheck::check(const MatchFinder::MatchResult &Result) { - const auto *MatchedDecl = Result.Nodes.getNodeAs("x"); - if (MatchedDecl->getName().startswith("awesome_")) - return; - diag(MatchedDecl->getLocation(), "function %0 is insufficiently awesome") - << MatchedDecl - << FixItHint::CreateInsertion(MatchedDecl->getLocation(), "awesome_"); - } - -(If you want to see an example of a useful check, look at -`clang-tidy/google/ExplicitConstructorCheck.h -`_ -and `clang-tidy/google/ExplicitConstructorCheck.cpp -`_). - - -Registering your Check ----------------------- - -(The ``add_new_check.py`` takes care of registering the check in an existing -module. If you want to create a new module or know the details, read on.) - -The check should be registered in the corresponding module with a distinct name: - -.. code-block:: c++ - - class MyModule : public ClangTidyModule { - public: - void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { - CheckFactories.registerCheck( - "my-explicit-constructor"); - } - }; - -Now we need to register the module in the ``ClangTidyModuleRegistry`` using a -statically initialized variable: - -.. code-block:: c++ - - static ClangTidyModuleRegistry::Add X("my-module", - "Adds my lint checks."); - - -When using LLVM build system, we need to use the following hack to ensure the -module is linked into the :program:`clang-tidy` binary: - -Add this near the ``ClangTidyModuleRegistry::Add`` variable: - -.. code-block:: c++ - - // This anchor is used to force the linker to link in the generated object file - // and thus register the MyModule. - volatile int MyModuleAnchorSource = 0; - -And this to the main translation unit of the :program:`clang-tidy` binary (or -the binary you link the ``clang-tidy`` library in) -``clang-tidy/tool/ClangTidyMain.cpp``: - -.. code-block:: c++ - - // This anchor is used to force the linker to link the MyModule. - extern volatile int MyModuleAnchorSource; - static int MyModuleAnchorDestination = MyModuleAnchorSource; - - -Configuring Checks ------------------- - -If a check needs configuration options, it can access check-specific options -using the ``Options.get("SomeOption", DefaultValue)`` call in the check -constructor. In this case the check should also override the -``ClangTidyCheck::storeOptions`` method to make the options provided by the -check discoverable. This method lets :program:`clang-tidy` know which options -the check implements and what the current values are (e.g. for the -``-dump-config`` command line option). - -.. code-block:: c++ - - class MyCheck : public ClangTidyCheck { - const unsigned SomeOption1; - const std::string SomeOption2; - - public: - MyCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context), - SomeOption(Options.get("SomeOption1", -1U)), - SomeOption(Options.get("SomeOption2", "some default")) {} - - void storeOptions(ClangTidyOptions::OptionMap &Opts) override { - Options.store(Opts, "SomeOption1", SomeOption1); - Options.store(Opts, "SomeOption2", SomeOption2); - } - ... - -Assuming the check is registered with the name "my-check", the option can then -be set in a ``.clang-tidy`` file in the following way: - -.. code-block:: yaml - - CheckOptions: - - key: my-check.SomeOption1 - value: 123 - - key: my-check.SomeOption2 - value: 'some other value' - -If you need to specify check options on a command line, you can use the inline -YAML format: - -.. code-block:: console - - $ clang-tidy -config="{CheckOptions: [{key: a, value: b}, {key: x, value: y}]}" ... - - -Testing Checks --------------- - -To run tests for :program:`clang-tidy` use the command: - -.. code-block:: console - - $ ninja check-clang-tools - -:program:`clang-tidy` checks can be tested using either unit tests or -`lit`_ tests. Unit tests may be more convenient to test complex replacements -with strict checks. `Lit`_ tests allow using partial text matching and regular -expressions which makes them more suitable for writing compact tests for -diagnostic messages. - -The ``check_clang_tidy.py`` script provides an easy way to test both -diagnostic messages and fix-its. It filters out ``CHECK`` lines from the test -file, runs :program:`clang-tidy` and verifies messages and fixes with two -separate `FileCheck`_ invocations: once with FileCheck's directive -prefix set to ``CHECK-MESSAGES``, validating the diagnostic messages, -and once with the directive prefix set to ``CHECK-FIXES``, running -against the fixed code (i.e., the code after generated fix-its are -applied). In particular, ``CHECK-FIXES:`` can be used to check -that code was not modified by fix-its, by checking that it is present -unchanged in the fixed code. The full set of `FileCheck`_ directives -is available (e.g., ``CHECK-MESSAGES-SAME:``, ``CHECK-MESSAGES-NOT:``), though -typically the basic ``CHECK`` forms (``CHECK-MESSAGES`` and ``CHECK-FIXES``) -are sufficient for clang-tidy tests. Note that the `FileCheck`_ -documentation mostly assumes the default prefix (``CHECK``), and hence -describes the directive as ``CHECK:``, ``CHECK-SAME:``, ``CHECK-NOT:``, etc. -Replace ``CHECK`` by either ``CHECK-FIXES`` or ``CHECK-MESSAGES`` for -clang-tidy tests. - -An additional check enabled by ``check_clang_tidy.py`` ensures that -if `CHECK-MESSAGES:` is used in a file then every warning or error -must have an associated CHECK in that file. Or, you can use ``CHECK-NOTES:`` -instead, if you want to **also** ensure that all the notes are checked. - -To use the ``check_clang_tidy.py`` script, put a .cpp file with the -appropriate ``RUN`` line in the ``test/clang-tidy`` directory. Use -``CHECK-MESSAGES:`` and ``CHECK-FIXES:`` lines to write checks against -diagnostic messages and fixed code. - -It's advised to make the checks as specific as possible to avoid checks matching -to incorrect parts of the input. Use ``[[@LINE+X]]``/``[[@LINE-X]]`` -substitutions and distinct function and variable names in the test code. - -Here's an example of a test using the ``check_clang_tidy.py`` script (the full -source code is at `test/clang-tidy/google-readability-casting.cpp`_): - -.. code-block:: c++ - - // RUN: %check_clang_tidy %s google-readability-casting %t - - void f(int a) { - int b = (int)a; - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant cast to the same type [google-readability-casting] - // CHECK-FIXES: int b = a; - } - -To check more than one scenario in the same test file use -``-check-suffix=SUFFIX-NAME`` on ``check_clang_tidy.py`` command line or -``-check-suffixes=SUFFIX-NAME-1,SUFFIX-NAME-2,...``. -With ``-check-suffix[es]=SUFFIX-NAME`` you need to replace your ``CHECK-*`` -directives with ``CHECK-MESSAGES-SUFFIX-NAME`` and ``CHECK-FIXES-SUFFIX-NAME``. - -Here's an example: - -.. code-block:: c++ - - // RUN: %check_clang_tidy -check-suffix=USING-A %s misc-unused-using-decls %t -- -- -DUSING_A - // RUN: %check_clang_tidy -check-suffix=USING-B %s misc-unused-using-decls %t -- -- -DUSING_B - // RUN: %check_clang_tidy %s misc-unused-using-decls %t - ... - // CHECK-MESSAGES-USING-A: :[[@LINE-8]]:10: warning: using decl 'A' {{.*}} - // CHECK-MESSAGES-USING-B: :[[@LINE-7]]:10: warning: using decl 'B' {{.*}} - // CHECK-MESSAGES: :[[@LINE-6]]:10: warning: using decl 'C' {{.*}} - // CHECK-FIXES-USING-A-NOT: using a::A;$ - // CHECK-FIXES-USING-B-NOT: using a::B;$ - // CHECK-FIXES-NOT: using a::C;$ - - -There are many dark corners in the C++ language, and it may be difficult to make -your check work perfectly in all cases, especially if it issues fix-it hints. The -most frequent pitfalls are macros and templates: - -1. code written in a macro body/template definition may have a different meaning - depending on the macro expansion/template instantiation; -2. multiple macro expansions/template instantiations may result in the same code - being inspected by the check multiple times (possibly, with different - meanings, see 1), and the same warning (or a slightly different one) may be - issued by the check multiple times; :program:`clang-tidy` will deduplicate - _identical_ warnings, but if the warnings are slightly different, all of them - will be shown to the user (and used for applying fixes, if any); -3. making replacements to a macro body/template definition may be fine for some - macro expansions/template instantiations, but easily break some other - expansions/instantiations. - -.. _lit: http://llvm.org/docs/CommandGuide/lit.html -.. _FileCheck: http://llvm.org/docs/CommandGuide/FileCheck.html -.. _test/clang-tidy/google-readability-casting.cpp: http://reviews.llvm.org/diffusion/L/browse/clang-tools-extra/trunk/test/clang-tidy/google-readability-casting.cpp - - -Running clang-tidy on LLVM --------------------------- - -To test a check it's best to try it out on a larger code base. LLVM and Clang -are the natural targets as you already have the source code around. The most -convenient way to run :program:`clang-tidy` is with a compile command database; -CMake can automatically generate one, for a description of how to enable it see -`How To Setup Tooling For LLVM`_. Once ``compile_commands.json`` is in place and -a working version of :program:`clang-tidy` is in ``PATH`` the entire code base -can be analyzed with ``clang-tidy/tool/run-clang-tidy.py``. The script executes -:program:`clang-tidy` with the default set of checks on every translation unit -in the compile command database and displays the resulting warnings and errors. -The script provides multiple configuration flags. - -* The default set of checks can be overridden using the ``-checks`` argument, - taking the identical format as :program:`clang-tidy` does. For example - ``-checks=-*,modernize-use-override`` will run the ``modernize-use-override`` - check only. - -* To restrict the files examined you can provide one or more regex arguments - that the file names are matched against. - ``run-clang-tidy.py clang-tidy/.*Check\.cpp`` will only analyze clang-tidy - checks. It may also be necessary to restrict the header files warnings are - displayed from using the ``-header-filter`` flag. It has the same behavior - as the corresponding :program:`clang-tidy` flag. - -* To apply suggested fixes ``-fix`` can be passed as an argument. This gathers - all changes in a temporary directory and applies them. Passing ``-format`` - will run clang-format over changed lines. - - -On checks profiling -------------------- - -:program:`clang-tidy` can collect per-check profiling info, and output it -for each processed source file (translation unit). - -To enable profiling info collection, use the ``-enable-check-profile`` argument. -The timings will be output to ``stderr`` as a table. Example output: - -.. code-block:: console - - $ clang-tidy -enable-check-profile -checks=-*,readability-function-size source.cpp - ===-------------------------------------------------------------------------=== - clang-tidy checks profiling - ===-------------------------------------------------------------------------=== - Total Execution Time: 1.0282 seconds (1.0258 wall clock) - - ---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name --- - 0.9136 (100.0%) 0.1146 (100.0%) 1.0282 (100.0%) 1.0258 (100.0%) readability-function-size - 0.9136 (100.0%) 0.1146 (100.0%) 1.0282 (100.0%) 1.0258 (100.0%) Total - -It can also store that data as JSON files for further processing. Example output: - -.. code-block:: console - - $ clang-tidy -enable-check-profile -store-check-profile=. -checks=-*,readability-function-size source.cpp - $ # Note that there won't be timings table printed to the console. - $ ls /tmp/out/ - 20180516161318717446360-source.cpp.json - $ cat 20180516161318717446360-source.cpp.json - { - "file": "/path/to/source.cpp", - "timestamp": "2018-05-16 16:13:18.717446360", - "profile": { - "time.clang-tidy.readability-function-size.wall": 1.0421266555786133e+00, - "time.clang-tidy.readability-function-size.user": 9.2088400000005421e-01, - "time.clang-tidy.readability-function-size.sys": 1.2418899999999974e-01 - } - } - -There is only one argument that controls profile storage: - -* ``-store-check-profile=`` - - By default reports are printed in tabulated format to stderr. When this option - is passed, these per-TU profiles are instead stored as JSON. - If the prefix is not an absolute path, it is considered to be relative to the - directory from where you have run :program:`clang-tidy`. All ``.`` and ``..`` - patterns in the path are collapsed, and symlinks are resolved. - - Example: - Let's suppose you have a source file named ``example.cpp``, located in the - ``/source`` directory. Only the input filename is used, not the full path - to the source file. Additionally, it is prefixed with the current timestamp. - - * If you specify ``-store-check-profile=/tmp``, then the profile will be saved - to ``/tmp/-example.cpp.json`` - - * If you run :program:`clang-tidy` from within ``/foo`` directory, and specify - ``-store-check-profile=.``, then the profile will still be saved to - ``/foo/-example.cpp.json`` diff --git a/clang-tools-extra/docs/clangd.rst b/clang-tools-extra/docs/clangd.rst index 0b276380000a7..8feca331c5d78 100644 --- a/clang-tools-extra/docs/clangd.rst +++ b/clang-tools-extra/docs/clangd.rst @@ -1,161 +1 @@ -============ -Clangd -============ - -.. contents:: - -.. toctree:: - :maxdepth: 1 - -:program:`Clangd` is an implementation of the `Language Server Protocol -`_ leveraging Clang. -Clangd's goal is to provide language "smartness" features like code completion, -find references, etc. for clients such as C/C++ Editors. - -Using Clangd -================== - -:program:`Clangd` is not meant to be used by C/C++ developers directly but -rather from a client implementing the protocol. A client would be typically -implemented in an IDE or an editor. - -At the moment, `Visual Studio Code `_ is mainly -used in order to test :program:`Clangd` but more clients are likely to make -use of :program:`Clangd` in the future as it matures and becomes a production -quality tool. If you are interested in trying :program:`Clangd` in combination -with Visual Studio Code, you can start by `installing Clangd`_ or -`building Clangd`_, then open Visual Studio Code in the clangd-vscode folder and -launch the extension. - -Installing Clangd -================== - -Packages are available for debian-based distributions, see the `LLVM packages -page `_. :program:`Clangd` is included in the -`clang-tools` package. -However, it is a good idea to check your distribution's packaging system first -as it might already be available. - -Otherwise, you can install :program:`Clangd` by `building Clangd`_ first. - -Building Clangd -================== - -You can follow the instructions for `building Clang -`_ but "extra Clang tools" is **not** -optional. - -Current Status -================== - -Many features could be implemented in :program:`Clangd`. -Here is a list of features that could be useful with the status of whether or -not they are already implemented in :program:`Clangd` and specified in the -Language Server Protocol. Note that for some of the features, it is not clear -whether or not they should be part of the Language Server Protocol, so those -features might be eventually developed outside :program:`Clangd` or as an -extension to the protocol. - -+-------------------------------------+------------+----------+ -| C/C++ Editor feature | LSP | Clangd | -+=====================================+============+==========+ -| Formatting | Yes | Yes | -+-------------------------------------+------------+----------+ -| Completion | Yes | Yes | -+-------------------------------------+------------+----------+ -| Diagnostics | Yes | Yes | -+-------------------------------------+------------+----------+ -| Fix-its | Yes | Yes | -+-------------------------------------+------------+----------+ -| Go to Definition | Yes | Yes | -+-------------------------------------+------------+----------+ -| Signature Help | Yes | Yes | -+-------------------------------------+------------+----------+ -| Document Highlights | Yes | Yes | -+-------------------------------------+------------+----------+ -| Rename | Yes | Yes | -+-------------------------------------+------------+----------+ -| Source hover | Yes | Yes | -+-------------------------------------+------------+----------+ -| Find References | Yes | No | -+-------------------------------------+------------+----------+ -| Code Lens | Yes | No | -+-------------------------------------+------------+----------+ -| Document Symbols | Yes | Yes | -+-------------------------------------+------------+----------+ -| Workspace Symbols | Yes | Yes | -+-------------------------------------+------------+----------+ -| Syntax and Semantic Coloring | No | No | -+-------------------------------------+------------+----------+ -| Code folding | No | No | -+-------------------------------------+------------+----------+ -| Call hierarchy | No | No | -+-------------------------------------+------------+----------+ -| Type hierarchy | No | No | -+-------------------------------------+------------+----------+ -| Organize Includes | No | No | -+-------------------------------------+------------+----------+ -| Quick Assist | No | No | -+-------------------------------------+------------+----------+ -| Extract Local Variable | No | No | -+-------------------------------------+------------+----------+ -| Extract Function/Method | No | No | -+-------------------------------------+------------+----------+ -| Hide Method | No | No | -+-------------------------------------+------------+----------+ -| Implement Method | No | No | -+-------------------------------------+------------+----------+ -| Gen. Getters/Setters | No | No | -+-------------------------------------+------------+----------+ - -Editor Integration -================== - -Any full-featured Language Server Protocol Client implementation should work -with :program:`Clangd`. This `list -`_ contains information about -extensions and plugins that are known to work for different editors. - -Vim Integration ---------------- - -LanguageClient-neovim -~~~~~~~~~~~~~~~~~~~~~ - -One of the options of using :program:`Clangd` in :program:`vim` (or -:program:`nvim`) is to utilize `LanguageClient-neovim -`_ plugin. Please see the -`Clangd Wiki page -`_ for -instructions. - -VSCode Integration ------------------- - -:program:`VSCode` provides `vscode-clangd -`_ -which is published in Visual Studio Marketplace and can be installed direcetly -from :program:`VSCode`. - -Emacs Integration ------------------ - -:program:`Emacs` provides `lsp-mode `_ and -`Eglot `_ plugins for LSP integration. - -Getting Involved -================== - -A good place for interested contributors is the `Clangd developer mailing list -`_. For discussions with the -broader community on topics not only related to Clangd, use -`Clang developer mailing list -`_. -If you're also interested in contributing patches to :program:`Clangd`, take a -look at the `LLVM Developer Policy -`_ and `Code Reviews -`_ page. Contributions of new features -to the `Language Server Protocol -`_ itself would also be -very useful, so that :program:`Clangd` can eventually implement them in a -conforming way. +:orphan: diff --git a/clang-tools-extra/docs/clangd/ApplyClangTidyFixInVSCode.gif b/clang-tools-extra/docs/clangd/ApplyClangTidyFixInVSCode.gif new file mode 100644 index 0000000000000..b07bdeb437df2 Binary files /dev/null and b/clang-tools-extra/docs/clangd/ApplyClangTidyFixInVSCode.gif differ diff --git a/clang-tools-extra/docs/clangd/ApplyFixInVSCode.gif b/clang-tools-extra/docs/clangd/ApplyFixInVSCode.gif new file mode 100644 index 0000000000000..929a98c31798e Binary files /dev/null and b/clang-tools-extra/docs/clangd/ApplyFixInVSCode.gif differ diff --git a/clang-tools-extra/docs/clangd/CodeCompletionInEmacsCompanyMode.png b/clang-tools-extra/docs/clangd/CodeCompletionInEmacsCompanyMode.png new file mode 100644 index 0000000000000..1accc5af57713 Binary files /dev/null and b/clang-tools-extra/docs/clangd/CodeCompletionInEmacsCompanyMode.png differ diff --git a/clang-tools-extra/docs/clangd/CodeCompletionInSublimeText.png b/clang-tools-extra/docs/clangd/CodeCompletionInSublimeText.png new file mode 100644 index 0000000000000..b09fed3bdfa26 Binary files /dev/null and b/clang-tools-extra/docs/clangd/CodeCompletionInSublimeText.png differ diff --git a/clang-tools-extra/docs/clangd/CodeCompletionInVSCode.png b/clang-tools-extra/docs/clangd/CodeCompletionInVSCode.png new file mode 100644 index 0000000000000..bc42e9dd73216 Binary files /dev/null and b/clang-tools-extra/docs/clangd/CodeCompletionInVSCode.png differ diff --git a/clang-tools-extra/docs/clangd/CodeCompletionInYCM.png b/clang-tools-extra/docs/clangd/CodeCompletionInYCM.png new file mode 100644 index 0000000000000..b74508d6dfaf7 Binary files /dev/null and b/clang-tools-extra/docs/clangd/CodeCompletionInYCM.png differ diff --git a/clang-tools-extra/docs/clangd/CodeCompletionInsertsNamespaceQualifiersInVSCode.gif b/clang-tools-extra/docs/clangd/CodeCompletionInsertsNamespaceQualifiersInVSCode.gif new file mode 100644 index 0000000000000..f0d49d630787c Binary files /dev/null and b/clang-tools-extra/docs/clangd/CodeCompletionInsertsNamespaceQualifiersInVSCode.gif differ diff --git a/clang-tools-extra/docs/clangd/DeveloperDocumentation.rst b/clang-tools-extra/docs/clangd/DeveloperDocumentation.rst new file mode 100644 index 0000000000000..75843279ef6f4 --- /dev/null +++ b/clang-tools-extra/docs/clangd/DeveloperDocumentation.rst @@ -0,0 +1,29 @@ +================================== +Developer documentation for clangd +================================== + +.. toctree:: + :maxdepth: 1 + + Extensions + +Compiling clangd +================ + +To build clangd from source, please follow the instructions for `building Clang +`_ and include LLVM, Clang, and the +"extra Clang tools" in your build. + +Contributing to clangd +====================== + +A good place for interested contributors is the `Clangd developer mailing list +`_. For discussions with +the broader community on topics not only related to Clangd, use `Clang +developer mailing list `_. If +you're also interested in contributing patches to clangd, take a look at the +`LLVM Developer Policy `_ and `Code +Reviews `_ page. Contributions of new +features to the `Language Server Protocol +`_ itself would also be +very useful, so that clangd can eventually implement them in a conforming way. diff --git a/clang-tools-extra/docs/clangd/DiagnosticsInEmacsEglot.png b/clang-tools-extra/docs/clangd/DiagnosticsInEmacsEglot.png new file mode 100644 index 0000000000000..f5be84bf5ac79 Binary files /dev/null and b/clang-tools-extra/docs/clangd/DiagnosticsInEmacsEglot.png differ diff --git a/clang-tools-extra/docs/clangd/ErrorsInVSCode.png b/clang-tools-extra/docs/clangd/ErrorsInVSCode.png new file mode 100644 index 0000000000000..52de402962703 Binary files /dev/null and b/clang-tools-extra/docs/clangd/ErrorsInVSCode.png differ diff --git a/clang-tools-extra/docs/clangd/Extensions.rst b/clang-tools-extra/docs/clangd/Extensions.rst new file mode 100644 index 0000000000000..1f340ae088714 --- /dev/null +++ b/clang-tools-extra/docs/clangd/Extensions.rst @@ -0,0 +1,181 @@ +=================== +Protocol extensions +=================== + +clangd supports some features that are not in the official +`Language Server Protocol specification +`__. + +We cautious about adding extensions. The most important considerations are: + +- **Editor support**: How many users will the feature be available to? +- **Standardization**: Is the feature stable? Is it likely to be adopted by more + editors over time? +- **Utility**: Does the feature provide a lot of value? +- **Complexity**: Is this hard to implement in clangd, or constrain future work? + Is the protocol complicated? + +These extensions may evolve or disappear over time. If you use them, try to +recover gracefully if the structures aren't what's expected. + +Switch between the implementation file and the header +===================================================== + +*This extension is supported in clangd 6 and newer.* + +Switching between the implementation file and the header is an important +feature for C++. A language server that understands C++ can do a better job +than the editor. + +**New client->server request**: ``textDocument/switchSourceHeader``. + +Lets editors switch between the main source file (``*.cpp``) and header (``*.h``). + +Parameter: ``TextDocumentIdentifier``: an open file. + +Result: ``string``: the URI of the corresponding header (if a source file was +provided) or source file (if a header was provided). + +If the corresponding file can't be determined, ``""`` is returned. + +.. _lsp-extension-file-status: + +File status +=========== + +*This extension is supported in clangd 8 and newer.* + +It is important to provide feedback to the user when the UI is not responsive. + +This extension provides information about activity on clangd's per-file worker +thread. This information can be displayed to users to let them know that the +language server is busy with something. For example, in clangd, building the +AST blocks many other operations. + +**New server->client notification**: ``textDocument/clangd.fileStatus`` + +Sent when the current activity for a file changes. Replaces previous activity +for that file. + +Parameter: ``FileStatus`` object with properties: + +- ``uri : string``: the document whose status is being updated. +- ``state : string``: human-readable information about current activity. + +**New initialization option**: ``initializationOptions.clangdFileStatus : bool`` + +Enables receiving ``textDocument/clangd.fileStatus`` notifications. + +.. _lsp-extension-compilation-commands: + +Compilation commands +==================== + +*This extension is supported in clangd 8 and newer.* + +clangd relies on knowing accurate compilation options to correctly interpret a +file. Typically they are found in a ``compile_commands.json`` file in a +directory that contains the file, or an ancestor directory. The following +extensions allow editors to supply the commands over LSP instead. + +**New initialization option**: ``initializationOptions.compilationDatabasePath : string`` + +Specifies the directory containing the compilation database (e.g., +``compile_commands.json``). This path will be used for all files, instead of +searching their ancestor directories. + +**New initialization option**: ``initializationOptions.fallbackFlags : string[]`` + +Controls the flags used when no specific compile command is found. The compile +command will be approximately ``clang $FILE $fallbackFlags`` in this case. + +**New configuration setting**: ``settings.compilationDatabaseChanges : {string: CompileCommand}`` + +Provides compile commands for files. This can also be provided on startup as +``initializationOptions.compilationDatabaseChanges``. + +Keys are file paths (Not URIs!) + +Values are ``{workingDirectory: string, compilationCommand: string[]}``. + +Force diagnostics generation +============================ + +*This extension is supported in clangd 7 and newer.* + +Clangd does not regenerate diagnostics for every version of a file (e.g., after +every keystroke), as that would be too slow. Its heuristics ensure: + +- diagnostics do not get too stale, +- if you stop editing, diagnostics will catch up. + +This extension allows editors to force diagnostics to be generated or not +generated at a particular revision. + +**New property of** ``textDocument/didChange`` **request**: ``wantDiagnostics : bool`` + +- if true, diagnostics will be produced for exactly this version. +- if false, diagnostics will not be produced for this version, even if there + are no further edits. +- if unset, diagnostics will be produced for this version or some subsequent + one in a bounded amount of time. + +Diagnostic categories +===================== + +*This extension is supported in clangd 8 and newer.* + +Clang compiler groups diagnostics into categories (e.g., "Inline Assembly +Issue"). Clangd can emit these categories for interested editors. + +**New property of** ``Diagnostic`` **object**: ``category : string``: + +A human-readable name for a group of related diagnostics. Diagnostics with the +same code will always have the same category. + +**New client capability**: ``textDocument.publishDiagnostics.categorySupport``: + +Requests that clangd send ``Diagnostic.category``. + +.. _lsp-extension-code-actions-in-diagnostics: + +Inline fixes for diagnostics +============================ + +*This extension is supported in clangd 8 and newer.* + +LSP specifies that code actions for diagnostics (fixes) are retrieved +asynchronously using ``textDocument/codeAction``. clangd always computes fixes +eagerly. Providing them alongside diagnostics can improve the UX in editors. + +**New property of** ``Diagnostic`` **object**: ``codeActions : CodeAction[]``: + +All the code actions that address this diagnostic. + +**New client capability**: ``textDocument.publishDiagnostics.codeActionsInline : bool`` + +Requests clangd to send ``Diagnostic.codeActions``. + +.. _lsp-extension-symbol-info: + +Symbol info request +=================== + +*This extension is supported in clangd 8 and newer.* + +**New client->server request**: ``textDocument/symbolInfo``: + +This request attempts to resolve the symbol under the cursor, without +retrieving further information (like definition location, which may require +consulting an index). This request was added to support integration with +indexes outside clangd. + +Parameter: ``TextDocumentPositionParams`` + +Response: ``SymbolDetails``, an object with properties: + +- ``name : string`` the unqualified name of the symbol +- ``containerName : string`` the enclosing namespace, class etc (without + trailing ``::``) +- ``usr : string``: the clang-specific "unified symbol resolution" identifier +- ``id : string?``: the clangd-specific opaque symbol ID diff --git a/clang-tools-extra/docs/clangd/Features.rst b/clang-tools-extra/docs/clangd/Features.rst new file mode 100644 index 0000000000000..f6a8c501480ea --- /dev/null +++ b/clang-tools-extra/docs/clangd/Features.rst @@ -0,0 +1,231 @@ +======== +Features +======== + +.. role:: raw-html(raw) + :format: html + +Here is what clangd can do for you. Screenshots below show `VSCode +`__; the available features and UI depend on +the editor. + +Errors and warnings +=================== + +clangd runs the clang compiler on your code as you type, and shows errors and +warnings in-place. Some errors are suppressed: diagnostics that require +expanding templates in headers are disabled for performance reasons. + +:raw-html:`
Screenshot` + +.. image:: ErrorsInVSCode.png + :align: center + :alt: Demonstration of errors + +:raw-html:`
` + +Fixes in errors and warnings +---------------------------- + +The compiler can suggest fixes for many common problems automatically, and +clangd can update the code for you. + +:raw-html:`
Animated demo` + +.. image:: ApplyFixInVSCode.gif + :align: center + :alt: Applying a fix suggested by the compiler + +:raw-html:`
` + +Code completion +=============== + +You'll see suggestions as you type based on what methods, variables, etc are +available in this context. + +:raw-html:`
Screenshot` + +.. image:: CodeCompletionInVSCode.png + :align: center + :alt: Code completion demonstration + +:raw-html:`
` + +Abbreviating words may help you find the right result faster. If you type in +``camelCase`` but the function you're looking for is ``snake_case``, that's OK. + +Insertion of namespace qualifiers and includes +---------------------------------------------- + +**(New in v8)** +clangd will sometimes suggest results from other files and namespaces. In this +case the correct qualifier and ``#include`` directive will be inserted. + +:raw-html:`
Animated demo` + +.. image:: CodeCompletionInsertsNamespaceQualifiersInVSCode.gif + :align: center + :alt: Code completion inserts namespace qualifiers + +:raw-html:`
` + +Signature help +-------------- + +Some editors will show you the parameters of the function you're calling, as +you fill them in. + +:raw-html:`
Animated demo` + +.. image:: SignatureHelpInVSCode.gif + :align: center + :alt: Demonstration of the signature help feature + +:raw-html:`
` + +Cross-references +================ + +The following features let you navigate your codebase. + +If there is no project-wide index, cross-references work across the files +you have opened. + +Find definition/declaration +--------------------------- + +Jump to the definition or declaration of a symbol under the cursor. + +:raw-html:`
Animated demo` + +.. image:: GoToDefinitionInVSCode.gif + :align: center + :alt: Demonstration of the "Go to definition" feature + +:raw-html:`
` + +Find references +--------------- + +Show all references to a symbol under the cursor. + +:raw-html:`
Animated demo` + +.. image:: FindAllReferencesInVSCode.gif + :align: center + :alt: Demonstration of the "Find all references" feature + +:raw-html:`
` + +Some editors will automatically highlight local references to the selected +symbol as you move around a file. + +Navigation +========== + +clangd informs the editor of the code structure in the current file. +Some editors use this to present an outline view: + +:raw-html:`
Screenshot` + +.. image:: OutlineInVSCode.png + :align: center + :alt: Outline of a file + +:raw-html:`
` + +In VSCode, the outline is also presented as breadcrumbs that allow jumping to a +symbol within the current file. Searching for symbols within the scope of the +whole project is also possible. + +:raw-html:`
Animated demo` + +.. image:: NavigationWithBreadcrumbsInVSCode.gif + :align: center + :alt: Navigation with breadcrumbs + +:raw-html:`
` + +Formatting +========== + +clangd embeds `clang-format `__, +which can reformat your code: fixing indentation, breaking lines, and reflowing +comments. + +:raw-html:`
Animated demo` + +.. image:: FormatSelectionInVSCode.gif + :align: center + :alt: Formatting selected code + +:raw-html:`
` + +clangd respects your project's ``.clang-format`` file which controls styling +options. + +Format-as-you-type is experimental and doesn't work well yet. + +Complete list of features +========================= + +Here is a list of features that could be useful for editors, together with the +implementation status in clangd, and specification in the Language Server +Protocol. + +It is not clear whether or not some of the features mentioned below should be a +part of the Language Server Protocol; those features might be eventually +developed outside clangd or become clangd extensions to LSP. + ++-------------------------------------+------------+----------+ +| C/C++ Editor feature | LSP | Clangd | ++=====================================+============+==========+ +| Formatting | Yes | Yes | ++-------------------------------------+------------+----------+ +| Completion | Yes | Yes | ++-------------------------------------+------------+----------+ +| Diagnostics | Yes | Yes | ++-------------------------------------+------------+----------+ +| Fix-its | Yes | Yes | ++-------------------------------------+------------+----------+ +| Go to Definition | Yes | Yes | ++-------------------------------------+------------+----------+ +| Signature Help | Yes | Yes | ++-------------------------------------+------------+----------+ +| Document Highlights | Yes | Yes | ++-------------------------------------+------------+----------+ +| Rename | Yes | Yes | ++-------------------------------------+------------+----------+ +| Source hover | Yes | Yes | ++-------------------------------------+------------+----------+ +| Find References | Yes | Yes | ++-------------------------------------+------------+----------+ +| Document Symbols | Yes | Yes | ++-------------------------------------+------------+----------+ +| Workspace Symbols | Yes | Yes | ++-------------------------------------+------------+----------+ +| Code Lens | Yes | No | ++-------------------------------------+------------+----------+ +| Code folding | Yes | No | ++-------------------------------------+------------+----------+ +| Extract Local Variable | Yes | No | ++-------------------------------------+------------+----------+ +| Extract Function/Method | Yes | No | ++-------------------------------------+------------+----------+ +| Quick Assist | Yes | No | ++-------------------------------------+------------+----------+ +| Hide Method | Yes | No | ++-------------------------------------+------------+----------+ +| Implement Method | Yes | No | ++-------------------------------------+------------+----------+ +| Gen. Getters/Setters | Yes | No | ++-------------------------------------+------------+----------+ +| Syntax and Semantic Coloring | No | No | ++-------------------------------------+------------+----------+ +| Call hierarchy | No | No | ++-------------------------------------+------------+----------+ +| Type hierarchy | No | No | ++-------------------------------------+------------+----------+ +| Organize Includes | No | No | ++-------------------------------------+------------+----------+ diff --git a/clang-tools-extra/docs/clangd/FindAllReferencesInVSCode.gif b/clang-tools-extra/docs/clangd/FindAllReferencesInVSCode.gif new file mode 100644 index 0000000000000..b9eecf3c86429 Binary files /dev/null and b/clang-tools-extra/docs/clangd/FindAllReferencesInVSCode.gif differ diff --git a/clang-tools-extra/docs/clangd/FormatSelectionInVSCode.gif b/clang-tools-extra/docs/clangd/FormatSelectionInVSCode.gif new file mode 100644 index 0000000000000..1d4be410b4c68 Binary files /dev/null and b/clang-tools-extra/docs/clangd/FormatSelectionInVSCode.gif differ diff --git a/clang-tools-extra/docs/clangd/GoToDefinitionInVSCode.gif b/clang-tools-extra/docs/clangd/GoToDefinitionInVSCode.gif new file mode 100644 index 0000000000000..396966f7ae3a4 Binary files /dev/null and b/clang-tools-extra/docs/clangd/GoToDefinitionInVSCode.gif differ diff --git a/clang-tools-extra/docs/clangd/Installation.rst b/clang-tools-extra/docs/clangd/Installation.rst new file mode 100644 index 0000000000000..3c7b36401dec1 --- /dev/null +++ b/clang-tools-extra/docs/clangd/Installation.rst @@ -0,0 +1,371 @@ +=========================== +Getting started with clangd +=========================== + +.. role:: raw-html(raw) + :format: html + +To use clangd, you need to: + +- install clangd, +- install a plugin for your editor, +- tell clangd how your project is built. + +Installing clangd +================= + +You need a **recent** version of clangd: 7.0 was the first usable release, and +8.0 is much better. + +After installing, ``clangd --version`` should print ``clangd version 7.0.0`` or +later. + +:raw-html:`
macOS` + +`Homebrew `__ can install clangd along with LLVM: + +.. code-block:: console + + $ brew install llvm + +If you don't want to use Homebrew, you can download the a binary release of +LLVM from `releases.llvm.org `__. +Alongside ``bin/clangd`` you will need at least ``lib/clang/*/include``: + +.. code-block:: console + + $ cp clang+llvm-7.0.0/bin/clangd /usr/local/bin/clangd + $ cp -r clang+llvm-7.0.0/lib/clang/ /usr/local/lib/ + +:raw-html:`
` + +:raw-html:`
Windows` + +Download and run the LLVM installer from `releases.llvm.org +`__. + +:raw-html:`
` + +:raw-html:`
Debian/Ubuntu` + +The ``clang-tools`` package usually contains an old version of clangd. + +Try to install the latest release (8.0): + +.. code-block:: console + + $ sudo apt-get install clang-tools-8 + +If that is not found, at least ``clang-tools-7`` should be available. + +The ``clangd`` executable will be installed as ``/usr/bin/clangd-8``. Make it +the default ``clangd``: + +.. code-block:: console + + $ sudo update-alternatives --install /usr/bin/clangd clangd /usr/bin/clangd-8 100 + +:raw-html:`
` + +:raw-html:`
Other systems` + +Most distributions include clangd in a ``clang-tools`` package, or in the full +``llvm`` distribution. + +For some platforms, binaries are also avaliable at `releases.llvm.org +`__. + +:raw-html:`
` + +Editor plugins +============== + +Language Server plugins are available for many editors. In principle, clangd +should work with any of them, though the feature set and UI may vary. + +Here are some plugins we know work well with clangd. + +:raw-html:`
YouCompleteMe for Vim` + +`YouCompleteMe `__ supports clangd. +However, clangd support is not turned on by default, so you must install +YouCompleteMe with ``install.py --clangd-completer``. + +We recommend changing a couple of YCM's default settings. In ``.vimrc`` add: + +:: + + " Let clangd fully control code completion + let g:ycm_clangd_uses_ycmd_caching = 0 + " Use installed clangd, not YCM-bundled clangd which doesn't get updates. + let g:ycm_clangd_binary_path = exepath("clangd") + +You should see errors highlighted and code completions as you type. + +.. image:: CodeCompletionInYCM.png + :align: center + :alt: Code completion in YouCompleteMe + +YouCompleteMe supports many of clangd's features: + +- code completion, +- diagnostics and fixes (``:YcmCompleter FixIt``), +- find declarations, references, and definitions (``:YcmCompleter GoTo`` etc), +- rename symbol (``:YcmCompleter RefactorRename``). + +**Under the hood** + +- **Debug logs**: run ``:YcmDebugInfo`` to see clangd status, and ``:YcmToggleLogs`` + to view clangd's debug logs. +- **Command-line flags**: Set ``g:ycm_clangd_args`` in ``.vimrc``, e.g.: + + :: + + let g:ycm_clangd_args = ['-log=verbose', '-pretty'] + +- **Alternate clangd binary**: set ``g:ycm_clangd_binary_path`` in ``.vimrc``. + +:raw-html:`
` + +:raw-html:`
LanguageClient for Vim and Neovim` + +`LanguageClient-neovim `__ +has `instructions for using clangd +`__, and **may** +be easier to install than YouCompleteMe. + +:raw-html:`
` + +:raw-html:`
Eglot for Emacs` + +`eglot `__ can be configured to work with +clangd. + +Install eglot with ``M-x package-install RET eglot RET``. + +Add the following to ``~/.emacs`` to enable clangd: + +:: + + (require 'eglot) + (add-to-list 'eglot-server-programs '((c++-mode c-mode) "clangd")) + (add-hook 'c-mode-hook 'eglot-ensure) + (add-hook 'c++-mode-hook 'eglot-ensure) + +After restarting you should see diagnostics for errors in your code, and ``M-x +completion-at-point`` should work. + +.. image:: DiagnosticsInEmacsEglot.png + :align: center + :alt: Diagnostics in Emacs + +eglot supports many of clangd's features, with caveats: + +- code completion, though the interaction is quite poor (even with + ``company-mode``, see below), +- diagnostics and fixes, +- find definitions and references (``M-x xref-find-definitions`` etc), +- hover and highlights, +- code actions (``M-x eglot-code-actions``). + +**company-mode** + +eglot does have basic integration with company-mode, which provides a more +fluent completion UI. + +You can install it with ``M-x package-install RET company RET``, and enable it +with ``M-x company-mode``. + +**company-clang is enabled by default**, and will interfere with clangd. +Disable it in ``M-x customize-variable RET company-backends RET``. + +Completion still has some major limitations: + +- completions are alphabetically sorted, not ranked. +- only pure-prefix completions are shown - no fuzzy matches. +- completion triggering seems to be a bit hit-and-miss. + +.. image:: CodeCompletionInEmacsCompanyMode.png + :align: center + :alt: Completion in company-mode + +**Under the hood** + +- **Debug logs**: available in the ``EGLOT stderr`` buffer. +- **Command-line flags and alternate binary**: instead of adding ``"clangd"`` + to ``eglot-server-programs``, add ``("/path/to/clangd" "-log=verbose")`` etc. + +:raw-html:`
` + +:raw-html:`
Visual Studio Code` + +The official extension is `vscode-clangd +`__ +and can be installed from within VSCode. + +Choose **View** --> **Extensions**, then search for "clangd". (Make sure the +Microsoft C/C++ extension is **not** installed). + +After restarting, you should see red underlines underneath errors, and you +should get rich code completions including e.g. function parameters. + +.. image:: CodeCompletionInVSCode.png + :align: center + :alt: Code completion in VSCode + +vscode-clangd has excellent support for all clangd features, including: + +- code completion +- diagnostics and fixes +- find declarations, references, and definitions +- find symbol in file (``Ctrl-P @foo``) or workspace (``Ctrl-P #foo``) +- hover and highlights +- code actions + +**Under the hood** + +- **Debug logs**: when clangd is running, you should see "Clang Language + Server" in the dropdown of the Output panel (**View** -> **Output**). + +- **Command-line flags**: these can be passed in the ``clangd.arguments`` array + in your ``settings.json``. (**File** -> **Preferences** -> **Settings**). + +- **Alternate clangd binary**: set the ``clangd.path`` string in + ``settings.json``. + +:raw-html:`
` + +:raw-html:`
Sublime Text` + +`tomv564/LSP `__ works with clangd out of the box. + +Select **Tools** --> **Install Package Control** (if you haven't installed it +yet). + +Press ``Ctrl-Shift-P`` and select **Package Control: Install Package**. Select +**LSP**. + +Press ``Ctrl-Shift-P`` and select **LSP: Enable Language Server Globally**. +Select **clangd**. + +Open a C++ file, and you should see diagnostics and completion: + +.. image:: CodeCompletionInSublimeText.png + :align: center + :alt: Code completion in Sublime Text + + +The LSP package has excellent support for all most clangd features, including: + +- code completion (a bit noisy due to how snippets are presented) +- diagnostics and fixes +- find definition and references +- hover and highlights +- code actions + +**Under the hood** + +Settings can be tweaked under **Preferences** --> **Package Settings** --> +**LSP**. + +- **Debug logs**: add ``"log_stderr": true`` +- **Command-line flags and alternate clangd binary**: inside the ``"clients": + {"clangd": { ... } }`` section, add ``"command": ["/path/to/clangd", + "-log=verbose"]`` etc. + +:raw-html:`
` + +:raw-html:`
Other editors` + +There is a directory of LSP clients at `langserver.org +`__. + +A generic client should be configured to run the command ``clangd``, and +communicate via the language server protocol on standard input/output. + +If you don't have strong feelings about an editor, we suggest you try out +`VSCode `__, it has excellent language server +support and most faithfully demonstrates what clangd can do. + +:raw-html:`
` + +Project setup +============= + +To understand source code in your project, clangd needs to know the build +flags. (This is just a fact of life in C++, source files are not +self-contained.) + +By default, clangd will assume that source code is built as ``clang +some_file.cc``, and you'll probably get spurious errors about missing +``#include``\ d files, etc. There are a couple of ways to fix this. + +``compile_commands.json`` +------------------------- + +``compile_commands.json`` file provides compile commands for all source files +in the project. This file is usually generated by the build system, or tools +integrated with the build system. Clangd will look for this file in the parent +directories of the files you edit. + +:raw-html:`
CMake-based projects` + +If your project builds with CMake, it can generate ``compile_commands.json``. +You should enable it with: + +:: + + $ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 + +``compile_commands.json`` will be written to your build directory. You should +symlink it (or copy it) to the root of your source tree, if they are different. + +:: + + $ ln -s ~/myproject/compile_commands.json ~/myproject-build/ + +:raw-html:`
` + +:raw-html:`
Other build systems, using Bear` + +`Bear `__ is a tool that generates a +``compile_commands.json`` file by recording a complete build. + +For a ``make``-based build, you can run ``make clean; bear make`` to generate the +file (and run a clean build!) + +:raw-html:`
` + +Other tools can also generate this file. See `the compile_commands.json +specification `__. + +``compile_flags.txt`` +--------------------- + +If all files in a project use the same build flags, you can put those flags, +one flag per line, in ``compile_flags.txt`` in your source root. + +Clangd will assume the compile command is ``clang $FLAGS some_file.cc``. + +Creating this file by hand is a reasonable place to start if your project is +quite simple. + +.. _project-wide-index: + +Project-wide Index +================== + +By default clangd only has a view on symbols coming from files you are +currently editing. You can extend this view to whole project by providing a +project-wide index to clangd. There are two ways to do this. + +- Pass an experimental `-background-index` command line argument. With + this feature enabled, clangd incrementally builds an index of projects + that you work on and uses the just-built index automatically. + +- Generate an index file using `clangd-indexer + `__ + Then you can pass generated index file to clangd using + `-index-file=/path/to/index_file`. *Note that clangd-indexer isn't + included alongside clangd in the Debian clang-tools package. You will + likely have to build clangd from source to use this option.* diff --git a/clang-tools-extra/docs/clangd/NavigationWithBreadcrumbsInVSCode.gif b/clang-tools-extra/docs/clangd/NavigationWithBreadcrumbsInVSCode.gif new file mode 100644 index 0000000000000..499f5c1af8468 Binary files /dev/null and b/clang-tools-extra/docs/clangd/NavigationWithBreadcrumbsInVSCode.gif differ diff --git a/clang-tools-extra/docs/clangd/OutlineInVSCode.png b/clang-tools-extra/docs/clangd/OutlineInVSCode.png new file mode 100644 index 0000000000000..570a80de8b71c Binary files /dev/null and b/clang-tools-extra/docs/clangd/OutlineInVSCode.png differ diff --git a/clang-tools-extra/docs/clangd/SignatureHelpInVSCode.gif b/clang-tools-extra/docs/clangd/SignatureHelpInVSCode.gif new file mode 100644 index 0000000000000..e5700f22b57db Binary files /dev/null and b/clang-tools-extra/docs/clangd/SignatureHelpInVSCode.gif differ diff --git a/clang-tools-extra/docs/clangd/index.rst b/clang-tools-extra/docs/clangd/index.rst new file mode 100644 index 0000000000000..46939062876f1 --- /dev/null +++ b/clang-tools-extra/docs/clangd/index.rst @@ -0,0 +1,27 @@ +====== +clangd +====== + +.. toctree:: + :maxdepth: 1 + + Installation + Features + +What is clangd? +=============== + +clangd understands your C++ code and adds smart features to your editor: code +completion, compile errors, go-to-definition and more. + +clangd is a language server that implements the `Language Server Protocol +`__; it can work with +many editors through a plugin. Here's Visual Studio Code with the clangd +plugin, demonstrating code completion: + +.. image:: CodeCompletionInVSCode.png + :align: center + :alt: Code completion in VSCode + +clangd is based on the `Clang `__ C++ compiler, and is +part of the `LLVM `__ project. diff --git a/clang-tools-extra/docs/conf.py b/clang-tools-extra/docs/conf.py index 1b07e8efe5ec5..badb8efa3709f 100644 --- a/clang-tools-extra/docs/conf.py +++ b/clang-tools-extra/docs/conf.py @@ -121,7 +121,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = [] +html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. diff --git a/clang-tools-extra/docs/index.rst b/clang-tools-extra/docs/index.rst index 8e6beb35a6091..b20f0485c84a2 100644 --- a/clang-tools-extra/docs/index.rst +++ b/clang-tools-extra/docs/index.rst @@ -1,14 +1,9 @@ -.. Extra Clang Tools documentation master file, created by - sphinx-quickstart on Wed Feb 13 10:00:18 2013. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - .. title:: Welcome to Extra Clang Tools's documentation! Introduction ============ Welcome to the clang-tools-extra project which contains extra tools built using -Clang's tooling API's. +Clang's tooling APIs. .. toctree:: :maxdepth: 1 @@ -25,28 +20,11 @@ Contents modularize pp-trace clang-rename - clangd + clangd/index + clangd/DeveloperDocumentation clang-doc -Doxygen Documentation -===================== -The Doxygen documentation describes the **internal** software that makes up the -tools of clang-tools-extra, not the **external** use of these tools. The Doxygen -documentation contains no instructions about how to use the tools, only the APIs -that make up the software. For usage instructions, please see the user's guide -or reference manual for each tool. - -* `Doxygen documentation`_ - -.. _`Doxygen documentation`: doxygen/annotated.html - -.. note:: - This documentation is generated directly from the source code with doxygen. - Since the tools of clang-tools-extra are constantly under active - development, what you're about to read is out of date! - - Indices and tables ================== diff --git a/clang-tools-extra/test/clang-tidy/misc-non-private-member-variables-in-classes.cpp b/clang-tools-extra/test/clang-tidy/misc-non-private-member-variables-in-classes.cpp index 31052716d2873..2a93ff6a18c38 100644 --- a/clang-tools-extra/test/clang-tidy/misc-non-private-member-variables-in-classes.cpp +++ b/clang-tools-extra/test/clang-tidy/misc-non-private-member-variables-in-classes.cpp @@ -35,6 +35,23 @@ class S1 { int S1_v3; }; +// Only data and implicit or static methods, do not warn + +class C { +public: + C() {} + ~C() {} +}; + +struct S1Implicit { + C S1Implicit_v0; +}; + +struct S1ImplicitAndStatic { + C S1Implicit_v0; + static void s() {} +}; + //----------------------------------------------------------------------------// // All functions are static, do not warn. diff --git a/clang-tools-extra/test/clang-tidy/modernize-avoid-c-arrays-ignores-main.cpp b/clang-tools-extra/test/clang-tidy/modernize-avoid-c-arrays-ignores-main.cpp new file mode 100644 index 0000000000000..6549422f393aa --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/modernize-avoid-c-arrays-ignores-main.cpp @@ -0,0 +1,18 @@ +// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t + +int not_main(int argc, char *argv[]) { + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not declare C-style arrays, use std::array<> instead + int f4[] = {1, 2}; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead +} + +int main(int argc, char *argv[]) { + int f5[] = {1, 2}; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead + + auto not_main = [](int argc, char *argv[]) { + // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: do not declare C-style arrays, use std::array<> instead + int f6[] = {1, 2}; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not declare C-style arrays, use std::array<> instead + }; +} diff --git a/clang-tools-extra/test/clang-tidy/modernize-avoid-c-arrays-ignores-three-arg-main.cpp b/clang-tools-extra/test/clang-tidy/modernize-avoid-c-arrays-ignores-three-arg-main.cpp new file mode 100644 index 0000000000000..22a4016f79f4d --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/modernize-avoid-c-arrays-ignores-three-arg-main.cpp @@ -0,0 +1,20 @@ +// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t + +int not_main(int argc, char *argv[], char *argw[]) { + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not declare C-style arrays, use std::array<> instead + // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: do not declare C-style arrays, use std::array<> instead + int f4[] = {1, 2}; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead +} + +int main(int argc, char *argv[], char *argw[]) { + int f5[] = {1, 2}; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead + + auto not_main = [](int argc, char *argv[], char *argw[]) { + // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: do not declare C-style arrays, use std::array<> instead + // CHECK-MESSAGES: :[[@LINE-2]]:46: warning: do not declare C-style arrays, use std::array<> instead + int f6[] = {1, 2}; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not declare C-style arrays, use std::array<> instead + }; +} diff --git a/clang-tools-extra/test/clang-tidy/readability-uppercase-literal-suffix-float16.cpp b/clang-tools-extra/test/clang-tidy/readability-uppercase-literal-suffix-float16.cpp new file mode 100644 index 0000000000000..b2b858f9345b5 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/readability-uppercase-literal-suffix-float16.cpp @@ -0,0 +1,51 @@ +// RUN: %check_clang_tidy %s readability-uppercase-literal-suffix %t -- -- -target aarch64-linux-gnu -I %S + +#include "readability-uppercase-literal-suffix.h" + +void float16_normal_literals() { + // _Float16 + + static constexpr auto v14 = 1.f16; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v14 = 1.f16; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} + // CHECK-FIXES: static constexpr auto v14 = 1.F16; + static_assert(is_same::value, ""); + static_assert(v14 == 1.F16, ""); + + static constexpr auto v15 = 1.e0f16; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v15 = 1.e0f16; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} + // CHECK-FIXES: static constexpr auto v15 = 1.e0F16; + static_assert(is_same::value, ""); + static_assert(v15 == 1.F16, ""); + + static constexpr auto v16 = 1.F16; // OK. + static_assert(is_same::value, ""); + static_assert(v16 == 1.F16, ""); + + static constexpr auto v17 = 1.e0F16; // OK. + static_assert(is_same::value, ""); + static_assert(v17 == 1.F16, ""); +} + +void float16_hexadecimal_literals() { +// _Float16 + + static constexpr auto v13 = 0xfp0f16; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase + // CHECK-MESSAGES-NEXT: static constexpr auto v13 = 0xfp0f16; + // CHECK-MESSAGES-NEXT: ^ ~ + // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} + // CHECK-FIXES: static constexpr auto v13 = 0xfp0F16; + static_assert(is_same::value, ""); + static_assert(v13 == 0xfp0F16, ""); + + static constexpr auto v14 = 0xfp0F16; // OK. + static_assert(is_same::value, ""); + static_assert(v14 == 0xfp0F16, ""); + +} diff --git a/clang-tools-extra/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp b/clang-tools-extra/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp index 4d41db7a5ec64..50e75fae6ae40 100644 --- a/clang-tools-extra/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp +++ b/clang-tools-extra/test/clang-tidy/readability-uppercase-literal-suffix-floating-point.cpp @@ -97,34 +97,6 @@ void floating_point_suffix() { static constexpr auto v13 = 1.e0Q; // OK. static_assert(is_same::value, ""); static_assert(v13 == 1., ""); - - // _Float16 - - static constexpr auto v14 = 1.f16; - // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase - // CHECK-MESSAGES-NEXT: static constexpr auto v14 = 1.f16; - // CHECK-MESSAGES-NEXT: ^ ~ - // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} - // CHECK-FIXES: static constexpr auto v14 = 1.F16; - static_assert(is_same::value, ""); - static_assert(v14 == 1.F16, ""); - - static constexpr auto v15 = 1.e0f16; - // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase - // CHECK-MESSAGES-NEXT: static constexpr auto v15 = 1.e0f16; - // CHECK-MESSAGES-NEXT: ^ ~ - // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} - // CHECK-FIXES: static constexpr auto v15 = 1.e0F16; - static_assert(is_same::value, ""); - static_assert(v15 == 1.F16, ""); - - static constexpr auto v16 = 1.F16; // OK. - static_assert(is_same::value, ""); - static_assert(v16 == 1.F16, ""); - - static constexpr auto v17 = 1.e0F16; // OK. - static_assert(is_same::value, ""); - static_assert(v17 == 1.F16, ""); } void floating_point_complex_suffix() { diff --git a/clang-tools-extra/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp b/clang-tools-extra/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp index 4cc9d6d2a7040..415c6d8e7915f 100644 --- a/clang-tools-extra/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp +++ b/clang-tools-extra/test/clang-tidy/readability-uppercase-literal-suffix-hexadecimal-floating-point.cpp @@ -93,21 +93,6 @@ void floating_point_suffix() { static constexpr auto v12 = 0xfp0Q; // OK. static_assert(is_same::value, ""); static_assert(v12 == 0xfp0, ""); - - // _Float16 - - static constexpr auto v13 = 0xfp0f16; - // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: floating point literal has suffix 'f16', which is not uppercase - // CHECK-MESSAGES-NEXT: static constexpr auto v13 = 0xfp0f16; - // CHECK-MESSAGES-NEXT: ^ ~ - // CHECK-MESSAGES-NEXT: {{^ *}}F16{{$}} - // CHECK-FIXES: static constexpr auto v13 = 0xfp0F16; - static_assert(is_same::value, ""); - static_assert(v13 == 0xfp0F16, ""); - - static constexpr auto v14 = 0xfp0F16; // OK. - static_assert(is_same::value, ""); - static_assert(v14 == 0xfp0F16, ""); } void floating_point_complex_suffix() { diff --git a/clang-tools-extra/test/clangd/background-index.test b/clang-tools-extra/test/clangd/background-index.test index 34c419ac68299..1d11736dfe821 100644 --- a/clang-tools-extra/test/clangd/background-index.test +++ b/clang-tools-extra/test/clangd/background-index.test @@ -13,7 +13,7 @@ # RUN: clangd -background-index -background-index-rebuild-period=0 -lit-test < %t/definition.jsonrpc | FileCheck %t/definition.jsonrpc # Test that the index is writing files in the expected location. -# RUN: ls %t/.clangd-index/foo.cpp.*.idx +# RUN: ls %t/.clangd/index/foo.cpp.*.idx # Test the index is read from disk: delete code and restart clangd. # RUN: rm %t/foo.cpp diff --git a/clang-tools-extra/unittests/clangd/BackgroundIndexTests.cpp b/clang-tools-extra/unittests/clangd/BackgroundIndexTests.cpp index 639d35c876ac7..09a117dbbe7d3 100644 --- a/clang-tools-extra/unittests/clangd/BackgroundIndexTests.cpp +++ b/clang-tools-extra/unittests/clangd/BackgroundIndexTests.cpp @@ -76,7 +76,7 @@ TEST_F(BackgroundIndexTest, NoCrashOnErrorFile) { size_t CacheHits = 0; MemoryShardStorage MSS(Storage, CacheHits); OverlayCDB CDB(/*Base=*/nullptr); - BackgroundIndex Idx(Context::empty(), "", FS, CDB, + BackgroundIndex Idx(Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }); tooling::CompileCommand Cmd; @@ -113,7 +113,7 @@ TEST_F(BackgroundIndexTest, IndexTwoFiles) { size_t CacheHits = 0; MemoryShardStorage MSS(Storage, CacheHits); OverlayCDB CDB(/*Base=*/nullptr); - BackgroundIndex Idx(Context::empty(), "", FS, CDB, + BackgroundIndex Idx(Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }); tooling::CompileCommand Cmd; @@ -168,7 +168,7 @@ TEST_F(BackgroundIndexTest, ShardStorageTest) { // Check nothing is loaded from Storage, but A.cc and A.h has been stored. { OverlayCDB CDB(/*Base=*/nullptr); - BackgroundIndex Idx(Context::empty(), "", FS, CDB, + BackgroundIndex Idx(Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }); CDB.setCompileCommand(testPath("root/A.cc"), Cmd); ASSERT_TRUE(Idx.blockUntilIdleForTest()); @@ -178,7 +178,7 @@ TEST_F(BackgroundIndexTest, ShardStorageTest) { { OverlayCDB CDB(/*Base=*/nullptr); - BackgroundIndex Idx(Context::empty(), "", FS, CDB, + BackgroundIndex Idx(Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }); CDB.setCompileCommand(testPath("root"), Cmd); ASSERT_TRUE(Idx.blockUntilIdleForTest()); @@ -224,7 +224,7 @@ TEST_F(BackgroundIndexTest, DirectIncludesTest) { Cmd.CommandLine = {"clang++", testPath("root/A.cc")}; { OverlayCDB CDB(/*Base=*/nullptr); - BackgroundIndex Idx(Context::empty(), "", FS, CDB, + BackgroundIndex Idx(Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }); CDB.setCompileCommand(testPath("root/A.cc"), Cmd); ASSERT_TRUE(Idx.blockUntilIdleForTest()); @@ -262,7 +262,7 @@ TEST_F(BackgroundIndexTest, DISABLED_PeriodicalIndex) { MemoryShardStorage MSS(Storage, CacheHits); OverlayCDB CDB(/*Base=*/nullptr); BackgroundIndex Idx( - Context::empty(), "", FS, CDB, [&](llvm::StringRef) { return &MSS; }, + Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }, /*BuildIndexPeriodMs=*/500); FS.Files[testPath("root/A.cc")] = "#include \"A.h\""; @@ -310,7 +310,7 @@ TEST_F(BackgroundIndexTest, ShardStorageLoad) { // Check nothing is loaded from Storage, but A.cc and A.h has been stored. { OverlayCDB CDB(/*Base=*/nullptr); - BackgroundIndex Idx(Context::empty(), "", FS, CDB, + BackgroundIndex Idx(Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }); CDB.setCompileCommand(testPath("root/A.cc"), Cmd); ASSERT_TRUE(Idx.blockUntilIdleForTest()); @@ -325,7 +325,7 @@ TEST_F(BackgroundIndexTest, ShardStorageLoad) { )cpp"; { OverlayCDB CDB(/*Base=*/nullptr); - BackgroundIndex Idx(Context::empty(), "", FS, CDB, + BackgroundIndex Idx(Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }); CDB.setCompileCommand(testPath("root"), Cmd); ASSERT_TRUE(Idx.blockUntilIdleForTest()); @@ -343,7 +343,7 @@ TEST_F(BackgroundIndexTest, ShardStorageLoad) { { CacheHits = 0; OverlayCDB CDB(/*Base=*/nullptr); - BackgroundIndex Idx(Context::empty(), "", FS, CDB, + BackgroundIndex Idx(Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }); CDB.setCompileCommand(testPath("root"), Cmd); ASSERT_TRUE(Idx.blockUntilIdleForTest()); @@ -384,7 +384,7 @@ TEST_F(BackgroundIndexTest, ShardStorageEmptyFile) { // Check that A.cc, A.h and B.h has been stored. { OverlayCDB CDB(/*Base=*/nullptr); - BackgroundIndex Idx(Context::empty(), "", FS, CDB, + BackgroundIndex Idx(Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }); CDB.setCompileCommand(testPath("root/A.cc"), Cmd); ASSERT_TRUE(Idx.blockUntilIdleForTest()); @@ -400,7 +400,7 @@ TEST_F(BackgroundIndexTest, ShardStorageEmptyFile) { { CacheHits = 0; OverlayCDB CDB(/*Base=*/nullptr); - BackgroundIndex Idx(Context::empty(), "", FS, CDB, + BackgroundIndex Idx(Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }); CDB.setCompileCommand(testPath("root/A.cc"), Cmd); ASSERT_TRUE(Idx.blockUntilIdleForTest()); @@ -416,7 +416,7 @@ TEST_F(BackgroundIndexTest, ShardStorageEmptyFile) { { CacheHits = 0; OverlayCDB CDB(/*Base=*/nullptr); - BackgroundIndex Idx(Context::empty(), "", FS, CDB, + BackgroundIndex Idx(Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }); CDB.setCompileCommand(testPath("root/A.cc"), Cmd); ASSERT_TRUE(Idx.blockUntilIdleForTest()); diff --git a/clang-tools-extra/unittests/clangd/ClangdTests.cpp b/clang-tools-extra/unittests/clangd/ClangdTests.cpp index c1cc623a05a11..356efe529dde0 100644 --- a/clang-tools-extra/unittests/clangd/ClangdTests.cpp +++ b/clang-tools-extra/unittests/clangd/ClangdTests.cpp @@ -10,6 +10,7 @@ #include "Annotations.h" #include "ClangdLSPServer.h" #include "ClangdServer.h" +#include "GlobalCompilationDatabase.h" #include "Matchers.h" #include "SyncAPI.h" #include "TestFS.h" @@ -1037,6 +1038,28 @@ TEST(ClangdTests, PreambleVFSStatCache) { } #endif +TEST_F(ClangdVFSTest, FlagsWithPlugins) { + MockFSProvider FS; + ErrorCheckingDiagConsumer DiagConsumer; + MockCompilationDatabase CDB; + CDB.ExtraClangFlags = { + "-Xclang", + "-add-plugin", + "-Xclang", + "random-plugin", + }; + OverlayCDB OCDB(&CDB); + ClangdServer Server(OCDB, FS, DiagConsumer, ClangdServer::optsForTest()); + + auto FooCpp = testPath("foo.cpp"); + const auto SourceContents = "int main() { return 0; }"; + FS.Files[FooCpp] = FooCpp; + Server.addDocument(FooCpp, SourceContents); + auto Result = dumpASTWithoutMemoryLocs(Server, FooCpp); + EXPECT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for diagnostics"; + EXPECT_NE(Result, ""); +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp b/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp index 02f12eab7dd6a..f26181decb80f 100644 --- a/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp +++ b/clang-tools-extra/unittests/clangd/CodeCompleteTests.cpp @@ -2320,6 +2320,17 @@ TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) { EXPECT_THAT(C, ElementsAre(SnippetSuffix("${1:(unsigned int)}"))); } +TEST(CompletionTest, WorksWithNullType) { + auto R = completions(R"cpp( + int main() { + for (auto [loopVar] : y ) { // y has to be unresolved. + int z = loopV^; + } + } + )cpp"); + EXPECT_THAT(R.Completions, ElementsAre(Named("loopVar"))); +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/unittests/clangd/GlobalCompilationDatabaseTests.cpp b/clang-tools-extra/unittests/clangd/GlobalCompilationDatabaseTests.cpp index b0052c751c27b..41c28bf35d5a3 100644 --- a/clang-tools-extra/unittests/clangd/GlobalCompilationDatabaseTests.cpp +++ b/clang-tools-extra/unittests/clangd/GlobalCompilationDatabaseTests.cpp @@ -65,7 +65,7 @@ class OverlayCDBTest : public ::testing::Test { }; TEST_F(OverlayCDBTest, GetCompileCommand) { - OverlayCDB CDB(Base.get()); + OverlayCDB CDB(Base.get(), {}, std::string("")); EXPECT_EQ(CDB.getCompileCommand(testPath("foo.cc")), Base->getCompileCommand(testPath("foo.cc"))); EXPECT_EQ(CDB.getCompileCommand(testPath("missing.cc")), llvm::None); @@ -85,7 +85,7 @@ TEST_F(OverlayCDBTest, GetFallbackCommand) { } TEST_F(OverlayCDBTest, NoBase) { - OverlayCDB CDB(nullptr, {"-DA=6"}); + OverlayCDB CDB(nullptr, {"-DA=6"}, std::string("")); EXPECT_EQ(CDB.getCompileCommand(testPath("bar.cc")), None); auto Override = cmd(testPath("bar.cc"), "-DA=5"); CDB.setCompileCommand(testPath("bar.cc"), Override); diff --git a/clang-tools-extra/unittests/clangd/XRefsTests.cpp b/clang-tools-extra/unittests/clangd/XRefsTests.cpp index 88394b6cc5126..8616fbdb179ef 100644 --- a/clang-tools-extra/unittests/clangd/XRefsTests.cpp +++ b/clang-tools-extra/unittests/clangd/XRefsTests.cpp @@ -1082,8 +1082,6 @@ TEST(GoToInclude, All) { // Test include outside of preamble. Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("6")); ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error"; - EXPECT_THAT(*Locations, - ElementsAre(FileRange(FooH, HeaderAnnotations.range()))); // Test a few positions that do not result in Locations. Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("4")); @@ -1092,13 +1090,9 @@ TEST(GoToInclude, All) { Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("5")); ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error"; - EXPECT_THAT(*Locations, - ElementsAre(FileRange(FooH, HeaderAnnotations.range()))); Locations = runFindDefinitions(Server, FooCpp, SourceAnnotations.point("7")); ASSERT_TRUE(bool(Locations)) << "findDefinitions returned an error"; - EXPECT_THAT(*Locations, - ElementsAre(FileRange(FooH, HeaderAnnotations.range()))); } TEST(GoToDefinition, WithPreamble) { diff --git a/clang/docs/AttributeReference.rst b/clang/docs/AttributeReference.rst index a763ddeaeb106..ce7a0f3cca860 100644 --- a/clang/docs/AttributeReference.rst +++ b/clang/docs/AttributeReference.rst @@ -1,13 +1,5216 @@ .. ------------------------------------------------------------------- NOTE: This file is automatically generated by running clang-tblgen - -gen-attr-docs. Do not edit this file by hand!! The contents for - this file are automatically generated by a server-side process. - - Please do not commit this file. The file exists for local testing - purposes only. + -gen-attr-docs. Do not edit this file by hand!! ------------------------------------------------------------------- =================== Attributes in Clang -=================== \ No newline at end of file +=================== +.. contents:: + :local: + +.. |br| raw:: html + +
+ +Introduction +============ + +This page lists the attributes currently supported by Clang. + +Function Attributes +=================== + + +#pragma omp declare simd +------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","","``omp declare simd``","" + +The `declare simd` construct can be applied to a function to enable the creation +of one or more versions that can process multiple arguments using SIMD +instructions from a single invocation in a SIMD loop. The `declare simd` +directive is a declarative directive. There may be multiple `declare simd` +directives for a function. The use of a `declare simd` construct on a function +enables the creation of SIMD versions of the associated function that can be +used to process multiple arguments from a single invocation from a SIMD loop +concurrently. +The syntax of the `declare simd` construct is as follows: + + .. code-block:: none + + #pragma omp declare simd [clause[[,] clause] ...] new-line + [#pragma omp declare simd [clause[[,] clause] ...] new-line] + [...] + function definition or declaration + +where clause is one of the following: + + .. code-block:: none + + simdlen(length) + linear(argument-list[:constant-linear-step]) + aligned(argument-list[:alignment]) + uniform(argument-list) + inbranch + notinbranch + + +#pragma omp declare target +-------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","","``omp declare target``","" + +The `declare target` directive specifies that variables and functions are mapped +to a device for OpenMP offload mechanism. + +The syntax of the declare target directive is as follows: + + .. code-block:: c + + #pragma omp declare target new-line + declarations-definition-seq + #pragma omp end declare target new-line + + +_Noreturn +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``_Noreturn``","","" + +A function declared as ``_Noreturn`` shall not return to its caller. The +compiler will generate a diagnostic for a function declared as ``_Noreturn`` +that appears to be capable of returning to its caller. + + +abi_tag +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``abi_tag``","``gnu::abi_tag``","","","","","Yes" + +The ``abi_tag`` attribute can be applied to a function, variable, class or +inline namespace declaration to modify the mangled name of the entity. It gives +the ability to distinguish between different versions of the same entity but +with different ABI versions supported. For example, a newer version of a class +could have a different set of data members and thus have a different size. Using +the ``abi_tag`` attribute, it is possible to have different mangled names for +a global variable of the class type. Therefore, the old code could keep using +the old manged name and the new code will use the new mangled name with tags. + + +acquire_capability, acquire_shared_capability +--------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``acquire_capability`` |br| ``acquire_shared_capability`` |br| ``exclusive_lock_function`` |br| ``shared_lock_function``","``clang::acquire_capability`` |br| ``clang::acquire_shared_capability``","","","","","" + +Marks a function as acquiring a capability. + + +alloc_align +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``alloc_align``","``gnu::alloc_align``","","","","","" + +Use ``__attribute__((alloc_align())`` on a function +declaration to specify that the return value of the function (which must be a +pointer type) is at least as aligned as the value of the indicated parameter. The +parameter is given by its index in the list of formal parameters; the first +parameter has index 1 unless the function is a C++ non-static member function, +in which case the first parameter has index 2 to account for the implicit ``this`` +parameter. + +.. code-block:: c++ + + // The returned pointer has the alignment specified by the first parameter. + void *a(size_t align) __attribute__((alloc_align(1))); + + // The returned pointer has the alignment specified by the second parameter. + void *b(void *v, size_t align) __attribute__((alloc_align(2))); + + // The returned pointer has the alignment specified by the second visible + // parameter, however it must be adjusted for the implicit 'this' parameter. + void *Foo::b(void *v, size_t align) __attribute__((alloc_align(3))); + +Note that this attribute merely informs the compiler that a function always +returns a sufficiently aligned pointer. It does not cause the compiler to +emit code to enforce that alignment. The behavior is undefined if the returned +poitner is not sufficiently aligned. + + +alloc_size +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``alloc_size``","``gnu::alloc_size``","","","","","Yes" + +The ``alloc_size`` attribute can be placed on functions that return pointers in +order to hint to the compiler how many bytes of memory will be available at the +returned pointer. ``alloc_size`` takes one or two arguments. + +- ``alloc_size(N)`` implies that argument number N equals the number of + available bytes at the returned pointer. +- ``alloc_size(N, M)`` implies that the product of argument number N and + argument number M equals the number of available bytes at the returned + pointer. + +Argument numbers are 1-based. + +An example of how to use ``alloc_size`` + +.. code-block:: c + + void *my_malloc(int a) __attribute__((alloc_size(1))); + void *my_calloc(int a, int b) __attribute__((alloc_size(1, 2))); + + int main() { + void *const p = my_malloc(100); + assert(__builtin_object_size(p, 0) == 100); + void *const a = my_calloc(20, 5); + assert(__builtin_object_size(a, 0) == 100); + } + +.. Note:: This attribute works differently in clang than it does in GCC. + Specifically, clang will only trace ``const`` pointers (as above); we give up + on pointers that are not marked as ``const``. In the vast majority of cases, + this is unimportant, because LLVM has support for the ``alloc_size`` + attribute. However, this may cause mildly unintuitive behavior when used with + other attributes, such as ``enable_if``. + + +artificial +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``artificial``","``gnu::artificial``","","","","","" + +The ``artificial`` attribute can be applied to an inline function. If such a +function is inlined, the attribute indicates that debuggers should associate +the resulting instructions with the call site, rather than with the +corresponding line within the inlined callee. + + +assert_capability, assert_shared_capability +------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``assert_capability`` |br| ``assert_shared_capability``","``clang::assert_capability`` |br| ``clang::assert_shared_capability``","","","","","" + +Marks a function that dynamically tests whether a capability is held, and halts +the program if it is not held. + + +assume_aligned +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``assume_aligned``","``gnu::assume_aligned``","","","","","Yes" + +Use ``__attribute__((assume_aligned([,]))`` on a function +declaration to specify that the return value of the function (which must be a +pointer type) has the specified offset, in bytes, from an address with the +specified alignment. The offset is taken to be zero if omitted. + +.. code-block:: c++ + + // The returned pointer value has 32-byte alignment. + void *a() __attribute__((assume_aligned (32))); + + // The returned pointer value is 4 bytes greater than an address having + // 32-byte alignment. + void *b() __attribute__((assume_aligned (32, 4))); + +Note that this attribute provides information to the compiler regarding a +condition that the code already ensures is true. It does not cause the compiler +to enforce the provided alignment assumption. + + +availability +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``availability``","``clang::availability``","``clang::availability``","","","","Yes" + +The ``availability`` attribute can be placed on declarations to describe the +lifecycle of that declaration relative to operating system versions. Consider +the function declaration for a hypothetical function ``f``: + +.. code-block:: c++ + + void f(void) __attribute__((availability(macos,introduced=10.4,deprecated=10.6,obsoleted=10.7))); + +The availability attribute states that ``f`` was introduced in macOS 10.4, +deprecated in macOS 10.6, and obsoleted in macOS 10.7. This information +is used by Clang to determine when it is safe to use ``f``: for example, if +Clang is instructed to compile code for macOS 10.5, a call to ``f()`` +succeeds. If Clang is instructed to compile code for macOS 10.6, the call +succeeds but Clang emits a warning specifying that the function is deprecated. +Finally, if Clang is instructed to compile code for macOS 10.7, the call +fails because ``f()`` is no longer available. + +The availability attribute is a comma-separated list starting with the +platform name and then including clauses specifying important milestones in the +declaration's lifetime (in any order) along with additional information. Those +clauses can be: + +introduced=\ *version* + The first version in which this declaration was introduced. + +deprecated=\ *version* + The first version in which this declaration was deprecated, meaning that + users should migrate away from this API. + +obsoleted=\ *version* + The first version in which this declaration was obsoleted, meaning that it + was removed completely and can no longer be used. + +unavailable + This declaration is never available on this platform. + +message=\ *string-literal* + Additional message text that Clang will provide when emitting a warning or + error about use of a deprecated or obsoleted declaration. Useful to direct + users to replacement APIs. + +replacement=\ *string-literal* + Additional message text that Clang will use to provide Fix-It when emitting + a warning about use of a deprecated declaration. The Fix-It will replace + the deprecated declaration with the new declaration specified. + +Multiple availability attributes can be placed on a declaration, which may +correspond to different platforms. Only the availability attribute with the +platform corresponding to the target platform will be used; any others will be +ignored. If no availability attribute specifies availability for the current +target platform, the availability attributes are ignored. Supported platforms +are: + +``ios`` + Apple's iOS operating system. The minimum deployment target is specified by + the ``-mios-version-min=*version*`` or ``-miphoneos-version-min=*version*`` + command-line arguments. + +``macos`` + Apple's macOS operating system. The minimum deployment target is + specified by the ``-mmacosx-version-min=*version*`` command-line argument. + ``macosx`` is supported for backward-compatibility reasons, but it is + deprecated. + +``tvos`` + Apple's tvOS operating system. The minimum deployment target is specified by + the ``-mtvos-version-min=*version*`` command-line argument. + +``watchos`` + Apple's watchOS operating system. The minimum deployment target is specified by + the ``-mwatchos-version-min=*version*`` command-line argument. + +A declaration can typically be used even when deploying back to a platform +version prior to when the declaration was introduced. When this happens, the +declaration is `weakly linked +`_, +as if the ``weak_import`` attribute were added to the declaration. A +weakly-linked declaration may or may not be present a run-time, and a program +can determine whether the declaration is present by checking whether the +address of that declaration is non-NULL. + +The flag ``strict`` disallows using API when deploying back to a +platform version prior to when the declaration was introduced. An +attempt to use such API before its introduction causes a hard error. +Weakly-linking is almost always a better API choice, since it allows +users to query availability at runtime. + +If there are multiple declarations of the same entity, the availability +attributes must either match on a per-platform basis or later +declarations must not have availability attributes for that +platform. For example: + +.. code-block:: c + + void g(void) __attribute__((availability(macos,introduced=10.4))); + void g(void) __attribute__((availability(macos,introduced=10.4))); // okay, matches + void g(void) __attribute__((availability(ios,introduced=4.0))); // okay, adds a new platform + void g(void); // okay, inherits both macos and ios availability from above. + void g(void) __attribute__((availability(macos,introduced=10.5))); // error: mismatch + +When one method overrides another, the overriding method can be more widely available than the overridden method, e.g.,: + +.. code-block:: objc + + @interface A + - (id)method __attribute__((availability(macos,introduced=10.4))); + - (id)method2 __attribute__((availability(macos,introduced=10.4))); + @end + + @interface B : A + - (id)method __attribute__((availability(macos,introduced=10.3))); // okay: method moved into base class later + - (id)method __attribute__((availability(macos,introduced=10.5))); // error: this method was available via the base class in 10.4 + @end + +Starting with the macOS 10.12 SDK, the ``API_AVAILABLE`` macro from +```` can simplify the spelling: + +.. code-block:: objc + + @interface A + - (id)method API_AVAILABLE(macos(10.11))); + - (id)otherMethod API_AVAILABLE(macos(10.11), ios(11.0)); + @end + +Also see the documentation for `@available +`_ + + +carries_dependency +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``carries_dependency``","``carries_dependency``","","","","","Yes" + +The ``carries_dependency`` attribute specifies dependency propagation into and +out of functions. + +When specified on a function or Objective-C method, the ``carries_dependency`` +attribute means that the return value carries a dependency out of the function, +so that the implementation need not constrain ordering upon return from that +function. Implementations of the function and its caller may choose to preserve +dependencies instead of emitting memory ordering instructions such as fences. + +Note, this attribute does not change the meaning of the program, but may result +in generation of more efficient code. + + +cf_consumed +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``cf_consumed``","``clang::cf_consumed``","``clang::cf_consumed``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +cf_returns_not_retained +----------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``cf_returns_not_retained``","``clang::cf_returns_not_retained``","``clang::cf_returns_not_retained``","","","","" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +cf_returns_retained +------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``cf_returns_retained``","``clang::cf_returns_retained``","``clang::cf_returns_retained``","","","","" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +code_seg +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","``code_seg``","","","" + +The ``__declspec(code_seg)`` attribute enables the placement of code into separate +named segments that can be paged or locked in memory individually. This attribute +is used to control the placement of instantiated templates and compiler-generated +code. See the documentation for `__declspec(code_seg)`_ on MSDN. + +.. _`__declspec(code_seg)`: http://msdn.microsoft.com/en-us/library/dn636922.aspx + + +convergent +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``convergent``","``clang::convergent``","``clang::convergent``","","","","Yes" + +The ``convergent`` attribute can be placed on a function declaration. It is +translated into the LLVM ``convergent`` attribute, which indicates that the call +instructions of a function with this attribute cannot be made control-dependent +on any additional values. + +In languages designed for SPMD/SIMT programming model, e.g. OpenCL or CUDA, +the call instructions of a function with this attribute must be executed by +all work items or threads in a work group or sub group. + +This attribute is different from ``noduplicate`` because it allows duplicating +function calls if it can be proved that the duplicated function calls are +not made control-dependent on any additional values, e.g., unrolling a loop +executed by all work items. + +Sample usage: +.. code-block:: c + + void convfunc(void) __attribute__((convergent)); + // Setting it as a C++11 attribute is also valid in a C++ program. + // void convfunc(void) [[clang::convergent]]; + + +cpu_dispatch +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``cpu_dispatch``","``clang::cpu_dispatch``","``clang::cpu_dispatch``","``cpu_dispatch``","","","Yes" + +The ``cpu_specific`` and ``cpu_dispatch`` attributes are used to define and +resolve multiversioned functions. This form of multiversioning provides a +mechanism for declaring versions across translation units and manually +specifying the resolved function list. A specified CPU defines a set of minimum +features that are required for the function to be called. The result of this is +that future processors execute the most restrictive version of the function the +new processor can execute. + +Function versions are defined with ``cpu_specific``, which takes one or more CPU +names as a parameter. For example: + +.. code-block:: c + + // Declares and defines the ivybridge version of single_cpu. + __attribute__((cpu_specific(ivybridge))) + void single_cpu(void){} + + // Declares and defines the atom version of single_cpu. + __attribute__((cpu_specific(atom))) + void single_cpu(void){} + + // Declares and defines both the ivybridge and atom version of multi_cpu. + __attribute__((cpu_specific(ivybridge, atom))) + void multi_cpu(void){} + +A dispatching (or resolving) function can be declared anywhere in a project's +source code with ``cpu_dispatch``. This attribute takes one or more CPU names +as a parameter (like ``cpu_specific``). Functions marked with ``cpu_dispatch`` +are not expected to be defined, only declared. If such a marked function has a +definition, any side effects of the function are ignored; trivial function +bodies are permissible for ICC compatibility. + +.. code-block:: c + + // Creates a resolver for single_cpu above. + __attribute__((cpu_dispatch(ivybridge, atom))) + void single_cpu(void){} + + // Creates a resolver for multi_cpu, but adds a 3rd version defined in another + // translation unit. + __attribute__((cpu_dispatch(ivybridge, atom, sandybridge))) + void multi_cpu(void){} + +Note that it is possible to have a resolving function that dispatches based on +more or fewer options than are present in the program. Specifying fewer will +result in the omitted options not being considered during resolution. Specifying +a version for resolution that isn't defined in the program will result in a +linking failure. + +It is also possible to specify a CPU name of ``generic`` which will be resolved +if the executing processor doesn't satisfy the features required in the CPU +name. The behavior of a program executing on a processor that doesn't satisfy +any option of a multiversioned function is undefined. + + +cpu_specific +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``cpu_specific``","``clang::cpu_specific``","``clang::cpu_specific``","``cpu_specific``","","","Yes" + +The ``cpu_specific`` and ``cpu_dispatch`` attributes are used to define and +resolve multiversioned functions. This form of multiversioning provides a +mechanism for declaring versions across translation units and manually +specifying the resolved function list. A specified CPU defines a set of minimum +features that are required for the function to be called. The result of this is +that future processors execute the most restrictive version of the function the +new processor can execute. + +Function versions are defined with ``cpu_specific``, which takes one or more CPU +names as a parameter. For example: + +.. code-block:: c + + // Declares and defines the ivybridge version of single_cpu. + __attribute__((cpu_specific(ivybridge))) + void single_cpu(void){} + + // Declares and defines the atom version of single_cpu. + __attribute__((cpu_specific(atom))) + void single_cpu(void){} + + // Declares and defines both the ivybridge and atom version of multi_cpu. + __attribute__((cpu_specific(ivybridge, atom))) + void multi_cpu(void){} + +A dispatching (or resolving) function can be declared anywhere in a project's +source code with ``cpu_dispatch``. This attribute takes one or more CPU names +as a parameter (like ``cpu_specific``). Functions marked with ``cpu_dispatch`` +are not expected to be defined, only declared. If such a marked function has a +definition, any side effects of the function are ignored; trivial function +bodies are permissible for ICC compatibility. + +.. code-block:: c + + // Creates a resolver for single_cpu above. + __attribute__((cpu_dispatch(ivybridge, atom))) + void single_cpu(void){} + + // Creates a resolver for multi_cpu, but adds a 3rd version defined in another + // translation unit. + __attribute__((cpu_dispatch(ivybridge, atom, sandybridge))) + void multi_cpu(void){} + +Note that it is possible to have a resolving function that dispatches based on +more or fewer options than are present in the program. Specifying fewer will +result in the omitted options not being considered during resolution. Specifying +a version for resolution that isn't defined in the program will result in a +linking failure. + +It is also possible to specify a CPU name of ``generic`` which will be resolved +if the executing processor doesn't satisfy the features required in the CPU +name. The behavior of a program executing on a processor that doesn't satisfy +any option of a multiversioned function is undefined. + + +deprecated +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``deprecated``","``gnu::deprecated`` |br| ``deprecated``","``deprecated``","``deprecated``","","","" + +The ``deprecated`` attribute can be applied to a function, a variable, or a +type. This is useful when identifying functions, variables, or types that are +expected to be removed in a future version of a program. + +Consider the function declaration for a hypothetical function ``f``: + +.. code-block:: c++ + + void f(void) __attribute__((deprecated("message", "replacement"))); + +When spelled as `__attribute__((deprecated))`, the deprecated attribute can have +two optional string arguments. The first one is the message to display when +emitting the warning; the second one enables the compiler to provide a Fix-It +to replace the deprecated name with a new name. Otherwise, when spelled as +`[[gnu::deprecated]] or [[deprecated]]`, the attribute can have one optional +string argument which is the message to display when emitting the warning. + + +diagnose_if +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``diagnose_if``","","","","","","" + +The ``diagnose_if`` attribute can be placed on function declarations to emit +warnings or errors at compile-time if calls to the attributed function meet +certain user-defined criteria. For example: + +.. code-block:: c + + int abs(int a) + __attribute__((diagnose_if(a >= 0, "Redundant abs call", "warning"))); + int must_abs(int a) + __attribute__((diagnose_if(a >= 0, "Redundant abs call", "error"))); + + int val = abs(1); // warning: Redundant abs call + int val2 = must_abs(1); // error: Redundant abs call + int val3 = abs(val); + int val4 = must_abs(val); // Because run-time checks are not emitted for + // diagnose_if attributes, this executes without + // issue. + + +``diagnose_if`` is closely related to ``enable_if``, with a few key differences: + +* Overload resolution is not aware of ``diagnose_if`` attributes: they're + considered only after we select the best candidate from a given candidate set. +* Function declarations that differ only in their ``diagnose_if`` attributes are + considered to be redeclarations of the same function (not overloads). +* If the condition provided to ``diagnose_if`` cannot be evaluated, no + diagnostic will be emitted. + +Otherwise, ``diagnose_if`` is essentially the logical negation of ``enable_if``. + +As a result of bullet number two, ``diagnose_if`` attributes will stack on the +same function. For example: + +.. code-block:: c + + int foo() __attribute__((diagnose_if(1, "diag1", "warning"))); + int foo() __attribute__((diagnose_if(1, "diag2", "warning"))); + + int bar = foo(); // warning: diag1 + // warning: diag2 + int (*fooptr)(void) = foo; // warning: diag1 + // warning: diag2 + + constexpr int supportsAPILevel(int N) { return N < 5; } + int baz(int a) + __attribute__((diagnose_if(!supportsAPILevel(10), + "Upgrade to API level 10 to use baz", "error"))); + int baz(int a) + __attribute__((diagnose_if(!a, "0 is not recommended.", "warning"))); + + int (*bazptr)(int) = baz; // error: Upgrade to API level 10 to use baz + int v = baz(0); // error: Upgrade to API level 10 to use baz + +Query for this feature with ``__has_attribute(diagnose_if)``. + + +disable_tail_calls +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``disable_tail_calls``","``clang::disable_tail_calls``","``clang::disable_tail_calls``","","","","Yes" + +The ``disable_tail_calls`` attribute instructs the backend to not perform tail call optimization inside the marked function. + +For example: + + .. code-block:: c + + int callee(int); + + int foo(int a) __attribute__((disable_tail_calls)) { + return callee(a); // This call is not tail-call optimized. + } + +Marking virtual functions as ``disable_tail_calls`` is legal. + + .. code-block:: c++ + + int callee(int); + + class Base { + public: + [[clang::disable_tail_calls]] virtual int foo1() { + return callee(); // This call is not tail-call optimized. + } + }; + + class Derived1 : public Base { + public: + int foo1() override { + return callee(); // This call is tail-call optimized. + } + }; + + +enable_if +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``enable_if``","","","","","","Yes" + +.. Note:: Some features of this attribute are experimental. The meaning of + multiple enable_if attributes on a single declaration is subject to change in + a future version of clang. Also, the ABI is not standardized and the name + mangling may change in future versions. To avoid that, use asm labels. + +The ``enable_if`` attribute can be placed on function declarations to control +which overload is selected based on the values of the function's arguments. +When combined with the ``overloadable`` attribute, this feature is also +available in C. + +.. code-block:: c++ + + int isdigit(int c); + int isdigit(int c) __attribute__((enable_if(c <= -1 || c > 255, "chosen when 'c' is out of range"))) __attribute__((unavailable("'c' must have the value of an unsigned char or EOF"))); + + void foo(char c) { + isdigit(c); + isdigit(10); + isdigit(-10); // results in a compile-time error. + } + +The enable_if attribute takes two arguments, the first is an expression written +in terms of the function parameters, the second is a string explaining why this +overload candidate could not be selected to be displayed in diagnostics. The +expression is part of the function signature for the purposes of determining +whether it is a redeclaration (following the rules used when determining +whether a C++ template specialization is ODR-equivalent), but is not part of +the type. + +The enable_if expression is evaluated as if it were the body of a +bool-returning constexpr function declared with the arguments of the function +it is being applied to, then called with the parameters at the call site. If the +result is false or could not be determined through constant expression +evaluation, then this overload will not be chosen and the provided string may +be used in a diagnostic if the compile fails as a result. + +Because the enable_if expression is an unevaluated context, there are no global +state changes, nor the ability to pass information from the enable_if +expression to the function body. For example, suppose we want calls to +strnlen(strbuf, maxlen) to resolve to strnlen_chk(strbuf, maxlen, size of +strbuf) only if the size of strbuf can be determined: + +.. code-block:: c++ + + __attribute__((always_inline)) + static inline size_t strnlen(const char *s, size_t maxlen) + __attribute__((overloadable)) + __attribute__((enable_if(__builtin_object_size(s, 0) != -1))), + "chosen when the buffer size is known but 'maxlen' is not"))) + { + return strnlen_chk(s, maxlen, __builtin_object_size(s, 0)); + } + +Multiple enable_if attributes may be applied to a single declaration. In this +case, the enable_if expressions are evaluated from left to right in the +following manner. First, the candidates whose enable_if expressions evaluate to +false or cannot be evaluated are discarded. If the remaining candidates do not +share ODR-equivalent enable_if expressions, the overload resolution is +ambiguous. Otherwise, enable_if overload resolution continues with the next +enable_if attribute on the candidates that have not been discarded and have +remaining enable_if attributes. In this way, we pick the most specific +overload out of a number of viable overloads using enable_if. + +.. code-block:: c++ + + void f() __attribute__((enable_if(true, ""))); // #1 + void f() __attribute__((enable_if(true, ""))) __attribute__((enable_if(true, ""))); // #2 + + void g(int i, int j) __attribute__((enable_if(i, ""))); // #1 + void g(int i, int j) __attribute__((enable_if(j, ""))) __attribute__((enable_if(true))); // #2 + +In this example, a call to f() is always resolved to #2, as the first enable_if +expression is ODR-equivalent for both declarations, but #1 does not have another +enable_if expression to continue evaluating, so the next round of evaluation has +only a single candidate. In a call to g(1, 1), the call is ambiguous even though +#2 has more enable_if attributes, because the first enable_if expressions are +not ODR-equivalent. + +Query for this feature with ``__has_attribute(enable_if)``. + +Note that functions with one or more ``enable_if`` attributes may not have +their address taken, unless all of the conditions specified by said +``enable_if`` are constants that evaluate to ``true``. For example: + +.. code-block:: c + + const int TrueConstant = 1; + const int FalseConstant = 0; + int f(int a) __attribute__((enable_if(a > 0, ""))); + int g(int a) __attribute__((enable_if(a == 0 || a != 0, ""))); + int h(int a) __attribute__((enable_if(1, ""))); + int i(int a) __attribute__((enable_if(TrueConstant, ""))); + int j(int a) __attribute__((enable_if(FalseConstant, ""))); + + void fn() { + int (*ptr)(int); + ptr = &f; // error: 'a > 0' is not always true + ptr = &g; // error: 'a == 0 || a != 0' is not a truthy constant + ptr = &h; // OK: 1 is a truthy constant + ptr = &i; // OK: 'TrueConstant' is a truthy constant + ptr = &j; // error: 'FalseConstant' is a constant, but not truthy + } + +Because ``enable_if`` evaluation happens during overload resolution, +``enable_if`` may give unintuitive results when used with templates, depending +on when overloads are resolved. In the example below, clang will emit a +diagnostic about no viable overloads for ``foo`` in ``bar``, but not in ``baz``: + +.. code-block:: c++ + + double foo(int i) __attribute__((enable_if(i > 0, ""))); + void *foo(int i) __attribute__((enable_if(i <= 0, ""))); + template + auto bar() { return foo(I); } + + template + auto baz() { return foo(T::number); } + + struct WithNumber { constexpr static int number = 1; }; + void callThem() { + bar(); + baz(); + } + +This is because, in ``bar``, ``foo`` is resolved prior to template +instantiation, so the value for ``I`` isn't known (thus, both ``enable_if`` +conditions for ``foo`` fail). However, in ``baz``, ``foo`` is resolved during +template instantiation, so the value for ``T::number`` is known. + + +exclude_from_explicit_instantiation +----------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``exclude_from_explicit_instantiation``","``clang::exclude_from_explicit_instantiation``","``clang::exclude_from_explicit_instantiation``","","","","Yes" + +The ``exclude_from_explicit_instantiation`` attribute opts-out a member of a +class template from being part of explicit template instantiations of that +class template. This means that an explicit instantiation will not instantiate +members of the class template marked with the attribute, but also that code +where an extern template declaration of the enclosing class template is visible +will not take for granted that an external instantiation of the class template +would provide those members (which would otherwise be a link error, since the +explicit instantiation won't provide those members). For example, let's say we +don't want the ``data()`` method to be part of libc++'s ABI. To make sure it +is not exported from the dylib, we give it hidden visibility: + + .. code-block:: c++ + + // in + template + class basic_string { + public: + __attribute__((__visibility__("hidden"))) + const value_type* data() const noexcept { ... } + }; + + template class basic_string; + +Since an explicit template instantiation declaration for ``basic_string`` +is provided, the compiler is free to assume that ``basic_string::data()`` +will be provided by another translation unit, and it is free to produce an +external call to this function. However, since ``data()`` has hidden visibility +and the explicit template instantiation is provided in a shared library (as +opposed to simply another translation unit), ``basic_string::data()`` +won't be found and a link error will ensue. This happens because the compiler +assumes that ``basic_string::data()`` is part of the explicit template +instantiation declaration, when it really isn't. To tell the compiler that +``data()`` is not part of the explicit template instantiation declaration, the +``exclude_from_explicit_instantiation`` attribute can be used: + + .. code-block:: c++ + + // in + template + class basic_string { + public: + __attribute__((__visibility__("hidden"))) + __attribute__((exclude_from_explicit_instantiation)) + const value_type* data() const noexcept { ... } + }; + + template class basic_string; + +Now, the compiler won't assume that ``basic_string::data()`` is provided +externally despite there being an explicit template instantiation declaration: +the compiler will implicitly instantiate ``basic_string::data()`` in the +TUs where it is used. + +This attribute can be used on static and non-static member functions of class +templates, static data members of class templates and member classes of class +templates. + + +external_source_symbol +---------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``external_source_symbol``","``clang::external_source_symbol``","``clang::external_source_symbol``","","","","Yes" + +The ``external_source_symbol`` attribute specifies that a declaration originates +from an external source and describes the nature of that source. + +The fact that Clang is capable of recognizing declarations that were defined +externally can be used to provide better tooling support for mixed-language +projects or projects that rely on auto-generated code. For instance, an IDE that +uses Clang and that supports mixed-language projects can use this attribute to +provide a correct 'jump-to-definition' feature. For a concrete example, +consider a protocol that's defined in a Swift file: + +.. code-block:: swift + + @objc public protocol SwiftProtocol { + func method() + } + +This protocol can be used from Objective-C code by including a header file that +was generated by the Swift compiler. The declarations in that header can use +the ``external_source_symbol`` attribute to make Clang aware of the fact +that ``SwiftProtocol`` actually originates from a Swift module: + +.. code-block:: objc + + __attribute__((external_source_symbol(language="Swift",defined_in="module"))) + @protocol SwiftProtocol + @required + - (void) method; + @end + +Consequently, when 'jump-to-definition' is performed at a location that +references ``SwiftProtocol``, the IDE can jump to the original definition in +the Swift source file rather than jumping to the Objective-C declaration in the +auto-generated header file. + +The ``external_source_symbol`` attribute is a comma-separated list that includes +clauses that describe the origin and the nature of the particular declaration. +Those clauses can be: + +language=\ *string-literal* + The name of the source language in which this declaration was defined. + +defined_in=\ *string-literal* + The name of the source container in which the declaration was defined. The + exact definition of source container is language-specific, e.g. Swift's + source containers are modules, so ``defined_in`` should specify the Swift + module name. + +generated_declaration + This declaration was automatically generated by some tool. + +The clauses can be specified in any order. The clauses that are listed above are +all optional, but the attribute has to have at least one clause. + + +flatten +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``flatten``","``gnu::flatten``","","","","","Yes" + +The ``flatten`` attribute causes calls within the attributed function to +be inlined unless it is impossible to do so, for example if the body of the +callee is unavailable or if the callee has the ``noinline`` attribute. + + +force_align_arg_pointer +----------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``force_align_arg_pointer``","``gnu::force_align_arg_pointer``","","","","","" + +Use this attribute to force stack alignment. + +Legacy x86 code uses 4-byte stack alignment. Newer aligned SSE instructions +(like 'movaps') that work with the stack require operands to be 16-byte aligned. +This attribute realigns the stack in the function prologue to make sure the +stack can be used with SSE instructions. + +Note that the x86_64 ABI forces 16-byte stack alignment at the call site. +Because of this, 'force_align_arg_pointer' is not needed on x86_64, except in +rare cases where the caller does not align the stack properly (e.g. flow +jumps from i386 arch code). + + .. code-block:: c + + __attribute__ ((force_align_arg_pointer)) + void f () { + ... + } + + +format +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``format``","``gnu::format``","","","","","" + +Clang supports the ``format`` attribute, which indicates that the function +accepts a ``printf`` or ``scanf``-like format string and corresponding +arguments or a ``va_list`` that contains these arguments. + +Please see `GCC documentation about format attribute +`_ to find details +about attribute syntax. + +Clang implements two kinds of checks with this attribute. + +#. Clang checks that the function with the ``format`` attribute is called with + a format string that uses format specifiers that are allowed, and that + arguments match the format string. This is the ``-Wformat`` warning, it is + on by default. + +#. Clang checks that the format string argument is a literal string. This is + the ``-Wformat-nonliteral`` warning, it is off by default. + + Clang implements this mostly the same way as GCC, but there is a difference + for functions that accept a ``va_list`` argument (for example, ``vprintf``). + GCC does not emit ``-Wformat-nonliteral`` warning for calls to such + functions. Clang does not warn if the format string comes from a function + parameter, where the function is annotated with a compatible attribute, + otherwise it warns. For example: + + .. code-block:: c + + __attribute__((__format__ (__scanf__, 1, 3))) + void foo(const char* s, char *buf, ...) { + va_list ap; + va_start(ap, buf); + + vprintf(s, ap); // warning: format string is not a string literal + } + + In this case we warn because ``s`` contains a format string for a + ``scanf``-like function, but it is passed to a ``printf``-like function. + + If the attribute is removed, clang still warns, because the format string is + not a string literal. + + Another example: + + .. code-block:: c + + __attribute__((__format__ (__printf__, 1, 3))) + void foo(const char* s, char *buf, ...) { + va_list ap; + va_start(ap, buf); + + vprintf(s, ap); // warning + } + + In this case Clang does not warn because the format string ``s`` and + the corresponding arguments are annotated. If the arguments are + incorrect, the caller of ``foo`` will receive a warning. + + +gnu_inline +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``gnu_inline``","``gnu::gnu_inline``","","","","","Yes" + +The ``gnu_inline`` changes the meaning of ``extern inline`` to use GNU inline +semantics, meaning: + +* If any declaration that is declared ``inline`` is not declared ``extern``, + then the ``inline`` keyword is just a hint. In particular, an out-of-line + definition is still emitted for a function with external linkage, even if all + call sites are inlined, unlike in C99 and C++ inline semantics. + +* If all declarations that are declared ``inline`` are also declared + ``extern``, then the function body is present only for inlining and no + out-of-line version is emitted. + +Some important consequences: ``static inline`` emits an out-of-line +version if needed, a plain ``inline`` definition emits an out-of-line version +always, and an ``extern inline`` definition (in a header) followed by a +(non-``extern``) ``inline`` declaration in a source file emits an out-of-line +version of the function in that source file but provides the function body for +inlining to all includers of the header. + +Either ``__GNUC_GNU_INLINE__`` (GNU inline semantics) or +``__GNUC_STDC_INLINE__`` (C99 semantics) will be defined (they are mutually +exclusive). If ``__GNUC_STDC_INLINE__`` is defined, then the ``gnu_inline`` +function attribute can be used to get GNU inline semantics on a per function +basis. If ``__GNUC_GNU_INLINE__`` is defined, then the translation unit is +already being compiled with GNU inline semantics as the implied default. It is +unspecified which macro is defined in a C++ compilation. + +GNU inline semantics are the default behavior with ``-std=gnu89``, +``-std=c89``, ``-std=c94``, or ``-fgnu89-inline``. + + +ifunc +----- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``ifunc``","``gnu::ifunc``","","","","","Yes" + +``__attribute__((ifunc("resolver")))`` is used to mark that the address of a declaration should be resolved at runtime by calling a resolver function. + +The symbol name of the resolver function is given in quotes. A function with this name (after mangling) must be defined in the current translation unit; it may be ``static``. The resolver function should return a pointer. + +The ``ifunc`` attribute may only be used on a function declaration. A function declaration with an ``ifunc`` attribute is considered to be a definition of the declared entity. The entity must not have weak linkage; for example, in C++, it cannot be applied to a declaration if a definition at that location would be considered inline. + +Not all targets support this attribute. ELF target support depends on both the linker and runtime linker, and is available in at least lld 4.0 and later, binutils 2.20.1 and later, glibc v2.11.1 and later, and FreeBSD 9.1 and later. Non-ELF targets currently do not support this attribute. + + +import_module +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``import_module``","``clang::import_module``","``clang::import_module``","","","","Yes" + +Clang supports the ``__attribute__((import_module()))`` +attribute for the WebAssembly target. This attribute may be attached to a +function declaration, where it modifies how the symbol is to be imported +within the WebAssembly linking environment. + +WebAssembly imports use a two-level namespace scheme, consisting of a module +name, which typically identifies a module from which to import, and a field +name, which typically identifies a field from that module to import. By +default, module names for C/C++ symbols are assigned automatically by the +linker. This attribute can be used to override the default behavior, and +reuqest a specific module name be used instead. + + +import_name +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``import_name``","``clang::import_name``","``clang::import_name``","","","","Yes" + +Clang supports the ``__attribute__((import_name()))`` +attribute for the WebAssembly target. This attribute may be attached to a +function declaration, where it modifies how the symbol is to be imported +within the WebAssembly linking environment. + +WebAssembly imports use a two-level namespace scheme, consisting of a module +name, which typically identifies a module from which to import, and a field +name, which typically identifies a field from that module to import. By +default, field names for C/C++ symbols are the same as their C/C++ symbol +names. This attribute can be used to override the default behavior, and +reuqest a specific field name be used instead. + + +internal_linkage +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``internal_linkage``","``clang::internal_linkage``","``clang::internal_linkage``","","","","Yes" + +The ``internal_linkage`` attribute changes the linkage type of the declaration to internal. +This is similar to C-style ``static``, but can be used on classes and class methods. When applied to a class definition, +this attribute affects all methods and static data members of that class. +This can be used to contain the ABI of a C++ library by excluding unwanted class methods from the export tables. + + +interrupt (ARM) +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``interrupt``","``gnu::interrupt``","","","","","" + +Clang supports the GNU style ``__attribute__((interrupt("TYPE")))`` attribute on +ARM targets. This attribute may be attached to a function definition and +instructs the backend to generate appropriate function entry/exit code so that +it can be used directly as an interrupt service routine. + +The parameter passed to the interrupt attribute is optional, but if +provided it must be a string literal with one of the following values: "IRQ", +"FIQ", "SWI", "ABORT", "UNDEF". + +The semantics are as follows: + +- If the function is AAPCS, Clang instructs the backend to realign the stack to + 8 bytes on entry. This is a general requirement of the AAPCS at public + interfaces, but may not hold when an exception is taken. Doing this allows + other AAPCS functions to be called. +- If the CPU is M-class this is all that needs to be done since the architecture + itself is designed in such a way that functions obeying the normal AAPCS ABI + constraints are valid exception handlers. +- If the CPU is not M-class, the prologue and epilogue are modified to save all + non-banked registers that are used, so that upon return the user-mode state + will not be corrupted. Note that to avoid unnecessary overhead, only + general-purpose (integer) registers are saved in this way. If VFP operations + are needed, that state must be saved manually. + + Specifically, interrupt kinds other than "FIQ" will save all core registers + except "lr" and "sp". "FIQ" interrupts will save r0-r7. +- If the CPU is not M-class, the return instruction is changed to one of the + canonical sequences permitted by the architecture for exception return. Where + possible the function itself will make the necessary "lr" adjustments so that + the "preferred return address" is selected. + + Unfortunately the compiler is unable to make this guarantee for an "UNDEF" + handler, where the offset from "lr" to the preferred return address depends on + the execution state of the code which generated the exception. In this case + a sequence equivalent to "movs pc, lr" will be used. + + +interrupt (AVR) +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``interrupt``","``gnu::interrupt``","","","","","Yes" + +Clang supports the GNU style ``__attribute__((interrupt))`` attribute on +AVR targets. This attribute may be attached to a function definition and instructs +the backend to generate appropriate function entry/exit code so that it can be used +directly as an interrupt service routine. + +On the AVR, the hardware globally disables interrupts when an interrupt is executed. +The first instruction of an interrupt handler declared with this attribute is a SEI +instruction to re-enable interrupts. See also the signal attribute that +does not insert a SEI instruction. + + +interrupt (MIPS) +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``interrupt``","``gnu::interrupt``","","","","","Yes" + +Clang supports the GNU style ``__attribute__((interrupt("ARGUMENT")))`` attribute on +MIPS targets. This attribute may be attached to a function definition and instructs +the backend to generate appropriate function entry/exit code so that it can be used +directly as an interrupt service routine. + +By default, the compiler will produce a function prologue and epilogue suitable for +an interrupt service routine that handles an External Interrupt Controller (eic) +generated interrupt. This behaviour can be explicitly requested with the "eic" +argument. + +Otherwise, for use with vectored interrupt mode, the argument passed should be +of the form "vector=LEVEL" where LEVEL is one of the following values: +"sw0", "sw1", "hw0", "hw1", "hw2", "hw3", "hw4", "hw5". The compiler will +then set the interrupt mask to the corresponding level which will mask all +interrupts up to and including the argument. + +The semantics are as follows: + +- The prologue is modified so that the Exception Program Counter (EPC) and + Status coprocessor registers are saved to the stack. The interrupt mask is + set so that the function can only be interrupted by a higher priority + interrupt. The epilogue will restore the previous values of EPC and Status. + +- The prologue and epilogue are modified to save and restore all non-kernel + registers as necessary. + +- The FPU is disabled in the prologue, as the floating pointer registers are not + spilled to the stack. + +- The function return sequence is changed to use an exception return instruction. + +- The parameter sets the interrupt mask for the function corresponding to the + interrupt level specified. If no mask is specified the interrupt mask + defaults to "eic". + + +interrupt (RISCV) +----------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``interrupt``","``gnu::interrupt``","","","","","Yes" + +Clang supports the GNU style ``__attribute__((interrupt))`` attribute on RISCV +targets. This attribute may be attached to a function definition and instructs +the backend to generate appropriate function entry/exit code so that it can be +used directly as an interrupt service routine. + +Permissible values for this parameter are ``user``, ``supervisor``, +and ``machine``. If there is no parameter, then it defaults to machine. + +Repeated interrupt attribute on the same declaration will cause a warning +to be emitted. In case of repeated declarations, the last one prevails. + +Refer to: +https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html +https://riscv.org/specifications/privileged-isa/ +The RISC-V Instruction Set Manual Volume II: Privileged Architecture +Version 1.10. + + +kernel +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``kernel``","","","","","","Yes" + +``__attribute__((kernel))`` is used to mark a ``kernel`` function in +RenderScript. + +In RenderScript, ``kernel`` functions are used to express data-parallel +computations. The RenderScript runtime efficiently parallelizes ``kernel`` +functions to run on computational resources such as multi-core CPUs and GPUs. +See the RenderScript_ documentation for more information. + +.. _RenderScript: https://developer.android.com/guide/topics/renderscript/compute.html + + +lifetimebound +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``lifetimebound``","``clang::lifetimebound``","","","","","" + +The ``lifetimebound`` attribute indicates that a resource owned by +a function parameter or implicit object parameter +is retained by the return value of the annotated function +(or, for a parameter of a constructor, in the value of the constructed object). +It is only supported in C++. + +This attribute provides an experimental implementation of the facility +described in the C++ committee paper [http://wg21.link/p0936r0](P0936R0), +and is subject to change as the design of the corresponding functionality +changes. + + +long_call, far +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``long_call`` |br| ``far``","``gnu::long_call`` |br| ``gnu::far``","","","","","Yes" + +Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``, +and ``__attribute__((near))`` attributes on MIPS targets. These attributes may +only be added to function declarations and change the code generated +by the compiler when directly calling the function. The ``near`` attribute +allows calls to the function to be made using the ``jal`` instruction, which +requires the function to be located in the same naturally aligned 256MB +segment as the caller. The ``long_call`` and ``far`` attributes are synonyms +and require the use of a different call sequence that works regardless +of the distance between the functions. + +These attributes have no effect for position-independent code. + +These attributes take priority over command line switches such +as ``-mlong-calls`` and ``-mno-long-calls``. + + +micromips +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``micromips``","``gnu::micromips``","","","","","Yes" + +Clang supports the GNU style ``__attribute__((micromips))`` and +``__attribute__((nomicromips))`` attributes on MIPS targets. These attributes +may be attached to a function definition and instructs the backend to generate +or not to generate microMIPS code for that function. + +These attributes override the `-mmicromips` and `-mno-micromips` options +on the command line. + + +min_vector_width +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``min_vector_width``","``clang::min_vector_width``","``clang::min_vector_width``","","","","Yes" + +Clang supports the ``__attribute__((min_vector_width(width)))`` attribute. This +attribute may be attached to a function and informs the backend that this +function desires vectors of at least this width to be generated. Target-specific +maximum vector widths still apply. This means even if you ask for something +larger than the target supports, you will only get what the target supports. +This attribute is meant to be a hint to control target heuristics that may +generate narrower vectors than what the target hardware supports. + +This is currently used by the X86 target to allow some CPUs that support 512-bit +vectors to be limited to using 256-bit vectors to avoid frequency penalties. +This is currently enabled with the ``-prefer-vector-width=256`` command line +option. The ``min_vector_width`` attribute can be used to prevent the backend +from trying to split vector operations to match the ``prefer-vector-width``. All +X86 vector intrinsics from x86intrin.h already set this attribute. Additionally, +use of any of the X86-specific vector builtins will implicitly set this +attribute on the calling function. The intent is that explicitly writing vector +code using the X86 intrinsics will prevent ``prefer-vector-width`` from +affecting the code. + + +no_caller_saved_registers +------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_caller_saved_registers``","``gnu::no_caller_saved_registers``","","","","","" + +Use this attribute to indicate that the specified function has no +caller-saved registers. That is, all registers are callee-saved except for +registers used for passing parameters to the function or returning parameters +from the function. +The compiler saves and restores any modified registers that were not used for +passing or returning arguments to the function. + +The user can call functions specified with the 'no_caller_saved_registers' +attribute from an interrupt handler without saving and restoring all +call-clobbered registers. + +Note that 'no_caller_saved_registers' attribute is not a calling convention. +In fact, it only overrides the decision of which registers should be saved by +the caller, but not how the parameters are passed from the caller to the callee. + +For example: + + .. code-block:: c + + __attribute__ ((no_caller_saved_registers, fastcall)) + void f (int arg1, int arg2) { + ... + } + + In this case parameters 'arg1' and 'arg2' will be passed in registers. + In this case, on 32-bit x86 targets, the function 'f' will use ECX and EDX as + register parameters. However, it will not assume any scratch registers and + should save and restore any modified registers except for ECX and EDX. + + +no_sanitize +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_sanitize``","``clang::no_sanitize``","``clang::no_sanitize``","","","","Yes" + +Use the ``no_sanitize`` attribute on a function or a global variable +declaration to specify that a particular instrumentation or set of +instrumentations should not be applied. The attribute takes a list of +string literals, which have the same meaning as values accepted by the +``-fno-sanitize=`` flag. For example, +``__attribute__((no_sanitize("address", "thread")))`` specifies that +AddressSanitizer and ThreadSanitizer should not be applied to the +function or variable. + +See :ref:`Controlling Code Generation ` for a +full list of supported sanitizer flags. + + +no_sanitize_address, no_address_safety_analysis +----------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_address_safety_analysis`` |br| ``no_sanitize_address`` |br| ``no_sanitize_thread`` |br| ``no_sanitize_memory``","``gnu::no_address_safety_analysis`` |br| ``gnu::no_sanitize_address`` |br| ``gnu::no_sanitize_thread`` |br| ``clang::no_sanitize_memory``","``clang::no_sanitize_memory``","","","","Yes" + +.. _langext-address_sanitizer: + +Use ``__attribute__((no_sanitize_address))`` on a function or a global +variable declaration to specify that address safety instrumentation +(e.g. AddressSanitizer) should not be applied. + + +no_sanitize_memory +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_address_safety_analysis`` |br| ``no_sanitize_address`` |br| ``no_sanitize_thread`` |br| ``no_sanitize_memory``","``gnu::no_address_safety_analysis`` |br| ``gnu::no_sanitize_address`` |br| ``gnu::no_sanitize_thread`` |br| ``clang::no_sanitize_memory``","``clang::no_sanitize_memory``","","","","Yes" + +.. _langext-memory_sanitizer: + +Use ``__attribute__((no_sanitize_memory))`` on a function declaration to +specify that checks for uninitialized memory should not be inserted +(e.g. by MemorySanitizer). The function may still be instrumented by the tool +to avoid false positives in other places. + + +no_sanitize_thread +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_address_safety_analysis`` |br| ``no_sanitize_address`` |br| ``no_sanitize_thread`` |br| ``no_sanitize_memory``","``gnu::no_address_safety_analysis`` |br| ``gnu::no_sanitize_address`` |br| ``gnu::no_sanitize_thread`` |br| ``clang::no_sanitize_memory``","``clang::no_sanitize_memory``","","","","Yes" + +.. _langext-thread_sanitizer: + +Use ``__attribute__((no_sanitize_thread))`` on a function declaration to +specify that checks for data races on plain (non-atomic) memory accesses should +not be inserted by ThreadSanitizer. The function is still instrumented by the +tool to avoid false positives and provide meaningful stack traces. + + +no_split_stack +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_split_stack``","``gnu::no_split_stack``","","","","","Yes" + +The ``no_split_stack`` attribute disables the emission of the split stack +preamble for a particular function. It has no effect if ``-fsplit-stack`` +is not specified. + + +no_stack_protector +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_stack_protector``","``clang::no_stack_protector``","``clang::no_stack_protector``","","","","Yes" + +Clang supports the ``__attribute__((no_stack_protector))`` attribute which disables +the stack protector on the specified function. This attribute is useful for +selectively disabling the stack protector on some functions when building with +``-fstack-protector`` compiler option. + +For example, it disables the stack protector for the function ``foo`` but function +``bar`` will still be built with the stack protector with the ``-fstack-protector`` +option. + +.. code-block:: c + + int __attribute__((no_stack_protector)) + foo (int x); // stack protection will be disabled for foo. + + int bar(int y); // bar can be built with the stack protector. + + +noalias +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","``noalias``","","","" + +The ``noalias`` attribute indicates that the only memory accesses inside +function are loads and stores from objects pointed to by its pointer-typed +arguments, with arbitrary offsets. + + +nocf_check +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``nocf_check``","``gnu::nocf_check``","","","","","Yes" + +Jump Oriented Programming attacks rely on tampering with addresses used by +indirect call / jmp, e.g. redirect control-flow to non-programmer +intended bytes in the binary. +X86 Supports Indirect Branch Tracking (IBT) as part of Control-Flow +Enforcement Technology (CET). IBT instruments ENDBR instructions used to +specify valid targets of indirect call / jmp. +The ``nocf_check`` attribute has two roles: +1. Appertains to a function - do not add ENDBR instruction at the beginning of +the function. +2. Appertains to a function pointer - do not track the target function of this +pointer (by adding nocf_check prefix to the indirect-call instruction). + + +nodiscard, warn_unused_result +----------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``warn_unused_result``","``nodiscard`` |br| ``clang::warn_unused_result`` |br| ``gnu::warn_unused_result``","``nodiscard``","","","","Yes" + +Clang supports the ability to diagnose when the results of a function call +expression are discarded under suspicious circumstances. A diagnostic is +generated when a function or its return type is marked with ``[[nodiscard]]`` +(or ``__attribute__((warn_unused_result))``) and the function call appears as a +potentially-evaluated discarded-value expression that is not explicitly cast to +`void`. + +.. code-block: c++ + struct [[nodiscard]] error_info { /*...*/ }; + error_info enable_missile_safety_mode(); + + void launch_missiles(); + void test_missiles() { + enable_missile_safety_mode(); // diagnoses + launch_missiles(); + } + error_info &foo(); + void f() { foo(); } // Does not diagnose, error_info is a reference. + + +noduplicate +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``noduplicate``","``clang::noduplicate``","``clang::noduplicate``","","","","Yes" + +The ``noduplicate`` attribute can be placed on function declarations to control +whether function calls to this function can be duplicated or not as a result of +optimizations. This is required for the implementation of functions with +certain special requirements, like the OpenCL "barrier" function, that might +need to be run concurrently by all the threads that are executing in lockstep +on the hardware. For example this attribute applied on the function +"nodupfunc" in the code below avoids that: + +.. code-block:: c + + void nodupfunc() __attribute__((noduplicate)); + // Setting it as a C++11 attribute is also valid + // void nodupfunc() [[clang::noduplicate]]; + void foo(); + void bar(); + + nodupfunc(); + if (a > n) { + foo(); + } else { + bar(); + } + +gets possibly modified by some optimizations into code similar to this: + +.. code-block:: c + + if (a > n) { + nodupfunc(); + foo(); + } else { + nodupfunc(); + bar(); + } + +where the call to "nodupfunc" is duplicated and sunk into the two branches +of the condition. + + +nomicromips +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``nomicromips``","``gnu::nomicromips``","","","","","Yes" + +Clang supports the GNU style ``__attribute__((micromips))`` and +``__attribute__((nomicromips))`` attributes on MIPS targets. These attributes +may be attached to a function definition and instructs the backend to generate +or not to generate microMIPS code for that function. + +These attributes override the `-mmicromips` and `-mno-micromips` options +on the command line. + + +noreturn +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","``noreturn``","","","","","Yes" + +A function declared as ``[[noreturn]]`` shall not return to its caller. The +compiler will generate a diagnostic for a function declared as ``[[noreturn]]`` +that appears to be capable of returning to its caller. + + +not_tail_called +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``not_tail_called``","``clang::not_tail_called``","``clang::not_tail_called``","","","","Yes" + +The ``not_tail_called`` attribute prevents tail-call optimization on statically bound calls. It has no effect on indirect calls. Virtual functions, objective-c methods, and functions marked as ``always_inline`` cannot be marked as ``not_tail_called``. + +For example, it prevents tail-call optimization in the following case: + + .. code-block:: c + + int __attribute__((not_tail_called)) foo1(int); + + int foo2(int a) { + return foo1(a); // No tail-call optimization on direct calls. + } + +However, it doesn't prevent tail-call optimization in this case: + + .. code-block:: c + + int __attribute__((not_tail_called)) foo1(int); + + int foo2(int a) { + int (*fn)(int) = &foo1; + + // not_tail_called has no effect on an indirect call even if the call can be + // resolved at compile time. + return (*fn)(a); + } + +Marking virtual functions as ``not_tail_called`` is an error: + + .. code-block:: c++ + + class Base { + public: + // not_tail_called on a virtual function is an error. + [[clang::not_tail_called]] virtual int foo1(); + + virtual int foo2(); + + // Non-virtual functions can be marked ``not_tail_called``. + [[clang::not_tail_called]] int foo3(); + }; + + class Derived1 : public Base { + public: + int foo1() override; + + // not_tail_called on a virtual function is an error. + [[clang::not_tail_called]] int foo2() override; + }; + + +nothrow +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``nothrow``","``gnu::nothrow``","","``nothrow``","","","Yes" + +Clang supports the GNU style ``__attribute__((nothrow))`` and Microsoft style +``__declspec(nothrow)`` attribute as an equivalent of `noexcept` on function +declarations. This attribute informs the compiler that the annotated function +does not throw an exception. This prevents exception-unwinding. This attribute +is particularly useful on functions in the C Standard Library that are +guaranteed to not throw an exception. + + +ns_consumed +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``ns_consumed``","``clang::ns_consumed``","``clang::ns_consumed``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +ns_consumes_self +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``ns_consumes_self``","``clang::ns_consumes_self``","``clang::ns_consumes_self``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +ns_returns_autoreleased +----------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``ns_returns_autoreleased``","``clang::ns_returns_autoreleased``","``clang::ns_returns_autoreleased``","","","","" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +ns_returns_not_retained +----------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``ns_returns_not_retained``","``clang::ns_returns_not_retained``","``clang::ns_returns_not_retained``","","","","" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +ns_returns_retained +------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``ns_returns_retained``","``clang::ns_returns_retained``","``clang::ns_returns_retained``","","","","" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +objc_boxable +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_boxable``","``clang::objc_boxable``","``clang::objc_boxable``","","","","Yes" + +Structs and unions marked with the ``objc_boxable`` attribute can be used +with the Objective-C boxed expression syntax, ``@(...)``. + +**Usage**: ``__attribute__((objc_boxable))``. This attribute +can only be placed on a declaration of a trivially-copyable struct or union: + +.. code-block:: objc + + struct __attribute__((objc_boxable)) some_struct { + int i; + }; + union __attribute__((objc_boxable)) some_union { + int i; + float f; + }; + typedef struct __attribute__((objc_boxable)) _some_struct some_struct; + + // ... + + some_struct ss; + NSValue *boxed = @(ss); + + +objc_method_family +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_method_family``","``clang::objc_method_family``","``clang::objc_method_family``","","","","Yes" + +Many methods in Objective-C have conventional meanings determined by their +selectors. It is sometimes useful to be able to mark a method as having a +particular conventional meaning despite not having the right selector, or as +not having the conventional meaning that its selector would suggest. For these +use cases, we provide an attribute to specifically describe the "method family" +that a method belongs to. + +**Usage**: ``__attribute__((objc_method_family(X)))``, where ``X`` is one of +``none``, ``alloc``, ``copy``, ``init``, ``mutableCopy``, or ``new``. This +attribute can only be placed at the end of a method declaration: + +.. code-block:: objc + + - (NSString *)initMyStringValue __attribute__((objc_method_family(none))); + +Users who do not wish to change the conventional meaning of a method, and who +merely want to document its non-standard retain and release semantics, should +use the retaining behavior attributes (``ns_returns_retained``, +``ns_returns_not_retained``, etc). + +Query for this feature with ``__has_attribute(objc_method_family)``. + + +objc_requires_super +------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_requires_super``","``clang::objc_requires_super``","``clang::objc_requires_super``","","","","Yes" + +Some Objective-C classes allow a subclass to override a particular method in a +parent class but expect that the overriding method also calls the overridden +method in the parent class. For these cases, we provide an attribute to +designate that a method requires a "call to ``super``" in the overriding +method in the subclass. + +**Usage**: ``__attribute__((objc_requires_super))``. This attribute can only +be placed at the end of a method declaration: + +.. code-block:: objc + + - (void)foo __attribute__((objc_requires_super)); + +This attribute can only be applied the method declarations within a class, and +not a protocol. Currently this attribute does not enforce any placement of +where the call occurs in the overriding method (such as in the case of +``-dealloc`` where the call must appear at the end). It checks only that it +exists. + +Note that on both OS X and iOS that the Foundation framework provides a +convenience macro ``NS_REQUIRES_SUPER`` that provides syntactic sugar for this +attribute: + +.. code-block:: objc + + - (void)foo NS_REQUIRES_SUPER; + +This macro is conditionally defined depending on the compiler's support for +this attribute. If the compiler does not support the attribute the macro +expands to nothing. + +Operationally, when a method has this annotation the compiler will warn if the +implementation of an override in a subclass does not call super. For example: + +.. code-block:: objc + + warning: method possibly missing a [super AnnotMeth] call + - (void) AnnotMeth{}; + ^ + + +objc_runtime_name +----------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_runtime_name``","``clang::objc_runtime_name``","``clang::objc_runtime_name``","","","","Yes" + +By default, the Objective-C interface or protocol identifier is used +in the metadata name for that object. The `objc_runtime_name` +attribute allows annotated interfaces or protocols to use the +specified string argument in the object's metadata name instead of the +default name. + +**Usage**: ``__attribute__((objc_runtime_name("MyLocalName")))``. This attribute +can only be placed before an @protocol or @interface declaration: + +.. code-block:: objc + + __attribute__((objc_runtime_name("MyLocalName"))) + @interface Message + @end + + +objc_runtime_visible +-------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_runtime_visible``","``clang::objc_runtime_visible``","``clang::objc_runtime_visible``","","","","Yes" + +This attribute specifies that the Objective-C class to which it applies is visible to the Objective-C runtime but not to the linker. Classes annotated with this attribute cannot be subclassed and cannot have categories defined for them. + + +optnone +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``optnone``","``clang::optnone``","``clang::optnone``","","","","Yes" + +The ``optnone`` attribute suppresses essentially all optimizations +on a function or method, regardless of the optimization level applied to +the compilation unit as a whole. This is particularly useful when you +need to debug a particular function, but it is infeasible to build the +entire application without optimization. Avoiding optimization on the +specified function can improve the quality of the debugging information +for that function. + +This attribute is incompatible with the ``always_inline`` and ``minsize`` +attributes. + + +os_consumed +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``os_consumed``","``clang::os_consumed``","``clang::os_consumed``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +os_consumes_this +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``os_consumes_this``","``clang::os_consumes_this``","``clang::os_consumes_this``","","","","" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +os_returns_not_retained +----------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``os_returns_not_retained``","``clang::os_returns_not_retained``","``clang::os_returns_not_retained``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +os_returns_retained +------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``os_returns_retained``","``clang::os_returns_retained``","``clang::os_returns_retained``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +os_returns_retained_on_non_zero +------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``os_returns_retained_on_non_zero``","``clang::os_returns_retained_on_non_zero``","``clang::os_returns_retained_on_non_zero``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +os_returns_retained_on_zero +--------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``os_returns_retained_on_zero``","``clang::os_returns_retained_on_zero``","``clang::os_returns_retained_on_zero``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +overloadable +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``overloadable``","``clang::overloadable``","``clang::overloadable``","","","","Yes" + +Clang provides support for C++ function overloading in C. Function overloading +in C is introduced using the ``overloadable`` attribute. For example, one +might provide several overloaded versions of a ``tgsin`` function that invokes +the appropriate standard function computing the sine of a value with ``float``, +``double``, or ``long double`` precision: + +.. code-block:: c + + #include + float __attribute__((overloadable)) tgsin(float x) { return sinf(x); } + double __attribute__((overloadable)) tgsin(double x) { return sin(x); } + long double __attribute__((overloadable)) tgsin(long double x) { return sinl(x); } + +Given these declarations, one can call ``tgsin`` with a ``float`` value to +receive a ``float`` result, with a ``double`` to receive a ``double`` result, +etc. Function overloading in C follows the rules of C++ function overloading +to pick the best overload given the call arguments, with a few C-specific +semantics: + +* Conversion from ``float`` or ``double`` to ``long double`` is ranked as a + floating-point promotion (per C99) rather than as a floating-point conversion + (as in C++). + +* A conversion from a pointer of type ``T*`` to a pointer of type ``U*`` is + considered a pointer conversion (with conversion rank) if ``T`` and ``U`` are + compatible types. + +* A conversion from type ``T`` to a value of type ``U`` is permitted if ``T`` + and ``U`` are compatible types. This conversion is given "conversion" rank. + +* If no viable candidates are otherwise available, we allow a conversion from a + pointer of type ``T*`` to a pointer of type ``U*``, where ``T`` and ``U`` are + incompatible. This conversion is ranked below all other types of conversions. + Please note: ``U`` lacking qualifiers that are present on ``T`` is sufficient + for ``T`` and ``U`` to be incompatible. + +The declaration of ``overloadable`` functions is restricted to function +declarations and definitions. If a function is marked with the ``overloadable`` +attribute, then all declarations and definitions of functions with that name, +except for at most one (see the note below about unmarked overloads), must have +the ``overloadable`` attribute. In addition, redeclarations of a function with +the ``overloadable`` attribute must have the ``overloadable`` attribute, and +redeclarations of a function without the ``overloadable`` attribute must *not* +have the ``overloadable`` attribute. e.g., + +.. code-block:: c + + int f(int) __attribute__((overloadable)); + float f(float); // error: declaration of "f" must have the "overloadable" attribute + int f(int); // error: redeclaration of "f" must have the "overloadable" attribute + + int g(int) __attribute__((overloadable)); + int g(int) { } // error: redeclaration of "g" must also have the "overloadable" attribute + + int h(int); + int h(int) __attribute__((overloadable)); // error: declaration of "h" must not + // have the "overloadable" attribute + +Functions marked ``overloadable`` must have prototypes. Therefore, the +following code is ill-formed: + +.. code-block:: c + + int h() __attribute__((overloadable)); // error: h does not have a prototype + +However, ``overloadable`` functions are allowed to use a ellipsis even if there +are no named parameters (as is permitted in C++). This feature is particularly +useful when combined with the ``unavailable`` attribute: + +.. code-block:: c++ + + void honeypot(...) __attribute__((overloadable, unavailable)); // calling me is an error + +Functions declared with the ``overloadable`` attribute have their names mangled +according to the same rules as C++ function names. For example, the three +``tgsin`` functions in our motivating example get the mangled names +``_Z5tgsinf``, ``_Z5tgsind``, and ``_Z5tgsine``, respectively. There are two +caveats to this use of name mangling: + +* Future versions of Clang may change the name mangling of functions overloaded + in C, so you should not depend on an specific mangling. To be completely + safe, we strongly urge the use of ``static inline`` with ``overloadable`` + functions. + +* The ``overloadable`` attribute has almost no meaning when used in C++, + because names will already be mangled and functions are already overloadable. + However, when an ``overloadable`` function occurs within an ``extern "C"`` + linkage specification, it's name *will* be mangled in the same way as it + would in C. + +For the purpose of backwards compatibility, at most one function with the same +name as other ``overloadable`` functions may omit the ``overloadable`` +attribute. In this case, the function without the ``overloadable`` attribute +will not have its name mangled. + +For example: + +.. code-block:: c + + // Notes with mangled names assume Itanium mangling. + int f(int); + int f(double) __attribute__((overloadable)); + void foo() { + f(5); // Emits a call to f (not _Z1fi, as it would with an overload that + // was marked with overloadable). + f(1.0); // Emits a call to _Z1fd. + } + +Support for unmarked overloads is not present in some versions of clang. You may +query for it using ``__has_extension(overloadable_unmarked)``. + +Query for this attribute with ``__has_attribute(overloadable)``. + + +reinitializes +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``reinitializes``","``clang::reinitializes``","","","","","" + +The ``reinitializes`` attribute can be applied to a non-static, non-const C++ +member function to indicate that this member function reinitializes the entire +object to a known state, independent of the previous state of the object. + +This attribute can be interpreted by static analyzers that warn about uses of an +object that has been left in an indeterminate state by a move operation. If a +member function marked with the ``reinitializes`` attribute is called on a +moved-from object, the analyzer can conclude that the object is no longer in an +indeterminate state. + +A typical example where this attribute would be used is on functions that clear +a container class: + +.. code-block:: c++ + + template + class Container { + public: + ... + [[clang::reinitializes]] void Clear(); + ... + }; + + +release_capability, release_shared_capability +--------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``release_capability`` |br| ``release_shared_capability`` |br| ``release_generic_capability`` |br| ``unlock_function``","``clang::release_capability`` |br| ``clang::release_shared_capability`` |br| ``clang::release_generic_capability`` |br| ``clang::unlock_function``","","","","","" + +Marks a function as releasing a capability. + + +short_call, near +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``short_call`` |br| ``near``","``gnu::short_call`` |br| ``gnu::near``","","","","","Yes" + +Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``, +``__attribute__((short__call))``, and ``__attribute__((near))`` attributes +on MIPS targets. These attributes may only be added to function declarations +and change the code generated by the compiler when directly calling +the function. The ``short_call`` and ``near`` attributes are synonyms and +allow calls to the function to be made using the ``jal`` instruction, which +requires the function to be located in the same naturally aligned 256MB segment +as the caller. The ``long_call`` and ``far`` attributes are synonyms and +require the use of a different call sequence that works regardless +of the distance between the functions. + +These attributes have no effect for position-independent code. + +These attributes take priority over command line switches such +as ``-mlong-calls`` and ``-mno-long-calls``. + + +signal +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``signal``","``gnu::signal``","","","","","Yes" + +Clang supports the GNU style ``__attribute__((signal))`` attribute on +AVR targets. This attribute may be attached to a function definition and instructs +the backend to generate appropriate function entry/exit code so that it can be used +directly as an interrupt service routine. + +Interrupt handler functions defined with the signal attribute do not re-enable interrupts. + + +speculative_load_hardening +-------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``speculative_load_hardening``","``clang::speculative_load_hardening``","``clang::speculative_load_hardening``","","","","Yes" + +This attribute can be applied to a function declaration in order to indicate + that `Speculative Load Hardening `_ + should be enabled for the function body. This can also be applied to a method + in Objective C. + + Speculative Load Hardening is a best-effort mitigation against + information leak attacks that make use of control flow + miss-speculation - specifically miss-speculation of whether a branch + is taken or not. Typically vulnerabilities enabling such attacks are + classified as "Spectre variant #1". Notably, this does not attempt to + mitigate against miss-speculation of branch target, classified as + "Spectre variant #2" vulnerabilities. + + When inlining, the attribute is sticky. Inlining a function that + carries this attribute will cause the caller to gain the + attribute. This is intended to provide a maximally conservative model + where the code in a function annotated with this attribute will always + (even after inlining) end up hardened. + + +target +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``target``","``gnu::target``","","","","","Yes" + +Clang supports the GNU style ``__attribute__((target("OPTIONS")))`` attribute. +This attribute may be attached to a function definition and instructs +the backend to use different code generation options than were passed on the +command line. + +The current set of options correspond to the existing "subtarget features" for +the target with or without a "-mno-" in front corresponding to the absence +of the feature, as well as ``arch="CPU"`` which will change the default "CPU" +for the function. + +Example "subtarget features" from the x86 backend include: "mmx", "sse", "sse4.2", +"avx", "xop" and largely correspond to the machine specific options handled by +the front end. + +Additionally, this attribute supports function multiversioning for ELF based +x86/x86-64 targets, which can be used to create multiple implementations of the +same function that will be resolved at runtime based on the priority of their +``target`` attribute strings. A function is considered a multiversioned function +if either two declarations of the function have different ``target`` attribute +strings, or if it has a ``target`` attribute string of ``default``. For +example: + + .. code-block:: c++ + + __attribute__((target("arch=atom"))) + void foo() {} // will be called on 'atom' processors. + __attribute__((target("default"))) + void foo() {} // will be called on any other processors. + +All multiversioned functions must contain a ``default`` (fallback) +implementation, otherwise usages of the function are considered invalid. +Additionally, a function may not become multiversioned after its first use. + + +try_acquire_capability, try_acquire_shared_capability +----------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``try_acquire_capability`` |br| ``try_acquire_shared_capability``","``clang::try_acquire_capability`` |br| ``clang::try_acquire_shared_capability``","","","","","" + +Marks a function that attempts to acquire a capability. This function may fail to +actually acquire the capability; they accept a Boolean value determining +whether acquiring the capability means success (true), or failing to acquire +the capability means success (false). + + +xray_always_instrument, xray_never_instrument, xray_log_args +------------------------------------------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``xray_always_instrument`` |br| ``xray_never_instrument``","``clang::xray_always_instrument`` |br| ``clang::xray_never_instrument``","``clang::xray_always_instrument`` |br| ``clang::xray_never_instrument``","","","","Yes" + +``__attribute__((xray_always_instrument))`` or ``[[clang::xray_always_instrument]]`` is used to mark member functions (in C++), methods (in Objective C), and free functions (in C, C++, and Objective C) to be instrumented with XRay. This will cause the function to always have space at the beginning and exit points to allow for runtime patching. + +Conversely, ``__attribute__((xray_never_instrument))`` or ``[[clang::xray_never_instrument]]`` will inhibit the insertion of these instrumentation points. + +If a function has neither of these attributes, they become subject to the XRay heuristics used to determine whether a function should be instrumented or otherwise. + +``__attribute__((xray_log_args(N)))`` or ``[[clang::xray_log_args(N)]]`` is used to preserve N function arguments for the logging function. Currently, only N==1 is supported. + + +xray_always_instrument, xray_never_instrument, xray_log_args +------------------------------------------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``xray_log_args``","``clang::xray_log_args``","``clang::xray_log_args``","","","","Yes" + +``__attribute__((xray_always_instrument))`` or ``[[clang::xray_always_instrument]]`` is used to mark member functions (in C++), methods (in Objective C), and free functions (in C, C++, and Objective C) to be instrumented with XRay. This will cause the function to always have space at the beginning and exit points to allow for runtime patching. + +Conversely, ``__attribute__((xray_never_instrument))`` or ``[[clang::xray_never_instrument]]`` will inhibit the insertion of these instrumentation points. + +If a function has neither of these attributes, they become subject to the XRay heuristics used to determine whether a function should be instrumented or otherwise. + +``__attribute__((xray_log_args(N)))`` or ``[[clang::xray_log_args(N)]]`` is used to preserve N function arguments for the logging function. Currently, only N==1 is supported. + + +Variable Attributes +=================== + + +always_destroy +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``always_destroy``","``clang::always_destroy``","","","","","Yes" + +The ``always_destroy`` attribute specifies that a variable with static or thread +storage duration should have its exit-time destructor run. This attribute is the +default unless clang was invoked with -fno-c++-static-destructors. + + +dllexport +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``dllexport``","``gnu::dllexport``","","``dllexport``","","","Yes" + +The ``__declspec(dllexport)`` attribute declares a variable, function, or +Objective-C interface to be exported from the module. It is available under the +``-fdeclspec`` flag for compatibility with various compilers. The primary use +is for COFF object files which explicitly specify what interfaces are available +for external use. See the dllexport_ documentation on MSDN for more +information. + +.. _dllexport: https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx + + +dllimport +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``dllimport``","``gnu::dllimport``","","``dllimport``","","","Yes" + +The ``__declspec(dllimport)`` attribute declares a variable, function, or +Objective-C interface to be imported from an external module. It is available +under the ``-fdeclspec`` flag for compatibility with various compilers. The +primary use is for COFF object files which explicitly specify what interfaces +are imported from external modules. See the dllimport_ documentation on MSDN +for more information. + +.. _dllimport: https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx + + +init_seg +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","","``init_seg``","" + +The attribute applied by ``pragma init_seg()`` controls the section into +which global initialization function pointers are emitted. It is only +available with ``-fms-extensions``. Typically, this function pointer is +emitted into ``.CRT$XCU`` on Windows. The user can change the order of +initialization by using a different section name with the same +``.CRT$XC`` prefix and a suffix that sorts lexicographically before or +after the standard ``.CRT$XCU`` sections. See the init_seg_ +documentation on MSDN for more information. + +.. _init_seg: http://msdn.microsoft.com/en-us/library/7977wcck(v=vs.110).aspx + + +maybe_unused, unused +-------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``unused``","``maybe_unused`` |br| ``gnu::unused``","``maybe_unused``","","","","" + +When passing the ``-Wunused`` flag to Clang, entities that are unused by the +program may be diagnosed. The ``[[maybe_unused]]`` (or +``__attribute__((unused))``) attribute can be used to silence such diagnostics +when the entity cannot be removed. For instance, a local variable may exist +solely for use in an ``assert()`` statement, which makes the local variable +unused when ``NDEBUG`` is defined. + +The attribute may be applied to the declaration of a class, a typedef, a +variable, a function or method, a function parameter, an enumeration, an +enumerator, a non-static data member, or a label. + +.. code-block: c++ + #include + + [[maybe_unused]] void f([[maybe_unused]] bool thing1, + [[maybe_unused]] bool thing2) { + [[maybe_unused]] bool b = thing1 && thing2; + assert(b); + } + + +no_destroy +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_destroy``","``clang::no_destroy``","","","","","Yes" + +The ``no_destroy`` attribute specifies that a variable with static or thread +storage duration shouldn't have its exit-time destructor run. Annotating every +static and thread duration variable with this attribute is equivalent to +invoking clang with -fno-c++-static-destructors. + + +nodebug +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``nodebug``","``gnu::nodebug``","","","","","Yes" + +The ``nodebug`` attribute allows you to suppress debugging information for a +function or method, or for a variable that is not a parameter or a non-static +data member. + + +noescape +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``noescape``","``clang::noescape``","``clang::noescape``","","","","Yes" + +``noescape`` placed on a function parameter of a pointer type is used to inform +the compiler that the pointer cannot escape: that is, no reference to the object +the pointer points to that is derived from the parameter value will survive +after the function returns. Users are responsible for making sure parameters +annotated with ``noescape`` do not actuallly escape. + +For example: + +.. code-block:: c + + int *gp; + + void nonescapingFunc(__attribute__((noescape)) int *p) { + *p += 100; // OK. + } + + void escapingFunc(__attribute__((noescape)) int *p) { + gp = p; // Not OK. + } + +Additionally, when the parameter is a `block pointer +`, the same restriction +applies to copies of the block. For example: + +.. code-block:: c + + typedef void (^BlockTy)(); + BlockTy g0, g1; + + void nonescapingFunc(__attribute__((noescape)) BlockTy block) { + block(); // OK. + } + + void escapingFunc(__attribute__((noescape)) BlockTy block) { + g0 = block; // Not OK. + g1 = Block_copy(block); // Not OK either. + } + + +nosvm +----- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``nosvm``","","","","","","Yes" + +OpenCL 2.0 supports the optional ``__attribute__((nosvm))`` qualifier for +pointer variable. It informs the compiler that the pointer does not refer +to a shared virtual memory region. See OpenCL v2.0 s6.7.2 for details. + +Since it is not widely used and has been removed from OpenCL 2.1, it is ignored +by Clang. + + +objc_externally_retained +------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_externally_retained``","``clang::objc_externally_retained``","``clang::objc_externally_retained``","","","","Yes" + +The ``objc_externally_retained`` attribute can be applied to strong local +variables, functions, methods, or blocks to opt into +`externally-retained semantics +`_. + +When applied to the definition of a function, method, or block, every parameter +of the function with implicit strong retainable object pointer type is +considered externally-retained, and becomes ``const``. By explicitly annotating +a parameter with ``__strong``, you can opt back into the default +non-externally-retained behaviour for that parameter. For instance, +``first_param`` is externally-retained below, but not ``second_param``: + +.. code-block:: objc + + __attribute__((objc_externally_retained)) + void f(NSArray *first_param, __strong NSArray *second_param) { + // ... + } + +Likewise, when applied to a strong local variable, that variable becomes +``const`` and is considered externally-retained. + +When compiled without ``-fobjc-arc``, this attribute is ignored. + + +pass_object_size +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``pass_object_size``","``clang::pass_object_size``","``clang::pass_object_size``","","","","Yes" + +.. Note:: The mangling of functions with parameters that are annotated with + ``pass_object_size`` is subject to change. You can get around this by + using ``__asm__("foo")`` to explicitly name your functions, thus preserving + your ABI; also, non-overloadable C functions with ``pass_object_size`` are + not mangled. + +The ``pass_object_size(Type)`` attribute can be placed on function parameters to +instruct clang to call ``__builtin_object_size(param, Type)`` at each callsite +of said function, and implicitly pass the result of this call in as an invisible +argument of type ``size_t`` directly after the parameter annotated with +``pass_object_size``. Clang will also replace any calls to +``__builtin_object_size(param, Type)`` in the function by said implicit +parameter. + +Example usage: + +.. code-block:: c + + int bzero1(char *const p __attribute__((pass_object_size(0)))) + __attribute__((noinline)) { + int i = 0; + for (/**/; i < (int)__builtin_object_size(p, 0); ++i) { + p[i] = 0; + } + return i; + } + + int main() { + char chars[100]; + int n = bzero1(&chars[0]); + assert(n == sizeof(chars)); + return 0; + } + +If successfully evaluating ``__builtin_object_size(param, Type)`` at the +callsite is not possible, then the "failed" value is passed in. So, using the +definition of ``bzero1`` from above, the following code would exit cleanly: + +.. code-block:: c + + int main2(int argc, char *argv[]) { + int n = bzero1(argv); + assert(n == -1); + return 0; + } + +``pass_object_size`` plays a part in overload resolution. If two overload +candidates are otherwise equally good, then the overload with one or more +parameters with ``pass_object_size`` is preferred. This implies that the choice +between two identical overloads both with ``pass_object_size`` on one or more +parameters will always be ambiguous; for this reason, having two such overloads +is illegal. For example: + +.. code-block:: c++ + + #define PS(N) __attribute__((pass_object_size(N))) + // OK + void Foo(char *a, char *b); // Overload A + // OK -- overload A has no parameters with pass_object_size. + void Foo(char *a PS(0), char *b PS(0)); // Overload B + // Error -- Same signature (sans pass_object_size) as overload B, and both + // overloads have one or more parameters with the pass_object_size attribute. + void Foo(void *a PS(0), void *b); + + // OK + void Bar(void *a PS(0)); // Overload C + // OK + void Bar(char *c PS(1)); // Overload D + + void main() { + char known[10], *unknown; + Foo(unknown, unknown); // Calls overload B + Foo(known, unknown); // Calls overload B + Foo(unknown, known); // Calls overload B + Foo(known, known); // Calls overload B + + Bar(known); // Calls overload D + Bar(unknown); // Calls overload D + } + +Currently, ``pass_object_size`` is a bit restricted in terms of its usage: + +* Only one use of ``pass_object_size`` is allowed per parameter. + +* It is an error to take the address of a function with ``pass_object_size`` on + any of its parameters. If you wish to do this, you can create an overload + without ``pass_object_size`` on any parameters. + +* It is an error to apply the ``pass_object_size`` attribute to parameters that + are not pointers. Additionally, any parameter that ``pass_object_size`` is + applied to must be marked ``const`` at its function's definition. + + +require_constant_initialization +------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``require_constant_initialization``","``clang::require_constant_initialization``","","","","","Yes" + +This attribute specifies that the variable to which it is attached is intended +to have a `constant initializer `_ +according to the rules of [basic.start.static]. The variable is required to +have static or thread storage duration. If the initialization of the variable +is not a constant initializer an error will be produced. This attribute may +only be used in C++. + +Note that in C++03 strict constant expression checking is not done. Instead +the attribute reports if Clang can emit the variable as a constant, even if it's +not technically a 'constant initializer'. This behavior is non-portable. + +Static storage duration variables with constant initializers avoid hard-to-find +bugs caused by the indeterminate order of dynamic initialization. They can also +be safely used during dynamic initialization across translation units. + +This attribute acts as a compile time assertion that the requirements +for constant initialization have been met. Since these requirements change +between dialects and have subtle pitfalls it's important to fail fast instead +of silently falling back on dynamic initialization. + +.. code-block:: c++ + + // -std=c++14 + #define SAFE_STATIC [[clang::require_constant_initialization]] + struct T { + constexpr T(int) {} + ~T(); // non-trivial + }; + SAFE_STATIC T x = {42}; // Initialization OK. Doesn't check destructor. + SAFE_STATIC T y = 42; // error: variable does not have a constant initializer + // copy initialization is not a constant expression on a non-literal type. + + +section, __declspec(allocate) +----------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``section``","``gnu::section``","","``allocate``","","","Yes" + +The ``section`` attribute allows you to specify a specific section a +global variable or function should be in after translation. + + +swift_context +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``swift_context``","``clang::swift_context``","``clang::swift_context``","","","","Yes" + +The ``swift_context`` attribute marks a parameter of a ``swiftcall`` +function as having the special context-parameter ABI treatment. + +This treatment generally passes the context value in a special register +which is normally callee-preserved. + +A ``swift_context`` parameter must either be the last parameter or must be +followed by a ``swift_error_result`` parameter (which itself must always be +the last parameter). + +A context parameter must have pointer or reference type. + + +swift_error_result +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``swift_error_result``","``clang::swift_error_result``","``clang::swift_error_result``","","","","Yes" + +The ``swift_error_result`` attribute marks a parameter of a ``swiftcall`` +function as having the special error-result ABI treatment. + +This treatment generally passes the underlying error value in and out of +the function through a special register which is normally callee-preserved. +This is modeled in C by pretending that the register is addressable memory: + +- The caller appears to pass the address of a variable of pointer type. + The current value of this variable is copied into the register before + the call; if the call returns normally, the value is copied back into the + variable. + +- The callee appears to receive the address of a variable. This address + is actually a hidden location in its own stack, initialized with the + value of the register upon entry. When the function returns normally, + the value in that hidden location is written back to the register. + +A ``swift_error_result`` parameter must be the last parameter, and it must be +preceded by a ``swift_context`` parameter. + +A ``swift_error_result`` parameter must have type ``T**`` or ``T*&`` for some +type T. Note that no qualifiers are permitted on the intermediate level. + +It is undefined behavior if the caller does not pass a pointer or +reference to a valid object. + +The standard convention is that the error value itself (that is, the +value stored in the apparent argument) will be null upon function entry, +but this is not enforced by the ABI. + + +swift_indirect_result +--------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``swift_indirect_result``","``clang::swift_indirect_result``","``clang::swift_indirect_result``","","","","Yes" + +The ``swift_indirect_result`` attribute marks a parameter of a ``swiftcall`` +function as having the special indirect-result ABI treatment. + +This treatment gives the parameter the target's normal indirect-result +ABI treatment, which may involve passing it differently from an ordinary +parameter. However, only the first indirect result will receive this +treatment. Furthermore, low-level lowering may decide that a direct result +must be returned indirectly; if so, this will take priority over the +``swift_indirect_result`` parameters. + +A ``swift_indirect_result`` parameter must either be the first parameter or +follow another ``swift_indirect_result`` parameter. + +A ``swift_indirect_result`` parameter must have type ``T*`` or ``T&`` for +some object type ``T``. If ``T`` is a complete type at the point of +definition of a function, it is undefined behavior if the argument +value does not point to storage of adequate size and alignment for a +value of type ``T``. + +Making indirect results explicit in the signature allows C functions to +directly construct objects into them without relying on language +optimizations like C++'s named return value optimization (NRVO). + + +swiftcall +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``swiftcall``","``clang::swiftcall``","``clang::swiftcall``","","","","" + +The ``swiftcall`` attribute indicates that a function should be called +using the Swift calling convention for a function or function pointer. + +The lowering for the Swift calling convention, as described by the Swift +ABI documentation, occurs in multiple phases. The first, "high-level" +phase breaks down the formal parameters and results into innately direct +and indirect components, adds implicit paraameters for the generic +signature, and assigns the context and error ABI treatments to parameters +where applicable. The second phase breaks down the direct parameters +and results from the first phase and assigns them to registers or the +stack. The ``swiftcall`` convention only handles this second phase of +lowering; the C function type must accurately reflect the results +of the first phase, as follows: + +- Results classified as indirect by high-level lowering should be + represented as parameters with the ``swift_indirect_result`` attribute. + +- Results classified as direct by high-level lowering should be represented + as follows: + + - First, remove any empty direct results. + + - If there are no direct results, the C result type should be ``void``. + + - If there is one direct result, the C result type should be a type with + the exact layout of that result type. + + - If there are a multiple direct results, the C result type should be + a struct type with the exact layout of a tuple of those results. + +- Parameters classified as indirect by high-level lowering should be + represented as parameters of pointer type. + +- Parameters classified as direct by high-level lowering should be + omitted if they are empty types; otherwise, they should be represented + as a parameter type with a layout exactly matching the layout of the + Swift parameter type. + +- The context parameter, if present, should be represented as a trailing + parameter with the ``swift_context`` attribute. + +- The error result parameter, if present, should be represented as a + trailing parameter (always following a context parameter) with the + ``swift_error_result`` attribute. + +``swiftcall`` does not support variadic arguments or unprototyped functions. + +The parameter ABI treatment attributes are aspects of the function type. +A function type which which applies an ABI treatment attribute to a +parameter is a different type from an otherwise-identical function type +that does not. A single parameter may not have multiple ABI treatment +attributes. + +Support for this feature is target-dependent, although it should be +supported on every target that Swift supports. Query for this support +with ``__has_attribute(swiftcall)``. This implies support for the +``swift_context``, ``swift_error_result``, and ``swift_indirect_result`` +attributes. + + +thread +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","``thread``","","","" + +The ``__declspec(thread)`` attribute declares a variable with thread local +storage. It is available under the ``-fms-extensions`` flag for MSVC +compatibility. See the documentation for `__declspec(thread)`_ on MSDN. + +.. _`__declspec(thread)`: http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx + +In Clang, ``__declspec(thread)`` is generally equivalent in functionality to the +GNU ``__thread`` keyword. The variable must not have a destructor and must have +a constant initializer, if any. The attribute only applies to variables +declared with static storage duration, such as globals, class static data +members, and static locals. + + +tls_model +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``tls_model``","``gnu::tls_model``","","","","","Yes" + +The ``tls_model`` attribute allows you to specify which thread-local storage +model to use. It accepts the following strings: + +* global-dynamic +* local-dynamic +* initial-exec +* local-exec + +TLS models are mutually exclusive. + + +trivial_abi +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``trivial_abi``","``clang::trivial_abi``","","","","","Yes" + +The ``trivial_abi`` attribute can be applied to a C++ class, struct, or union. +It instructs the compiler to pass and return the type using the C ABI for the +underlying type when the type would otherwise be considered non-trivial for the +purpose of calls. +A class annotated with `trivial_abi` can have non-trivial destructors or copy/move constructors without automatically becoming non-trivial for the purposes of calls. For example: + + .. code-block:: c++ + + // A is trivial for the purposes of calls because `trivial_abi` makes the + // user-provided special functions trivial. + struct __attribute__((trivial_abi)) A { + ~A(); + A(const A &); + A(A &&); + int x; + }; + + // B's destructor and copy/move constructor are considered trivial for the + // purpose of calls because A is trivial. + struct B { + A a; + }; + +If a type is trivial for the purposes of calls, has a non-trivial destructor, +and is passed as an argument by value, the convention is that the callee will +destroy the object before returning. + +Attribute ``trivial_abi`` has no effect in the following cases: + +- The class directly declares a virtual base or virtual methods. +- The class has a base class that is non-trivial for the purposes of calls. +- The class has a non-static data member whose type is non-trivial for the purposes of calls, which includes: + + - classes that are non-trivial for the purposes of calls + - __weak-qualified types in Objective-C++ + - arrays of any of the above + + +uninitialized +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``uninitialized``","``clang::uninitialized``","","","","","" + +The command-line parameter ``-ftrivial-auto-var-init=*`` can be used to +initialize trivial automatic stack variables. By default, trivial automatic +stack variables are uninitialized. This attribute is used to override the +command-line parameter, forcing variables to remain uninitialized. It has no +semantic meaning in that using uninitialized values is undefined behavior, +it rather documents the programmer's intent. + + +Type Attributes +=============== + + +__single_inhertiance, __multiple_inheritance, __virtual_inheritance +------------------------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``__single_inheritance`` |br| ``__multiple_inheritance`` |br| ``__virtual_inheritance`` |br| ``__unspecified_inheritance``","","" + +This collection of keywords is enabled under ``-fms-extensions`` and controls +the pointer-to-member representation used on ``*-*-win32`` targets. + +The ``*-*-win32`` targets utilize a pointer-to-member representation which +varies in size and alignment depending on the definition of the underlying +class. + +However, this is problematic when a forward declaration is only available and +no definition has been made yet. In such cases, Clang is forced to utilize the +most general representation that is available to it. + +These keywords make it possible to use a pointer-to-member representation other +than the most general one regardless of whether or not the definition will ever +be present in the current translation unit. + +This family of keywords belong between the ``class-key`` and ``class-name``: + +.. code-block:: c++ + + struct __single_inheritance S; + int S::*i; + struct S {}; + +This keyword can be applied to class templates but only has an effect when used +on full specializations: + +.. code-block:: c++ + + template struct __single_inheritance A; // warning: inheritance model ignored on primary template + template struct __multiple_inheritance A; // warning: inheritance model ignored on partial specialization + template <> struct __single_inheritance A; + +Note that choosing an inheritance model less general than strictly necessary is +an error: + +.. code-block:: c++ + + struct __multiple_inheritance S; // error: inheritance model does not match definition + int S::*i; + struct S {}; + + +align_value +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``align_value``","","","","","","Yes" + +The align_value attribute can be added to the typedef of a pointer type or the +declaration of a variable of pointer or reference type. It specifies that the +pointer will point to, or the reference will bind to, only objects with at +least the provided alignment. This alignment value must be some positive power +of 2. + + .. code-block:: c + + typedef double * aligned_double_ptr __attribute__((align_value(64))); + void foo(double & x __attribute__((align_value(128)), + aligned_double_ptr y) { ... } + +If the pointer value does not have the specified alignment at runtime, the +behavior of the program is undefined. + + +empty_bases +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","``empty_bases``","","","" + +The empty_bases attribute permits the compiler to utilize the +empty-base-optimization more frequently. +This attribute only applies to struct, class, and union types. +It is only supported when using the Microsoft C++ ABI. + + +enum_extensibility +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``enum_extensibility``","``clang::enum_extensibility``","``clang::enum_extensibility``","","","","Yes" + +Attribute ``enum_extensibility`` is used to distinguish between enum definitions +that are extensible and those that are not. The attribute can take either +``closed`` or ``open`` as an argument. ``closed`` indicates a variable of the +enum type takes a value that corresponds to one of the enumerators listed in the +enum definition or, when the enum is annotated with ``flag_enum``, a value that +can be constructed using values corresponding to the enumerators. ``open`` +indicates a variable of the enum type can take any values allowed by the +standard and instructs clang to be more lenient when issuing warnings. + +.. code-block:: c + + enum __attribute__((enum_extensibility(closed))) ClosedEnum { + A0, A1 + }; + + enum __attribute__((enum_extensibility(open))) OpenEnum { + B0, B1 + }; + + enum __attribute__((enum_extensibility(closed),flag_enum)) ClosedFlagEnum { + C0 = 1 << 0, C1 = 1 << 1 + }; + + enum __attribute__((enum_extensibility(open),flag_enum)) OpenFlagEnum { + D0 = 1 << 0, D1 = 1 << 1 + }; + + void foo1() { + enum ClosedEnum ce; + enum OpenEnum oe; + enum ClosedFlagEnum cfe; + enum OpenFlagEnum ofe; + + ce = A1; // no warnings + ce = 100; // warning issued + oe = B1; // no warnings + oe = 100; // no warnings + cfe = C0 | C1; // no warnings + cfe = C0 | C1 | 4; // warning issued + ofe = D0 | D1; // no warnings + ofe = D0 | D1 | 4; // no warnings + } + + +flag_enum +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``flag_enum``","``clang::flag_enum``","``clang::flag_enum``","","","","Yes" + +This attribute can be added to an enumerator to signal to the compiler that it +is intended to be used as a flag type. This will cause the compiler to assume +that the range of the type includes all of the values that you can get by +manipulating bits of the enumerator when issuing warnings. + + +layout_version +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","``layout_version``","","","" + +The layout_version attribute requests that the compiler utilize the class +layout rules of a particular compiler version. +This attribute only applies to struct, class, and union types. +It is only supported when using the Microsoft C++ ABI. + + +lto_visibility_public +--------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``lto_visibility_public``","``clang::lto_visibility_public``","``clang::lto_visibility_public``","","","","Yes" + +See :doc:`LTOVisibility`. + + +noderef +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``noderef``","``clang::noderef``","``clang::noderef``","","","","" + +The ``noderef`` attribute causes clang to diagnose dereferences of annotated pointer types. +This is ideally used with pointers that point to special memory which cannot be read +from or written to, but allowing for the pointer to be used in pointer arithmetic. +The following are examples of valid expressions where dereferences are diagnosed: + +.. code-block:: c + + int __attribute__((noderef)) *p; + int x = *p; // warning + + int __attribute__((noderef)) **p2; + x = **p2; // warning + + int * __attribute__((noderef)) *p3; + p = *p3; // warning + + struct S { + int a; + }; + struct S __attribute__((noderef)) *s; + x = s->a; // warning + x = (*s).a; // warning + +Not all dereferences may diagnose a warning if the value directed by the pointer may not be +accessed. The following are examples of valid expressions where may not be diagnosed: + +.. code-block:: c + + int *q; + int __attribute__((noderef)) *p; + q = &*p; + q = *&p; + + struct S { + int a; + }; + struct S __attribute__((noderef)) *s; + p = &s->a; + p = &(*s).a; + +``noderef`` is currently only supported for pointers and arrays and not usable for +references or Objective-C object pointers. + +.. code-block: c++ + + int x = 2; + int __attribute__((noderef)) &y = x; // warning: 'noderef' can only be used on an array or pointer type + +.. code-block: objc + + id __attribute__((noderef)) obj = [NSObject new]; // warning: 'noderef' can only be used on an array or pointer type + + +novtable +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","``novtable``","","","" + +This attribute can be added to a class declaration or definition to signal to +the compiler that constructors and destructors will not reference the virtual +function table. It is only supported when using the Microsoft C++ ABI. + + +objc_subclassing_restricted +--------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_subclassing_restricted``","``clang::objc_subclassing_restricted``","``clang::objc_subclassing_restricted``","","","","Yes" + +This attribute can be added to an Objective-C ``@interface`` declaration to +ensure that this class cannot be subclassed. + + +selectany +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``selectany``","``gnu::selectany``","","``selectany``","","","" + +This attribute appertains to a global symbol, causing it to have a weak +definition ( +`linkonce `_ +), allowing the linker to select any definition. + +For more information see +`gcc documentation `_ +or `msvc documentation `_. + + +transparent_union +----------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``transparent_union``","``gnu::transparent_union``","","","","","" + +This attribute can be applied to a union to change the behaviour of calls to +functions that have an argument with a transparent union type. The compiler +behaviour is changed in the following manner: + +- A value whose type is any member of the transparent union can be passed as an + argument without the need to cast that value. + +- The argument is passed to the function using the calling convention of the + first member of the transparent union. Consequently, all the members of the + transparent union should have the same calling convention as its first member. + +Transparent unions are not supported in C++. + + +Statement Attributes +==================== + + +#pragma clang loop +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","","``clang loop`` |br| ``unroll`` |br| ``nounroll`` |br| ``unroll_and_jam`` |br| ``nounroll_and_jam``","" + +The ``#pragma clang loop`` directive allows loop optimization hints to be +specified for the subsequent loop. The directive allows pipelining to be +disabled, or vectorization, interleaving, and unrolling to be enabled or disabled. +Vector width, interleave count, unrolling count, and the initiation interval +for pipelining can be explicitly specified. See `language extensions +`_ +for details. + + +#pragma unroll, #pragma nounroll +-------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","","``clang loop`` |br| ``unroll`` |br| ``nounroll`` |br| ``unroll_and_jam`` |br| ``nounroll_and_jam``","" + +Loop unrolling optimization hints can be specified with ``#pragma unroll`` and +``#pragma nounroll``. The pragma is placed immediately before a for, while, +do-while, or c++11 range-based for loop. + +Specifying ``#pragma unroll`` without a parameter directs the loop unroller to +attempt to fully unroll the loop if the trip count is known at compile time and +attempt to partially unroll the loop if the trip count is not known at compile +time: + +.. code-block:: c++ + + #pragma unroll + for (...) { + ... + } + +Specifying the optional parameter, ``#pragma unroll _value_``, directs the +unroller to unroll the loop ``_value_`` times. The parameter may optionally be +enclosed in parentheses: + +.. code-block:: c++ + + #pragma unroll 16 + for (...) { + ... + } + + #pragma unroll(16) + for (...) { + ... + } + +Specifying ``#pragma nounroll`` indicates that the loop should not be unrolled: + +.. code-block:: c++ + + #pragma nounroll + for (...) { + ... + } + +``#pragma unroll`` and ``#pragma unroll _value_`` have identical semantics to +``#pragma clang loop unroll(full)`` and +``#pragma clang loop unroll_count(_value_)`` respectively. ``#pragma nounroll`` +is equivalent to ``#pragma clang loop unroll(disable)``. See +`language extensions +`_ +for further details including limitations of the unroll hints. + + +__read_only, __write_only, __read_write (read_only, write_only, read_write) +--------------------------------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``__read_only`` |br| ``read_only`` |br| ``__write_only`` |br| ``write_only`` |br| ``__read_write`` |br| ``read_write``","","" + +The access qualifiers must be used with image object arguments or pipe arguments +to declare if they are being read or written by a kernel or function. + +The read_only/__read_only, write_only/__write_only and read_write/__read_write +names are reserved for use as access qualifiers and shall not be used otherwise. + +.. code-block:: c + + kernel void + foo (read_only image2d_t imageA, + write_only image2d_t imageB) { + ... + } + +In the above example imageA is a read-only 2D image object, and imageB is a +write-only 2D image object. + +The read_write (or __read_write) qualifier can not be used with pipe. + +More details can be found in the OpenCL C language Spec v2.0, Section 6.6. + + +fallthrough +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","``fallthrough`` |br| ``clang::fallthrough``","``fallthrough``","","","","" + +The ``fallthrough`` (or ``clang::fallthrough``) attribute is used +to annotate intentional fall-through +between switch labels. It can only be applied to a null statement placed at a +point of execution between any statement and the next switch label. It is +common to mark these places with a specific comment, but this attribute is +meant to replace comments with a more strict annotation, which can be checked +by the compiler. This attribute doesn't change semantics of the code and can +be used wherever an intended fall-through occurs. It is designed to mimic +control-flow statements like ``break;``, so it can be placed in most places +where ``break;`` can, but only if there are no statements on the execution path +between it and the next switch label. + +By default, Clang does not warn on unannotated fallthrough from one ``switch`` +case to another. Diagnostics on fallthrough without a corresponding annotation +can be enabled with the ``-Wimplicit-fallthrough`` argument. + +Here is an example: + +.. code-block:: c++ + + // compile with -Wimplicit-fallthrough + switch (n) { + case 22: + case 33: // no warning: no statements between case labels + f(); + case 44: // warning: unannotated fall-through + g(); + [[clang::fallthrough]]; + case 55: // no warning + if (x) { + h(); + break; + } + else { + i(); + [[clang::fallthrough]]; + } + case 66: // no warning + p(); + [[clang::fallthrough]]; // warning: fallthrough annotation does not + // directly precede case label + q(); + case 77: // warning: unannotated fall-through + r(); + } + + +intel_reqd_sub_group_size +------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``intel_reqd_sub_group_size``","","","","","","Yes" + +The optional attribute intel_reqd_sub_group_size can be used to indicate that +the kernel must be compiled and executed with the specified subgroup size. When +this attribute is present, get_max_sub_group_size() is guaranteed to return the +specified integer value. This is important for the correctness of many subgroup +algorithms, and in some cases may be used by the compiler to generate more optimal +code. See `cl_intel_required_subgroup_size +` +for details. + + +opencl_unroll_hint +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``opencl_unroll_hint``","","","","","","" + +The opencl_unroll_hint attribute qualifier can be used to specify that a loop +(for, while and do loops) can be unrolled. This attribute qualifier can be +used to specify full unrolling or partial unrolling by a specified amount. +This is a compiler hint and the compiler may ignore this directive. See +`OpenCL v2.0 `_ +s6.11.5 for details. + + +suppress +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","``gsl::suppress``","","","","","" + +The ``[[gsl::suppress]]`` attribute suppresses specific +clang-tidy diagnostics for rules of the `C++ Core Guidelines`_ in a portable +way. The attribute can be attached to declarations, statements, and at +namespace scope. + +.. code-block:: c++ + + [[gsl::suppress("Rh-public")]] + void f_() { + int *p; + [[gsl::suppress("type")]] { + p = reinterpret_cast(7); + } + } + namespace N { + [[clang::suppress("type", "bounds")]]; + ... + } + +.. _`C++ Core Guidelines`: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#inforce-enforcement + + +AMD GPU Attributes +================== + + +amdgpu_flat_work_group_size +--------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``amdgpu_flat_work_group_size``","``clang::amdgpu_flat_work_group_size``","","","","","Yes" + +The flat work-group size is the number of work-items in the work-group size +specified when the kernel is dispatched. It is the product of the sizes of the +x, y, and z dimension of the work-group. + +Clang supports the +``__attribute__((amdgpu_flat_work_group_size(, )))`` attribute for the +AMDGPU target. This attribute may be attached to a kernel function definition +and is an optimization hint. + +```` parameter specifies the minimum flat work-group size, and ```` +parameter specifies the maximum flat work-group size (must be greater than +````) to which all dispatches of the kernel will conform. Passing ``0, 0`` +as ``, `` implies the default behavior (``128, 256``). + +If specified, the AMDGPU target backend might be able to produce better machine +code for barriers and perform scratch promotion by estimating available group +segment size. + +An error will be given if: + - Specified values violate subtarget specifications; + - Specified values are not compatible with values provided through other + attributes. + + +amdgpu_num_sgpr +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``amdgpu_num_sgpr``","``clang::amdgpu_num_sgpr``","","","","","Yes" + +Clang supports the ``__attribute__((amdgpu_num_sgpr()))`` and +``__attribute__((amdgpu_num_vgpr()))`` attributes for the AMDGPU +target. These attributes may be attached to a kernel function definition and are +an optimization hint. + +If these attributes are specified, then the AMDGPU target backend will attempt +to limit the number of SGPRs and/or VGPRs used to the specified value(s). The +number of used SGPRs and/or VGPRs may further be rounded up to satisfy the +allocation requirements or constraints of the subtarget. Passing ``0`` as +``num_sgpr`` and/or ``num_vgpr`` implies the default behavior (no limits). + +These attributes can be used to test the AMDGPU target backend. It is +recommended that the ``amdgpu_waves_per_eu`` attribute be used to control +resources such as SGPRs and VGPRs since it is aware of the limits for different +subtargets. + +An error will be given if: + - Specified values violate subtarget specifications; + - Specified values are not compatible with values provided through other + attributes; + - The AMDGPU target backend is unable to create machine code that can meet the + request. + + +amdgpu_num_vgpr +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``amdgpu_num_vgpr``","``clang::amdgpu_num_vgpr``","","","","","Yes" + +Clang supports the ``__attribute__((amdgpu_num_sgpr()))`` and +``__attribute__((amdgpu_num_vgpr()))`` attributes for the AMDGPU +target. These attributes may be attached to a kernel function definition and are +an optimization hint. + +If these attributes are specified, then the AMDGPU target backend will attempt +to limit the number of SGPRs and/or VGPRs used to the specified value(s). The +number of used SGPRs and/or VGPRs may further be rounded up to satisfy the +allocation requirements or constraints of the subtarget. Passing ``0`` as +``num_sgpr`` and/or ``num_vgpr`` implies the default behavior (no limits). + +These attributes can be used to test the AMDGPU target backend. It is +recommended that the ``amdgpu_waves_per_eu`` attribute be used to control +resources such as SGPRs and VGPRs since it is aware of the limits for different +subtargets. + +An error will be given if: + - Specified values violate subtarget specifications; + - Specified values are not compatible with values provided through other + attributes; + - The AMDGPU target backend is unable to create machine code that can meet the + request. + + +amdgpu_waves_per_eu +------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``amdgpu_waves_per_eu``","``clang::amdgpu_waves_per_eu``","","","","","Yes" + +A compute unit (CU) is responsible for executing the wavefronts of a work-group. +It is composed of one or more execution units (EU), which are responsible for +executing the wavefronts. An EU can have enough resources to maintain the state +of more than one executing wavefront. This allows an EU to hide latency by +switching between wavefronts in a similar way to symmetric multithreading on a +CPU. In order to allow the state for multiple wavefronts to fit on an EU, the +resources used by a single wavefront have to be limited. For example, the number +of SGPRs and VGPRs. Limiting such resources can allow greater latency hiding, +but can result in having to spill some register state to memory. + +Clang supports the ``__attribute__((amdgpu_waves_per_eu([, ])))`` +attribute for the AMDGPU target. This attribute may be attached to a kernel +function definition and is an optimization hint. + +```` parameter specifies the requested minimum number of waves per EU, and +*optional* ```` parameter specifies the requested maximum number of waves +per EU (must be greater than ```` if specified). If ```` is omitted, +then there is no restriction on the maximum number of waves per EU other than +the one dictated by the hardware for which the kernel is compiled. Passing +``0, 0`` as ``, `` implies the default behavior (no limits). + +If specified, this attribute allows an advanced developer to tune the number of +wavefronts that are capable of fitting within the resources of an EU. The AMDGPU +target backend can use this information to limit resources, such as number of +SGPRs, number of VGPRs, size of available group and private memory segments, in +such a way that guarantees that at least ```` wavefronts and at most +```` wavefronts are able to fit within the resources of an EU. Requesting +more wavefronts can hide memory latency but limits available registers which +can result in spilling. Requesting fewer wavefronts can help reduce cache +thrashing, but can reduce memory latency hiding. + +This attribute controls the machine code generated by the AMDGPU target backend +to ensure it is capable of meeting the requested values. However, when the +kernel is executed, there may be other reasons that prevent meeting the request, +for example, there may be wavefronts from other kernels executing on the EU. + +An error will be given if: + - Specified values violate subtarget specifications; + - Specified values are not compatible with values provided through other + attributes; + - The AMDGPU target backend is unable to create machine code that can meet the + request. + + +OpenCL Address Spaces +===================== +The address space qualifier may be used to specify the region of memory that is +used to allocate the object. OpenCL supports the following address spaces: +__generic(generic), __global(global), __local(local), __private(private), +__constant(constant). + + .. code-block:: c + + __constant int c = ...; + + __generic int* foo(global int* g) { + __local int* l; + private int p; + ... + return l; + } + +More details can be found in the OpenCL C language Spec v2.0, Section 6.5. + +constant +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``__constant`` |br| ``constant``","","" + +The constant address space attribute signals that an object is located in +a constant (non-modifiable) memory region. It is available to all work items. +Any type can be annotated with the constant address space attribute. Objects +with the constant address space qualifier can be declared in any scope and must +have an initializer. + + +generic +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``__generic`` |br| ``generic``","","" + +The generic address space attribute is only available with OpenCL v2.0 and later. +It can be used with pointer types. Variables in global and local scope and +function parameters in non-kernel functions can have the generic address space +type attribute. It is intended to be a placeholder for any other address space +except for '__constant' in OpenCL code which can be used with multiple address +spaces. + + +global +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``__global`` |br| ``global``","","" + +The global address space attribute specifies that an object is allocated in +global memory, which is accessible by all work items. The content stored in this +memory area persists between kernel executions. Pointer types to the global +address space are allowed as function parameters or local variables. Starting +with OpenCL v2.0, the global address space can be used with global (program +scope) variables and static local variable as well. + + +local +----- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``__local`` |br| ``local``","","" + +The local address space specifies that an object is allocated in the local (work +group) memory area, which is accessible to all work items in the same work +group. The content stored in this memory region is not accessible after +the kernel execution ends. In a kernel function scope, any variable can be in +the local address space. In other scopes, only pointer types to the local address +space are allowed. Local address space variables cannot have an initializer. + + +private +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``__private`` |br| ``private``","","" + +The private address space specifies that an object is allocated in the private +(work item) memory. Other work items cannot access the same memory area and its +content is destroyed after work item execution ends. Local variables can be +declared in the private address space. Function arguments are always in the +private address space. Kernel function arguments of a pointer or an array type +cannot point to the private address space. + + +Calling Conventions +=================== +Clang supports several different calling conventions, depending on the target +platform and architecture. The calling convention used for a function determines +how parameters are passed, how results are returned to the caller, and other +low-level details of calling a function. + +aarch64_vector_pcs +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``aarch64_vector_pcs``","``clang::aarch64_vector_pcs``","``clang::aarch64_vector_pcs``","","","","" + +On AArch64 targets, this attribute changes the calling convention of a +function to preserve additional floating-point and Advanced SIMD registers +relative to the default calling convention used for AArch64. + +This means it is more efficient to call such functions from code that performs +extensive floating-point and vector calculations, because fewer live SIMD and FP +registers need to be saved. This property makes it well-suited for e.g. +floating-point or vector math library functions, which are typically leaf +functions that require a small number of registers. + +However, using this attribute also means that it is more expensive to call +a function that adheres to the default calling convention from within such +a function. Therefore, it is recommended that this attribute is only used +for leaf functions. + +For more information, see the documentation for `aarch64_vector_pcs`_ on +the Arm Developer website. + +.. _`aarch64_vector_pcs`: https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi + + +fastcall +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``fastcall``","``gnu::fastcall``","","","``__fastcall`` |br| ``_fastcall``","","" + +On 32-bit x86 targets, this attribute changes the calling convention of a +function to use ECX and EDX as register parameters and clear parameters off of +the stack on return. This convention does not support variadic calls or +unprototyped functions in C, and has no effect on x86_64 targets. This calling +convention is supported primarily for compatibility with existing code. Users +seeking register parameters should use the ``regparm`` attribute, which does +not require callee-cleanup. See the documentation for `__fastcall`_ on MSDN. + +.. _`__fastcall`: http://msdn.microsoft.com/en-us/library/6xa169sk.aspx + + +ms_abi +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``ms_abi``","``gnu::ms_abi``","","","","","" + +On non-Windows x86_64 targets, this attribute changes the calling convention of +a function to match the default convention used on Windows x86_64. This +attribute has no effect on Windows targets or non-x86_64 targets. + + +pcs +--- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``pcs``","``gnu::pcs``","","","","","" + +On ARM targets, this attribute can be used to select calling conventions +similar to ``stdcall`` on x86. Valid parameter values are "aapcs" and +"aapcs-vfp". + + +preserve_all +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``preserve_all``","``clang::preserve_all``","``clang::preserve_all``","","","","" + +On X86-64 and AArch64 targets, this attribute changes the calling convention of +a function. The ``preserve_all`` calling convention attempts to make the code +in the caller even less intrusive than the ``preserve_most`` calling convention. +This calling convention also behaves identical to the ``C`` calling convention +on how arguments and return values are passed, but it uses a different set of +caller/callee-saved registers. This removes the burden of saving and +recovering a large register set before and after the call in the caller. If +the arguments are passed in callee-saved registers, then they will be +preserved by the callee across the call. This doesn't apply for values +returned in callee-saved registers. + +- On X86-64 the callee preserves all general purpose registers, except for + R11. R11 can be used as a scratch register. Furthermore it also preserves + all floating-point registers (XMMs/YMMs). + +The idea behind this convention is to support calls to runtime functions +that don't need to call out to any other functions. + +This calling convention, like the ``preserve_most`` calling convention, will be +used by a future version of the Objective-C runtime and should be considered +experimental at this time. + + +preserve_most +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``preserve_most``","``clang::preserve_most``","``clang::preserve_most``","","","","" + +On X86-64 and AArch64 targets, this attribute changes the calling convention of +a function. The ``preserve_most`` calling convention attempts to make the code +in the caller as unintrusive as possible. This convention behaves identically +to the ``C`` calling convention on how arguments and return values are passed, +but it uses a different set of caller/callee-saved registers. This alleviates +the burden of saving and recovering a large register set before and after the +call in the caller. If the arguments are passed in callee-saved registers, +then they will be preserved by the callee across the call. This doesn't +apply for values returned in callee-saved registers. + +- On X86-64 the callee preserves all general purpose registers, except for + R11. R11 can be used as a scratch register. Floating-point registers + (XMMs/YMMs) are not preserved and need to be saved by the caller. + +The idea behind this convention is to support calls to runtime functions +that have a hot path and a cold path. The hot path is usually a small piece +of code that doesn't use many registers. The cold path might need to call out to +another function and therefore only needs to preserve the caller-saved +registers, which haven't already been saved by the caller. The +`preserve_most` calling convention is very similar to the ``cold`` calling +convention in terms of caller/callee-saved registers, but they are used for +different types of function calls. ``coldcc`` is for function calls that are +rarely executed, whereas `preserve_most` function calls are intended to be +on the hot path and definitely executed a lot. Furthermore ``preserve_most`` +doesn't prevent the inliner from inlining the function call. + +This calling convention will be used by a future version of the Objective-C +runtime and should therefore still be considered experimental at this time. +Although this convention was created to optimize certain runtime calls to +the Objective-C runtime, it is not limited to this runtime and might be used +by other runtimes in the future too. The current implementation only +supports X86-64 and AArch64, but the intention is to support more architectures +in the future. + + +regcall +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``regcall``","``gnu::regcall``","","","``__regcall``","","" + +On x86 targets, this attribute changes the calling convention to +`__regcall`_ convention. This convention aims to pass as many arguments +as possible in registers. It also tries to utilize registers for the +return value whenever it is possible. + +.. _`__regcall`: https://software.intel.com/en-us/node/693069 + + +regparm +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``regparm``","``gnu::regparm``","","","","","" + +On 32-bit x86 targets, the regparm attribute causes the compiler to pass +the first three integer parameters in EAX, EDX, and ECX instead of on the +stack. This attribute has no effect on variadic functions, and all parameters +are passed via the stack as normal. + + +stdcall +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``stdcall``","``gnu::stdcall``","","","``__stdcall`` |br| ``_stdcall``","","" + +On 32-bit x86 targets, this attribute changes the calling convention of a +function to clear parameters off of the stack on return. This convention does +not support variadic calls or unprototyped functions in C, and has no effect on +x86_64 targets. This calling convention is used widely by the Windows API and +COM applications. See the documentation for `__stdcall`_ on MSDN. + +.. _`__stdcall`: http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx + + +thiscall +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``thiscall``","``gnu::thiscall``","","","``__thiscall`` |br| ``_thiscall``","","" + +On 32-bit x86 targets, this attribute changes the calling convention of a +function to use ECX for the first parameter (typically the implicit ``this`` +parameter of C++ methods) and clear parameters off of the stack on return. This +convention does not support variadic calls or unprototyped functions in C, and +has no effect on x86_64 targets. See the documentation for `__thiscall`_ on +MSDN. + +.. _`__thiscall`: http://msdn.microsoft.com/en-us/library/ek8tkfbw.aspx + + +vectorcall +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``vectorcall``","``clang::vectorcall``","``clang::vectorcall``","","``__vectorcall`` |br| ``_vectorcall``","","" + +On 32-bit x86 *and* x86_64 targets, this attribute changes the calling +convention of a function to pass vector parameters in SSE registers. + +On 32-bit x86 targets, this calling convention is similar to ``__fastcall``. +The first two integer parameters are passed in ECX and EDX. Subsequent integer +parameters are passed in memory, and callee clears the stack. On x86_64 +targets, the callee does *not* clear the stack, and integer parameters are +passed in RCX, RDX, R8, and R9 as is done for the default Windows x64 calling +convention. + +On both 32-bit x86 and x86_64 targets, vector and floating point arguments are +passed in XMM0-XMM5. Homogeneous vector aggregates of up to four elements are +passed in sequential SSE registers if enough are available. If AVX is enabled, +256 bit vectors are passed in YMM0-YMM5. Any vector or aggregate type that +cannot be passed in registers for any reason is passed by reference, which +allows the caller to align the parameter memory. + +See the documentation for `__vectorcall`_ on MSDN for more details. + +.. _`__vectorcall`: http://msdn.microsoft.com/en-us/library/dn375768.aspx + + +Consumed Annotation Checking +============================ +Clang supports additional attributes for checking basic resource management +properties, specifically for unique objects that have a single owning reference. +The following attributes are currently supported, although **the implementation +for these annotations is currently in development and are subject to change.** + +callable_when +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``callable_when``","``clang::callable_when``","","","","","Yes" + +Use ``__attribute__((callable_when(...)))`` to indicate what states a method +may be called in. Valid states are unconsumed, consumed, or unknown. Each +argument to this attribute must be a quoted string. E.g.: + +``__attribute__((callable_when("unconsumed", "unknown")))`` + + +consumable +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``consumable``","``clang::consumable``","","","","","Yes" + +Each ``class`` that uses any of the typestate annotations must first be marked +using the ``consumable`` attribute. Failure to do so will result in a warning. + +This attribute accepts a single parameter that must be one of the following: +``unknown``, ``consumed``, or ``unconsumed``. + + +param_typestate +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``param_typestate``","``clang::param_typestate``","","","","","Yes" + +This attribute specifies expectations about function parameters. Calls to an +function with annotated parameters will issue a warning if the corresponding +argument isn't in the expected state. The attribute is also used to set the +initial state of the parameter when analyzing the function's body. + + +return_typestate +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``return_typestate``","``clang::return_typestate``","","","","","Yes" + +The ``return_typestate`` attribute can be applied to functions or parameters. +When applied to a function the attribute specifies the state of the returned +value. The function's body is checked to ensure that it always returns a value +in the specified state. On the caller side, values returned by the annotated +function are initialized to the given state. + +When applied to a function parameter it modifies the state of an argument after +a call to the function returns. The function's body is checked to ensure that +the parameter is in the expected state before returning. + + +set_typestate +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``set_typestate``","``clang::set_typestate``","","","","","Yes" + +Annotate methods that transition an object into a new state with +``__attribute__((set_typestate(new_state)))``. The new state must be +unconsumed, consumed, or unknown. + + +test_typestate +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``test_typestate``","``clang::test_typestate``","","","","","Yes" + +Use ``__attribute__((test_typestate(tested_state)))`` to indicate that a method +returns true if the object is in the specified state.. + + +Type Safety Checking +==================== +Clang supports additional attributes to enable checking type safety properties +that can't be enforced by the C type system. To see warnings produced by these +checks, ensure that -Wtype-safety is enabled. Use cases include: + +* MPI library implementations, where these attributes enable checking that + the buffer type matches the passed ``MPI_Datatype``; +* for HDF5 library there is a similar use case to MPI; +* checking types of variadic functions' arguments for functions like + ``fcntl()`` and ``ioctl()``. + +You can detect support for these attributes with ``__has_attribute()``. For +example: + +.. code-block:: c++ + + #if defined(__has_attribute) + # if __has_attribute(argument_with_type_tag) && \ + __has_attribute(pointer_with_type_tag) && \ + __has_attribute(type_tag_for_datatype) + # define ATTR_MPI_PWT(buffer_idx, type_idx) __attribute__((pointer_with_type_tag(mpi,buffer_idx,type_idx))) + /* ... other macros ... */ + # endif + #endif + + #if !defined(ATTR_MPI_PWT) + # define ATTR_MPI_PWT(buffer_idx, type_idx) + #endif + + int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */) + ATTR_MPI_PWT(1,3); + +argument_with_type_tag +---------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``argument_with_type_tag`` |br| ``pointer_with_type_tag``","``clang::argument_with_type_tag`` |br| ``clang::pointer_with_type_tag``","``clang::argument_with_type_tag`` |br| ``clang::pointer_with_type_tag``","","","","" + +Use ``__attribute__((argument_with_type_tag(arg_kind, arg_idx, +type_tag_idx)))`` on a function declaration to specify that the function +accepts a type tag that determines the type of some other argument. + +This attribute is primarily useful for checking arguments of variadic functions +(``pointer_with_type_tag`` can be used in most non-variadic cases). + +In the attribute prototype above: + * ``arg_kind`` is an identifier that should be used when annotating all + applicable type tags. + * ``arg_idx`` provides the position of a function argument. The expected type of + this function argument will be determined by the function argument specified + by ``type_tag_idx``. In the code example below, "3" means that the type of the + function's third argument will be determined by ``type_tag_idx``. + * ``type_tag_idx`` provides the position of a function argument. This function + argument will be a type tag. The type tag will determine the expected type of + the argument specified by ``arg_idx``. In the code example below, "2" means + that the type tag associated with the function's second argument should agree + with the type of the argument specified by ``arg_idx``. + +For example: + +.. code-block:: c++ + + int fcntl(int fd, int cmd, ...) + __attribute__(( argument_with_type_tag(fcntl,3,2) )); + // The function's second argument will be a type tag; this type tag will + // determine the expected type of the function's third argument. + + +pointer_with_type_tag +--------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``argument_with_type_tag`` |br| ``pointer_with_type_tag``","``clang::argument_with_type_tag`` |br| ``clang::pointer_with_type_tag``","``clang::argument_with_type_tag`` |br| ``clang::pointer_with_type_tag``","","","","" + +Use ``__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx, type_tag_idx)))`` +on a function declaration to specify that the function accepts a type tag that +determines the pointee type of some other pointer argument. + +In the attribute prototype above: + * ``ptr_kind`` is an identifier that should be used when annotating all + applicable type tags. + * ``ptr_idx`` provides the position of a function argument; this function + argument will have a pointer type. The expected pointee type of this pointer + type will be determined by the function argument specified by + ``type_tag_idx``. In the code example below, "1" means that the pointee type + of the function's first argument will be determined by ``type_tag_idx``. + * ``type_tag_idx`` provides the position of a function argument; this function + argument will be a type tag. The type tag will determine the expected pointee + type of the pointer argument specified by ``ptr_idx``. In the code example + below, "3" means that the type tag associated with the function's third + argument should agree with the pointee type of the pointer argument specified + by ``ptr_idx``. + +For example: + +.. code-block:: c++ + + typedef int MPI_Datatype; + int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */) + __attribute__(( pointer_with_type_tag(mpi,1,3) )); + // The function's 3rd argument will be a type tag; this type tag will + // determine the expected pointee type of the function's 1st argument. + + +type_tag_for_datatype +--------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``type_tag_for_datatype``","``clang::type_tag_for_datatype``","``clang::type_tag_for_datatype``","","","","" + +When declaring a variable, use +``__attribute__((type_tag_for_datatype(kind, type)))`` to create a type tag that +is tied to the ``type`` argument given to the attribute. + +In the attribute prototype above: + * ``kind`` is an identifier that should be used when annotating all applicable + type tags. + * ``type`` indicates the name of the type. + +Clang supports annotating type tags of two forms. + + * **Type tag that is a reference to a declared identifier.** + Use ``__attribute__((type_tag_for_datatype(kind, type)))`` when declaring that + identifier: + + .. code-block:: c++ + + typedef int MPI_Datatype; + extern struct mpi_datatype mpi_datatype_int + __attribute__(( type_tag_for_datatype(mpi,int) )); + #define MPI_INT ((MPI_Datatype) &mpi_datatype_int) + // &mpi_datatype_int is a type tag. It is tied to type "int". + + * **Type tag that is an integral literal.** + Declare a ``static const`` variable with an initializer value and attach + ``__attribute__((type_tag_for_datatype(kind, type)))`` on that declaration: + + .. code-block:: c++ + + typedef int MPI_Datatype; + static const MPI_Datatype mpi_datatype_int + __attribute__(( type_tag_for_datatype(mpi,int) )) = 42; + #define MPI_INT ((MPI_Datatype) 42) + // The number 42 is a type tag. It is tied to type "int". + + +The ``type_tag_for_datatype`` attribute also accepts an optional third argument +that determines how the type of the function argument specified by either +``arg_idx`` or ``ptr_idx`` is compared against the type associated with the type +tag. (Recall that for the ``argument_with_type_tag`` attribute, the type of the +function argument specified by ``arg_idx`` is compared against the type +associated with the type tag. Also recall that for the ``pointer_with_type_tag`` +attribute, the pointee type of the function argument specified by ``ptr_idx`` is +compared against the type associated with the type tag.) There are two supported +values for this optional third argument: + + * ``layout_compatible`` will cause types to be compared according to + layout-compatibility rules (In C++11 [class.mem] p 17, 18, see the + layout-compatibility rules for two standard-layout struct types and for two + standard-layout union types). This is useful when creating a type tag + associated with a struct or union type. For example: + + .. code-block:: c++ + + /* In mpi.h */ + typedef int MPI_Datatype; + struct internal_mpi_double_int { double d; int i; }; + extern struct mpi_datatype mpi_datatype_double_int + __attribute__(( type_tag_for_datatype(mpi, + struct internal_mpi_double_int, layout_compatible) )); + + #define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int) + + int MPI_Send(void *buf, int count, MPI_Datatype datatype, ...) + __attribute__(( pointer_with_type_tag(mpi,1,3) )); + + /* In user code */ + struct my_pair { double a; int b; }; + struct my_pair *buffer; + MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ... */); // no warning because the + // layout of my_pair is + // compatible with that of + // internal_mpi_double_int + + struct my_int_pair { int a; int b; } + struct my_int_pair *buffer2; + MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ... */); // warning because the + // layout of my_int_pair + // does not match that of + // internal_mpi_double_int + + * ``must_be_null`` specifies that the function argument specified by either + ``arg_idx`` (for the ``argument_with_type_tag`` attribute) or ``ptr_idx`` (for + the ``pointer_with_type_tag`` attribute) should be a null pointer constant. + The second argument to the ``type_tag_for_datatype`` attribute is ignored. For + example: + + .. code-block:: c++ + + /* In mpi.h */ + typedef int MPI_Datatype; + extern struct mpi_datatype mpi_datatype_null + __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) )); + + #define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null) + int MPI_Send(void *buf, int count, MPI_Datatype datatype, ...) + __attribute__(( pointer_with_type_tag(mpi,1,3) )); + + /* In user code */ + struct my_pair { double a; int b; }; + struct my_pair *buffer; + MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ... */); // warning: MPI_DATATYPE_NULL + // was specified but buffer + // is not a null pointer + + +Nullability Attributes +====================== +Whether a particular pointer may be "null" is an important concern when working with pointers in the C family of languages. The various nullability attributes indicate whether a particular pointer can be null or not, which makes APIs more expressive and can help static analysis tools identify bugs involving null pointers. Clang supports several kinds of nullability attributes: the ``nonnull`` and ``returns_nonnull`` attributes indicate which function or method parameters and result types can never be null, while nullability type qualifiers indicate which pointer types can be null (``_Nullable``) or cannot be null (``_Nonnull``). + +The nullability (type) qualifiers express whether a value of a given pointer type can be null (the ``_Nullable`` qualifier), doesn't have a defined meaning for null (the ``_Nonnull`` qualifier), or for which the purpose of null is unclear (the ``_Null_unspecified`` qualifier). Because nullability qualifiers are expressed within the type system, they are more general than the ``nonnull`` and ``returns_nonnull`` attributes, allowing one to express (for example) a nullable pointer to an array of nonnull pointers. Nullability qualifiers are written to the right of the pointer to which they apply. For example: + + .. code-block:: c + + // No meaningful result when 'ptr' is null (here, it happens to be undefined behavior). + int fetch(int * _Nonnull ptr) { return *ptr; } + + // 'ptr' may be null. + int fetch_or_zero(int * _Nullable ptr) { + return ptr ? *ptr : 0; + } + + // A nullable pointer to non-null pointers to const characters. + const char *join_strings(const char * _Nonnull * _Nullable strings, unsigned n); + +In Objective-C, there is an alternate spelling for the nullability qualifiers that can be used in Objective-C methods and properties using context-sensitive, non-underscored keywords. For example: + + .. code-block:: objective-c + + @interface NSView : NSResponder + - (nullable NSView *)ancestorSharedWithView:(nonnull NSView *)aView; + @property (assign, nullable) NSView *superview; + @property (readonly, nonnull) NSArray *subviews; + @end + +_Nonnull +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``_Nonnull``","","" + +The ``_Nonnull`` nullability qualifier indicates that null is not a meaningful value for a value of the ``_Nonnull`` pointer type. For example, given a declaration such as: + + .. code-block:: c + + int fetch(int * _Nonnull ptr); + +a caller of ``fetch`` should not provide a null value, and the compiler will produce a warning if it sees a literal null value passed to ``fetch``. Note that, unlike the declaration attribute ``nonnull``, the presence of ``_Nonnull`` does not imply that passing null is undefined behavior: ``fetch`` is free to consider null undefined behavior or (perhaps for backward-compatibility reasons) defensively handle null. + + +_Null_unspecified +----------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``_Null_unspecified``","","" + +The ``_Null_unspecified`` nullability qualifier indicates that neither the ``_Nonnull`` nor ``_Nullable`` qualifiers make sense for a particular pointer type. It is used primarily to indicate that the role of null with specific pointers in a nullability-annotated header is unclear, e.g., due to overly-complex implementations or historical factors with a long-lived API. + + +_Nullable +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``_Nullable``","","" + +The ``_Nullable`` nullability qualifier indicates that a value of the ``_Nullable`` pointer type can be null. For example, given: + + .. code-block:: c + + int fetch_or_zero(int * _Nullable ptr); + +a caller of ``fetch_or_zero`` can provide null. + + +nonnull +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``nonnull``","``gnu::nonnull``","","","","","" + +The ``nonnull`` attribute indicates that some function parameters must not be null, and can be used in several different ways. It's original usage (`from GCC `_) is as a function (or Objective-C method) attribute that specifies which parameters of the function are nonnull in a comma-separated list. For example: + + .. code-block:: c + + extern void * my_memcpy (void *dest, const void *src, size_t len) + __attribute__((nonnull (1, 2))); + +Here, the ``nonnull`` attribute indicates that parameters 1 and 2 +cannot have a null value. Omitting the parenthesized list of parameter indices means that all parameters of pointer type cannot be null: + + .. code-block:: c + + extern void * my_memcpy (void *dest, const void *src, size_t len) + __attribute__((nonnull)); + +Clang also allows the ``nonnull`` attribute to be placed directly on a function (or Objective-C method) parameter, eliminating the need to specify the parameter index ahead of type. For example: + + .. code-block:: c + + extern void * my_memcpy (void *dest __attribute__((nonnull)), + const void *src __attribute__((nonnull)), size_t len); + +Note that the ``nonnull`` attribute indicates that passing null to a non-null parameter is undefined behavior, which the optimizer may take advantage of to, e.g., remove null checks. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable. + + +returns_nonnull +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``returns_nonnull``","``gnu::returns_nonnull``","","","","","Yes" + +The ``returns_nonnull`` attribute indicates that a particular function (or Objective-C method) always returns a non-null pointer. For example, a particular system ``malloc`` might be defined to terminate a process when memory is not available rather than returning a null pointer: + + .. code-block:: c + + extern void * malloc (size_t size) __attribute__((returns_nonnull)); + +The ``returns_nonnull`` attribute implies that returning a null pointer is undefined behavior, which the optimizer may take advantage of. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable + + diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst index e852c3e387985..3dafac54a02bd 100644 --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -198,6 +198,10 @@ Filename (or -) to write dependency output to Emit Clang AST files for source inputs +.. option:: -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang + +Trivial automatic variable initialization to zero is only here for benchmarks, it'll eventually be removed, and I'm OK with that because I'm only using it to benchmark + .. option:: -exported\_symbols\_list .. option:: -faligned-new= @@ -210,10 +214,6 @@ Use approximate transcendental functions Flush denormal floating point values to zero in CUDA device mode. -.. option:: -fcuda-rdc, -fno-cuda-rdc - -Generate relocatable device code, also known as separate compilation mode. - .. option:: -fcuda-short-ptr, -fno-cuda-short-ptr Use 32-bit pointers for accessing const/local/shared address spaces. @@ -222,6 +222,10 @@ Use 32-bit pointers for accessing const/local/shared address spaces. Reserve register r19 (Hexagon only) +.. option:: -fgpu-rdc, -fcuda-rdc, -fno-gpu-rdc + +Generate relocatable device code, also known as separate compilation mode. + .. option:: -fheinous-gnu-extensions .. option:: -flat\_namespace @@ -254,6 +258,10 @@ Use the gcc toolchain at the given directory Generate CodeView debug information +.. option:: -gcodeview-ghash, -gno-codeview-ghash + +Emit type record hashes in a .debug$H section + .. option:: -headerpad\_max\_install\_names .. option:: -help, --help @@ -288,6 +296,10 @@ Make the next included directory (-I or -F) an indexer header map .. option:: -mbig-endian, -EB +.. option:: -mbranch-protection= + +Enforce targets of indirect branches and function returns + .. option:: --migrate Run the migrator @@ -792,15 +804,7 @@ Don't use blacklist file for sanitizers .. option:: -fparse-all-comments -.. option:: -frecord-command-line, -frecord-gcc-switches, -fno-record-command-line, -fno-record-gcc-switches - -Generate a section named ".GCC.command.line" containing the clang driver -command-line. After linking, the section may contain multiple command lines, -which will be individually terminated by null bytes. Separate arguments within -a command line are combined with spaces; spaces and backslashes within an -argument are escaped with backslashes. This format differs from the format of -the equivalent section produced by GCC with the -frecord-gcc-switches flag. -This option is currently only supported on ELF targets. +.. option:: -frecord-command-line, -fno-record-command-line, -frecord-gcc-switches .. option:: -fsanitize-address-field-padding= @@ -810,20 +814,18 @@ Level of field padding for AddressSanitizer Enable linker dead stripping of globals in AddressSanitizer -.. option:: -fsanitize-address-use-odr-indicator, -fno-sanitize-address-use-odr-indicator - -Enable ODR indicator globals to avoid false ODR violation reports in partially sanitized programs at the cost of an increase in binary size - .. option:: -fsanitize-address-poison-custom-array-cookie, -fno-sanitize-address-poison-custom-array-cookie -Enable "poisoning" array cookies when allocating arrays with a custom operator new\[\] in Address Sanitizer, preventing accesses to the cookies from user code. An array cookie is a small implementation-defined header added to certain array allocations to record metadata such as the length of the array. Accesses to array cookies from user code are technically allowed by the standard but are more likely to be the result of an out-of-bounds array access. - -An operator new\[\] is "custom" if it is not one of the allocation functions provided by the C++ standard library. Array cookies from non-custom allocation functions are always poisoned. +Enable poisoning array cookies when using custom operator new\[\] in AddressSanitizer .. option:: -fsanitize-address-use-after-scope, -fno-sanitize-address-use-after-scope Enable use-after-scope detection in AddressSanitizer +.. option:: -fsanitize-address-use-odr-indicator, -fno-sanitize-address-use-odr-indicator + +Enable ODR indicator globals to avoid false ODR violation reports in partially sanitized programs at the cost of an increase in binary size + .. option:: -fsanitize-blacklist= Path to blacklist file for sanitizers @@ -840,6 +842,10 @@ Generalize pointers in CFI indirect call type signature checks Specify the type of coverage instrumentation for Sanitizers +.. option:: -fsanitize-hwaddress-abi= + +Select the HWAddressSanitizer ABI to target (interceptor or platform, default interceptor) + .. option:: -fsanitize-link-c++-runtime .. option:: -fsanitize-memory-track-origins, -fno-sanitize-memory-track-origins @@ -1072,6 +1078,10 @@ Set directory to include search path with prefix Add directory to SYSTEM include search path, absolute paths are relative to -isysroot +.. option:: --libomptarget-nvptx-path= + +Path to libomptarget-nvptx libraries + .. option:: --ptxas-path= Path to ptxas (used for compiling CUDA code) @@ -1283,6 +1293,8 @@ Enable C++ static destructor registration (the default) Instrument control-flow architecture protection. Options: return, branch, full, none. +.. option:: -fcf-runtime-abi= + .. option:: -fchar8\_t, -fno-char8\_t Enable C++ builtin type char8\_t @@ -1343,6 +1355,10 @@ Emit macro debug information remap file source paths in debug info +.. option:: -fdebug-ranges-base-address, -fno-debug-ranges-base-address + +Use DWARF base address selection entries in debug\_ranges + .. option:: -fdebug-types-section, -fno-debug-types-section Place debug types in their own section (ELF Only) @@ -1651,6 +1667,8 @@ Synthesize retain and release calls for Objective-C pointers Use EH-safe code when synthesizing retains and releases in -fobjc-arc +.. option:: -fobjc-convert-messages-to-runtime-calls, -fno-objc-convert-messages-to-runtime-calls + .. option:: -fobjc-exceptions, -fno-objc-exceptions Enable Objective-C exceptions @@ -1737,6 +1755,14 @@ Load the named plugin (dynamic shared object) .. option:: -fprofile-dir= +.. option:: -fprofile-exclude-files= + +Instrument only functions from files where names don't match all the regexes separated by a semi-colon + +.. option:: -fprofile-filter-files= + +Instrument only functions from files where names match any regex separated by a semi-colon + .. option:: -fprofile-generate, -fno-profile-generate Generate instrumented code to collect execution counts into default.profraw (overridden by LLVM\_PROFILE\_FILE env var) @@ -1765,6 +1791,10 @@ Generate instrumented code to collect execution counts into (overridden b Use instrumentation data for profile-guided optimization +.. option:: -fprofile-remapping-file=, -fprofile-remapping-file + +Use the remappings described in to match the profile data against names in the program + .. option:: -fprofile-sample-accurate, -fauto-profile-accurate, -fno-profile-sample-accurate Specifies that the sample profile is accurate. If the sample @@ -1876,19 +1906,23 @@ Enable the superword-level parallelism vectorization passes Provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF +.. option:: -fsplit-lto-unit, -fno-split-lto-unit + +Enables splitting of the LTO unit. + .. option:: -fsplit-stack .. option:: -fstack-protector, -fno-stack-protector -Enable stack protectors for functions potentially vulnerable to stack smashing +Enable stack protectors for some functions vulnerable to stack smashing. This uses a loose heuristic which considers functions vulnerable if they contain a char (or 8bit integer) array or constant sized calls to alloca, which are of greater size than ssp-buffer-size (default: 8 bytes). All variable sized calls to alloca are considered vulnerable .. option:: -fstack-protector-all -Force the usage of stack protectors for all functions +Enable stack protectors for all functions .. option:: -fstack-protector-strong -Use a strong heuristic to apply stack protectors to functions +Enable stack protectors for some functions vulnerable to stack smashing. Compared to -fstack-protector, this uses a stronger heuristic that includes functions containing arrays of any size (and any type), as well as any calls to alloca or the taking of an address from a local variable .. option:: -fstack-size-section, -fno-stack-size-section @@ -1962,6 +1996,10 @@ Specify the function to be called on overflow Process trigraph sequences +.. option:: -ftrivial-auto-var-init= + +Initialize trivial automatic stack variables: uninitialized (default) \| pattern + .. option:: -funique-section-names, -fno-unique-section-names Use unique names for text and data sections (ELF Only) @@ -2000,6 +2038,10 @@ Enable the loop vectorization passes .. option:: -fverbose-asm, -fno-verbose-asm +.. option:: -fvisibility-global-new-delete-hidden + +Give global C++ operator new and delete declarations hidden visibility + .. option:: -fvisibility-inlines-hidden Give inline C++ member functions hidden visibility by default @@ -2162,7 +2204,7 @@ Link stack frames through backchain on System Z .. option:: -mconsole -.. option:: -mcpu=, -mv5 (equivalent to -mcpu=hexagonv5), -mv55 (equivalent to -mcpu=hexagonv55), -mv60 (equivalent to -mcpu=hexagonv60), -mv62 (equivalent to -mcpu=hexagonv62), -mv65 (equivalent to -mcpu=hexagonv65) +.. option:: -mcpu=, -mv5 (equivalent to -mcpu=hexagonv5), -mv55 (equivalent to -mcpu=hexagonv55), -mv60 (equivalent to -mcpu=hexagonv60), -mv62 (equivalent to -mcpu=hexagonv62), -mv65 (equivalent to -mcpu=hexagonv65), -mv66 (equivalent to -mcpu=hexagonv66) .. option:: -mcrc, -mno-crc @@ -2196,6 +2238,8 @@ Enable merging of globals .. option:: -mhwdiv=, --mhwdiv , --mhwdiv= +.. option:: -mhwmult= + .. option:: -miamcu, -mno-iamcu Use Intel MCU ABI @@ -2272,6 +2316,8 @@ Select return address signing scope Use software floating point +.. option:: -mspeculative-load-hardening, -mno-speculative-load-hardening + .. option:: -mstack-alignment= Set the stack alignment @@ -2296,6 +2342,10 @@ The thread model to use, e.g. posix, single (posix by default) .. option:: -mthumb, -mno-thumb +.. option:: -mtls-direct-seg-refs, -mno-tls-direct-seg-refs + +Enable direct TLS access through segment registers (default) + .. option:: -mtune= .. option:: -mtvos-version-min=, -mappletvos-version-min= @@ -2314,41 +2364,33 @@ The thread model to use, e.g. posix, single (posix by default) AARCH64 ------- -.. option:: -ffixed-x1 - -Reserve the x1 register (AArch64 only) - -.. option:: -ffixed-x2 - -Reserve the x2 register (AArch64 only) - -.. option:: -ffixed-x3 +.. option:: -fcall-saved-x10 -Reserve the x3 register (AArch64 only) +Make the x10 register call-saved (AArch64 only) -.. option:: -ffixed-x4 +.. option:: -fcall-saved-x11 -Reserve the x4 register (AArch64 only) +Make the x11 register call-saved (AArch64 only) -.. option:: -ffixed-x5 +.. option:: -fcall-saved-x12 -Reserve the x5 register (AArch64 only) +Make the x12 register call-saved (AArch64 only) -.. option:: -ffixed-x6 +.. option:: -fcall-saved-x13 -Reserve the x6 register (AArch64 only) +Make the x13 register call-saved (AArch64 only) -.. option:: -ffixed-x7 +.. option:: -fcall-saved-x14 -Reserve the x7 register (AArch64 only) +Make the x14 register call-saved (AArch64 only) -.. option:: -ffixed-x18 +.. option:: -fcall-saved-x15 -Reserve the x18 register (AArch64 only) +Make the x15 register call-saved (AArch64 only) -.. option:: -ffixed-x20 +.. option:: -fcall-saved-x18 -Reserve the x20 register (AArch64 only) +Make the x18 register call-saved (AArch64 only) .. option:: -fcall-saved-x8 @@ -2358,33 +2400,41 @@ Make the x8 register call-saved (AArch64 only) Make the x9 register call-saved (AArch64 only) -.. option:: -fcall-saved-x10 +.. option:: -ffixed-x1 -Make the x10 register call-saved (AArch64 only) +Reserve the 1 register (AArch64 only) -.. option:: -fcall-saved-x11 +.. option:: -ffixed-x18 -Make the x11 register call-saved (AArch64 only) +Reserve the 18 register (AArch64 only) -.. option:: -fcall-saved-x12 +.. option:: -ffixed-x2 -Make the x12 register call-saved (AArch64 only) +Reserve the 2 register (AArch64 only) -.. option:: -fcall-saved-x13 +.. option:: -ffixed-x20 -Make the x13 register call-saved (AArch64 only) +Reserve the 20 register (AArch64 only) -.. option:: -fcall-saved-x14 +.. option:: -ffixed-x3 -Make the x14 register call-saved (AArch64 only) +Reserve the 3 register (AArch64 only) -.. option:: -fcall-saved-x15 +.. option:: -ffixed-x4 -Make the x15 register call-saved (AArch64 only) +Reserve the 4 register (AArch64 only) -.. option:: -fcall-saved-x18 +.. option:: -ffixed-x5 -Make the x18 register call-saved (AArch64 only) +Reserve the 5 register (AArch64 only) + +.. option:: -ffixed-x6 + +Reserve the 6 register (AArch64 only) + +.. option:: -ffixed-x7 + +Reserve the 7 register (AArch64 only) .. option:: -mfix-cortex-a53-835769, -mno-fix-cortex-a53-835769 @@ -2396,6 +2446,14 @@ Generate code which only uses the general purpose registers (AArch64 only) AMDGPU ------ +.. option:: -mcode-object-v3, -mno-code-object-v3 + +Enable code object v3 (AMDGPU only) + +.. option:: -msram-ecc, -mno-sram-ecc + +Enable SRAM ECC (AMDGPU only) + .. option:: -mxnack, -mno-xnack Enable XNACK (AMDGPU only) @@ -2594,6 +2652,8 @@ WebAssembly .. option:: -msimd128, -mno-simd128 +.. option:: -munimplemented-simd128, -mno-unimplemented-simd128 + X86 --- .. option:: -m3dnow, -mno-3dnow @@ -2811,6 +2871,10 @@ ___________ .. option:: -ggdb3 +.. option:: -gline-directives-only + +Emit debug line info directives only + .. option:: -gline-tables-only, -g1, -gmlt Emit debug line number tables only @@ -2841,10 +2905,16 @@ Embed source text in DWARF debug sections .. option:: -gpubnames, -gno-pubnames -.. option:: -grecord-command-line, -grecord-gcc-switches, -gno-record-command-line, -gno-record-gcc-switches +.. option:: -grecord-command-line, -gno-record-command-line, -grecord-gcc-switches .. option:: -gsplit-dwarf +.. program:: clang1 +.. option:: -gsplit-dwarf= +.. program:: clang + +Set DWARF fission mode to either 'split' or 'single' + .. option:: -gstrict-dwarf, -gno-strict-dwarf .. option:: -gz diff --git a/clang/docs/DiagnosticsReference.rst b/clang/docs/DiagnosticsReference.rst index 7d9b1e8359a8d..ef0218e8b49e4 100644 --- a/clang/docs/DiagnosticsReference.rst +++ b/clang/docs/DiagnosticsReference.rst @@ -207,17 +207,6 @@ This diagnostic is enabled by default. Controls `-Wpointer-bool-conversion`_, `-Wstring-compare`_, `-Wtautological-pointer-compare`_. --Waddress-of-array-temporary ----------------------------- -This diagnostic is enabled by default. - -**Diagnostic text:** - -+---------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`pointer is initialized by a temporary array, which will be destroyed at the end of the full-expression`| -+---------------------------------------------------------------------------------------------------------------------------------------------+ - - -Waddress-of-packed-member -------------------------- This diagnostic is enabled by default. @@ -244,21 +233,6 @@ This diagnostic is an error by default, but the flag ``-Wno-address-of-temporary ------------------ This diagnostic flag exists for GCC compatibility, and has no effect in Clang. --Waligned-allocation-unavailable --------------------------------- -This diagnostic is an error by default, but the flag ``-Wno-aligned-allocation-unavailable`` can be used to disable the error. - -**Diagnostic text:** - -+--------------------------------------------------+--------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:error:`error:` |nbsp| :diagtext:`aligned` |nbsp| |+------------------------+| |nbsp| :diagtext:`function of type '`:placeholder:`B`:diagtext:`' is only available on` |nbsp| :placeholder:`C` |nbsp| :placeholder:`D` |nbsp| :diagtext:`or newer`| -| ||:diagtext:`allocation` || | -| |+------------------------+| | -| ||:diagtext:`deallocation`|| | -| |+------------------------+| | -+--------------------------------------------------+--------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - - -Wall ----- Some of the diagnostics controlled by this flag are enabled by default. @@ -473,6 +447,17 @@ This diagnostic is enabled by default. +-----------------------------------------------------------------------------------------------------------------------------+ +-Wargument-outside-range +------------------------ +This diagnostic is an error by default, but the flag ``-Wno-argument-outside-range`` can be used to disable the error. + +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:error:`error:` |nbsp| :diagtext:`argument value` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is outside the valid range \[`:placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`\]`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Warray-bounds -------------- This diagnostic is enabled by default. @@ -572,13 +557,41 @@ This diagnostic is enabled by default. -Wat-protocol ------------- +This diagnostic flag exists for GCC compatibility, and has no effect in Clang. + +-Watimport-in-framework-header +------------------------------ This diagnostic is enabled by default. **Diagnostic text:** -+-------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`@protocol is using a forward protocol declaration of` |nbsp| :placeholder:`A`| -+-------------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`use of '@import' in framework header is discouraged, including this header requires -fmodules`| ++------------------------------------------------------------------------------------------------------------------------------------+ + + +-Watomic-alignment +------------------ +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------+------------------------+------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+----------------------+| |nbsp| :diagtext:`atomic operation may incur significant performance penalty`| +| ||:diagtext:`large` || | +| |+----------------------+| | +| ||:diagtext:`misaligned`|| | +| |+----------------------+| | ++---------------------------+------------------------+------------------------------------------------------------------------------+ + + +-Watomic-implicit-seq-cst +------------------------- +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary`| ++---------------------------------------------------------------------------------------------------------------------------------------+ -Watomic-memory-ordering @@ -690,6 +703,20 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`'unavailable' availability overrides all other availability information`| +--------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------+----------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ignoring availability attribute` |nbsp| |+--------------------------------------+| +| ||:diagtext:`on '+load' method` || +| |+--------------------------------------+| +| ||:diagtext:`with constructor attribute`|| +| |+--------------------------------------+| +| ||:diagtext:`with destructor attribute` || +| |+--------------------------------------+| ++------------------------------------------------------------------------------+----------------------------------------+ + ++---------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`only 'unavailable' and 'deprecated' are supported for Swift availability`| ++---------------------------------------------------------------------------------------------------------------+ + +------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`unknown platform` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in availability macro`| +------------------------------------------------------------------------------------------------------------------------+ @@ -779,31 +806,44 @@ Also controls `-Wc++98-compat-bind-to-temporary-copy`_. | |+---------------------+| +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+ -+--------------------------------------------------------------------+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`no viable constructor` |nbsp| |+---------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`B`:diagtext:`; C++98 requires a copy constructor when binding a reference to a temporary`| -| ||:diagtext:`copying variable` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying parameter` || | -| |+---------------------------------------+| | -| ||:diagtext:`returning object` || | -| |+---------------------------------------+| | -| ||:diagtext:`throwing object` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying member subobject` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying array element` || | -| |+---------------------------------------+| | -| ||:diagtext:`allocating object` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying temporary` || | -| |+---------------------------------------+| | -| ||:diagtext:`initializing base subobject`|| | -| |+---------------------------------------+| | -| ||:diagtext:`initializing vector element`|| | -| |+---------------------------------------+| | -| ||:diagtext:`capturing value` || | -| |+---------------------------------------+| | -+--------------------------------------------------------------------+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------+------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`no viable constructor` |nbsp| |+----------------------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`B`:diagtext:`; C++98 requires a copy constructor when binding a reference to a temporary`| +| ||:diagtext:`copying variable` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying parameter` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`returning object` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`initializing statement expression result`|| | +| |+----------------------------------------------------+| | +| ||:diagtext:`throwing object` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying member subobject` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying array element` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`allocating object` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying temporary` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`initializing base subobject` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`initializing vector element` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`capturing value` || | +| |+----------------------------------------------------+| | ++--------------------------------------------------------------------+------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ + + +-Wbinding-in-condition +---------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++--------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ISO C++17 does not permit structured binding declaration in a condition`| ++--------------------------------------------------------------------------------------------------------------+ -Wbitfield-constant-conversion @@ -944,9 +984,9 @@ This diagnostic is enabled by default. **Diagnostic text:** -+------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`will always overflow destination buffer`| -+------------------------------------------------------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' will always overflow; destination buffer has size` |nbsp| :placeholder:`B`:diagtext:`, but size argument is` |nbsp| :placeholder:`C`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -Wbuiltin-requires-header @@ -1180,28 +1220,6 @@ Also controls `-Wc++11-extra-semi`_, `-Wc++11-inline-namespace`_, `-Wc++11-long- |:warning:`warning:` |nbsp| :diagtext:`default template arguments for a function template are a C++11 extension`| +---------------------------------------------------------------------------------------------------------------+ -+-------------------------------------------------------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`first declaration of` |nbsp| |+-------------------------------------+| |nbsp| :diagtext:`specialization of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`outside namespace` |nbsp| :placeholder:`C` |nbsp| :diagtext:`is a C++11 extension`| -| ||:diagtext:`class template` || | -| |+-------------------------------------+| | -| ||:diagtext:`class template partial` || | -| |+-------------------------------------+| | -| ||:diagtext:`variable template` || | -| |+-------------------------------------+| | -| ||:diagtext:`variable template partial`|| | -| |+-------------------------------------+| | -| ||:diagtext:`function template` || | -| |+-------------------------------------+| | -| ||:diagtext:`member function` || | -| |+-------------------------------------+| | -| ||:diagtext:`static data member` || | -| |+-------------------------------------+| | -| ||:diagtext:`member class` || | -| |+-------------------------------------+| | -| ||:diagtext:`member enumeration` || | -| |+-------------------------------------+| | -+-------------------------------------------------------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - +------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`'typename' occurs outside of a template`| +------------------------------------------------------------------------------+ @@ -1402,6 +1420,10 @@ Some of the diagnostics controlled by this flag are enabled by default. **Diagnostic text:** ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ISO C++ standards before C++17 do not allow new expression for type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to use list-initialization`| ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`constexpr if is a C++17 extension`| +------------------------------------------------------------------------+ @@ -1501,8 +1523,22 @@ Synonym for `-Wc++17-extensions`_. -Wc++2a-compat -------------- +Some of the diagnostics controlled by this flag are enabled by default. + **Diagnostic text:** ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`aggregate initialization of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`with user-declared constructors is incompatible with C++2a`| ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'<=>' is a single token in C++2a; add a space to avoid a change in behavior`| ++------------------------------------------------------------------------------------------------------------------+ + ++--------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`type of UTF-8 string literal will change from array of const char to array of const char8\_t in C++2a`| ++--------------------------------------------------------------------------------------------------------------------------------------------+ + +-------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' is a keyword in C++2a`| +-------------------------------------------------------------------------------------------+ @@ -1523,10 +1559,34 @@ Some of the diagnostics controlled by this flag are enabled by default. |:warning:`warning:` |nbsp| :diagtext:`default member initializer for bit-field is a C++2a extension`| +----------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------+-------------------------+----------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`use of this statement in a constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is a C++2a extension`| +| ||:diagtext:`function` || | +| |+-----------------------+| | +| ||:diagtext:`constructor`|| | +| |+-----------------------+| | ++-----------------------------------------------------------------------------------+-------------------------+----------------------------------------+ + ++------------------------------------------------------------------------------+-------------------------+----------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`function try block in constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is a C++2a extension`| +| ||:diagtext:`function` || | +| |+-----------------------+| | +| ||:diagtext:`constructor`|| | +| |+-----------------------+| | ++------------------------------------------------------------------------------+-------------------------+----------------------------------------+ + +--------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`explicit capture of 'this' with a capture default of '=' is a C++2a extension`| +--------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`range-based for loop initialization statements are a C++2a extension`| ++-----------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`inline nested namespace definition is a C++2a extension`| ++----------------------------------------------------------------------------------------------+ + +--------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`invoking a pointer to a 'const &' member function on an rvalue is a C++2a extension`| +--------------------------------------------------------------------------------------------------------------------------+ @@ -1540,10 +1600,66 @@ Some of the diagnostics controlled by this flag are enabled by default. |:warning:`warning:` |nbsp| :diagtext:`default member initializer for bit-field is incompatible with C++ standards before C++2a`| +-------------------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------+-------------------------+-------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`use of this statement in a constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is incompatible with C++ standards before C++2a`| +| ||:diagtext:`function` || | +| |+-----------------------+| | +| ||:diagtext:`constructor`|| | +| |+-----------------------+| | ++-----------------------------------------------------------------------------------+-------------------------+-------------------------------------------------------------------+ + ++------------------------------------------------------------------------------+-------------------------+-------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`function try block in constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is incompatible with C++ standards before C++2a`| +| ||:diagtext:`function` || | +| |+-----------------------+| | +| ||:diagtext:`constructor`|| | +| |+-----------------------+| | ++------------------------------------------------------------------------------+-------------------------+-------------------------------------------------------------------+ + ++-------------------------------------------------------------------------+--------------------------------------+----------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`explicitly defaulting this` |nbsp| |+------------------------------------+| |nbsp| :diagtext:`with a type different from the implicit type is incompatible with C++ standards before C++2a`| +| ||:diagtext:`default constructor` || | +| |+------------------------------------+| | +| ||:diagtext:`copy constructor` || | +| |+------------------------------------+| | +| ||:diagtext:`move constructor` || | +| |+------------------------------------+| | +| ||:diagtext:`copy assignment operator`|| | +| |+------------------------------------+| | +| ||:diagtext:`move assignment operator`|| | +| |+------------------------------------+| | +| ||:diagtext:`destructor` || | +| |+------------------------------------+| | ++-------------------------------------------------------------------------+--------------------------------------+----------------------------------------------------------------------------------------------------------------+ + +-----------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`explicit capture of 'this' with a capture default of '=' is incompatible with C++ standards before C++2a`| +-----------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`range-based for loop initialization statements are incompatible with C++ standards before C++2a`| ++--------------------------------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`inline nested namespace definition is incompatible with C++ standards before C++2a`| ++-------------------------------------------------------------------------------------------------------------------------+ + ++---------------------------+----------------------------------+-----------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+--------------------------------+| |nbsp| :diagtext:`of lambda is incompatible with C++ standards before C++2a`| +| ||:diagtext:`default construction`|| | +| |+--------------------------------+| | +| ||:diagtext:`assignment` || | +| |+--------------------------------+| | ++---------------------------+----------------------------------+-----------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'<=>' operator is incompatible with C++ standards before C++2a`| ++-----------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'char8\_t' type specifier is incompatible with C++ standards before C++20`| ++----------------------------------------------------------------------------------------------------------------+ + -Wc++98-c++11-c++14-c++17-compat-pedantic ----------------------------------------- @@ -1560,6 +1676,16 @@ Also controls `-Wc++98-c++11-c++14-c++17-compat`_. -------------------------- **Diagnostic text:** ++------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`class template argument deduction is incompatible with C++ standards before C++17`|+---------------------------------------------------------------------------------+| +| || || +| |+---------------------------------------------------------------------------------+| +| ||+-------------------------------------------------------------------------------+|| +| |||:diagtext:`; for compatibility, use explicit type name` |nbsp| :placeholder:`B`||| +| ||+-------------------------------------------------------------------------------+|| +| |+---------------------------------------------------------------------------------+| ++------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------+ + +---------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`constexpr if is incompatible with C++ standards before C++17`| +---------------------------------------------------------------------------------------------------+ @@ -1688,10 +1814,18 @@ Also controls `-Wc++98-c++11-c++14-compat`_. |:warning:`warning:` |nbsp| :diagtext:`'decltype(auto)' type specifier is incompatible with C++ standards before C++14`| +----------------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`return type deduction is incompatible with C++ standards before C++14`| ++------------------------------------------------------------------------------------------------------------+ + +--------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`digit separators are incompatible with C++ standards before C++14`| +--------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`generic lambdas are incompatible with C++11`| ++----------------------------------------------------------------------------------+ + +-------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`initialized lambda captures are incompatible with C++ standards before C++14`| +-------------------------------------------------------------------------------------------------------------------+ @@ -1855,7 +1989,7 @@ Also controls `-Wc++98-c++11-c++14-c++17-compat`_, `-Wc++98-c++11-c++14-compat`_ +---------------------------+------------------------------+------------------------------------------------------------------------------------------------+--------------------------------------+----------------------------------------------+ |:warning:`warning:` |nbsp| |+----------------------------+| |nbsp| :diagtext:`member` |nbsp| :placeholder:`B` |nbsp| :diagtext:`with a non-trivial` |nbsp| |+------------------------------------+| |nbsp| :diagtext:`is incompatible with C++98`| -| ||:diagtext:`anonymous struct`|| ||:diagtext:`constructor` || | +| ||:diagtext:`anonymous struct`|| ||:diagtext:`default constructor` || | | |+----------------------------+| |+------------------------------------+| | | ||:diagtext:`union` || ||:diagtext:`copy constructor` || | | |+----------------------------+| |+------------------------------------+| | @@ -1949,28 +2083,6 @@ Also controls `-Wc++98-c++11-c++14-c++17-compat`_, `-Wc++98-c++11-c++14-compat`_ |:warning:`warning:` |nbsp| :diagtext:`default template arguments for a function template are incompatible with C++98`| +---------------------------------------------------------------------------------------------------------------------+ -+---------------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------------------------+| |nbsp| :diagtext:`specialization of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`outside namespace` |nbsp| :placeholder:`C` |nbsp| :diagtext:`is incompatible with C++98`| -| ||:diagtext:`class template` || | -| |+-------------------------------------+| | -| ||:diagtext:`class template partial` || | -| |+-------------------------------------+| | -| ||:diagtext:`variable template` || | -| |+-------------------------------------+| | -| ||:diagtext:`variable template partial`|| | -| |+-------------------------------------+| | -| ||:diagtext:`function template` || | -| |+-------------------------------------+| | -| ||:diagtext:`member function` || | -| |+-------------------------------------+| | -| ||:diagtext:`static data member` || | -| |+-------------------------------------+| | -| ||:diagtext:`member class` || | -| |+-------------------------------------+| | -| ||:diagtext:`member enumeration` || | -| |+-------------------------------------+| | -+---------------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - +----------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`trailing return types are incompatible with C++98`| +----------------------------------------------------------------------------------------+ @@ -2022,29 +2134,42 @@ Also controls `-Wc++98-c++11-c++14-c++17-compat`_, `-Wc++98-c++11-c++14-compat`_ ------------------------------------- **Diagnostic text:** -+---------------------------+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+----------------------------+ -|:warning:`warning:` |nbsp| |+---------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`C` |nbsp| :diagtext:`when binding a reference to a temporary would` |nbsp| |+----------------------------------------------+| |nbsp| :diagtext:`in C++98`| -| ||:diagtext:`copying variable` || ||:diagtext:`invoke an inaccessible constructor`|| | -| |+---------------------------------------+| |+----------------------------------------------+| | -| ||:diagtext:`copying parameter` || ||:diagtext:`find no viable constructor` || | -| |+---------------------------------------+| |+----------------------------------------------+| | -| ||:diagtext:`returning object` || ||:diagtext:`find ambiguous constructors` || | -| |+---------------------------------------+| |+----------------------------------------------+| | -| ||:diagtext:`throwing object` || ||:diagtext:`invoke a deleted constructor` || | -| |+---------------------------------------+| |+----------------------------------------------+| | -| ||:diagtext:`copying member subobject` || | | | -| |+---------------------------------------+| | | | -| ||:diagtext:`copying array element` || | | | -| |+---------------------------------------+| | | | -| ||:diagtext:`allocating object` || | | | -| |+---------------------------------------+| | | | -| ||:diagtext:`copying temporary` || | | | -| |+---------------------------------------+| | | | -| ||:diagtext:`initializing base subobject`|| | | | -| |+---------------------------------------+| | | | -| ||:diagtext:`initializing vector element`|| | | | -| |+---------------------------------------+| | | | -+---------------------------+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+----------------------------+ ++---------------------------+------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+----------------------------+ +|:warning:`warning:` |nbsp| |+----------------------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`C` |nbsp| :diagtext:`when binding a reference to a temporary would` |nbsp| |+----------------------------------------------+| |nbsp| :diagtext:`in C++98`| +| ||:diagtext:`copying variable` || ||:diagtext:`invoke an inaccessible constructor`|| | +| |+----------------------------------------------------+| |+----------------------------------------------+| | +| ||:diagtext:`copying parameter` || ||:diagtext:`find no viable constructor` || | +| |+----------------------------------------------------+| |+----------------------------------------------+| | +| ||:diagtext:`returning object` || ||:diagtext:`find ambiguous constructors` || | +| |+----------------------------------------------------+| |+----------------------------------------------+| | +| ||:diagtext:`initializing statement expression result`|| ||:diagtext:`invoke a deleted constructor` || | +| |+----------------------------------------------------+| |+----------------------------------------------+| | +| ||:diagtext:`throwing object` || | | | +| |+----------------------------------------------------+| | | | +| ||:diagtext:`copying member subobject` || | | | +| |+----------------------------------------------------+| | | | +| ||:diagtext:`copying array element` || | | | +| |+----------------------------------------------------+| | | | +| ||:diagtext:`allocating object` || | | | +| |+----------------------------------------------------+| | | | +| ||:diagtext:`copying temporary` || | | | +| |+----------------------------------------------------+| | | | +| ||:diagtext:`initializing base subobject` || | | | +| |+----------------------------------------------------+| | | | +| ||:diagtext:`initializing vector element` || | | | +| |+----------------------------------------------------+| | | | +| ||:diagtext:`capturing value` || | | | +| |+----------------------------------------------------+| | | | ++---------------------------+------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+----------------------------+ + + +-Wc++98-compat-extra-semi +------------------------- +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`extra ';' outside of a function is incompatible with C++98`| ++-------------------------------------------------------------------------------------------------+ -Wc++98-compat-local-type-template-args @@ -2058,7 +2183,7 @@ Also controls `-Wc++98-c++11-c++14-c++17-compat`_, `-Wc++98-c++11-c++14-compat`_ -Wc++98-compat-pedantic ----------------------- -Also controls `-Wc++98-c++11-c++14-c++17-compat-pedantic`_, `-Wc++98-c++11-c++14-compat-pedantic`_, `-Wc++98-c++11-compat-pedantic`_, `-Wc++98-compat`_, `-Wc++98-compat-bind-to-temporary-copy`_. +Also controls `-Wc++98-c++11-c++14-c++17-compat-pedantic`_, `-Wc++98-c++11-c++14-compat-pedantic`_, `-Wc++98-c++11-compat-pedantic`_, `-Wc++98-compat`_, `-Wc++98-compat-bind-to-temporary-copy`_, `-Wc++98-compat-extra-semi`_. **Diagnostic text:** @@ -2098,10 +2223,6 @@ Also controls `-Wc++98-c++11-c++14-c++17-compat-pedantic`_, `-Wc++98-c++11-c++14 |:warning:`warning:` |nbsp| :diagtext:`#line number greater than 32767 is incompatible with C++98`| +-------------------------------------------------------------------------------------------------+ -+-------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`extra ';' outside of a function is incompatible with C++98`| -+-------------------------------------------------------------------------------------------------+ - +----------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`variadic macros are incompatible with C++98`| +----------------------------------------------------------------------------------+ @@ -2225,6 +2346,21 @@ Some of the diagnostics controlled by this flag are enabled by default. +---------------------------------------------------------------------------------------+ +-Wcall-to-pure-virtual-from-ctor-dtor +------------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`call to pure virtual member function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has undefined behavior; overrides of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in subclasses are not available in the` |nbsp| |+-----------------------+| |nbsp| :diagtext:`of` |nbsp| :placeholder:`C`| +| ||:diagtext:`constructor`|| | +| |+-----------------------+| | +| ||:diagtext:`destructor` || | +| |+-----------------------+| | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------+ + + -Wcast-align ------------ **Diagnostic text:** @@ -2275,6 +2411,29 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +-Wcast-qual-unrelated +--------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------------------------------------------------+-----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ISO C++ does not allow` |nbsp| |+---------------------------------+| |nbsp| :diagtext:`from` |nbsp| :placeholder:`B` |nbsp| :diagtext:`to` |nbsp| :placeholder:`C` |nbsp| :diagtext:`because it casts away qualifiers, even though the source and destination types are unrelated`| +| ||:diagtext:`const\_cast` || | +| |+---------------------------------+| | +| ||:diagtext:`static\_cast` || | +| |+---------------------------------+| | +| ||:diagtext:`reinterpret\_cast` || | +| |+---------------------------------+| | +| ||:diagtext:`dynamic\_cast` || | +| |+---------------------------------+| | +| ||:diagtext:`C-style cast` || | +| |+---------------------------------+| | +| ||:diagtext:`functional-style cast`|| | +| |+---------------------------------+| | ++---------------------------------------------------------------------+-----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wchar-align ------------ This diagnostic flag exists for GCC compatibility, and has no effect in Clang. @@ -2310,14 +2469,18 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`support for '/Yc' and '/Yu' with different filenames not implemented yet; flags ignored`| +------------------------------------------------------------------------------------------------------------------------------+ -+--------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`support for '`:placeholder:`A`:diagtext:`' without a filename not implemented yet; flag ignored`| -+--------------------------------------------------------------------------------------------------------------------------------------+ - +----------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`support for '`:placeholder:`A`:diagtext:`' without a corresponding /FI flag not implemented yet; flag ignored`| +----------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`#pragma hdrstop filename not supported, /Fp can be used to specify precompiled header filename`| ++-------------------------------------------------------------------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`definition of macro` |nbsp| :placeholder:`A` |nbsp| :diagtext:`does not match definition in precompiled header`| ++-----------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wclass-varargs --------------- @@ -2516,7 +2679,7 @@ This diagnostic is enabled by default. ------------ Some of the diagnostics controlled by this flag are enabled by default. -Also controls `-Wbitfield-enum-conversion`_, `-Wbool-conversion`_, `-Wconstant-conversion`_, `-Wenum-conversion`_, `-Wfloat-conversion`_, `-Wint-conversion`_, `-Wliteral-conversion`_, `-Wnon-literal-null-conversion`_, `-Wnull-conversion`_, `-Wobjc-literal-conversion`_, `-Wshorten-64-to-32`_, `-Wsign-conversion`_, `-Wstring-conversion`_. +Also controls `-Wbitfield-enum-conversion`_, `-Wbool-conversion`_, `-Wconstant-conversion`_, `-Wenum-conversion`_, `-Wfloat-conversion`_, `-Wimplicit-float-conversion`_, `-Wimplicit-int-conversion`_, `-Wint-conversion`_, `-Wliteral-conversion`_, `-Wnon-literal-null-conversion`_, `-Wnull-conversion`_, `-Wobjc-literal-conversion`_, `-Wshorten-64-to-32`_, `-Wsign-conversion`_, `-Wstring-conversion`_. **Diagnostic text:** @@ -2524,18 +2687,14 @@ Also controls `-Wbitfield-enum-conversion`_, `-Wbool-conversion`_, `-Wconstant-c |:warning:`warning:` |nbsp| :diagtext:`implicit conversion discards imaginary component:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| +--------------------------------------------------------------------------------------------------------------------------------------------------------------+ -+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`implicit conversion loses floating-point precision:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| -+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ - -+---------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`implicit conversion loses integer precision:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| -+---------------------------------------------------------------------------------------------------------------------------------------------------------+ - +--------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`implicit conversion turns vector to scalar:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| +--------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`passing non-generic address space pointer to` |nbsp| :placeholder:`A` |nbsp| :diagtext:`may cause dynamic conversion affecting performance`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`non-type template argument with value '`:placeholder:`A`:diagtext:`' converted to '`:placeholder:`B`:diagtext:`' for unsigned template parameter of type` |nbsp| :placeholder:`C`| +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -2597,6 +2756,17 @@ Synonym for `-W#warnings`_. ------------------- This diagnostic flag exists for GCC compatibility, and has no effect in Clang. +-Wctu +----- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`imported AST from '`:placeholder:`A`:diagtext:`' had been generated for a different target, current:` |nbsp| :placeholder:`B`:diagtext:`, imported:` |nbsp| :placeholder:`C`| ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wcuda-compat ------------- Some of the diagnostics controlled by this flag are enabled by default. @@ -2637,6 +2807,55 @@ Some of the diagnostics controlled by this flag are enabled by default. +---------------------------------------------------------------------------------------------------------------------------------------+--------------------+----------------------------------------------------------------------------+ +-Wdangling +---------- +This diagnostic is enabled by default. + +Also controls `-Wdangling-field`_, `-Wdangling-initializer-list`_, `-Wreturn-stack-address`_. + +**Diagnostic text:** + ++---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------+----------------------------+---------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| |nbsp| |+--------------------------+|:diagtext:`will be destroyed at the end of the full-expression`| +| ||+-----------------------------+---------------------------------------------------------+--------+------------------------------------------------------------------------+|| ||+------------------------+|| | +| |||:diagtext:`temporary` |nbsp| |+-------------------------------------------------------+| |nbsp| |+----------------------------------------------------------------------+||| |||:placeholder:`D` |nbsp| ||| | +| ||| ||:diagtext:`whose address is used as value of` || ||+-------------------------------+------------------------------------+|||| ||+------------------------+|| | +| ||| |+-------------------------------------------------------+| |||+-----------------------------+|:diagtext:`member of local variable`||||| |+--------------------------+| | +| ||| ||+--------------------------------+--------------------+|| |||| || ||||| || || | +| ||| |||+------------------------------+|:diagtext:`bound to`||| |||+-----------------------------+| ||||| |+--------------------------+| | +| ||| |||| || ||| ||||:diagtext:`reference` |nbsp| || ||||| | | | +| ||| |||+------------------------------+| ||| |||+-----------------------------+| ||||| | | | +| ||| ||||:diagtext:`implicitly` |nbsp| || ||| ||+-------------------------------+------------------------------------+|||| | | | +| ||| |||+------------------------------+| ||| |+----------------------------------------------------------------------+||| | | | +| ||| ||+--------------------------------+--------------------+|| ||+-------------------------+-----------------------+ |||| | | | +| ||| |+-------------------------------------------------------+| |||:diagtext:`local` |nbsp| |+---------------------+| |||| | | | +| ||| | | ||| ||:diagtext:`variable` || |||| | | | +| ||| | | ||| |+---------------------+| |||| | | | +| ||| | | ||| ||:diagtext:`reference`|| |||| | | | +| ||| | | ||| |+---------------------+| |||| | | | +| ||| | | ||+-------------------------+-----------------------+ |||| | | | +| ||| | | |+----------------------------------------------------------------------+||| | | | +| ||+-----------------------------+---------------------------------------------------------+--------+------------------------------------------------------------------------+|| | | | +| |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| | | | +| ||+---------------------------------+----------------------------------------------------------+ || | | | +| |||:diagtext:`array backing` |nbsp| |+--------------------------------------------------------+| || | | | +| ||| ||:diagtext:`initializer list subobject of local variable`|| || | | | +| ||| |+--------------------------------------------------------+| || | | | +| ||| ||:diagtext:`local initializer list` || || | | | +| ||| |+--------------------------------------------------------+| || | | | +| ||+---------------------------------+----------------------------------------------------------+ || | | | +| |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| | | | ++---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------+----------------------------+---------------------------------------------------------------+ + ++---------------------------------------------------------------------------+-----------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+---------------------------+--------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`sorry, lifetime extension of` |nbsp| |+---------------------------------------------+| |nbsp| :diagtext:`created by aggregate initialization using default member initializer is not supported; lifetime of` |nbsp| |+-------------------------+| |nbsp| :diagtext:`will end at the end of the full-expression`| +| ||:diagtext:`temporary` || ||:diagtext:`temporary` || | +| |+---------------------------------------------+| |+-------------------------+| | +| ||:diagtext:`backing array of initializer list`|| ||:diagtext:`backing array`|| | +| |+---------------------------------------------+| |+-------------------------+| | ++---------------------------------------------------------------------------+-----------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+---------------------------+--------------------------------------------------------------+ + + -Wdangling-else --------------- This diagnostic is enabled by default. @@ -2654,21 +2873,33 @@ This diagnostic is enabled by default. **Diagnostic text:** -+---------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`binding reference member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to stack allocated parameter` |nbsp| :placeholder:`B`| -+---------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------------------------+-----------------------+------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`binding reference member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to stack allocated` |nbsp| |+---------------------+| |nbsp| :placeholder:`B`| +| ||:diagtext:`variable` || | +| |+---------------------+| | +| ||:diagtext:`parameter`|| | +| |+---------------------+| | ++-------------------------------------------------------------------------------------------------------------------------------------+-----------------------+------------------------+ -+----------------------------------------------------------------+----------------------------------+----------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`binding reference` |nbsp| |+--------------------------------+|:diagtext:`member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to a temporary value`| -| || || | -| |+--------------------------------+| | -| ||:diagtext:`subobject of` |nbsp| || | -| |+--------------------------------+| | -+----------------------------------------------------------------+----------------------------------+----------------------------------------------------------------------------------+ ++---------------------------+--------------------------------------------------------+--------+----------------------------------+--------------------------------------------------+----------------------+------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+------------------------------------------------------+| |nbsp| |+--------------------------------+|:diagtext:`member` |nbsp| :placeholder:`A` |nbsp| |+--------------------+| |nbsp| :diagtext:`a temporary object whose lifetime is shorter than the lifetime of the constructed object`| +| ||:diagtext:`reference` || || || ||:diagtext:`binds to`|| | +| |+------------------------------------------------------+| |+--------------------------------+| |+--------------------+| | +| ||:diagtext:`backing array for 'std::initializer\_list'`|| ||:diagtext:`subobject of` |nbsp| || ||:diagtext:`is` || | +| |+------------------------------------------------------+| |+--------------------------------+| |+--------------------+| | ++---------------------------+--------------------------------------------------------+--------+----------------------------------+--------------------------------------------------+----------------------+------------------------------------------------------------------------------------------------------------+ -+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`initializing pointer member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`with the stack address of parameter` |nbsp| :placeholder:`B`| -+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`initializing pointer member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`with the stack address of` |nbsp| |+---------------------+| |nbsp| :placeholder:`B`| +| ||:diagtext:`variable` || | +| |+---------------------+| | +| ||:diagtext:`parameter`|| | +| |+---------------------+| | ++-----------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+------------------------+ + ++--------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`temporary bound to reference member of allocated object will be destroyed at the end of the full-expression`| ++--------------------------------------------------------------------------------------------------------------------------------------------------+ -Wdangling-initializer-list @@ -2677,13 +2908,24 @@ This diagnostic is enabled by default. **Diagnostic text:** -+-----------------------------------------------------------------------------------------------------------------+---------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`array backing the initializer list will be destroyed at the end of` |nbsp| |+-------------------------------+| -| ||:diagtext:`the full-expression`|| -| |+-------------------------------+| -| ||:diagtext:`the constructor` || -| |+-------------------------------+| -+-----------------------------------------------------------------------------------------------------------------+---------------------------------+ ++------------------------------------------------------------+----------------------------------------------------------------+-----------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`array backing` |nbsp| |+--------------------------------------------------------------+| |nbsp| :diagtext:`will be destroyed at the end of the full-expression`| +| ||:diagtext:`initializer list subobject of the allocated object`|| | +| |+--------------------------------------------------------------+| | +| ||:diagtext:`the allocated initializer list` || | +| |+--------------------------------------------------------------+| | ++------------------------------------------------------------+----------------------------------------------------------------+-----------------------------------------------------------------------+ + + +-Wdarwin-sdk-settings +--------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`SDK settings were ignored as 'SDKSettings.json' could not be parsed`| ++----------------------------------------------------------------------------------------------------------+ -Wdate-time @@ -2726,6 +2968,29 @@ This diagnostic is enabled by default. +-----------------------------------------------------------------------------------+ +-Wdefaulted-function-deleted +---------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------+--------------------------------------+-----------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`explicitly defaulted` |nbsp| |+------------------------------------+| |nbsp| :diagtext:`is implicitly deleted`| +| ||:diagtext:`default constructor` || | +| |+------------------------------------+| | +| ||:diagtext:`copy constructor` || | +| |+------------------------------------+| | +| ||:diagtext:`move constructor` || | +| |+------------------------------------+| | +| ||:diagtext:`copy assignment operator`|| | +| |+------------------------------------+| | +| ||:diagtext:`move assignment operator`|| | +| |+------------------------------------+| | +| ||:diagtext:`destructor` || | +| |+------------------------------------+| | ++-------------------------------------------------------------------+--------------------------------------+-----------------------------------------+ + + -Wdelegating-ctor-cycles ------------------------ This diagnostic is an error by default, but the flag ``-Wno-delegating-ctor-cycles`` can be used to disable the error. @@ -2737,6 +3002,21 @@ This diagnostic is an error by default, but the flag ``-Wno-delegating-ctor-cycl +------------------------------------------------------------------------------------------------------------------------+ +-Wdelete-abstract-non-virtual-dtor +---------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------+------------------------+------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+----------------------+| |nbsp| :diagtext:`called on` |nbsp| :placeholder:`B` |nbsp| :diagtext:`that is abstract but has non-virtual destructor`| +| ||:diagtext:`delete` || | +| |+----------------------+| | +| ||:diagtext:`destructor`|| | +| |+----------------------+| | ++---------------------------+------------------------+------------------------------------------------------------------------------------------------------------------------+ + + -Wdelete-incomplete ------------------- This diagnostic is enabled by default. @@ -2752,20 +3032,10 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------------------------------------------------------------------------+ --Wdelete-non-virtual-dtor -------------------------- -Some of the diagnostics controlled by this flag are enabled by default. - +-Wdelete-non-abstract-non-virtual-dtor +-------------------------------------- **Diagnostic text:** -+---------------------------+------------------------+------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+----------------------+| |nbsp| :diagtext:`called on` |nbsp| :placeholder:`B` |nbsp| :diagtext:`that is abstract but has non-virtual destructor`| -| ||:diagtext:`delete` || | -| |+----------------------+| | -| ||:diagtext:`destructor`|| | -| |+----------------------+| | -+---------------------------+------------------------+------------------------------------------------------------------------------------------------------------------------+ - +---------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| |+----------------------+| |nbsp| :diagtext:`called on non-final` |nbsp| :placeholder:`B` |nbsp| :diagtext:`that has virtual functions but non-virtual destructor`| | ||:diagtext:`delete` || | @@ -2775,11 +3045,18 @@ Some of the diagnostics controlled by this flag are enabled by default. +---------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +-Wdelete-non-virtual-dtor +------------------------- +Some of the diagnostics controlled by this flag are enabled by default. + +Controls `-Wdelete-abstract-non-virtual-dtor`_, `-Wdelete-non-abstract-non-virtual-dtor`_. + + -Wdeprecated ------------ Some of the diagnostics controlled by this flag are enabled by default. -Also controls `-Wdeprecated-attributes`_, `-Wdeprecated-declarations`_, `-Wdeprecated-dynamic-exception-spec`_, `-Wdeprecated-increment-bool`_, `-Wdeprecated-register`_, `-Wdeprecated-writable-strings`_. +Also controls `-Wdeprecated-attributes`_, `-Wdeprecated-declarations`_, `-Wdeprecated-dynamic-exception-spec`_, `-Wdeprecated-increment-bool`_, `-Wdeprecated-register`_, `-Wdeprecated-this-capture`_, `-Wdeprecated-writable-strings`_. **Diagnostic text:** @@ -2957,6 +3234,15 @@ This diagnostic is enabled by default. +-------------------------------------------------------------------------------------------------------------------+ +-Wdeprecated-this-capture +------------------------- +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit capture of 'this' with a capture default of '=' is deprecated`| ++-------------------------------------------------------------------------------------------------------------+ + + -Wdeprecated-writable-strings ----------------------------- Synonym for `-Wc++11-compat-deprecated-writable-strings`_. @@ -3283,7 +3569,7 @@ Also controls `-Wdocumentation-unknown-command`_. -Wduplicate-decl-specifier -------------------------- -This diagnostic is enabled by default. +Some of the diagnostics controlled by this flag are enabled by default. **Diagnostic text:** @@ -3295,6 +3581,14 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`duplicate '`:placeholder:`A`:diagtext:`' declaration specifier`| +-----------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`multiple identical address spaces specified for type`| ++-------------------------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`duplicate '`:placeholder:`A`:diagtext:`' declaration specifier`| ++-----------------------------------------------------------------------------------------------------+ + -Wduplicate-enum ---------------- @@ -3418,6 +3712,21 @@ This diagnostic is enabled by default. +-------------------------------------------------------------------------------------------------+ +-Wempty-init-stmt +----------------- +**Diagnostic text:** + ++--------------------------------------------------------------------------+-----------------------------+---------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`empty initialization statement of '`|+---------------------------+|:diagtext:`' has no effect`| +| ||:diagtext:`if` || | +| |+---------------------------+| | +| ||:diagtext:`switch` || | +| |+---------------------------+| | +| ||:diagtext:`range-based for`|| | +| |+---------------------------+| | ++--------------------------------------------------------------------------+-----------------------------+---------------------------+ + + -Wempty-translation-unit ------------------------ **Diagnostic text:** @@ -3540,6 +3849,21 @@ Some of the diagnostics controlled by this flag are enabled by default. +-------------------------------------------------------------------------------------------------+ +-Wexperimental-isel +------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`-fexperimental-isel support for the '`:placeholder:`A`:diagtext:`' architecture is incomplete`| ++------------------------------------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`-fexperimental-isel support is incomplete for this architecture at the current optimization level`| ++----------------------------------------------------------------------------------------------------------------------------------------+ + + -Wexplicit-initialize-call -------------------------- This diagnostic is enabled by default. @@ -3564,15 +3888,6 @@ This diagnostic is enabled by default. +-------------------------------------------------------------------------------------------------------------------------------------+ --Wextended-offsetof -------------------- -**Diagnostic text:** - -+--------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`using extended field designator is an extension`| -+--------------------------------------------------------------------------------------+ - - -Wextern-c-compat ----------------- This diagnostic is enabled by default. @@ -3603,7 +3918,7 @@ This diagnostic is enabled by default. ------- Some of the diagnostics controlled by this flag are enabled by default. -Also controls `-Wignored-qualifiers`_, `-Winitializer-overrides`_, `-Wmissing-field-initializers`_, `-Wmissing-method-return-type`_, `-Wnull-pointer-arithmetic`_, `-Wsemicolon-before-method-body`_, `-Wsign-compare`_, `-Wunused-parameter`_. +Also controls `-Wempty-init-stmt`_, `-Wignored-qualifiers`_, `-Winitializer-overrides`_, `-Wmissing-field-initializers`_, `-Wmissing-method-return-type`_, `-Wnull-pointer-arithmetic`_, `-Wsemicolon-before-method-body`_, `-Wsign-compare`_, `-Wunused-parameter`_. **Diagnostic text:** @@ -3625,7 +3940,7 @@ This diagnostic is enabled by default. -Wextra-semi ------------ -Also controls `-Wc++11-extra-semi`_. +Also controls `-Wc++11-extra-semi`_, `-Wc++98-compat-extra-semi`_. **Diagnostic text:** @@ -3648,6 +3963,17 @@ Also controls `-Wc++11-extra-semi`_. +---------------------------------------------------------------------------------+ +-Wextra-semi-stmt +----------------- +Also controls `-Wempty-init-stmt`_. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`empty expression statement has no effect; remove unnecessary ';' to silence this warning`| ++-------------------------------------------------------------------------------------------------------------------------------+ + + -Wextra-tokens -------------- This diagnostic is enabled by default. @@ -3674,6 +4000,15 @@ This diagnostic is enabled by default. +------------------------------------------------------------------------------+ +-Wfixed-enum-extension +---------------------- +**Diagnostic text:** + ++-----------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`enumeration types with a fixed underlying type are a Clang extension`| ++-----------------------------------------------------------------------------------------------------------+ + + -Wflag-enum ----------- This diagnostic is enabled by default. @@ -3722,9 +4057,13 @@ Also controls `-Wfloat-overflow-conversion`_, `-Wfloat-zero-conversion`_. --------------------------- **Diagnostic text:** -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`implicit conversion of out of range value from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`changes value from` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to` |nbsp| :placeholder:`D`| -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit conversion from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`changes value from` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to` |nbsp| :placeholder:`D`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit conversion of out of range value from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is undefined`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -Wfloat-zero-conversion @@ -3960,6 +4299,14 @@ This diagnostic is enabled by default. ----------------- **Diagnostic text:** ++---------------------------+----------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+--------------------------------------------+| |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' should not be used as format arguments; add an explicit cast to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`instead`| +| ||:diagtext:`values of type` || | +| |+--------------------------------------------+| | +| ||:diagtext:`enum values with underlying type`|| | +| |+--------------------------------------------+| | ++---------------------------+----------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+------------------------+ |:warning:`warning:` |nbsp| :diagtext:`format specifies type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`but the argument has` |nbsp| |+---------------------------+| |nbsp| :placeholder:`B`| | ||:diagtext:`type` || | @@ -4024,6 +4371,17 @@ The text of this diagnostic is not controlled by Clang. +--------------------------------------------------------------------------------------------------------------------------------------+ +-Wframework-include-private-from-public +--------------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`public framework header includes private framework header '`:placeholder:`A`:diagtext:`'`| ++-------------------------------------------------------------------------------------------------------------------------------+ + + -Wfunction-def-in-objc-container -------------------------------- This diagnostic is enabled by default. @@ -4035,6 +4393,21 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------------------------------+ +-Wfunction-multiversion +----------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`body of cpu\_dispatch function will be ignored`| ++-------------------------------------------------------------------------------------+ + ++---------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`CPU list contains duplicate entries; attribute ignored`| ++---------------------------------------------------------------------------------------------+ + + -Wfuture-compat --------------- This diagnostic flag exists for GCC compatibility, and has no effect in Clang. @@ -4073,6 +4446,14 @@ Some of the diagnostics controlled by this flag are enabled by default. |:warning:`warning:` |nbsp| :diagtext:`GCC does not allow an attribute in this position on a function declaration`| +-----------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`GCC does not allow the` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute to be written on a type`| ++------------------------------------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`GCC does not allow variable declarations in for loop initializers before C99`| ++-------------------------------------------------------------------------------------------------------------------+ + +----------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' is bound to current loop, GCC binds it to the enclosing loop`| +----------------------------------------------------------------------------------------------------------------------------------+ @@ -4433,6 +4814,10 @@ This diagnostic is enabled by default. **Diagnostic text:** ++--------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'trivial\_abi' cannot be applied to` |nbsp| :placeholder:`A`| ++--------------------------------------------------------------------------------------------------+ + +---------------------------+-------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| |+-----------------+| |nbsp| :diagtext:`will always resolve to` |nbsp| :placeholder:`A` |nbsp| :diagtext:`even if weak definition of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is overridden`| | ||:diagtext:`alias`|| | @@ -4557,103 +4942,39 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`\_\_weak attribute cannot be specified on an automatic variable when ARC is not enabled`| +------------------------------------------------------------------------------------------------------------------------------+ -+------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`unions` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables and functions` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions and global variables` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, variables, and Objective-C interfaces` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions and methods` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`parameters` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, methods and blocks` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, methods, and classes` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, methods, and parameters` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, methods, and global variables` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`classes` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`enums` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`methods` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`fields and global variables` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`structs` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`parameters and typedefs` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables and typedefs` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`thread-local variables` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables and fields` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables, data members and tag types` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`types and namespaces` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`Objective-C interfaces` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`methods and properties` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, methods, and properties` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`struct or union` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`struct, union or class` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`types` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`Objective-C instance methods` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`init methods of interface or class extension declarations` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables, functions and classes` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, variables, classes, and Objective-C interfaces` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`Objective-C protocols` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables with static or thread storage duration` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, methods, properties, and global variables` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`structs, unions, and typedefs` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`structs and typedefs` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`interface or protocol declarations` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`kernel functions` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`non-K&R-style functions` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables, enums, fields and typedefs` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, methods, enums, and classes` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`structs, classes, variables, functions, and inline namespaces` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members`|| -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`classes and enumerations` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`named declarations` || -| |+----------------------------------------------------------------------------------------------------------------+| -+------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------+---------------------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| |+-------------------------------------------------+| +| ||:diagtext:`functions` || +| |+-------------------------------------------------+| +| ||:diagtext:`unions` || +| |+-------------------------------------------------+| +| ||:diagtext:`variables and functions` || +| |+-------------------------------------------------+| +| ||:diagtext:`functions and methods` || +| |+-------------------------------------------------+| +| ||:diagtext:`functions, methods and blocks` || +| |+-------------------------------------------------+| +| ||:diagtext:`functions, methods, and parameters` || +| |+-------------------------------------------------+| +| ||:diagtext:`variables` || +| |+-------------------------------------------------+| +| ||:diagtext:`variables and fields` || +| |+-------------------------------------------------+| +| ||:diagtext:`variables, data members and tag types`|| +| |+-------------------------------------------------+| +| ||:diagtext:`types and namespaces` || +| |+-------------------------------------------------+| +| ||:diagtext:`variables, functions and classes` || +| |+-------------------------------------------------+| +| ||:diagtext:`kernel functions` || +| |+-------------------------------------------------+| +| ||:diagtext:`non-K&R-style functions` || +| |+-------------------------------------------------+| ++------------------------------------------------------------------------------------------------+---------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| :placeholder:`B`| ++----------------------------------------------------------------------------------------------------------------+ +--------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`ignored, because it cannot be applied to omitted return type`| @@ -4721,6 +5042,14 @@ This diagnostic is enabled by default. | |+----------------------------------+| +---------------------------------------------------------------------------+------------------------------------+ ++------------------------------------------------------------------------------------------------------------------+-----------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'objc\_externally\_retained' can only be applied to local variables` |nbsp| |+---------------------------------+| +| ||:diagtext:`of retainable type` || +| |+---------------------------------+| +| ||:diagtext:`with strong ownership`|| +| |+---------------------------------+| ++------------------------------------------------------------------------------------------------------------------+-----------------------------------+ + +--------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`'internal\_linkage' attribute on a non-static local variable is ignored`| +--------------------------------------------------------------------------------------------------------------+ @@ -4741,15 +5070,33 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`unknown attribute '`:placeholder:`A`:diagtext:`'`| +---------------------------------------------------------------------------------------+ -+------------------------------------------------------------------------------------------------+-----------------------------------+------------------------------+ -|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| |+---------------------------------+| |nbsp| :diagtext:`parameters`| -| ||:diagtext:`Objective-C object` || | -| |+---------------------------------+| | -| ||:diagtext:`pointer` || | -| |+---------------------------------+| | -| ||:diagtext:`pointer-to-CF-pointer`|| | -| |+---------------------------------+| | -+------------------------------------------------------------------------------------------------+-----------------------------------+------------------------------+ ++---------------------------------------------------------------------------------------------------------------+----------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`MSP430 'interrupt' attribute only applies to functions that have` |nbsp| |+--------------------------------+| +| ||:diagtext:`no parameters` || +| |+--------------------------------+| +| ||:diagtext:`a 'void' return type`|| +| |+--------------------------------+| ++---------------------------------------------------------------------------------------------------------------+----------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'nocf\_check' attribute ignored; use -fcf-protection to enable the attribute`| ++-------------------------------------------------------------------------------------------------------------------+ + ++---------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'noderef' can only be used on an array or pointer type`| ++---------------------------------------------------------------------------------------------+ + ++------------------------------------------------------------------------------------------------+---------------------------------------------------+------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| |+-------------------------------------------------+| |nbsp| :diagtext:`parameters`| +| ||:diagtext:`Objective-C object` || | +| |+-------------------------------------------------+| | +| ||:diagtext:`pointer` || | +| |+-------------------------------------------------+| | +| ||:diagtext:`pointer-to-CF-pointer` || | +| |+-------------------------------------------------+| | +| ||:diagtext:`pointer/reference-to-OSObject-pointer`|| | +| |+-------------------------------------------------+| | ++------------------------------------------------------------------------------------------------+---------------------------------------------------+------------------------------+ +------------------------------------------------------------------------------------------------+------------------------+---------------------------------------+--------------------------------------+ |:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| |+----------------------+| |nbsp| :diagtext:`that return` |nbsp| |+------------------------------------+| @@ -4765,6 +5112,18 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute is deprecated and ignored in OpenCL version` |nbsp| :placeholder:`B`| +--------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------+----------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`RISC-V 'interrupt' attribute only applies to functions that have` |nbsp| |+--------------------------------+| +| ||:diagtext:`no parameters` || +| |+--------------------------------+| +| ||:diagtext:`a 'void' return type`|| +| |+--------------------------------+| ++---------------------------------------------------------------------------------------------------------------+----------------------------------+ + ++----------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`repeated RISC-V 'interrupt' attribute`| ++----------------------------------------------------------------------------+ + +---------------------------+-----------------------+---------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+-------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| |+---------------------+| |nbsp| :diagtext:`of field` |nbsp| :placeholder:`B` |nbsp| :diagtext:`(`:placeholder:`C` |nbsp| :diagtext:`bits) does not match the` |nbsp| |+---------------------+| |nbsp| :diagtext:`of the first field in transparent union; transparent\_union attribute ignored`| | ||:diagtext:`alignment`|| ||:diagtext:`alignment`|| | @@ -4803,13 +5162,17 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`\_\_declspec attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not supported`| +-------------------------------------------------------------------------------------------------------------------------+ -+-------------------------------------------------------+-------------------------+----------------------------------+---------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`ignoring` |nbsp| |+-----------------------+|+--------------------------------+| |nbsp| :diagtext:`'`:placeholder:`C`:diagtext:`' in the target attribute string`| -| ||:diagtext:`unsupported`||| || | -| |+-----------------------+|+--------------------------------+| | -| ||:diagtext:`duplicate` ||| |nbsp| :diagtext:`architecture`|| | -| |+-----------------------+|+--------------------------------+| | -+-------------------------------------------------------+-------------------------+----------------------------------+---------------------------------------------------------------------------------+ ++---------------------------+-------------------------+----------------------------------+---------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+-----------------------+|+--------------------------------+| |nbsp| :diagtext:`'`:placeholder:`C`:diagtext:`' in the 'target' attribute string; 'target' attribute ignored`| +| ||:diagtext:`unsupported`||| || | +| |+-----------------------+|+--------------------------------+| | +| ||:diagtext:`duplicate` ||| |nbsp| :diagtext:`architecture`|| | +| |+-----------------------+|+--------------------------------+| | ++---------------------------+-------------------------+----------------------------------+---------------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'\_\_clang\_\_' is a predefined macro name, not an attribute scope specifier; did you mean '\_Clang' instead?`| ++----------------------------------------------------------------------------------------------------------------------------------------------------+ -Wignored-optimization-argument @@ -4842,11 +5205,22 @@ This diagnostic is enabled by default. +------------------------------------------------------------------------------------------+------------------------------------------------------------------------------+ +-Wignored-pragma-optimize +------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++--------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'#pragma optimize' is not supported`| ++--------------------------------------------------------------------------+ + + -Wignored-pragmas ----------------- This diagnostic is enabled by default. -Also controls `-Wignored-pragma-intrinsic`_. +Also controls `-Wignored-pragma-intrinsic`_, `-Wignored-pragma-optimize`_. **Diagnostic text:** @@ -4894,6 +5268,10 @@ Also controls `-Wignored-pragma-intrinsic`_. |:warning:`warning:` |nbsp| :diagtext:`missing ':' or ')' after` |nbsp| :placeholder:`A` |nbsp| :diagtext:`- ignoring`| +---------------------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`expected ',' in '#pragma` |nbsp| :placeholder:`A`:diagtext:`'`| ++----------------------------------------------------------------------------------------------------+ + +---------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`expected identifier in '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`| +---------------------------------------------------------------------------------------------------------------------+ @@ -4942,6 +5320,10 @@ Also controls `-Wignored-pragma-intrinsic`_. |:warning:`warning:` |nbsp| :diagtext:`expected push, pop or a string literal for the section name in '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`| +-------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`expected string literal in '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignoring`| ++--------------------------------------------------------------------------------------------------------------------------+ + +---------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`extra tokens at end of '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`| +---------------------------------------------------------------------------------------------------------------------+ @@ -4958,10 +5340,30 @@ Also controls `-Wignored-pragma-intrinsic`_. |:warning:`warning:` |nbsp| :diagtext:`unknown action for '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`| +-----------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`unexpected argument '`:placeholder:`A`:diagtext:`' to '#pragma` |nbsp| :placeholder:`B`:diagtext:`'`|+------------------------------------------------+| +| || || +| |+------------------------------------------------+| +| ||+----------------------------------------------+|| +| |||:diagtext:`; expected` |nbsp| :placeholder:`D`||| +| ||+----------------------------------------------+|| +| |+------------------------------------------------+| ++------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------+ + +------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`unknown action '`:placeholder:`B`:diagtext:`' for '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`| +------------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------------------------+--------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`missing argument to '#pragma` |nbsp| :placeholder:`A`:diagtext:`'`|+------------------------------------------------+| +| || || +| |+------------------------------------------------+| +| ||+----------------------------------------------+|| +| |||:diagtext:`; expected` |nbsp| :placeholder:`C`||| +| ||+----------------------------------------------+|| +| |+------------------------------------------------+| ++--------------------------------------------------------------------------------------------------------+--------------------------------------------------+ + +----------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`incorrect use of '#pragma ms\_struct on\|off' - ignored`| +----------------------------------------------------------------------------------------------+ @@ -5039,13 +5441,13 @@ Some of the diagnostics controlled by this flag are enabled by default. |:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' qualifier on omitted return type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`has no effect`| +---------------------------------------------------------------------------------------------------------------------------------------------------------------+ -+------------------------------------------------------------------------------------+---------------+------------------------------------------+-------------------+-----------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' type qualifier`|+-------------+| |nbsp| :diagtext:`on return type` |nbsp| |+-----------------+| |nbsp| :diagtext:`no effect`| -| || || ||:diagtext:`:has` || | -| |+-------------+| |+-----------------+| | -| ||:diagtext:`s`|| ||:diagtext:`:have`|| | -| |+-------------+| |+-----------------+| | -+------------------------------------------------------------------------------------+---------------+------------------------------------------+-------------------+-----------------------------+ ++------------------------------------------------------------------------------------+---------------+------------------------------------------+------------------+-----------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' type qualifier`|+-------------+| |nbsp| :diagtext:`on return type` |nbsp| |+----------------+| |nbsp| :diagtext:`no effect`| +| || || ||:diagtext:`has` || | +| |+-------------+| |+----------------+| | +| ||:diagtext:`s`|| ||:diagtext:`have`|| | +| |+-------------+| |+----------------+| | ++------------------------------------------------------------------------------------+---------------+------------------------------------------+------------------+-----------------------------+ +---------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' qualifier on function type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`has no effect`| @@ -5126,19 +5528,28 @@ Also controls `-Wimplicit-fallthrough-per-function`_. +------------------------------------------------------------------------------------------------------------------+ +-Wimplicit-float-conversion +--------------------------- +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit conversion loses floating-point precision:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit conversion when assigning computation result loses floating-point precision:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wimplicit-function-declaration ------------------------------- Some of the diagnostics controlled by this flag are enabled by default. **Diagnostic text:** -+----------------------------------------------------------------------------------------------------------------------------------------+--------------------+ -|:warning:`warning:` |nbsp| :diagtext:`implicit declaration of function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is invalid in` |nbsp| |+------------------+| -| ||:diagtext:`C99` || -| |+------------------+| -| ||:diagtext:`OpenCL`|| -| |+------------------+| -+----------------------------------------------------------------------------------------------------------------------------------------+--------------------+ ++------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit declaration of function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is invalid in C99`| ++------------------------------------------------------------------------------------------------------------------------------------+ +---------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`implicitly declaring library function '`:placeholder:`A`:diagtext:`' with type` |nbsp| :placeholder:`B`| @@ -5164,6 +5575,19 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------+ +-Wimplicit-int-conversion +------------------------- +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`higher order bits are zeroes after implicit conversion`| ++---------------------------------------------------------------------------------------------+ + ++---------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit conversion loses integer precision:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wimplicit-retain-self ---------------------- **Diagnostic text:** @@ -5295,6 +5719,10 @@ This diagnostic is an error by default, but the flag ``-Wno-incompatible-ms-stru |:error:`error:` |nbsp| :diagtext:`ms\_struct may not produce Microsoft-compatible layouts for classes with base classes or virtual functions`| +---------------------------------------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:error:`error:` |nbsp| :diagtext:`ms\_struct may not produce Microsoft-compatible layouts with fundamental data types with sizes that aren't a power of two`| ++------------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wincompatible-pointer-types ---------------------------- @@ -5388,6 +5816,17 @@ This diagnostic is enabled by default. +------------------------------------------------------------------------------------------------------------------------------------+ +-Wincomplete-framework-module-declaration +----------------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`skipping '`:placeholder:`A`:diagtext:`' because module declaration of '`:placeholder:`B`:diagtext:`' lacks the 'framework' qualifier`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wincomplete-implementation --------------------------- This diagnostic is enabled by default. @@ -5642,6 +6081,18 @@ Also controls `-Wignored-optimization-argument`_. **Diagnostic text:** ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`the given MCU supports` |nbsp| :placeholder:`A` |nbsp| :diagtext:`hardware multiply, but -mhwmult is set to` |nbsp| :placeholder:`B`:diagtext:`.`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`no MCU device specified, but '-mhwmult' is set to 'auto', assuming no hardware multiply. Use -mmcu to specify a MSP430 device, or -mhwmult to set hardware multiply type explicitly.`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`the given MCU does not support hardware multiply, but -mhwmult is set to` |nbsp| :placeholder:`A`:diagtext:`.`| ++----------------------------------------------------------------------------------------------------------------------------------------------------+ + +-----------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`the object size sanitizer has no effect at -O0, but is explicitly enabled:` |nbsp| :placeholder:`A`| +-----------------------------------------------------------------------------------------------------------------------------------------+ @@ -5900,6 +6351,10 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`implicit conversion from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`changes value from` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to` |nbsp| :placeholder:`D`| +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit conversion of out of range value from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is undefined`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wliteral-range --------------- @@ -6065,6 +6520,21 @@ This diagnostic is enabled by default. +----------------------------------------------------------------+---------------------------------------+------------------------------------------------------+ +-Wmemset-transposed-args +------------------------ +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------+-----------------------------------------------------+---------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+---------------------------------------------------+|:diagtext:`; did you mean to transpose the last two arguments?`| +| ||:diagtext:`'size' argument to memset is '0'` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`setting buffer to a 'sizeof' expression`|| | +| |+---------------------------------------------------+| | ++---------------------------+-----------------------------------------------------+---------------------------------------------------------------+ + + -Wmemsize-comparison -------------------- This diagnostic is enabled by default. @@ -6333,6 +6803,17 @@ This diagnostic is enabled by default. +----------------------------------------------------------------------------------------------------------+ +-Wmicrosoft-inaccessible-base +----------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`accessing inaccessible direct base` |nbsp| :placeholder:`A` |nbsp| :diagtext:`of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is a Microsoft extension`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wmicrosoft-include ------------------- This diagnostic is enabled by default. @@ -6400,10 +6881,6 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`use of identifier` |nbsp| :placeholder:`A` |nbsp| :diagtext:`found via unqualified lookup into dependent bases of class templates is a Microsoft extension`| +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -+--------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`explicit specialization of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`within class scope is a Microsoft extension`| -+--------------------------------------------------------------------------------------------------------------------------------------------------------+ - +-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`using the undeclared type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`as a default template argument is a Microsoft extension`| +-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -6412,27 +6889,27 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`non-type template argument containing a dereference operation is a Microsoft extension`| +-----------------------------------------------------------------------------------------------------------------------------+ -+---------------------------+---------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------------------------+| |nbsp| :diagtext:`specialization of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`outside namespace enclosing` |nbsp| :placeholder:`C` |nbsp| :diagtext:`is a Microsoft extension`| -| ||:diagtext:`class template` || | -| |+-------------------------------------+| | -| ||:diagtext:`class template partial` || | -| |+-------------------------------------+| | -| ||:diagtext:`variable template` || | -| |+-------------------------------------+| | -| ||:diagtext:`variable template partial`|| | -| |+-------------------------------------+| | -| ||:diagtext:`function template` || | -| |+-------------------------------------+| | -| ||:diagtext:`member function` || | -| |+-------------------------------------+| | -| ||:diagtext:`static data member` || | -| |+-------------------------------------+| | -| ||:diagtext:`member class` || | -| |+-------------------------------------+| | -| ||:diagtext:`member enumeration` || | -| |+-------------------------------------+| | -+---------------------------+---------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------+---------------------------------------+-----------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------+--------------------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------------------------+| |nbsp| :diagtext:`specialization of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`not in` |nbsp| |+----------------------------------------------------------------------------------------+| |nbsp| :diagtext:`is a Microsoft extension`| +| ||:diagtext:`class template` || ||+---------------------------------------------------------+ || | +| |+-------------------------------------+| |||:diagtext:`a namespace enclosing` |nbsp| :placeholder:`C`| || | +| ||:diagtext:`class template partial` || ||+---------------------------------------------------------+ || | +| |+-------------------------------------+| |+----------------------------------------------------------------------------------------+| | +| ||:diagtext:`variable template` || ||+--------------------------------------------------------------------------------------+|| | +| |+-------------------------------------+| |||:diagtext:`class` |nbsp| :placeholder:`C` |nbsp| :diagtext:`or an enclosing namespace`||| | +| ||:diagtext:`variable template partial`|| ||+--------------------------------------------------------------------------------------+|| | +| |+-------------------------------------+| |+----------------------------------------------------------------------------------------+| | +| ||:diagtext:`function template` || | | | +| |+-------------------------------------+| | | | +| ||:diagtext:`member function` || | | | +| |+-------------------------------------+| | | | +| ||:diagtext:`static data member` || | | | +| |+-------------------------------------+| | | | +| ||:diagtext:`member class` || | | | +| |+-------------------------------------+| | | | +| ||:diagtext:`member enumeration` || | | | +| |+-------------------------------------+| | | | ++---------------------------+---------------------------------------+-----------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------+--------------------------------------------+ +------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`template argument for template type parameter must be a type; omitted 'typename' is a Microsoft extension`| @@ -6528,25 +7005,25 @@ This diagnostic is enabled by default. ----------------- **Diagnostic text:** -+---------------------------------------------------------------------------------+--------------------------+------------------------------+-----------------------------------------------------------+--------------------------+------------------------------+ -|:warning:`warning:` |nbsp| :placeholder:`C` |nbsp| :diagtext:`defined as` |nbsp| |+------------------------+|+----------------------------+| |nbsp| :diagtext:`here but previously declared as` |nbsp| |+------------------------+|+----------------------------+| -| ||:diagtext:`a struct` ||| || ||:diagtext:`a struct` ||| || -| |+------------------------+|+----------------------------+| |+------------------------+|+----------------------------+| -| ||:diagtext:`an interface`||| |nbsp| :diagtext:`template`|| ||:diagtext:`an interface`||| |nbsp| :diagtext:`template`|| -| |+------------------------+|+----------------------------+| |+------------------------+|+----------------------------+| -| ||:diagtext:`a class` || | ||:diagtext:`a class` || | -| |+------------------------+| | |+------------------------+| | -+---------------------------------------------------------------------------------+--------------------------+------------------------------+-----------------------------------------------------------+--------------------------+------------------------------+ ++---------------------------------------------------------------------------------+--------------------------+------------------------------+-----------------------------------------------------------+--------------------------+------------------------------+----------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`C` |nbsp| :diagtext:`defined as` |nbsp| |+------------------------+|+----------------------------+| |nbsp| :diagtext:`here but previously declared as` |nbsp| |+------------------------+|+----------------------------+|:diagtext:`; this is valid, but may result in linker errors under the Microsoft C++ ABI`| +| ||:diagtext:`a struct` ||| || ||:diagtext:`a struct` ||| || | +| |+------------------------+|+----------------------------+| |+------------------------+|+----------------------------+| | +| ||:diagtext:`an interface`||| |nbsp| :diagtext:`template`|| ||:diagtext:`an interface`||| |nbsp| :diagtext:`template`|| | +| |+------------------------+|+----------------------------+| |+------------------------+|+----------------------------+| | +| ||:diagtext:`a class` || | ||:diagtext:`a class` || | | +| |+------------------------+| | |+------------------------+| | | ++---------------------------------------------------------------------------------+--------------------------+------------------------------+-----------------------------------------------------------+--------------------------+------------------------------+----------------------------------------------------------------------------------------+ -+---------------------------+-----------------------+------------------------------+--------------------------------------------------------------------------------+-----------------------+------------------------------+ -|:warning:`warning:` |nbsp| |+---------------------+|+----------------------------+| |nbsp| :placeholder:`C` |nbsp| :diagtext:`was previously declared as a` |nbsp| |+---------------------+|+----------------------------+| -| ||:diagtext:`struct` ||| || ||:diagtext:`struct` ||| || -| |+---------------------+|+----------------------------+| |+---------------------+|+----------------------------+| -| ||:diagtext:`interface`||| |nbsp| :diagtext:`template`|| ||:diagtext:`interface`||| |nbsp| :diagtext:`template`|| -| |+---------------------+|+----------------------------+| |+---------------------+|+----------------------------+| -| ||:diagtext:`class` || | ||:diagtext:`class` || | -| |+---------------------+| | |+---------------------+| | -+---------------------------+-----------------------+------------------------------+--------------------------------------------------------------------------------+-----------------------+------------------------------+ ++---------------------------+-----------------------+------------------------------+--------------------------------------------------------------------------------+-----------------------+------------------------------+----------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+---------------------+|+----------------------------+| |nbsp| :placeholder:`C` |nbsp| :diagtext:`was previously declared as a` |nbsp| |+---------------------+|+----------------------------+|:diagtext:`; this is valid, but may result in linker errors under the Microsoft C++ ABI`| +| ||:diagtext:`struct` ||| || ||:diagtext:`struct` ||| || | +| |+---------------------+|+----------------------------+| |+---------------------+|+----------------------------+| | +| ||:diagtext:`interface`||| |nbsp| :diagtext:`template`|| ||:diagtext:`interface`||| |nbsp| :diagtext:`template`|| | +| |+---------------------+|+----------------------------+| |+---------------------+|+----------------------------+| | +| ||:diagtext:`class` || | ||:diagtext:`class` || | | +| |+---------------------+| | |+---------------------+| | | ++---------------------------+-----------------------+------------------------------+--------------------------------------------------------------------------------+-----------------------+------------------------------+----------------------------------------------------------------------------------------+ -Wmissing-braces @@ -6797,7 +7274,7 @@ Controls `-Wcast-of-sel-type`_, `-Wchar-subscripts`_, `-Wcomment`_, `-Wdelete-no -Wmove ------ -Controls `-Wpessimizing-move`_, `-Wredundant-move`_, `-Wself-move`_. +Controls `-Wpessimizing-move`_, `-Wredundant-move`_, `-Wreturn-std-move`_, `-Wself-move`_. -Wmsvc-include @@ -6888,6 +7365,25 @@ This diagnostic is enabled by default. +----------------------------------------------------------------+ +-Wnoderef +--------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`dereferencing` |nbsp| :placeholder:`A`:diagtext:`; was declared with a 'noderef' type`| ++----------------------------------------------------------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`dereferencing expression marked as 'noderef'`| ++-----------------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`casting to dereferenceable pointer removes 'noderef' attribute`| ++-----------------------------------------------------------------------------------------------------+ + + -Wnoexcept-type --------------- Synonym for `-Wc++17-compat-mangling`_. @@ -7033,6 +7529,25 @@ This diagnostic is enabled by default. +---------------------------------------------------------------------------------------------------------------------+ +-Wnontrivial-memaccess +---------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------+ +|:warning:`warning:` |nbsp| |+-----------------------------+| |nbsp| :diagtext:`this` |nbsp| :placeholder:`B` |nbsp| :diagtext:`call is a pointer to record` |nbsp| :placeholder:`C` |nbsp| :diagtext:`that is not trivial to` |nbsp| |+----------------------------------------+| +| ||:diagtext:`destination for` || ||:diagtext:`primitive-default-initialize`|| +| |+-----------------------------+| |+----------------------------------------+| +| ||:diagtext:`source of` || ||:diagtext:`primitive-copy` || +| |+-----------------------------+| |+----------------------------------------+| +| ||:diagtext:`first operand of` || | | +| |+-----------------------------+| | | +| ||:diagtext:`second operand of`|| | | +| |+-----------------------------+| | | ++---------------------------+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------+ + + -Wnsconsumed-mismatch --------------------- This diagnostic is enabled by default. @@ -7280,9 +7795,9 @@ This diagnostic is enabled by default. **Diagnostic text:** -+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`adding '`:placeholder:`A`:diagtext:`' to '`:placeholder:`B`:diagtext:`' might cause circular dependency in container`| -+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`adding` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`might cause circular dependency in container`| ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -Wobjc-cocoa-api @@ -7504,6 +8019,15 @@ This diagnostic is enabled by default. +-----------------------------------------------------------------------------------------------------------------------------+ +-Wobjc-property-assign-on-object-type +------------------------------------- +**Diagnostic text:** + ++--------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'assign' property of object type may become a dangling reference; consider using 'unsafe\_unretained'`| ++--------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wobjc-property-implementation ------------------------------ This diagnostic is enabled by default. @@ -7772,6 +8296,14 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`The OpenMP offloading target '`:placeholder:`A`:diagtext:`' is similar to target '`:placeholder:`B`:diagtext:`' already specified - will be ignored.`| +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`No library '`:placeholder:`A`:diagtext:`' found in the default clang lib directory or in LIBRARY\_PATH. Expect degraded performance due to no inlining of runtime functions on target devices.`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`Non-trivial type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is mapped, only trivial types are guaranteed to be mapped correctly`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +-----------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`declaration is not declared in any declare target region`| +-----------------------------------------------------------------------------------------------+ @@ -7787,14 +8319,14 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`option '-ffine-grained-bitfield-accesses' cannot be enabled together with a sanitizer; flag ignored`| +------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`The '`:placeholder:`A`:diagtext:`' architecture does not support -moutline; flag ignored`| ++-------------------------------------------------------------------------------------------------------------------------------+ + +----------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`option '`:placeholder:`A`:diagtext:`' was ignored by the PS4 toolchain, using '-fPIC'`| +----------------------------------------------------------------------------------------------------------------------------+ -+-------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`ignoring '-mabicalls' option as it cannot be used with non position-independent code and the N64 ABI`| -+-------------------------------------------------------------------------------------------------------------------------------------------+ - +-------------------------------------------------------------------------------------------------------------------+-------------------------------------------+----------------------+ |:warning:`warning:` |nbsp| :diagtext:`ignoring '-mlong-calls' option as it is not currently supported with` |nbsp| |+-----------------------------------------+|:diagtext:`-mabicalls`| | || || | @@ -7803,6 +8335,29 @@ This diagnostic is enabled by default. | |+-----------------------------------------+| | +-------------------------------------------------------------------------------------------------------------------+-------------------------------------------+----------------------+ ++-----------------------------------------------------------------------------------------------------------------------+-------------------------------+----------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ignoring '`:placeholder:`A`:diagtext:`' option as it cannot be used with` |nbsp| |+-----------------------------+| |nbsp| :diagtext:`-mabicalls and the N64 ABI`| +| ||:diagtext:`implicit usage of`|| | +| |+-----------------------------+| | +| || || | +| |+-----------------------------+| | ++-----------------------------------------------------------------------------------------------------------------------+-------------------------------+----------------------------------------------+ + ++----------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`auto-vectorization requires HVX, use -mhvx to enable it`| ++----------------------------------------------------------------------------------------------+ + + +-Wordered-compare-function-pointers +----------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ordered comparison of function pointers (`:placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B`:diagtext:`)`| ++------------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wout-of-line-declaration ------------------------- @@ -7885,6 +8440,7 @@ This diagnostic is enabled by default. | |+---------------------+| +-----------------------------------------------------------------------------------------------+-----------------------+ + -Woverride-init --------------- Synonym for `-Winitializer-overrides`_. @@ -8079,10 +8635,14 @@ This diagnostic is enabled by default. -Wpedantic ---------- -Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-literal`_, `-Wc11-extensions`_, `-Wcomplex-component-init`_, `-Wdeclaration-after-statement`_, `-Wdollar-in-identifier-extension`_, `-Wembedded-directive`_, `-Wempty-translation-unit`_, `-Wextended-offsetof`_, `-Wflexible-array-extensions`_, `-Wformat-pedantic`_, `-Wfour-char-constants`_, `-Wgnu-anonymous-struct`_, `-Wgnu-auto-type`_, `-Wgnu-binary-literal`_, `-Wgnu-case-range`_, `-Wgnu-complex-integer`_, `-Wgnu-compound-literal-initializer`_, `-Wgnu-conditional-omitted-operand`_, `-Wgnu-empty-initializer`_, `-Wgnu-empty-struct`_, `-Wgnu-flexible-array-initializer`_, `-Wgnu-flexible-array-union-member`_, `-Wgnu-folding-constant`_, `-Wgnu-imaginary-constant`_, `-Wgnu-include-next`_, `-Wgnu-label-as-value`_, `-Wgnu-redeclared-enum`_, `-Wgnu-statement-expression`_, `-Wgnu-union-cast`_, `-Wgnu-zero-line-directive`_, `-Wgnu-zero-variadic-macro-arguments`_, `-Wimport-preprocessor-directive-pedantic`_, `-Wkeyword-macro`_, `-Wlanguage-extension-token`_, `-Wlong-long`_, `-Wmicrosoft-charize`_, `-Wmicrosoft-comment-paste`_, `-Wmicrosoft-cpp-macro`_, `-Wmicrosoft-end-of-file`_, `-Wmicrosoft-enum-value`_, `-Wmicrosoft-fixed-enum`_, `-Wmicrosoft-flexible-array`_, `-Wmicrosoft-redeclare-static`_, `-Wnested-anon-types`_, `-Wnullability-extension`_, `-Woverlength-strings`_, `-Wretained-language-linkage`_, `-Wundefined-internal-type`_, `-Wvla-extension`_, `-Wzero-length-array`_. +Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-literal`_, `-Wc11-extensions`_, `-Wcomplex-component-init`_, `-Wdeclaration-after-statement`_, `-Wdollar-in-identifier-extension`_, `-Wembedded-directive`_, `-Wempty-translation-unit`_, `-Wfixed-enum-extension`_, `-Wflexible-array-extensions`_, `-Wfour-char-constants`_, `-Wgnu-anonymous-struct`_, `-Wgnu-auto-type`_, `-Wgnu-binary-literal`_, `-Wgnu-case-range`_, `-Wgnu-complex-integer`_, `-Wgnu-compound-literal-initializer`_, `-Wgnu-conditional-omitted-operand`_, `-Wgnu-empty-initializer`_, `-Wgnu-empty-struct`_, `-Wgnu-flexible-array-initializer`_, `-Wgnu-flexible-array-union-member`_, `-Wgnu-folding-constant`_, `-Wgnu-imaginary-constant`_, `-Wgnu-include-next`_, `-Wgnu-label-as-value`_, `-Wgnu-redeclared-enum`_, `-Wgnu-statement-expression`_, `-Wgnu-union-cast`_, `-Wgnu-zero-line-directive`_, `-Wgnu-zero-variadic-macro-arguments`_, `-Wimport-preprocessor-directive-pedantic`_, `-Wkeyword-macro`_, `-Wlanguage-extension-token`_, `-Wlong-long`_, `-Wmicrosoft-charize`_, `-Wmicrosoft-comment-paste`_, `-Wmicrosoft-cpp-macro`_, `-Wmicrosoft-end-of-file`_, `-Wmicrosoft-enum-value`_, `-Wmicrosoft-fixed-enum`_, `-Wmicrosoft-flexible-array`_, `-Wmicrosoft-redeclare-static`_, `-Wnested-anon-types`_, `-Wnullability-extension`_, `-Woverlength-strings`_, `-Wretained-language-linkage`_, `-Wundefined-internal-type`_, `-Wvla-extension`_, `-Wzero-length-array`_. **Diagnostic text:** ++-----------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`duplicate '`:placeholder:`A`:diagtext:`' declaration specifier`| ++-----------------------------------------------------------------------------------------------------+ + +------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`'enable\_if' is a clang extension`| +------------------------------------------------------------------------+ @@ -8115,31 +8675,37 @@ Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-liter | |+------------------+| | +--------------------------------------------------------+--------------------+------------------------------------------------------------+ -+--------------------------------------------------------------------+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`no viable constructor` |nbsp| |+---------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`B`:diagtext:`; C++98 requires a copy constructor when binding a reference to a temporary`| -| ||:diagtext:`copying variable` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying parameter` || | -| |+---------------------------------------+| | -| ||:diagtext:`returning object` || | -| |+---------------------------------------+| | -| ||:diagtext:`throwing object` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying member subobject` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying array element` || | -| |+---------------------------------------+| | -| ||:diagtext:`allocating object` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying temporary` || | -| |+---------------------------------------+| | -| ||:diagtext:`initializing base subobject`|| | -| |+---------------------------------------+| | -| ||:diagtext:`initializing vector element`|| | -| |+---------------------------------------+| | -| ||:diagtext:`capturing value` || | -| |+---------------------------------------+| | -+--------------------------------------------------------------------+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------+------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`no viable constructor` |nbsp| |+----------------------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`B`:diagtext:`; C++98 requires a copy constructor when binding a reference to a temporary`| +| ||:diagtext:`copying variable` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying parameter` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`returning object` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`initializing statement expression result`|| | +| |+----------------------------------------------------+| | +| ||:diagtext:`throwing object` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying member subobject` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying array element` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`allocating object` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying temporary` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`initializing base subobject` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`initializing vector element` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`capturing value` || | +| |+----------------------------------------------------+| | ++--------------------------------------------------------------------+------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ + ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ISO C++ standards before C++17 do not allow new expression for type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to use list-initialization`| ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +--------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`parameter` |nbsp| :placeholder:`A` |nbsp| :diagtext:`was not declared, defaulting to type 'int'`| @@ -8185,25 +8751,33 @@ Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-liter |:warning:`warning:` |nbsp| :diagtext:`flexible array members are a C99 feature`| +-------------------------------------------------------------------------------+ -+---------------------------------------------------------------+-----------------------+--------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------+|:diagtext:`' to a function type`| -| ||:diagtext:`sizeof` || | -| |+---------------------+| | -| ||:diagtext:`alignof` || | -| |+---------------------+| | -| ||:diagtext:`vec\_step`|| | -| |+---------------------+| | -+---------------------------------------------------------------+-----------------------+--------------------------------+ - -+---------------------------------------------------------------+-----------------------+----------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------+|:diagtext:`' to a void type`| -| ||:diagtext:`sizeof` || | -| |+---------------------+| | -| ||:diagtext:`alignof` || | -| |+---------------------+| | -| ||:diagtext:`vec\_step`|| | -| |+---------------------+| | -+---------------------------------------------------------------+-----------------------+----------------------------+ ++---------------------------------------------------------------+-----------------------------------------------------+--------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------------------------------------+|:diagtext:`' to a function type`| +| ||:diagtext:`sizeof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`alignof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`vec\_step` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_builtin\_omp\_required\_simd\_align`|| | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_alignof` || | +| |+---------------------------------------------------+| | ++---------------------------------------------------------------+-----------------------------------------------------+--------------------------------+ + ++---------------------------------------------------------------+-----------------------------------------------------+----------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------------------------------------+|:diagtext:`' to a void type`| +| ||:diagtext:`sizeof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`alignof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`vec\_step` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_builtin\_omp\_required\_simd\_align`|| | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_alignof` || | +| |+---------------------------------------------------+| | ++---------------------------------------------------------------+-----------------------------------------------------+----------------------------+ +-------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`ISO C90 does not allow subscripting non-lvalue array`| @@ -8313,6 +8887,14 @@ Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-liter | |+------------------+| | +-----------------------------------------------------------------------------+--------------------+---------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`format specifies type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`but the argument has` |nbsp| |+---------------------------+| |nbsp| :placeholder:`B`| +| ||:diagtext:`type` || | +| |+---------------------------+| | +| ||:diagtext:`underlying type`|| | +| |+---------------------------+| | ++------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+------------------------+ + +---------------------------------------------------+----------------------+-----------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`void` |nbsp| |+--------------------+| |nbsp| :placeholder:`A` |nbsp| :diagtext:`should not return void expression`| | ||:diagtext:`function`|| | @@ -8510,25 +9092,33 @@ Some of the diagnostics controlled by this flag are enabled by default. | |+---------------------+| |+-------------+| | +----------------------------------------------------+-----------------------+---------------------------+---------------+----------------------------------------------+ -+---------------------------------------------------------------+-----------------------+--------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------+|:diagtext:`' to a function type`| -| ||:diagtext:`sizeof` || | -| |+---------------------+| | -| ||:diagtext:`alignof` || | -| |+---------------------+| | -| ||:diagtext:`vec\_step`|| | -| |+---------------------+| | -+---------------------------------------------------------------+-----------------------+--------------------------------+ - -+---------------------------------------------------------------+-----------------------+----------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------+|:diagtext:`' to a void type`| -| ||:diagtext:`sizeof` || | -| |+---------------------+| | -| ||:diagtext:`alignof` || | -| |+---------------------+| | -| ||:diagtext:`vec\_step`|| | -| |+---------------------+| | -+---------------------------------------------------------------+-----------------------+----------------------------+ ++---------------------------------------------------------------+-----------------------------------------------------+--------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------------------------------------+|:diagtext:`' to a function type`| +| ||:diagtext:`sizeof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`alignof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`vec\_step` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_builtin\_omp\_required\_simd\_align`|| | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_alignof` || | +| |+---------------------------------------------------+| | ++---------------------------------------------------------------+-----------------------------------------------------+--------------------------------+ + ++---------------------------------------------------------------+-----------------------------------------------------+----------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------------------------------------+|:diagtext:`' to a void type`| +| ||:diagtext:`sizeof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`alignof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`vec\_step` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_builtin\_omp\_required\_simd\_align`|| | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_alignof` || | +| |+---------------------------------------------------+| | ++---------------------------------------------------------------+-----------------------------------------------------+----------------------------+ +-----------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`subtraction of pointers to type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`of zero size has undefined behavior`| @@ -8560,6 +9150,17 @@ This diagnostic is enabled by default. +-------------------------------------------------+------------------------------+---------------------------------------------------------------------------------+ +-Wpointer-integer-compare +------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`comparison between pointer and integer (`:placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B`:diagtext:`)`| ++-----------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wpointer-sign -------------- This diagnostic is enabled by default. @@ -8726,26 +9327,34 @@ This diagnostic is enabled by default. **Diagnostic text:** -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`top-level module '`:placeholder:`A`:diagtext:`' in private module map, expected a submodule of '`:placeholder:`B`:diagtext:`'`| -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`expected canonical name for private module '`:placeholder:`A`:diagtext:`'`| ++----------------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`private submodule '`:placeholder:`A`:diagtext:`' in private module map, expected top-level module`| ++----------------------------------------------------------------------------------------------------------------------------------------+ +----------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`module '`:placeholder:`A`:diagtext:`' already re-exported as '`:placeholder:`B`:diagtext:`'`| +----------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`no submodule named` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in module '`:placeholder:`B`:diagtext:`'; using top level '`:placeholder:`C`:diagtext:`'`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wprofile-instr-missing ----------------------- **Diagnostic text:** -+-----------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+---------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`profile data may be incomplete: of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`function`|+-------------+|:diagtext:`,` |nbsp| :placeholder:`B` |nbsp| |+-----------------+| |nbsp| :diagtext:`no data`| -| || || ||:diagtext:`:has` || | -| |+-------------+| |+-----------------+| | -| ||:diagtext:`s`|| ||:diagtext:`:have`|| | -| |+-------------+| |+-----------------+| | -+-----------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+---------------------------+ ++-----------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+------------------+---------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`profile data may be incomplete: of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`function`|+-------------+|:diagtext:`,` |nbsp| :placeholder:`B` |nbsp| |+----------------+| |nbsp| :diagtext:`no data`| +| || || ||:diagtext:`has` || | +| |+-------------+| |+----------------+| | +| ||:diagtext:`s`|| ||:diagtext:`have`|| | +| |+-------------+| |+----------------+| | ++-----------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+------------------+---------------------------+ -Wprofile-instr-out-of-date @@ -8754,13 +9363,13 @@ This diagnostic is enabled by default. **Diagnostic text:** -+------------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+--------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`profile data may be out of date: of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`function`|+-------------+|:diagtext:`,` |nbsp| :placeholder:`B` |nbsp| |+-----------------+| |nbsp| :diagtext:`mismatched data that will be ignored`| -| || || ||:diagtext:`:has` || | -| |+-------------+| |+-----------------+| | -| ||:diagtext:`s`|| ||:diagtext:`:have`|| | -| |+-------------+| |+-----------------+| | -+------------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+--------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+------------------+--------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`profile data may be out of date: of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`function`|+-------------+|:diagtext:`,` |nbsp| :placeholder:`B` |nbsp| |+----------------+| |nbsp| :diagtext:`mismatched data that will be ignored`| +| || || ||:diagtext:`has` || | +| |+-------------+| |+----------------+| | +| ||:diagtext:`s`|| ||:diagtext:`have`|| | +| |+-------------+| |+----------------+| | ++------------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+------------------+--------------------------------------------------------+ -Wprofile-instr-unprofiled @@ -8861,6 +9470,15 @@ This diagnostic is enabled by default. +---------------------------------------------------------------------------------------------------------+ +-Wquoted-include-in-framework-header +------------------------------------ +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`double-quoted include "`:placeholder:`A`:diagtext:`" in framework header, expected angle-bracketed instead`| ++-------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wrange-loop-analysis --------------------- **Diagnostic text:** @@ -9064,13 +9682,35 @@ This diagnostic is enabled by default. | |+------------------------+| | +--------------------------------------------------------+--------------------------+------------------------------------------+ -+---------------------------+--------------------------+-------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+------------------------+| |nbsp| :diagtext:`stack memory associated with local variable` |nbsp| :placeholder:`B` |nbsp| :diagtext:`returned`| -| ||:diagtext:`address of` || | -| |+------------------------+| | -| ||:diagtext:`reference to`|| | -| |+------------------------+| | -+---------------------------+--------------------------+-------------------------------------------------------------------------------------------------------------------+ ++---------------------------+--------------------------+--------------------------------------------------------+----------------------------+----------------------------------------------------+ +|:warning:`warning:` |nbsp| |+------------------------+| |nbsp| :diagtext:`stack memory associated with` |nbsp| |+--------------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`returned`| +| ||:diagtext:`address of` || ||:diagtext:`local variable`|| | +| |+------------------------+| |+--------------------------+| | +| ||:diagtext:`reference to`|| ||:diagtext:`parameter` || | +| |+------------------------+| |+--------------------------+| | ++---------------------------+--------------------------+--------------------------------------------------------+----------------------------+----------------------------------------------------+ + + +-Wreturn-std-move +----------------- +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------------+----------------------+---------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`local variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`will be copied despite being` |nbsp| |+--------------------+| |nbsp| :diagtext:`by name`| +| ||:diagtext:`returned`|| | +| |+--------------------+| | +| ||:diagtext:`thrown` || | +| |+--------------------+| | ++-------------------------------------------------------------------------------------------------------------------------------------+----------------------+---------------------------+ + + +-Wreturn-std-move-in-c++11 +-------------------------- +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`prior to the resolution of a defect report against ISO C++11, local variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`would have been copied despite being returned by name, due to its not matching the function return type`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -Wreturn-type @@ -9149,17 +9789,6 @@ This diagnostic is enabled by default. +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ --Wrtti-for-exceptions ---------------------- -This diagnostic is enabled by default. - -**Diagnostic text:** - -+--------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`implicitly enabling rtti for exception handling`| -+--------------------------------------------------------------------------------------+ - - -Rsanitize-address ------------------ **Diagnostic text:** @@ -9199,9 +9828,17 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`section attribute is specified on redeclared variable`| +--------------------------------------------------------------------------------------------+ -+----------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`section does not match previous declaration`| -+----------------------------------------------------------------------------------+ ++------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`duplicate code segment specifiers`| ++------------------------------------------------------------------------+ + ++---------------------------+---------------------+-------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`does not match previous declaration`| +| ||:diagtext:`codeseg`|| | +| |+-------------------+| | +| ||:diagtext:`section`|| | +| |+-------------------+| | ++---------------------------+---------------------+-------------------------------------------------------+ -Wselector @@ -9228,7 +9865,7 @@ Also controls `-Wselector-type-mismatch`_. ------------- Some of the diagnostics controlled by this flag are enabled by default. -Also controls `-Wself-assign-field`_. +Also controls `-Wself-assign-field`_, `-Wself-assign-overloaded`_. **Diagnostic text:** @@ -9252,6 +9889,15 @@ This diagnostic is enabled by default. +--------------------------------------------------------+-------------------------------+-----------------------------+ +-Wself-assign-overloaded +------------------------ +**Diagnostic text:** + ++------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`explicitly assigning value of variable of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to itself`| ++------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wself-move ----------- **Diagnostic text:** @@ -9357,9 +10003,15 @@ Controls `-Wshadow`_, `-Wshadow-field`_, `-Wshadow-field-in-constructor`_, `-Wsh -------------- **Diagnostic text:** -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`non-static data member '`:placeholder:`A`:diagtext:`' of '`:placeholder:`B`:diagtext:`' shadows member inherited from type '`:placeholder:`C`:diagtext:`'`| -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------+------------------------------------+--------------------------------+--------------------------------------------------+----------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+----------------------------------+| |nbsp| :placeholder:`A` |nbsp| |+------------------------------------------------+|:diagtext:`shadows member inherited from type` |nbsp| :placeholder:`C`| +| ||:diagtext:`parameter` || || || | +| |+----------------------------------+| |+------------------------------------------------+| | +| ||:diagtext:`non-static data member`|| ||+----------------------------------------------+|| | +| |+----------------------------------+| |||:diagtext:`of` |nbsp| :placeholder:`B` |nbsp| ||| | +| | | ||+----------------------------------------------+|| | +| | | |+------------------------------------------------+| | ++---------------------------+------------------------------------+--------------------------------+--------------------------------------------------+----------------------------------------------------------------------+ -Wshadow-field-in-constructor @@ -9518,6 +10170,10 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`operand of ? changes signedness:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| +---------------------------------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`the resulting value is always non-negative after implicit conversion`| ++-----------------------------------------------------------------------------------------------------------+ + -Wsign-promo ------------ @@ -9554,6 +10210,17 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +-Wsizeof-pointer-div +-------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' will return the size of the pointer, not the array itself`| ++-------------------------------------------------------------------------------------------------------------------------------+ + + -Wsizeof-pointer-memaccess -------------------------- This diagnostic is enabled by default. @@ -9728,6 +10395,17 @@ This diagnostic is enabled by default. +----------------------------------------------------------------------------------------------------------------------------------------------------+ +-Wstdlibcxx-not-found +--------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`include path for stdlibc++ headers not found; pass '-stdlib=libc++' on the command line to use the libc++ standard library instead`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wstrict-aliasing ----------------- This diagnostic flag exists for GCC compatibility, and has no effect in Clang. @@ -9896,6 +10574,24 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------------------------------------------------------+ +-Wsuspicious-bzero +------------------ +This diagnostic is enabled by default. + +**Diagnostic text:** + ++----------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'size' argument to bzero is '0'`| ++----------------------------------------------------------------------+ + + +-Wsuspicious-memaccess +---------------------- +This diagnostic is enabled by default. + +Controls `-Wdynamic-class-memaccess`_, `-Wmemset-transposed-args`_, `-Wnontrivial-memaccess`_, `-Wsizeof-pointer-memaccess`_, `-Wsuspicious-bzero`_. + + -Wswitch -------- This diagnostic is enabled by default. @@ -9906,25 +10602,25 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`overflow converting case value to switch condition type (`:placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`:diagtext:`)`| +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -+---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+-----------------------------------------------------------------------------------------------+ || -| |||:diagtext:`:enumeration value` |nbsp| :placeholder:`B` |nbsp| :diagtext:`not handled in switch`| || -| ||+-----------------------------------------------------------------------------------------------+ || -| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+-----------------------------------------------------------------------------------------------------------------------------------------------+ || -| |||:diagtext:`:enumeration values` |nbsp| :placeholder:`B` |nbsp| :diagtext:`and` |nbsp| :placeholder:`C` |nbsp| :diagtext:`not handled in switch`| || -| ||+-----------------------------------------------------------------------------------------------------------------------------------------------+ || -| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || -| |||:diagtext:`:enumeration values` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`, and` |nbsp| :placeholder:`D` |nbsp| :diagtext:`not handled in switch`| || -| ||+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || -| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| -| |||:diagtext:`:`:placeholder:`A` |nbsp| :diagtext:`enumeration values not handled in switch:` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`,` |nbsp| :placeholder:`D`:diagtext:`...`||| -| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| -| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -+---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+----------------------------------------------------------------------------------------------+ || +| |||:diagtext:`enumeration value` |nbsp| :placeholder:`B` |nbsp| :diagtext:`not handled in switch`| || +| ||+----------------------------------------------------------------------------------------------+ || +| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+----------------------------------------------------------------------------------------------------------------------------------------------+ || +| |||:diagtext:`enumeration values` |nbsp| :placeholder:`B` |nbsp| :diagtext:`and` |nbsp| :placeholder:`C` |nbsp| :diagtext:`not handled in switch`| || +| ||+----------------------------------------------------------------------------------------------------------------------------------------------+ || +| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || +| |||:diagtext:`enumeration values` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`, and` |nbsp| :placeholder:`D` |nbsp| :diagtext:`not handled in switch`| || +| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || +| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| +| |||:placeholder:`A` |nbsp| :diagtext:`enumeration values not handled in switch:` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`,` |nbsp| :placeholder:`D`:diagtext:`...`||| +| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| +| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| ++---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`case value not in enumerated type` |nbsp| :placeholder:`A`| @@ -9950,25 +10646,25 @@ This diagnostic flag exists for GCC compatibility, and has no effect in Clang. ------------- **Diagnostic text:** -+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+----------------------------------------------------------------------------------------------------------+ || -| |||:diagtext:`:enumeration value` |nbsp| :placeholder:`B` |nbsp| :diagtext:`not explicitly handled in switch`| || -| ||+----------------------------------------------------------------------------------------------------------+ || -| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------+ || -| |||:diagtext:`:enumeration values` |nbsp| :placeholder:`B` |nbsp| :diagtext:`and` |nbsp| :placeholder:`C` |nbsp| :diagtext:`not explicitly handled in switch`| || -| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------+ || -| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || -| |||:diagtext:`:enumeration values` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`, and` |nbsp| :placeholder:`D` |nbsp| :diagtext:`not explicitly handled in switch`| || -| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || -| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| -| |||:diagtext:`:`:placeholder:`A` |nbsp| :diagtext:`enumeration values not explicitly handled in switch:` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`,` |nbsp| :placeholder:`D`:diagtext:`...`||| -| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| -| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+---------------------------------------------------------------------------------------------------------+ || +| |||:diagtext:`enumeration value` |nbsp| :placeholder:`B` |nbsp| :diagtext:`not explicitly handled in switch`| || +| ||+---------------------------------------------------------------------------------------------------------+ || +| |+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+---------------------------------------------------------------------------------------------------------------------------------------------------------+ || +| |||:diagtext:`enumeration values` |nbsp| :placeholder:`B` |nbsp| :diagtext:`and` |nbsp| :placeholder:`C` |nbsp| :diagtext:`not explicitly handled in switch`| || +| ||+---------------------------------------------------------------------------------------------------------------------------------------------------------+ || +| |+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || +| |||:diagtext:`enumeration values` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`, and` |nbsp| :placeholder:`D` |nbsp| :diagtext:`not explicitly handled in switch`| || +| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || +| |+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| +| |||:placeholder:`A` |nbsp| :diagtext:`enumeration values not explicitly handled in switch:` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`,` |nbsp| :placeholder:`D`:diagtext:`...`||| +| ||+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| +| |+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| ++---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -Wsync-fetch-and-nand-semantics-changed @@ -9996,12 +10692,10 @@ Also controls `-Wtautological-constant-compare`_, `-Wtautological-overlap-compar +---------------------------+---------------------------+--------------------------------------------------+------------------------+ |:warning:`warning:` |nbsp| |+-------------------------+|:diagtext:`comparison always evaluates to` |nbsp| |+----------------------+| -| ||:diagtext:`self-` || ||:diagtext:`false` || +| ||:diagtext:`self-` || ||:diagtext:`a constant`|| | |+-------------------------+| |+----------------------+| -| ||:diagtext:`array` |nbsp| || ||:diagtext:`true` || +| ||:diagtext:`array` |nbsp| || ||:placeholder:`C` || | |+-------------------------+| |+----------------------+| -| | | ||:diagtext:`a constant`|| -| | | |+----------------------+| +---------------------------+---------------------------+--------------------------------------------------+------------------------+ +-------------------------------------------------------------------------------------+-------------------+ @@ -10017,17 +10711,26 @@ Also controls `-Wtautological-constant-compare`_, `-Wtautological-overlap-compar ------------------------------- This diagnostic is enabled by default. -Also controls `-Wtautological-constant-out-of-range-compare`_, `-Wtautological-unsigned-enum-zero-compare`_, `-Wtautological-unsigned-zero-compare`_. +Also controls `-Wtautological-constant-out-of-range-compare`_. **Diagnostic text:** -+---------------------------------------------------------+------------------+--------------------------------+------------------+-------------------------------------+-------------------+ -|:warning:`warning:` |nbsp| :diagtext:`comparison` |nbsp| |+----------------+| |nbsp| :placeholder:`C` |nbsp| |+----------------+| |nbsp| :diagtext:`is always` |nbsp| |+-----------------+| -| ||:placeholder:`D`|| ||:placeholder:`B`|| ||:diagtext:`false`|| -| |+----------------+| |+----------------+| |+-----------------+| -| ||:placeholder:`B`|| ||:placeholder:`D`|| ||:diagtext:`true` || -| |+----------------+| |+----------------+| |+-----------------+| -+---------------------------------------------------------+------------------+--------------------------------+------------------+-------------------------------------+-------------------+ ++----------------------------------------------------------------------+------------------------------------------------+--------------------------------+----------------------------------------------------------+-----------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`result of comparison of` |nbsp| |+----------------------------------------------+| |nbsp| :diagtext:`with` |nbsp| |+--------------------------------------------------------+| |nbsp| :diagtext:`is always` |nbsp| :placeholder:`E`| +| ||+--------------------------------------------+|| ||+------------------------------------------------------+|| | +| |||:diagtext:`constant` |nbsp| :placeholder:`A`||| |||:diagtext:`expression of type` |nbsp| :placeholder:`C`||| | +| ||+--------------------------------------------+|| ||+------------------------------------------------------+|| | +| |+----------------------------------------------+| |+--------------------------------------------------------+| | +| ||:diagtext:`true` || ||:diagtext:`boolean expression` || | +| |+----------------------------------------------+| |+--------------------------------------------------------+| | +| ||:diagtext:`false` || | | | +| |+----------------------------------------------+| | | | ++----------------------------------------------------------------------+------------------------------------------------+--------------------------------+----------------------------------------------------------+-----------------------------------------------------+ + + +-Wtautological-constant-in-range-compare +---------------------------------------- +Controls `-Wtautological-type-limit-compare`_, `-Wtautological-unsigned-enum-zero-compare`_, `-Wtautological-unsigned-zero-compare`_. -Wtautological-constant-out-of-range-compare @@ -10036,17 +10739,17 @@ This diagnostic is enabled by default. **Diagnostic text:** -+------------------------------------------------------------+------------------------------------------------+--------------------------------+----------------------------------------------------------+-------------------------------------+-------------------+ -|:warning:`warning:` |nbsp| :diagtext:`comparison of` |nbsp| |+----------------------------------------------+| |nbsp| :diagtext:`with` |nbsp| |+--------------------------------------------------------+| |nbsp| :diagtext:`is always` |nbsp| |+-----------------+| -| ||+--------------------------------------------+|| ||+------------------------------------------------------+|| ||:diagtext:`false`|| -| |||:diagtext:`constant` |nbsp| :placeholder:`A`||| |||:diagtext:`expression of type` |nbsp| :placeholder:`C`||| |+-----------------+| -| ||+--------------------------------------------+|| ||+------------------------------------------------------+|| ||:diagtext:`true` || -| |+----------------------------------------------+| |+--------------------------------------------------------+| |+-----------------+| -| ||:diagtext:`true` || ||:diagtext:`boolean expression` || | | -| |+----------------------------------------------+| |+--------------------------------------------------------+| | | -| ||:diagtext:`false` || | | | | -| |+----------------------------------------------+| | | | | -+------------------------------------------------------------+------------------------------------------------+--------------------------------+----------------------------------------------------------+-------------------------------------+-------------------+ ++----------------------------------------------------------------------+------------------------------------------------+--------------------------------+----------------------------------------------------------+-----------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`result of comparison of` |nbsp| |+----------------------------------------------+| |nbsp| :diagtext:`with` |nbsp| |+--------------------------------------------------------+| |nbsp| :diagtext:`is always` |nbsp| :placeholder:`E`| +| ||+--------------------------------------------+|| ||+------------------------------------------------------+|| | +| |||:diagtext:`constant` |nbsp| :placeholder:`A`||| |||:diagtext:`expression of type` |nbsp| :placeholder:`C`||| | +| ||+--------------------------------------------+|| ||+------------------------------------------------------+|| | +| |+----------------------------------------------+| |+--------------------------------------------------------+| | +| ||:diagtext:`true` || ||:diagtext:`boolean expression` || | +| |+----------------------------------------------+| |+--------------------------------------------------------+| | +| ||:diagtext:`false` || | | | +| |+----------------------------------------------+| | | | ++----------------------------------------------------------------------+------------------------------------------------+--------------------------------+----------------------------------------------------------+-----------------------------------------------------+ -Wtautological-overlap-compare @@ -10087,6 +10790,19 @@ This diagnostic is enabled by default. +------------------------------------------------------------+------------------------+----------------------------------------------------------+-------------------------+-----------------------------------------------------+-------------------+ +-Wtautological-type-limit-compare +--------------------------------- +**Diagnostic text:** + ++-------------------------------------------------------------------+------------------+--------------------------------+------------------+-----------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`result of comparison` |nbsp| |+----------------+| |nbsp| :placeholder:`C` |nbsp| |+----------------+| |nbsp| :diagtext:`is always` |nbsp| :placeholder:`E`| +| ||:placeholder:`D`|| ||:placeholder:`B`|| | +| |+----------------+| |+----------------+| | +| ||:placeholder:`B`|| ||:placeholder:`D`|| | +| |+----------------+| |+----------------+| | ++-------------------------------------------------------------------+------------------+--------------------------------+------------------+-----------------------------------------------------+ + + -Wtautological-undefined-compare -------------------------------- This diagnostic is enabled by default. @@ -10112,32 +10828,28 @@ This diagnostic is enabled by default. -Wtautological-unsigned-enum-zero-compare ----------------------------------------- -This diagnostic is enabled by default. - **Diagnostic text:** -+------------------------------------------------------------+--------------------------------------+--------------------------------+--------------------------------------+-------------------------------------+-------------------+ -|:warning:`warning:` |nbsp| :diagtext:`comparison of` |nbsp| |+------------------------------------+| |nbsp| :placeholder:`C` |nbsp| |+------------------------------------+| |nbsp| :diagtext:`is always` |nbsp| |+-----------------+| -| ||:placeholder:`D` || ||:diagtext:`unsigned enum expression`|| ||:diagtext:`false`|| -| |+------------------------------------+| |+------------------------------------+| |+-----------------+| -| ||:diagtext:`unsigned enum expression`|| ||:placeholder:`D` || ||:diagtext:`true` || -| |+------------------------------------+| |+------------------------------------+| |+-----------------+| -+------------------------------------------------------------+--------------------------------------+--------------------------------+--------------------------------------+-------------------------------------+-------------------+ ++----------------------------------------------------------------------+--------------------------------------+--------------------------------+--------------------------------------+-----------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`result of comparison of` |nbsp| |+------------------------------------+| |nbsp| :placeholder:`C` |nbsp| |+------------------------------------+| |nbsp| :diagtext:`is always` |nbsp| :placeholder:`E`| +| ||:placeholder:`D` || ||:diagtext:`unsigned enum expression`|| | +| |+------------------------------------+| |+------------------------------------+| | +| ||:diagtext:`unsigned enum expression`|| ||:placeholder:`D` || | +| |+------------------------------------+| |+------------------------------------+| | ++----------------------------------------------------------------------+--------------------------------------+--------------------------------+--------------------------------------+-----------------------------------------------------+ -Wtautological-unsigned-zero-compare ------------------------------------ -This diagnostic is enabled by default. - **Diagnostic text:** -+------------------------------------------------------------+---------------------------------+--------------------------------+---------------------------------+-------------------------------------+-------------------+ -|:warning:`warning:` |nbsp| :diagtext:`comparison of` |nbsp| |+-------------------------------+| |nbsp| :placeholder:`C` |nbsp| |+-------------------------------+| |nbsp| :diagtext:`is always` |nbsp| |+-----------------+| -| ||:placeholder:`D` || ||:diagtext:`unsigned expression`|| ||:diagtext:`false`|| -| |+-------------------------------+| |+-------------------------------+| |+-----------------+| -| ||:diagtext:`unsigned expression`|| ||:placeholder:`D` || ||:diagtext:`true` || -| |+-------------------------------+| |+-------------------------------+| |+-----------------+| -+------------------------------------------------------------+---------------------------------+--------------------------------+---------------------------------+-------------------------------------+-------------------+ ++----------------------------------------------------------------------+---------------------------------+--------------------------------+---------------------------------+-----------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`result of comparison of` |nbsp| |+-------------------------------+| |nbsp| :placeholder:`C` |nbsp| |+-------------------------------+| |nbsp| :diagtext:`is always` |nbsp| :placeholder:`E`| +| ||:placeholder:`D` || ||:diagtext:`unsigned expression`|| | +| |+-------------------------------+| |+-------------------------------+| | +| ||:diagtext:`unsigned expression`|| ||:placeholder:`D` || | +| |+-------------------------------+| |+-------------------------------+| | ++----------------------------------------------------------------------+---------------------------------+--------------------------------+---------------------------------+-----------------------------------------------------+ -Wtentative-definition-incomplete-type @@ -10188,17 +10900,17 @@ Controls `-Wthread-safety-analysis`_, `-Wthread-safety-attributes`_, `-Wthread-s |:warning:`warning:` |nbsp| :diagtext:`cannot call function '`:placeholder:`B`:diagtext:`' while` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`C`:diagtext:`' is held`| +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`calling function '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||+------------------------------------------+ || -| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||+------------------------------------------+ || -| |+--------------------------------------------------------+| -| ||+------------------------------------------------------+|| -| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| ||+------------------------------------------------------+|| -| |+--------------------------------------------------------+| -+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`calling function` |nbsp| :placeholder:`B` |nbsp| :diagtext:`requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||+------------------------------------------+ || +| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||+------------------------------------------+ || +| |+--------------------------------------------------------+| +| ||+------------------------------------------------------+|| +| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| ||+------------------------------------------------------+|| +| |+--------------------------------------------------------+| ++---------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +--------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' is acquired exclusively and shared in the same scope`| @@ -10224,45 +10936,45 @@ Controls `-Wthread-safety-analysis`_, `-Wthread-safety-attributes`_, `-Wthread-s | |+---------------------+| |+---------------------+| | +----------------------------------------------------------------------------------------------------------------------------------------+-----------------------+--------------------------------------------+-----------------------+--------------------------+ -+---------------------------+---------------------+---------------------------------------------------------------------------------------------------+-----------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by '`:placeholder:`A`:diagtext:`' requires holding` |nbsp| |+---------------------------------+| -| ||:diagtext:`reading`|| ||:diagtext:`any mutex` || -| |+-------------------+| |+---------------------------------+| -| ||:diagtext:`writing`|| ||:diagtext:`any mutex exclusively`|| -| |+-------------------+| |+---------------------------------+| -+---------------------------+---------------------+---------------------------------------------------------------------------------------------------+-----------------------------------+ - -+---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||:diagtext:`reading`|| ||+------------------------------------------+ || -| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||:diagtext:`writing`|| ||+------------------------------------------+ || -| |+-------------------+| |+--------------------------------------------------------+| -| | | ||+------------------------------------------------------+|| -| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| | | ||+------------------------------------------------------+|| -| | | |+--------------------------------------------------------+| -+---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ - -+---------------------------+---------------------+------------------------------------------------------------------------------------+-----------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable '`:placeholder:`A`:diagtext:`' requires holding` |nbsp| |+---------------------------------+| -| ||:diagtext:`reading`|| ||:diagtext:`any mutex` || -| |+-------------------+| |+---------------------------------+| -| ||:diagtext:`writing`|| ||:diagtext:`any mutex exclusively`|| -| |+-------------------+| |+---------------------------------+| -+---------------------------+---------------------+------------------------------------------------------------------------------------+-----------------------------------+ - -+---------------------------+---------------------+------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||:diagtext:`reading`|| ||+------------------------------------------+ || -| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||:diagtext:`writing`|| ||+------------------------------------------+ || -| |+-------------------+| |+--------------------------------------------------------+| -| | | ||+------------------------------------------------------+|| -| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| | | ||+------------------------------------------------------+|| -| | | |+--------------------------------------------------------+| -+---------------------------+---------------------+------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ ++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------+-----------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by` |nbsp| :placeholder:`A` |nbsp| :diagtext:`requires holding` |nbsp| |+---------------------------------+| +| ||:diagtext:`reading`|| ||:diagtext:`any mutex` || +| |+-------------------+| |+---------------------------------+| +| ||:diagtext:`writing`|| ||:diagtext:`any mutex exclusively`|| +| |+-------------------+| |+---------------------------------+| ++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------+-----------------------------------+ + ++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by` |nbsp| :placeholder:`B` |nbsp| :diagtext:`requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||:diagtext:`reading`|| ||+------------------------------------------+ || +| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||:diagtext:`writing`|| ||+------------------------------------------+ || +| |+-------------------+| |+--------------------------------------------------------+| +| | | ||+------------------------------------------------------+|| +| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| | | ||+------------------------------------------------------+|| +| | | |+--------------------------------------------------------+| ++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ + ++---------------------------+---------------------+------------------------------------------------------------------------------------------------+-----------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`requires holding` |nbsp| |+---------------------------------+| +| ||:diagtext:`reading`|| ||:diagtext:`any mutex` || +| |+-------------------+| |+---------------------------------+| +| ||:diagtext:`writing`|| ||:diagtext:`any mutex exclusively`|| +| |+-------------------+| |+---------------------------------+| ++---------------------------+---------------------+------------------------------------------------------------------------------------------------+-----------------------------------+ + ++---------------------------+---------------------+------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable` |nbsp| :placeholder:`B` |nbsp| :diagtext:`requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||:diagtext:`reading`|| ||+------------------------------------------+ || +| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||:diagtext:`writing`|| ||+------------------------------------------+ || +| |+-------------------+| |+--------------------------------------------------------+| +| | | ||+------------------------------------------------------+|| +| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| | | ||+------------------------------------------------------+|| +| | | |+--------------------------------------------------------+| ++---------------------------+---------------------+------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -Wthread-safety-attributes @@ -10289,6 +11001,14 @@ Controls `-Wthread-safety-analysis`_, `-Wthread-safety-attributes`_, `-Wthread-s |:warning:`warning:` |nbsp| :diagtext:`ignoring` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute because its argument is invalid`| +------------------------------------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute without capability arguments refers to 'this', but` |nbsp| :placeholder:`B` |nbsp| :diagtext:`isn't annotated with 'capability' or 'scoped\_lockable' attribute`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute without capability arguments can only be applied to non-static methods of a class`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wthread-safety-beta -------------------- @@ -10312,70 +11032,70 @@ Controls `-Wthread-safety-analysis`_, `-Wthread-safety-attributes`_, `-Wthread-s ----------------------- **Diagnostic text:** -+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`calling function '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||+------------------------------------------+ || -| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||+------------------------------------------+ || -| |+--------------------------------------------------------+| -| ||+------------------------------------------------------+|| -| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| ||+------------------------------------------------------+|| -| |+--------------------------------------------------------+| -+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ - -+---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||:diagtext:`reading`|| ||+------------------------------------------+ || -| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||:diagtext:`writing`|| ||+------------------------------------------+ || -| |+-------------------+| |+--------------------------------------------------------+| -| | | ||+------------------------------------------------------+|| -| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| | | ||+------------------------------------------------------+|| -| | | |+--------------------------------------------------------+| -+---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ - -+---------------------------+---------------------+------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||:diagtext:`reading`|| ||+------------------------------------------+ || -| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||:diagtext:`writing`|| ||+------------------------------------------+ || -| |+-------------------+| |+--------------------------------------------------------+| -| | | ||+------------------------------------------------------+|| -| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| | | ||+------------------------------------------------------+|| -| | | |+--------------------------------------------------------+| -+---------------------------+---------------------+------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`calling function` |nbsp| :placeholder:`B` |nbsp| :diagtext:`requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||+------------------------------------------+ || +| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||+------------------------------------------+ || +| |+--------------------------------------------------------+| +| ||+------------------------------------------------------+|| +| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| ||+------------------------------------------------------+|| +| |+--------------------------------------------------------+| ++---------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ + ++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by` |nbsp| :placeholder:`B` |nbsp| :diagtext:`requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||:diagtext:`reading`|| ||+------------------------------------------+ || +| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||:diagtext:`writing`|| ||+------------------------------------------+ || +| |+-------------------+| |+--------------------------------------------------------+| +| | | ||+------------------------------------------------------+|| +| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| | | ||+------------------------------------------------------+|| +| | | |+--------------------------------------------------------+| ++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ + ++---------------------------+---------------------+------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable` |nbsp| :placeholder:`B` |nbsp| :diagtext:`requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||:diagtext:`reading`|| ||+------------------------------------------+ || +| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||:diagtext:`writing`|| ||+------------------------------------------+ || +| |+-------------------+| |+--------------------------------------------------------+| +| | | ||+------------------------------------------------------+|| +| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| | | ||+------------------------------------------------------+|| +| | | |+--------------------------------------------------------+| ++---------------------------+---------------------+------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -Wthread-safety-reference ------------------------- **Diagnostic text:** -+----------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`passing variable '`:placeholder:`B`:diagtext:`' by reference requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||+------------------------------------------+ || -| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||+------------------------------------------+ || -| |+--------------------------------------------------------+| -| ||+------------------------------------------------------+|| -| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| ||+------------------------------------------------------+|| -| |+--------------------------------------------------------+| -+----------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ - -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`passing the value that '`:placeholder:`B`:diagtext:`' points to by reference requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||+------------------------------------------+ || -| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||+------------------------------------------+ || -| |+--------------------------------------------------------+| -| ||+------------------------------------------------------+|| -| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| ||+------------------------------------------------------+|| -| |+--------------------------------------------------------+| -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`passing variable` |nbsp| :placeholder:`B` |nbsp| :diagtext:`by reference requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||+------------------------------------------+ || +| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||+------------------------------------------+ || +| |+--------------------------------------------------------+| +| ||+------------------------------------------------------+|| +| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| ||+------------------------------------------------------+|| +| |+--------------------------------------------------------+| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ + ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`passing the value that` |nbsp| :placeholder:`B` |nbsp| :diagtext:`points to by reference requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||+------------------------------------------+ || +| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||+------------------------------------------+ || +| |+--------------------------------------------------------+| +| ||+------------------------------------------------------+|| +| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| ||+------------------------------------------------------+|| +| |+--------------------------------------------------------+| ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -Wthread-safety-verbose @@ -10656,6 +11376,17 @@ This diagnostic is enabled by default. +---------------------------------------------------------------------------------------------+ +-Wunicode-homoglyph +------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`treating Unicode character as identifier character rather than as '`:placeholder:`B`:diagtext:`' symbol`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wunicode-whitespace -------------------- This diagnostic is enabled by default. @@ -10667,6 +11398,17 @@ This diagnostic is enabled by default. +-------------------------------------------------------------------------------+ +-Wunicode-zero-width +-------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`identifier contains Unicode character that is invisible in some environments`| ++----------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wuninitialized --------------- Some of the diagnostics controlled by this flag are enabled by default. @@ -10718,6 +11460,10 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`unknown argument ignored in clang-cl: '`:placeholder:`A`:diagtext:`'`| +-----------------------------------------------------------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`unknown argument ignored in clang-cl '`:placeholder:`A`:diagtext:`' (did you mean '`:placeholder:`B`:diagtext:`'?)`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wunknown-attributes -------------------- @@ -11048,6 +11794,17 @@ This diagnostic is enabled by default. +-------------------------------------------------------------------------------------------------------------------------------------------------+ +-Wunsupported-target-opt +------------------------ +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`debug information option '`:placeholder:`A`:diagtext:`' is not supported for target '`:placeholder:`B`:diagtext:`'`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wunsupported-visibility ------------------------ This diagnostic is enabled by default. @@ -11138,19 +11895,17 @@ This diagnostic is enabled by default. **Diagnostic text:** -+---------------------------+-----------------------------------------+--------------------------------------------+ -|:warning:`warning:` |nbsp| |+---------------------------------------+| |nbsp| :diagtext:`comparison result unused`| -| ||+----------------+--------------------+|| | -| |||+--------------+|:diagtext:`equality`||| | -| |||| || ||| | -| |||+--------------+| ||| | -| ||||:diagtext:`in`|| ||| | -| |||+--------------+| ||| | -| ||+----------------+--------------------+|| | -| |+---------------------------------------+| | -| ||:diagtext:`relational` || | -| |+---------------------------------------+| | -+---------------------------+-----------------------------------------+--------------------------------------------+ ++---------------------------+------------------------+--------------------------------------------+ +|:warning:`warning:` |nbsp| |+----------------------+| |nbsp| :diagtext:`comparison result unused`| +| ||:diagtext:`equality` || | +| |+----------------------+| | +| ||:diagtext:`inequality`|| | +| |+----------------------+| | +| ||:diagtext:`relational`|| | +| |+----------------------+| | +| ||:diagtext:`three-way` || | +| |+----------------------+| | ++---------------------------+------------------------+--------------------------------------------+ -Wunused-const-variable diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index e155cefb7890d..5782edd353701 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -474,44 +474,58 @@ Half-Precision Floating Point ============================= Clang supports two half-precision (16-bit) floating point types: ``__fp16`` and -``_Float16``. ``__fp16`` is defined in the ARM C Language Extensions (`ACLE -`_) -and ``_Float16`` in ISO/IEC TS 18661-3:2015. - -``__fp16`` is a storage and interchange format only. This means that values of -``__fp16`` promote to (at least) float when used in arithmetic operations. -There are two ``__fp16`` formats. Clang supports the IEEE 754-2008 format and -not the ARM alternative format. - -ISO/IEC TS 18661-3:2015 defines C support for additional floating point types. -``_FloatN`` is defined as a binary floating type, where the N suffix denotes -the number of bits and is 16, 32, 64, or greater and equal to 128 and a -multiple of 32. Clang supports ``_Float16``. The difference from ``__fp16`` is -that arithmetic on ``_Float16`` is performed in half-precision, thus it is not -a storage-only format. ``_Float16`` is available as a source language type in -both C and C++ mode. - -It is recommended that portable code use the ``_Float16`` type because -``__fp16`` is an ARM C-Language Extension (ACLE), whereas ``_Float16`` is -defined by the C standards committee, so using ``_Float16`` will not prevent -code from being ported to architectures other than Arm. Also, ``_Float16`` -arithmetic and operations will directly map on half-precision instructions when -they are available (e.g. Armv8.2-A), avoiding conversions to/from -single-precision, and thus will result in more performant code. If -half-precision instructions are unavailable, values will be promoted to -single-precision, similar to the semantics of ``__fp16`` except that the -results will be stored in single-precision. - -In an arithmetic operation where one operand is of ``__fp16`` type and the -other is of ``_Float16`` type, the ``_Float16`` type is first converted to -``__fp16`` type and then the operation is completed as if both operands were of -``__fp16`` type. - -To define a ``_Float16`` literal, suffix ``f16`` can be appended to the compile-time -constant declaration. There is no default argument promotion for ``_Float16``; this -applies to the standard floating types only. As a consequence, for example, an -explicit cast is required for printing a ``_Float16`` value (there is no string -format specifier for ``_Float16``). +``_Float16``. These types are supported in all language modes. + +``__fp16`` is supported on every target, as it is purely a storage format; see below. +``_Float16`` is currently only supported on the following targets, with further +targets pending ABI standardization: +- 32-bit ARM +- 64-bit ARM (AArch64) +- SPIR +``_Float16`` will be supported on more targets as they define ABIs for it. + +``__fp16`` is a storage and interchange format only. This means that values of +``__fp16`` are immediately promoted to (at least) ``float`` when used in arithmetic +operations, so that e.g. the result of adding two ``__fp16`` values has type ``float``. +The behavior of ``__fp16`` is specified by the ARM C Language Extensions (`ACLE `_). +Clang uses the ``binary16`` format from IEEE 754-2008 for ``__fp16``, not the ARM +alternative format. + +``_Float16`` is an extended floating-point type. This means that, just like arithmetic on +``float`` or ``double``, arithmetic on ``_Float16`` operands is formally performed in the +``_Float16`` type, so that e.g. the result of adding two ``_Float16`` values has type +``_Float16``. The behavior of ``_Float16`` is specified by ISO/IEC TS 18661-3:2015 +("Floating-point extensions for C"). As with ``__fp16``, Clang uses the ``binary16`` +format from IEEE 754-2008 for ``_Float16``. + +``_Float16`` arithmetic will be performed using native half-precision support +when available on the target (e.g. on ARMv8.2a); otherwise it will be performed +at a higher precision (currently always ``float``) and then truncated down to +``_Float16``. Note that C and C++ allow intermediate floating-point operands +of an expression to be computed with greater precision than is expressible in +their type, so Clang may avoid intermediate truncations in certain cases; this may +lead to results that are inconsistent with native arithmetic. + +It is recommended that portable code use ``_Float16`` instead of ``__fp16``, +as it has been defined by the C standards committee and has behavior that is +more familiar to most programmers. + +Because ``__fp16`` operands are always immediately promoted to ``float``, the +common real type of ``__fp16`` and ``_Float16`` for the purposes of the usual +arithmetic conversions is ``float``. + +A literal can be given ``_Float16`` type using the suffix ``f16``; for example: +``` +3.14f16 +``` + +Because default argument promotion only applies to the standard floating-point +types, ``_Float16`` values are not promoted to ``double`` when passed as variadic +or untyped arguments. As a consequence, some caution must be taken when using +certain library facilities with ``_Float16``; for example, there is no ``printf`` format +specifier for ``_Float16``, and (unlike ``float``) it will not be implicitly promoted to +``double`` when passed to ``printf``, so the programmer must explicitly cast it to +``double`` before using it with an ``%f`` or similar specifier. Messages on ``deprecated`` and ``unavailable`` Attributes ========================================================= diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst index 04a9648ca2942..7b567c966ee53 100644 --- a/clang/docs/OpenMPSupport.rst +++ b/clang/docs/OpenMPSupport.rst @@ -17,60 +17,50 @@ OpenMP Support ================== -Clang fully supports OpenMP 4.5. Clang supports offloading to X86_64, AArch64, -PPC64[LE] and has `basic support for Cuda devices`_. - -Standalone directives -===================== - -* #pragma omp [for] simd: :good:`Complete`. - -* #pragma omp declare simd: :partial:`Partial`. We support parsing/semantic - analysis + generation of special attributes for X86 target, but still - missing the LLVM pass for vectorization. - -* #pragma omp taskloop [simd]: :good:`Complete`. - -* #pragma omp target [enter|exit] data: :good:`Complete`. - -* #pragma omp target update: :good:`Complete`. - -* #pragma omp target: :good:`Complete`. +Clang supports the following OpenMP 5.0 features -* #pragma omp declare target: :good:`Complete`. +* The `reduction`-based clauses in the `task` and `target`-based directives. -* #pragma omp teams: :good:`Complete`. +* Support relational-op != (not-equal) as one of the canonical forms of random + access iterator. -* #pragma omp distribute [simd]: :good:`Complete`. +* Support for mapping of the lambdas in target regions. -* #pragma omp distribute parallel for [simd]: :good:`Complete`. +* Parsing/sema analysis for the requires directive. -Combined directives -=================== +* Nested declare target directives. -* #pragma omp parallel for simd: :good:`Complete`. +* Make the `this` pointer implicitly mapped as `map(this[:1])`. -* #pragma omp target parallel: :good:`Complete`. +* The `close` *map-type-modifier*. -* #pragma omp target parallel for [simd]: :good:`Complete`. - -* #pragma omp target simd: :good:`Complete`. - -* #pragma omp target teams: :good:`Complete`. - -* #pragma omp teams distribute [simd]: :good:`Complete`. - -* #pragma omp target teams distribute [simd]: :good:`Complete`. - -* #pragma omp teams distribute parallel for [simd]: :good:`Complete`. - -* #pragma omp target teams distribute parallel for [simd]: :good:`Complete`. +Clang fully supports OpenMP 4.5. Clang supports offloading to X86_64, AArch64, +PPC64[LE] and has `basic support for Cuda devices`_. -Clang does not support any constructs/updates from OpenMP 5.0 except -for `reduction`-based clauses in the `task` and `target`-based directives. +* #pragma omp declare simd: :partial:`Partial`. We support parsing/semantic + analysis + generation of special attributes for X86 target, but still + missing the LLVM pass for vectorization. In addition, the LLVM OpenMP runtime `libomp` supports the OpenMP Tools -Interface (OMPT) on x86, x86_64, AArch64, and PPC64 on Linux, Windows, and mac OS. +Interface (OMPT) on x86, x86_64, AArch64, and PPC64 on Linux, Windows, and macOS. + +General improvements +-------------------- +- New collapse clause scheme to avoid expensive remainder operations. + Compute loop index variables after collapsing a loop nest via the + collapse clause by replacing the expensive remainder operation with + multiplications and additions. + +- The default schedules for the `distribute` and `for` constructs in a + parallel region and in SPMD mode have changed to ensure coalesced + accesses. For the `distribute` construct, a static schedule is used + with a chunk size equal to the number of threads per team (default + value of threads or as specified by the `thread_limit` clause if + present). For the `for` construct, the schedule is static with chunk + size of one. + +- Simplified SPMD code generation for `distribute parallel for` when + the new default schedules are applicable. .. _basic support for Cuda devices: diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b6a405dbc78b2..e6892203f4571 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1,6 +1,6 @@ -======================================= -Clang 8.0.0 (In-Progress) Release Notes -======================================= +========================= +Clang 8.0.0 Release Notes +========================= .. contents:: :local: @@ -8,33 +8,22 @@ Clang 8.0.0 (In-Progress) Release Notes Written by the `LLVM Team `_ -.. warning:: - - These are in-progress notes for the upcoming Clang 8 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ -This document contains the release notes for the Clang C/C++/Objective-C +This document contains the release notes for the Clang C/C++/Objective-C/OpenCL frontend, part of the LLVM Compiler Infrastructure, release 8.0.0. Here we describe the status of Clang in some detail, including major improvements from the previous release and new feature work. For the general LLVM release notes, see `the LLVM documentation `_. All LLVM -releases may be downloaded from the `LLVM releases web -site `_. +releases may be downloaded +from the `LLVM releases web site `_. For more information about Clang or LLVM, including information about the latest release, please see the `Clang Web Site `_ or the `LLVM Web Site `_. -Note that if you are reading this file from a Subversion checkout or the -main Clang web page, this document applies to the *next* release, not -the current one. To see the release notes for a specific release, please -see the `releases page `_. - What's New in Clang 8.0.0? ========================== @@ -50,7 +39,36 @@ Major New Features profile data captured for one version of a program to be applied when building another version where symbols have changed (for example, due to renaming a class or namespace). - See the :doc:`UsersManual` for details. + See the :ref:`UsersManual ` for details. + +- Clang has new options to initialize automatic variables with a pattern. The default is still that automatic variables are uninitialized. This isn't meant to change the semantics of C and C++. Rather, it's meant to be a last resort when programmers inadvertently have some undefined behavior in their code. These options aim to make undefined behavior hurt less, which security-minded people will be very happy about. Notably, this means that there's no inadvertent information leak when: + + * The compiler re-uses stack slots, and a value is used uninitialized. + + * The compiler re-uses a register, and a value is used uninitialized. + + * Stack structs / arrays / unions with padding are copied. + + These options only address stack and register information leaks. + + Caveats: + + * Variables declared in unreachable code and used later aren't initialized. This affects goto statements, Duff's device, and other objectionable uses of switch statements. This should instead be a hard-error in any serious codebase. + + * These options don't affect volatile stack variables. + + * Padding isn't fully handled yet. + + How to use it on the command line: + + * ``-ftrivial-auto-var-init=uninitialized`` (the default) + + * ``-ftrivial-auto-var-init=pattern`` + + There is also a new attribute to request a variable to not be initialized, mainly to disable initialization of large stack arrays when deemed too expensive: + + * ``int dont_initialize_me __attribute((uninitialized));`` + Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -127,32 +145,43 @@ Non-comprehensive list of changes in this release manually and rely on the old behaviour you will need to add appropriate compiler flags for finding the corresponding libc++ include directory. +- The integrated assembler is used now by default for all MIPS targets. + +- Improved support for MIPS N32 ABI and MIPS R6 target triples. + +- Clang now includes builtin functions for bitwise rotation of common value + sizes, such as: `__builtin_rotateleft32 + `_ + +- Improved optimization for the corresponding MSVC compatibility builtins such + as ``_rotl()``. + New Compiler Flags ------------------ +- ``-mspeculative-load-hardening`` Clang now has an option to enable + Speculative Load Hardening. + - ``-fprofile-filter-files=[regexes]`` and ``-fprofile-exclude-files=[regexes]``. Clang has now options to filter or exclude some files when instrumenting for gcov-based profiling. - See the :doc:`UsersManual` for details. - -- ... + See the `UsersManual `_ for details. -Deprecated Compiler Flags -------------------------- +- When using a custom stack alignment, the ``stackrealign`` attribute is now + implicitly set on the main function. -The following options are deprecated and ignored. They will be removed in -future versions of Clang. - -- ... +- Emission of ``R_MIPS_JALR`` and ``R_MICROMIPS_JALR`` relocations can now + be controlled by the ``-mrelax-pic-calls`` and ``-mno-relax-pic-calls`` + options. Modified Compiler Flags ----------------------- -- As of clang 8, `alignof` and `_Alignof` return the ABI alignment of a type, - as opposed to the preferred alignment. `__alignof` still returns the - preferred alignment. `-fclang-abi-compat=7` (and previous) will make - `alignof` and `_Alignof` return preferred alignment again. +- As of clang 8, ``alignof`` and ``_Alignof`` return the ABI alignment of a type, + as opposed to the preferred alignment. ``__alignof`` still returns the + preferred alignment. ``-fclang-abi-compat=7`` (and previous) will make + ``alignof`` and ``_Alignof`` return preferred alignment again. New Pragmas in Clang @@ -164,12 +193,14 @@ New Pragmas in Clang Attribute Changes in Clang -------------------------- -- ... +* Clang now supports enabling/disabling speculative load hardening on a + per-function basis using the function attribute + ``speculative_load_hardening``/``no_speculative_load_hardening``. Windows Support --------------- -- clang-cl now supports the use of the precompiled header options /Yc and /Yu +- clang-cl now supports the use of the precompiled header options ``/Yc`` and ``/Yu`` without the filename argument. When these options are used without the filename, a `#pragma hdrstop` inside the source marks the end of the precompiled code. @@ -179,66 +210,102 @@ Windows Support `dllexport` and `dllimport` attributes not apply to inline member functions. This can significantly reduce compile and link times. See the `User's Manual `_ for more info. -- ... +- For MinGW, ``-municode`` now correctly defines ``UNICODE`` during + preprocessing. -C Language Changes in Clang ---------------------------- +- For MinGW, clang now produces vtables and RTTI for dllexported classes + without key functions. This fixes building Qt in debug mode. -- ... +- Allow using Address Sanitizer and Undefined Behaviour Sanitizer on MinGW. -... +- Structured Exception Handling support for ARM64 Windows. The ARM64 Windows + target is in pretty good shape now. -C11 Feature Support -^^^^^^^^^^^^^^^^^^^ -... +OpenCL Kernel Language Changes in Clang +--------------------------------------- -C++ Language Changes in Clang ------------------------------ +Misc: -- ... +- Improved address space support with Clang builtins. -C++1z Feature Support -^^^^^^^^^^^^^^^^^^^^^ +- Improved various diagnostics for vectors with element types from extensions; + values used in attributes; duplicate address spaces. -... +- Allow blocks to capture arrays. -Objective-C Language Changes in Clang -------------------------------------- +- Allow zero assignment and comparisons between variables of ``queue_t`` type. -... +- Improved diagnostics of formatting specifiers and argument promotions for + vector types in ``printf``. -OpenCL C Language Changes in Clang ----------------------------------- +- Fixed return type of enqueued kernel and pipe builtins. + +- Fixed address space of ``clk_event_t`` generated in the IR. + +- Fixed address space when passing/returning structs. + +Header file fixes: + +- Added missing extension guards around several builtin function overloads. + +- Fixed serialization support when registering vendor extensions using pragmas. + +- Fixed OpenCL version in declarations of builtin functions with sampler-less + image accesses. + +New vendor extensions added: + +- ``cl_intel_planar_yuv`` + +- ``cl_intel_device_side_avc_motion_estimation`` + + +C++ for OpenCL: + +- Added support of address space conversions in C style casts. + +- Enabled address spaces for references. + +- Fixed use of address spaces in templates: address space deduction and diagnostics. + +- Changed default address space to work with C++ specific concepts: class members, + template parameters, etc. + +- Added generic address space by default to the generated hidden 'this' parameter. + +- Extend overload ranking rules for address spaces. -... ABI Changes in Clang -------------------- -- `_Alignof` and `alignof` now return the ABI alignment of a type, as opposed +- ``_Alignof`` and ``alignof`` now return the ABI alignment of a type, as opposed to the preferred alignment. - This is more in keeping with the language of the standards, as well as being compatible with gcc - - `__alignof` and `__alignof__` still return the preferred alignment of + - ``__alignof`` and ``__alignof__`` still return the preferred alignment of a type - This shouldn't break any ABI except for things that explicitly ask for - `alignas(alignof(T))`. + ``alignas(alignof(T))``. - If you have interfaces that break with this change, you may wish to switch - to `alignas(__alignof(T))`, instead of using the `-fclang-abi-compat` + to ``alignas(__alignof(T))``, instead of using the ``-fclang-abi-compat`` switch. OpenMP Support in Clang ---------------------------------- -- Support relational-op != (not-equal) as one of the canonical forms of random - access iterator. +- OpenMP 5.0 features -- Added support for mapping of the lambdas in target regions. - -- Added parsing/sema analysis for OpenMP 5.0 requires directive. + - Support relational-op != (not-equal) as one of the canonical forms of random + access iterator. + - Added support for mapping of the lambdas in target regions. + - Added parsing/sema analysis for the requires directive. + - Support nested declare target directives. + - Make the `this` pointer implicitly mapped as `map(this[:1])`. + - Added the `close` *map-type-modifier*. - Various bugfixes and improvements. @@ -250,44 +317,17 @@ New features supported for Cuda devices: - Fixed support for lastprivate/reduction variables in SPMD constructs. -- General performance improvement. - -CUDA Support in Clang ---------------------- - - -Internal API Changes --------------------- - -These are major API changes that have happened since the 7.0.0 release of -Clang. If upgrading an external codebase that uses Clang as a library, -this section should help get you past the largest hurdles of upgrading. - -- ... +- New collapse clause scheme to avoid expensive remainder operations. -AST Matchers ------------- +- New default schedule for distribute and parallel constructs. -- ... +- Simplified code generation for distribute and parallel in SPMD mode. -clang-format ------------- +- Flag (``-fopenmp_optimistic_collapse``) for user to limit collapsed + loop counter width when safe to do so. +- General performance improvement. -- ... - -libclang --------- - -... - - -Static Analyzer ---------------- - -- ... - -... .. _release-notes-ubsan: @@ -364,25 +404,6 @@ Undefined Behavior Sanitizer (UBSan) data[x] *= data[x]; } -Core Analysis Improvements -========================== - -- ... - -New Issues Found -================ - -- ... - -Python Binding Changes ----------------------- - -The following methods have been added: - -- ... - -Significant Known Problems -========================== Additional Information ====================== diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 7634d24eb5a6a..38f7615bf95b0 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1799,6 +1799,8 @@ In these cases, you can use the flag ``-fno-profile-instr-generate`` (or Note that these flags should appear after the corresponding profile flags to have an effect. +.. _profile_remapping: + Profile remapping ^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index d4057c9da5f38..055f13f3620b4 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -257,6 +257,12 @@ class APValue { return const_cast(this)->getInt(); } + /// Try to convert this value to an integral constant. This works if it's an + /// integer, null pointer, or offset from a null pointer. Returns true on + /// success. + bool toIntegralConstant(APSInt &Result, QualType SrcTy, + const ASTContext &Ctx) const; + APFloat &getFloat() { assert(isFloat() && "Invalid accessor"); return *(APFloat*)(char*)Data.buffer; diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 3de73428829b3..bf4f3babbd3c6 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2577,6 +2577,11 @@ class CallExpr : public Expr { NumArgs = NewNumArgs; } + /// Bluntly set a new number of arguments without doing any checks whatsoever. + /// Only used during construction of a CallExpr in a few places in Sema. + /// FIXME: Find a way to remove it. + void setNumArgsUnsafe(unsigned NewNumArgs) { NumArgs = NewNumArgs; } + typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; typedef llvm::iterator_range arg_range; diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 1fe1dd39948a1..b792db2852a80 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -103,13 +103,6 @@ def ObjCInstanceMethod : SubsetSubjectisInstanceMethod()}], "Objective-C instance methods">; -def ObjCInterfaceDeclInitMethod : SubsetSubjectgetMethodFamily() == OMF_init && - (isa(S->getDeclContext()) || - (isa(S->getDeclContext()) && - cast(S->getDeclContext())->IsClassExtension()))}], - "init methods of interface or class extension declarations">; - def Struct : SubsetSubjectisUnion()}], "structs">; @@ -329,6 +322,7 @@ def TargetMSP430 : TargetArch<["msp430"]>; def TargetRISCV : TargetArch<["riscv32", "riscv64"]>; def TargetX86 : TargetArch<["x86"]>; def TargetAnyX86 : TargetArch<["x86", "x86_64"]>; +def TargetWebAssembly : TargetArch<["wasm32", "wasm64"]>; def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch64"]> { let OSes = ["Win32"]; } @@ -1500,6 +1494,22 @@ def AMDGPUNumVGPR : InheritableAttr { let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; } +def WebAssemblyImportModule : InheritableAttr, + TargetSpecificAttr { + let Spellings = [Clang<"import_module">]; + let Args = [StringArgument<"ImportModule">]; + let Documentation = [WebAssemblyImportModuleDocs]; + let Subjects = SubjectList<[Function], ErrorDiag>; +} + +def WebAssemblyImportName : InheritableAttr, + TargetSpecificAttr { + let Spellings = [Clang<"import_name">]; + let Args = [StringArgument<"ImportName">]; + let Documentation = [WebAssemblyImportNameDocs]; + let Subjects = SubjectList<[Function], ErrorDiag>; +} + def NoSplitStack : InheritableAttr { let Spellings = [GCC<"no_split_stack">]; let Subjects = SubjectList<[Function], ErrorDiag>; @@ -1745,7 +1755,7 @@ def ObjCExplicitProtocolImpl : InheritableAttr { def ObjCDesignatedInitializer : Attr { let Spellings = [Clang<"objc_designated_initializer">]; - let Subjects = SubjectList<[ObjCInterfaceDeclInitMethod], ErrorDiag>; + let Subjects = SubjectList<[ObjCMethod], ErrorDiag>; let Documentation = [Undocumented]; } diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 5773a92c9c15d..ff1905f685d7c 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3652,7 +3652,40 @@ definition ( For more information see `gcc documentation `_ or `msvc documentation `_. -}]; +}]; } + +def WebAssemblyImportModuleDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the ``__attribute__((import_module()))`` +attribute for the WebAssembly target. This attribute may be attached to a +function declaration, where it modifies how the symbol is to be imported +within the WebAssembly linking environment. + +WebAssembly imports use a two-level namespace scheme, consisting of a module +name, which typically identifies a module from which to import, and a field +name, which typically identifies a field from that module to import. By +default, module names for C/C++ symbols are assigned automatically by the +linker. This attribute can be used to override the default behavior, and +reuqest a specific module name be used instead. + }]; +} + +def WebAssemblyImportNameDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the ``__attribute__((import_name()))`` +attribute for the WebAssembly target. This attribute may be attached to a +function declaration, where it modifies how the symbol is to be imported +within the WebAssembly linking environment. + +WebAssembly imports use a two-level namespace scheme, consisting of a module +name, which typically identifies a module from which to import, and a field +name, which typically identifies a field from that module to import. By +default, field names for C/C++ symbols are the same as their C/C++ symbol +names. This attribute can be used to override the default behavior, and +reuqest a specific field name be used instead. + }]; } def ArtificialDocs : Documentation { @@ -3788,13 +3821,13 @@ The ``gnu_inline`` changes the meaning of ``extern inline`` to use GNU inline semantics, meaning: * If any declaration that is declared ``inline`` is not declared ``extern``, -then the ``inline`` keyword is just a hint. In particular, an out-of-line -definition is still emitted for a function with external linkage, even if all -call sites are inlined, unlike in C99 and C++ inline semantics. + then the ``inline`` keyword is just a hint. In particular, an out-of-line + definition is still emitted for a function with external linkage, even if all + call sites are inlined, unlike in C99 and C++ inline semantics. * If all declarations that are declared ``inline`` are also declared -``extern``, then the function body is present only for inlining and no -out-of-line version is emitted. + ``extern``, then the function body is present only for inlining and no + out-of-line version is emitted. Some important consequences: ``static inline`` emits an out-of-line version if needed, a plain ``inline`` definition emits an out-of-line version diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def index 1892ff11a31dc..054662e688317 100644 --- a/clang/include/clang/Basic/BuiltinsAArch64.def +++ b/clang/include/clang/Basic/BuiltinsAArch64.def @@ -33,7 +33,7 @@ BUILTIN(__builtin_arm_clrex, "v", "") // Bit manipulation BUILTIN(__builtin_arm_rbit, "UiUi", "nc") -BUILTIN(__builtin_arm_rbit64, "LUiLUi", "nc") +BUILTIN(__builtin_arm_rbit64, "WUiWUi", "nc") // HINT BUILTIN(__builtin_arm_nop, "v", "") @@ -50,8 +50,8 @@ BUILTIN(__builtin_arm_crc32h, "UiUiUs", "nc") BUILTIN(__builtin_arm_crc32ch, "UiUiUs", "nc") BUILTIN(__builtin_arm_crc32w, "UiUiUi", "nc") BUILTIN(__builtin_arm_crc32cw, "UiUiUi", "nc") -BUILTIN(__builtin_arm_crc32d, "UiUiLUi", "nc") -BUILTIN(__builtin_arm_crc32cd, "UiUiLUi", "nc") +BUILTIN(__builtin_arm_crc32d, "UiUiWUi", "nc") +BUILTIN(__builtin_arm_crc32cd, "UiUiWUi", "nc") // Memory barrier BUILTIN(__builtin_arm_dmb, "vUi", "nc") @@ -63,10 +63,10 @@ BUILTIN(__builtin_arm_prefetch, "vvC*UiUiUiUi", "nc") // System Registers BUILTIN(__builtin_arm_rsr, "UicC*", "nc") -BUILTIN(__builtin_arm_rsr64, "LUicC*", "nc") +BUILTIN(__builtin_arm_rsr64, "WUicC*", "nc") BUILTIN(__builtin_arm_rsrp, "v*cC*", "nc") BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc") -BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc") +BUILTIN(__builtin_arm_wsr64, "vcC*WUi", "nc") BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc") // MSVC @@ -204,8 +204,8 @@ TARGET_HEADER_BUILTIN(_InterlockedDecrement64_rel, "LLiLLiD*", "nh", "intrin.h", TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(__getReg, "ULLii", "nh", "intrin.h", ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(_ReadStatusReg, "ii", "nh", "intrin.h", ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(_WriteStatusReg, "vii", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_ReadStatusReg, "LLii", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_WriteStatusReg, "viLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "") #undef BUILTIN diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5feb877e46c51..7ef57b02fe1c6 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -274,6 +274,10 @@ def warn_riscv_interrupt_attribute : Warning< "RISC-V 'interrupt' attribute only applies to functions that have " "%select{no parameters|a 'void' return type}0">, InGroup; +def warn_msp430_interrupt_attribute : Warning< + "MSP430 'interrupt' attribute only applies to functions that have " + "%select{no parameters|a 'void' return type}0">, + InGroup; def warn_unused_parameter : Warning<"unused parameter %0">, InGroup, DefaultIgnore; def warn_unused_variable : Warning<"unused variable %0">, @@ -3456,6 +3460,9 @@ def warn_objc_secondary_init_missing_init_call : Warning< def warn_objc_implementation_missing_designated_init_override : Warning< "method override for the designated initializer of the superclass %objcinstance0 not found">, InGroup; +def err_designated_init_attr_non_init : Error< + "'objc_designated_initializer' attribute only applies to init methods " + "of interface or class extension declarations">; // objc_bridge attribute diagnostics. def err_objc_attr_not_id : Error< diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index 05464ed85f136..8b3b59b51c542 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -96,7 +96,7 @@ FEATURE(objc_arc, LangOpts.ObjCAutoRefCount) FEATURE(objc_arc_fields, true) FEATURE(objc_arc_weak, LangOpts.ObjCWeak) FEATURE(objc_default_synthesize_properties, LangOpts.ObjC) -FEATURE(objc_fixed_enum, true) +FEATURE(objc_fixed_enum, LangOpts.ObjC) FEATURE(objc_instancetype, LangOpts.ObjC) FEATURE(objc_kindof, LangOpts.ObjC) FEATURE(objc_modules, LangOpts.ObjC && LangOpts.Modules) diff --git a/clang/include/clang/Basic/FileManager.h b/clang/include/clang/Basic/FileManager.h index e7891baf53047..6a71289f74c1d 100644 --- a/clang/include/clang/Basic/FileManager.h +++ b/clang/include/clang/Basic/FileManager.h @@ -70,15 +70,14 @@ class FileEntry { bool IsNamedPipe; bool InPCH; bool IsValid; // Is this \c FileEntry initialized and valid? - bool DeferredOpen; // Created by getFile(OpenFile=0); may open later. /// The open file, if it is owned by the \p FileEntry. mutable std::unique_ptr File; public: FileEntry() - : UniqueID(0, 0), IsNamedPipe(false), InPCH(false), IsValid(false), - DeferredOpen(false) {} + : UniqueID(0, 0), IsNamedPipe(false), InPCH(false), IsValid(false) + {} FileEntry(const FileEntry &) = delete; FileEntry &operator=(const FileEntry &) = delete; diff --git a/clang/include/clang/Basic/OpenCLOptions.h b/clang/include/clang/Basic/OpenCLOptions.h index cc4e9922dca03..c76fa88092b9b 100644 --- a/clang/include/clang/Basic/OpenCLOptions.h +++ b/clang/include/clang/Basic/OpenCLOptions.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_BASIC_OPENCLOPTIONS_H #define LLVM_CLANG_BASIC_OPENCLOPTIONS_H +#include "clang/Basic/LangOptions.h" #include "llvm/ADT/StringMap.h" namespace clang { @@ -42,25 +43,29 @@ class OpenCLOptions { // Is supported as either an extension or an (optional) core feature for // OpenCL version \p CLVer. - bool isSupported(llvm::StringRef Ext, unsigned CLVer) const { + bool isSupported(llvm::StringRef Ext, LangOptions LO) const { + // In C++ mode all extensions should work at least as in v2.0. + auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; auto I = OptMap.find(Ext)->getValue(); return I.Supported && I.Avail <= CLVer; } // Is supported (optional) OpenCL core features for OpenCL version \p CLVer. // For supported extension, return false. - bool isSupportedCore(llvm::StringRef Ext, unsigned CLVer) const { + bool isSupportedCore(llvm::StringRef Ext, LangOptions LO) const { + // In C++ mode all extensions should work at least as in v2.0. + auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; auto I = OptMap.find(Ext)->getValue(); - return I.Supported && I.Avail <= CLVer && - I.Core != ~0U && CLVer >= I.Core; + return I.Supported && I.Avail <= CLVer && I.Core != ~0U && CLVer >= I.Core; } // Is supported OpenCL extension for OpenCL version \p CLVer. // For supported (optional) core feature, return false. - bool isSupportedExtension(llvm::StringRef Ext, unsigned CLVer) const { + bool isSupportedExtension(llvm::StringRef Ext, LangOptions LO) const { + // In C++ mode all extensions should work at least as in v2.0. + auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion; auto I = OptMap.find(Ext)->getValue(); - return I.Supported && I.Avail <= CLVer && - (I.Core == ~0U || CLVer < I.Core); + return I.Supported && I.Avail <= CLVer && (I.Core == ~0U || CLVer < I.Core); } void enable(llvm::StringRef Ext, bool V = true) { @@ -122,10 +127,10 @@ class OpenCLOptions { I->second.Enabled = false; } - void enableSupportedCore(unsigned CLVer) { - for (llvm::StringMap::iterator I = OptMap.begin(), - E = OptMap.end(); I != E; ++I) - if (isSupportedCore(I->getKey(), CLVer)) + void enableSupportedCore(LangOptions LO) { + for (llvm::StringMap::iterator I = OptMap.begin(), E = OptMap.end(); + I != E; ++I) + if (isSupportedCore(I->getKey(), LO)) I->second.Enabled = true; } @@ -133,6 +138,6 @@ class OpenCLOptions { friend class ASTReader; }; -} // end namespace clang +} // end namespace clang #endif diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 786b1c251ca82..c95cf599ffd4a 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -64,6 +64,7 @@ class TargetInfo : public RefCountedBase { bool HasLegalHalfType; // True if the backend supports operations on the half // LLVM IR type. bool HasFloat128; + bool HasFloat16; unsigned char PointerWidth, PointerAlign; unsigned char BoolWidth, BoolAlign; unsigned char IntWidth, IntAlign; @@ -517,6 +518,9 @@ class TargetInfo : public RefCountedBase { /// Determine whether the __float128 type is supported on this target. virtual bool hasFloat128Type() const { return HasFloat128; } + /// Determine whether the _Float16 type is supported on this target. + virtual bool hasFloat16Type() const { return HasFloat16; } + /// Return the alignment that is suitable for storing any /// object with a fundamental alignment requirement. unsigned getSuitableAlign() const { return SuitableAlign; } @@ -803,6 +807,7 @@ class TargetInfo : public RefCountedBase { struct { int Min; int Max; + bool isConstrained; } ImmRange; llvm::SmallSet ImmSet; @@ -813,6 +818,7 @@ class TargetInfo : public RefCountedBase { : Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()), Name(Name.str()) { ImmRange.Min = ImmRange.Max = 0; + ImmRange.isConstrained = false; } const std::string &getConstraintStr() const { return ConstraintStr; } @@ -841,8 +847,9 @@ class TargetInfo : public RefCountedBase { return (Flags & CI_ImmediateConstant) != 0; } bool isValidAsmImmediate(const llvm::APInt &Value) const { - return (Value.sge(ImmRange.Min) && Value.sle(ImmRange.Max)) || - ImmSet.count(Value.getZExtValue()) != 0; + if (!ImmSet.empty()) + return ImmSet.count(Value.getZExtValue()) != 0; + return !ImmRange.isConstrained || (Value.sge(ImmRange.Min) && Value.sle(ImmRange.Max)); } void setIsReadWrite() { Flags |= CI_ReadWrite; } @@ -854,6 +861,7 @@ class TargetInfo : public RefCountedBase { Flags |= CI_ImmediateConstant; ImmRange.Min = Min; ImmRange.Max = Max; + ImmRange.isConstrained = true; } void setRequiresImmediate(llvm::ArrayRef Exacts) { Flags |= CI_ImmediateConstant; @@ -866,8 +874,6 @@ class TargetInfo : public RefCountedBase { } void setRequiresImmediate() { Flags |= CI_ImmediateConstant; - ImmRange.Min = INT_MIN; - ImmRange.Max = INT_MAX; } /// Indicate that this is an input operand that is tied to diff --git a/clang/include/clang/Driver/CLCompatOptions.td b/clang/include/clang/Driver/CLCompatOptions.td index 3e0dc2db7d07e..ca23f7b819654 100644 --- a/clang/include/clang/Driver/CLCompatOptions.td +++ b/clang/include/clang/Driver/CLCompatOptions.td @@ -395,7 +395,9 @@ def _SLASH_Zo_ : CLIgnoredFlag<"Zo-">; // Unsupported: -def _SLASH_AI : CLJoined<"AI">; +def _SLASH_await : CLFlag<"await">; +def _SLASH_constexpr : CLJoined<"constexpr:">; +def _SLASH_AI : CLJoinedOrSeparate<"AI">; def _SLASH_Bt : CLFlag<"Bt">; def _SLASH_Bt_plus : CLFlag<"Bt+">; def _SLASH_clr : CLJoined<"clr">; @@ -430,6 +432,9 @@ def _SLASH_Qfast_transcendentals : CLFlag<"Qfast_transcendentals">; def _SLASH_QIfist : CLFlag<"QIfist">; def _SLASH_Qimprecise_fwaits : CLFlag<"Qimprecise_fwaits">; def _SLASH_Qpar : CLFlag<"Qpar">; +def _SLASH_Qpar_report : CLJoined<"Qpar-report">; +def _SLASH_Qsafe_fp_loads : CLFlag<"Qsafe_fp_loads">; +def _SLASH_Qspectre : CLFlag<"Qspectre">; def _SLASH_Qvec_report : CLJoined<"Qvec-report">; def _SLASH_u : CLFlag<"u">; def _SLASH_V : CLFlag<"V">; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index f02a7190f5a7a..d02d9744d78d4 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -552,9 +552,9 @@ def cuda_compile_host_device : Flag<["--"], "cuda-compile-host-device">, HelpText<"Compile CUDA code for both host and device (default). Has no " "effect on non-CUDA compilations.">; def cuda_include_ptx_EQ : Joined<["--"], "cuda-include-ptx=">, Flags<[DriverOption]>, - HelpText<"Include PTX for the follwing GPU architecture (e.g. sm_35) or 'all'. May be specified more than once.">; + HelpText<"Include PTX for the following GPU architecture (e.g. sm_35) or 'all'. May be specified more than once.">; def no_cuda_include_ptx_EQ : Joined<["--"], "no-cuda-include-ptx=">, Flags<[DriverOption]>, - HelpText<"Do not include PTX for the follwing GPU architecture (e.g. sm_35) or 'all'. May be specified more than once.">; + HelpText<"Do not include PTX for the following GPU architecture (e.g. sm_35) or 'all'. May be specified more than once.">; def cuda_gpu_arch_EQ : Joined<["--"], "cuda-gpu-arch=">, Flags<[DriverOption]>, HelpText<"CUDA GPU architecture (e.g. sm_35). May be specified more than once.">; def hip_link : Flag<["--"], "hip-link">, @@ -2418,6 +2418,14 @@ def modd_spreg : Flag<["-"], "modd-spreg">, Group, def mno_odd_spreg : Flag<["-"], "mno-odd-spreg">, Group, HelpText<"Disable odd single-precision floating point registers">, Flags<[HelpHidden]>; +def mrelax_pic_calls : Flag<["-"], "mrelax-pic-calls">, + Group, + HelpText<"Try turning PIC calls (j{al}r{c} $25) into direct calls " + "(MIPS only)">, Flags<[HelpHidden]>; +def mno_relax_pic_calls : Flag<["-"], "mno-relax-pic-calls">, + Group, + HelpText<"Do not try turning PIC calls (j{al}r{c} $25) into direct calls " + "(MIPS only)">, Flags<[HelpHidden]>; def mglibc : Flag<["-"], "mglibc">, Group, Flags<[HelpHidden]>; def muclibc : Flag<["-"], "muclibc">, Group, Flags<[HelpHidden]>; def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1Option]>, Group, diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 438ff0e2ed450..46e4431913e76 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -360,11 +360,6 @@ class Parser : public CodeCompletionHandler { /// just a regular sub-expression. SourceLocation ExprStatementTokLoc; - /// Tests whether an expression value is discarded based on token lookahead. - /// It will return true if the lexer is currently processing the }) - /// terminating a GNU statement expression and false otherwise. - bool isExprValueDiscarded(); - public: Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies); ~Parser() override; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e5b7465820a98..ced5773f0c073 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1369,7 +1369,6 @@ class Sema { void PopCompoundScope(); sema::CompoundScopeInfo &getCurCompoundScope() const; - bool isCurCompoundStmtAStmtExpr() const; bool hasAnyUnrecoverableErrorsInThisFunction() const; @@ -3690,17 +3689,16 @@ class Sema { return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation()); } FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) { - return FullExprArg( - ActOnFinishFullExpr(Arg, CC, /*DiscardedValue*/ false).get()); + return FullExprArg(ActOnFinishFullExpr(Arg, CC).get()); } FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) { ExprResult FE = - ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(), - /*DiscardedValue*/ true); + ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(), + /*DiscardedValue*/ true); return FullExprArg(FE.get()); } - StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true); + StmtResult ActOnExprStmt(ExprResult Arg); StmtResult ActOnExprStmtError(); StmtResult ActOnNullStmt(SourceLocation SemiLoc, @@ -5346,12 +5344,13 @@ class Sema { CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, bool BoundToLvalueReference); - ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue) { - return ActOnFinishFullExpr( - Expr, Expr ? Expr->getExprLoc() : SourceLocation(), DiscardedValue); + ExprResult ActOnFinishFullExpr(Expr *Expr) { + return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc() + : SourceLocation()); } ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC, - bool DiscardedValue, bool IsConstexpr = false); + bool DiscardedValue = false, + bool IsConstexpr = false); StmtResult ActOnFinishFullStmt(Stmt *Stmt); // Marks SS invalid if it represents an incomplete type. diff --git a/clang/include/clang/Tooling/ArgumentsAdjusters.h b/clang/include/clang/Tooling/ArgumentsAdjusters.h index 94ccf1f34e576..e31839b9a8f73 100644 --- a/clang/include/clang/Tooling/ArgumentsAdjusters.h +++ b/clang/include/clang/Tooling/ArgumentsAdjusters.h @@ -61,6 +61,10 @@ ArgumentsAdjuster getInsertArgumentAdjuster( const char *Extra, ArgumentInsertPosition Pos = ArgumentInsertPosition::END); +/// Gets an argument adjuster which strips plugin related command line +/// arguments. +ArgumentsAdjuster getStripPluginsAdjuster(); + /// Gets an argument adjuster which adjusts the arguments in sequence /// with the \p First adjuster and then with the \p Second one. ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First, diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index c05b160b8e3d9..0c2ba57f7986b 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -600,6 +600,26 @@ std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const { return Result; } +bool APValue::toIntegralConstant(APSInt &Result, QualType SrcTy, + const ASTContext &Ctx) const { + if (isInt()) { + Result = getInt(); + return true; + } + + if (isLValue() && isNullPointer()) { + Result = Ctx.MakeIntValue(Ctx.getTargetNullPointerValue(SrcTy), SrcTy); + return true; + } + + if (isLValue() && !getLValueBase()) { + Result = Ctx.MakeIntValue(getLValueOffset().getQuantity(), SrcTy); + return true; + } + + return false; +} + const APValue::LValueBase APValue::getLValueBase() const { assert(isLValue() && "Invalid accessor"); return ((const LV*)(const void*)Data.buffer)->Base; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index da093ff22c123..bfe6c78a0ddcb 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9821,13 +9821,12 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { return true; } - uint64_t V; - if (LV.isNullPointer()) - V = Info.Ctx.getTargetNullPointerValue(SrcType); - else - V = LV.getLValueOffset().getQuantity(); + APSInt AsInt; + APValue V; + LV.moveInto(V); + if (!V.toIntegralConstant(AsInt, SrcType, Info.Ctx)) + llvm_unreachable("Can't cast this!"); - APSInt AsInt = Info.Ctx.MakeIntValue(V, SrcType); return Success(HandleIntToIntCast(Info, E, DestType, SrcType, AsInt), E); } @@ -10986,6 +10985,7 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage, const ASTContext &Ctx) const { EvalInfo::EvaluationMode EM = EvalInfo::EM_ConstantExpression; EvalInfo Info(Ctx, Result, EM); + Info.InConstantContext = true; if (!::Evaluate(Result.Val, Info, this)) return false; @@ -11626,6 +11626,7 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, const Expr *This) const { Expr::EvalStatus Status; EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated); + Info.InConstantContext = true; LValue ThisVal; const LValue *ThisPtr = nullptr; @@ -11709,6 +11710,7 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E, EvalInfo Info(FD->getASTContext(), Status, EvalInfo::EM_PotentialConstantExpressionUnevaluated); + Info.InConstantContext = true; // Fabricate a call stack frame to give the arguments a plausible cover story. ArrayRef Args; diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 92e9679e49aa3..896c4a1cf2b39 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1937,8 +1937,9 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, // ::= _M # unsigned __int128 // ::= _N # bool // _O # - // ::= _T # __float80 (Intel) + // ::= _Q # char8_t // ::= _S # char16_t + // ::= _T # __float80 (Intel) // ::= _U # char32_t // ::= _W # wchar_t // ::= _Z # __float80 (Digital Mars) @@ -1999,6 +2000,9 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, case BuiltinType::Bool: Out << "_N"; break; + case BuiltinType::Char8: + Out << "_Q"; + break; case BuiltinType::Char16: Out << "_S"; break; @@ -2094,7 +2098,6 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, case BuiltinType::SatUShortFract: case BuiltinType::SatUFract: case BuiltinType::SatULongFract: - case BuiltinType::Char8: case BuiltinType::Float128: { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID( diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp index f5a2d4894c13e..01ec1d69cde53 100644 --- a/clang/lib/Basic/FileManager.cpp +++ b/clang/lib/Basic/FileManager.cpp @@ -189,21 +189,15 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, *SeenFileEntries.insert(std::make_pair(Filename, nullptr)).first; // See if there is already an entry in the map. - if (NamedFileEnt.second) { - if (NamedFileEnt.second == NON_EXISTENT_FILE) - return nullptr; - // Entry exists: return it *unless* it wasn't opened and open is requested. - if (!(NamedFileEnt.second->DeferredOpen && openFile)) - return NamedFileEnt.second; - // We previously stat()ed the file, but didn't open it: do that below. - // FIXME: the below does other redundant work too (stats the dir and file). - } else { - // By default, initialize it to invalid. - NamedFileEnt.second = NON_EXISTENT_FILE; - } + if (NamedFileEnt.second) + return NamedFileEnt.second == NON_EXISTENT_FILE ? nullptr + : NamedFileEnt.second; ++NumFileCacheMisses; + // By default, initialize it to invalid. + NamedFileEnt.second = NON_EXISTENT_FILE; + // Get the null-terminated file name as stored as the key of the // SeenFileEntries map. StringRef InterndFileName = NamedFileEnt.first(); @@ -241,7 +235,6 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, // It exists. See if we have already opened a file with the same inode. // This occurs when one dir is symlinked to another, for example. FileEntry &UFE = UniqueRealFiles[Data.UniqueID]; - UFE.DeferredOpen = !openFile; NamedFileEnt.second = &UFE; @@ -258,15 +251,6 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, InterndFileName = NamedFileEnt.first().data(); } - // If we opened the file for the first time, record the resulting info. - // Do this even if the cache entry was valid, maybe we didn't previously open. - if (F && !UFE.File) { - if (auto PathName = F->getName()) - fillRealPathName(&UFE, *PathName); - UFE.File = std::move(F); - assert(!UFE.DeferredOpen && "we just opened it!"); - } - if (UFE.isValid()) { // Already have an entry with this inode, return it. // FIXME: this hack ensures that if we look up a file by a virtual path in @@ -297,9 +281,13 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile, UFE.UniqueID = Data.UniqueID; UFE.IsNamedPipe = Data.IsNamedPipe; UFE.InPCH = Data.InPCH; + UFE.File = std::move(F); UFE.IsValid = true; - // Note File and DeferredOpen were initialized above. + if (UFE.File) { + if (auto PathName = UFE.File->getName()) + fillRealPathName(&UFE, *PathName); + } return &UFE; } @@ -371,7 +359,6 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size, UFE->UID = NextFileUID++; UFE->IsValid = true; UFE->File.reset(); - UFE->DeferredOpen = false; return UFE; } diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 269fad38b8d57..8b7621d7962e1 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -35,6 +35,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) { NoAsmVariants = false; HasLegalHalfType = false; HasFloat128 = false; + HasFloat16 = false; PointerWidth = PointerAlign = 32; BoolWidth = BoolAlign = 8; IntWidth = IntAlign = 32; diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index cf87bc484621c..3c139d724796e 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -570,19 +570,27 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, Triple.getVendor() != llvm::Triple::UnknownVendor || !Triple.isOSBinFormatWasm()) return nullptr; - if (Triple.getOS() != llvm::Triple::UnknownOS && - Triple.getOS() != llvm::Triple::WASI) - return nullptr; - return new WebAssemblyOSTargetInfo(Triple, Opts); + switch (Triple.getOS()) { + case llvm::Triple::WASI: + return new WASITargetInfo(Triple, Opts); + case llvm::Triple::UnknownOS: + return new WebAssemblyOSTargetInfo(Triple, Opts); + default: + return nullptr; + } case llvm::Triple::wasm64: if (Triple.getSubArch() != llvm::Triple::NoSubArch || Triple.getVendor() != llvm::Triple::UnknownVendor || !Triple.isOSBinFormatWasm()) return nullptr; - if (Triple.getOS() != llvm::Triple::UnknownOS && - Triple.getOS() != llvm::Triple::WASI) - return nullptr; - return new WebAssemblyOSTargetInfo(Triple, Opts); + switch (Triple.getOS()) { + case llvm::Triple::WASI: + return new WASITargetInfo(Triple, Opts); + case llvm::Triple::UnknownOS: + return new WebAssemblyOSTargetInfo(Triple, Opts); + default: + return nullptr; + } case llvm::Triple::renderscript32: return new LinuxTargetInfo(Triple, Opts); diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 62919a02dcb9f..6297f23c5aa47 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -50,6 +50,7 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple, // All AArch64 implementations support ARMv8 FP, which makes half a legal type. HasLegalHalfType = true; + HasFloat16 = true; LongWidth = LongAlign = PointerWidth = PointerAlign = 64; MaxVectorAlign = 128; diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp index 16644ace108b7..23eee34eaa93d 100644 --- a/clang/lib/Basic/Targets/ARM.cpp +++ b/clang/lib/Basic/Targets/ARM.cpp @@ -397,6 +397,7 @@ bool ARMTargetInfo::handleTargetFeatures(std::vector &Features, SoftFloat = SoftFloatABI = false; HWDiv = 0; DotProd = 0; + HasFloat16 = true; // This does not diagnose illegal cases like having both // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp". diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h index 085efa02cc5f1..09867d82c382e 100644 --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -764,8 +764,9 @@ class LLVM_LIBRARY_VISIBILITY FuchsiaTargetInfo : public OSTargetInfo { template class LLVM_LIBRARY_VISIBILITY WebAssemblyOSTargetInfo : public OSTargetInfo { +protected: void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, - MacroBuilder &Builder) const final { + MacroBuilder &Builder) const { // A common platform macro. if (Opts.POSIXThreads) Builder.defineMacro("_REENTRANT"); @@ -783,6 +784,21 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyOSTargetInfo } }; +// WASI target +template +class LLVM_LIBRARY_VISIBILITY WASITargetInfo + : public WebAssemblyOSTargetInfo { + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const final { + WebAssemblyOSTargetInfo::getOSDefines(Opts, Triple, Builder); + Builder.defineMacro("__wasi__"); + } + +public: + explicit WASITargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : WebAssemblyOSTargetInfo(Triple, Opts) {} +}; + } // namespace targets } // namespace clang #endif // LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index 058970a0e098b..cbe7a9a2fa85e 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -331,9 +331,15 @@ class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public PPCTargetInfo { break; } - if (getTriple().isOSFreeBSD()) { + switch (getTriple().getOS()) { + case llvm::Triple::FreeBSD: + case llvm::Triple::NetBSD: + case llvm::Triple::OpenBSD: LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + break; + default: + break; } // PPC32 supports atomics up to 4 bytes. diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index 9815292fc276d..e8d92f11a1224 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -48,6 +48,7 @@ class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public TargetInfo { AddrSpaceMap = &SPIRAddrSpaceMap; UseAddrSpaceMapMangling = true; HasLegalHalfType = true; + HasFloat16 = true; // Define available target features // These must be defined in sorted order! NoAsmVariants = true; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index a718f2f19aa65..ccc657493b28b 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -7052,19 +7052,16 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, llvm::Value *Metadata = llvm::MetadataAsValue::get(Context, RegName); llvm::Type *RegisterType = Int64Ty; - llvm::Type *ValueType = Int32Ty; llvm::Type *Types[] = { RegisterType }; if (BuiltinID == AArch64::BI_ReadStatusReg) { llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::read_register, Types); - llvm::Value *Call = Builder.CreateCall(F, Metadata); - return Builder.CreateTrunc(Call, ValueType); + return Builder.CreateCall(F, Metadata); } llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::write_register, Types); llvm::Value *ArgValue = EmitScalarExpr(E->getArg(1)); - ArgValue = Builder.CreateZExt(ArgValue, RegisterType); return Builder.CreateCall(F, { Metadata, ArgValue }); } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 41f8721468a32..ad1a9157a127a 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1817,32 +1817,24 @@ CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD, } llvm::DINodeArray CGDebugInfo::CollectVarTemplateParams(const VarDecl *VL, - llvm::DIFile *Unit) { - if (auto *TS = dyn_cast(VL)) { - auto T = TS->getSpecializedTemplateOrPartial(); - auto TA = TS->getTemplateArgs().asArray(); - // Collect parameters for a partial specialization - if (T.is()) { - const TemplateParameterList *TList = - T.get() - ->getTemplateParameters(); - return CollectTemplateParams(TList, TA, Unit); - } - - // Collect parameters for an explicit specialization - if (T.is()) { - const TemplateParameterList *TList = T.get() - ->getTemplateParameters(); - return CollectTemplateParams(TList, TA, Unit); - } - } - return llvm::DINodeArray(); + llvm::DIFile *Unit) { + // Always get the full list of parameters, not just the ones from the + // specialization. A partial specialization may have fewer parameters than + // there are arguments. + auto *TS = dyn_cast(VL); + if (!TS) + return llvm::DINodeArray(); + VarTemplateDecl *T = TS->getSpecializedTemplate(); + const TemplateParameterList *TList = T->getTemplateParameters(); + auto TA = TS->getTemplateArgs().asArray(); + return CollectTemplateParams(TList, TA, Unit); } llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams( const ClassTemplateSpecializationDecl *TSpecial, llvm::DIFile *Unit) { - // Always get the full list of parameters, not just the ones from - // the specialization. + // Always get the full list of parameters, not just the ones from the + // specialization. A partial specialization may have fewer parameters than + // there are arguments. TemplateParameterList *TPList = TSpecial->getSpecializedTemplate()->getTemplateParameters(); const TemplateArgumentList &TAList = TSpecial->getTemplateArgs(); diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 5959d889b4551..790a8df3d7e41 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1620,8 +1620,9 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { bool capturedByInit = Init && emission.IsEscapingByRef && isCapturedBy(D, Init); - Address Loc = - capturedByInit ? emission.Addr : emission.getObjectAddress(*this); + bool locIsByrefHeader = !capturedByInit; + const Address Loc = + locIsByrefHeader ? emission.getObjectAddress(*this) : emission.Addr; // Note: constexpr already initializes everything correctly. LangOptions::TrivialAutoVarInitKind trivialAutoVarInit = @@ -1631,11 +1632,15 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { ? LangOptions::TrivialAutoVarInitKind::Uninitialized : getContext().getLangOpts().getTrivialAutoVarInit())); - auto initializeWhatIsTechnicallyUninitialized = [&]() { + auto initializeWhatIsTechnicallyUninitialized = [&](Address Loc) { if (trivialAutoVarInit == LangOptions::TrivialAutoVarInitKind::Uninitialized) return; + // Only initialize a __block's storage: we always initialize the header. + if (emission.IsEscapingByRef && !locIsByrefHeader) + Loc = emitBlockByrefAddress(Loc, &D, /*follow=*/false); + CharUnits Size = getContext().getTypeSizeInChars(type); if (!Size.isZero()) { switch (trivialAutoVarInit) { @@ -1713,7 +1718,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { }; if (isTrivialInitializer(Init)) { - initializeWhatIsTechnicallyUninitialized(); + initializeWhatIsTechnicallyUninitialized(Loc); return; } @@ -1727,7 +1732,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { } if (!constant) { - initializeWhatIsTechnicallyUninitialized(); + initializeWhatIsTechnicallyUninitialized(Loc); LValue lv = MakeAddrLValue(Loc, type); lv.setNonGC(true); return EmitExprAsInit(Init, &D, lv, capturedByInit); @@ -1741,10 +1746,9 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { } llvm::Type *BP = CGM.Int8Ty->getPointerTo(Loc.getAddressSpace()); - if (Loc.getType() != BP) - Loc = Builder.CreateBitCast(Loc, BP); - - emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant); + emitStoresForConstant( + CGM, D, (Loc.getType() == BP) ? Loc : Builder.CreateBitCast(Loc, BP), + isVolatile, Builder, constant); } /// Emit an expression as an initializer for an object (variable, field, etc.) diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 0242b48659d10..b2b32759b6f73 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -1821,8 +1821,15 @@ llvm::Value* CodeGenFunction::EmitAsmInput( // (immediate or symbolic), try to emit it as such. if (!Info.allowsRegister() && !Info.allowsMemory()) { if (Info.requiresImmediateConstant()) { - llvm::APSInt AsmConst = InputExpr->EvaluateKnownConstInt(getContext()); - return llvm::ConstantInt::get(getLLVMContext(), AsmConst); + Expr::EvalResult EVResult; + InputExpr->EvaluateAsRValue(EVResult, getContext(), true); + + llvm::APSInt IntResult; + if (!EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(), + getContext())) + llvm_unreachable("Invalid immediate constant!"); + + return llvm::ConstantInt::get(getLLVMContext(), IntResult); } Expr::EvalResult Result; diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index eb1304d89345e..44dc1cdee0b53 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -1518,8 +1518,9 @@ void CodeGenFunction::EmitOMPPrivateLoopCounters( I < E; ++I) { const auto *DRE = cast(C->getLoopCounter(I)); const auto *VD = cast(DRE->getDecl()); - // Override only those variables that are really emitted already. - if (LocalDeclMap.count(VD)) { + // Override only those variables that can be captured to avoid re-emission + // of the variables declared within the loops. + if (DRE->refersToEnclosingVariableOrCapture()) { (void)LoopScope.addPrivate(VD, [this, DRE, VD]() { return CreateMemTemp(DRE->getType(), VD->getName()); }); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 244738042cef0..2ac59fb4de25f 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3762,13 +3762,15 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context, } } - // Microsoft's link.exe doesn't support alignments greater than 32 for common - // symbols, so symbols with greater alignment requirements cannot be common. + // Microsoft's link.exe doesn't support alignments greater than 32 bytes for + // common symbols, so symbols with greater alignment requirements cannot be + // common. // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two // alignments for common symbols via the aligncomm directive, so this // restriction only applies to MSVC environments. if (Context.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() && - Context.getTypeAlignIfKnown(D->getType()) > 32) + Context.getTypeAlignIfKnown(D->getType()) > + Context.toBits(CharUnits::fromQuantity(32))) return true; return false; diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index b53304528c3d8..c56875a036809 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -2463,10 +2463,12 @@ ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD, CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Wrapper); // Always resolve references to the wrapper at link time. - if (!Wrapper->hasLocalLinkage() && !(isThreadWrapperReplaceable(VD, CGM) && - !llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) && - !llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()))) - Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility); + if (!Wrapper->hasLocalLinkage()) + if (!isThreadWrapperReplaceable(VD, CGM) || + llvm::GlobalVariable::isLinkOnceLinkage(Wrapper->getLinkage()) || + llvm::GlobalVariable::isWeakODRLinkage(Wrapper->getLinkage()) || + VD->getVisibility() == HiddenVisibility) + Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility); if (isThreadWrapperReplaceable(VD, CGM)) { Wrapper->setCallingConv(llvm::CallingConv::CXX_FAST_TLS); diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 89ec73670a735..94fccb15ff6ec 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -761,6 +761,22 @@ class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo { void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const override { + TargetCodeGenInfo::setTargetAttributes(D, GV, CGM); + if (const auto *FD = dyn_cast_or_null(D)) { + if (const auto *Attr = FD->getAttr()) { + llvm::Function *Fn = cast(GV); + llvm::AttrBuilder B; + B.addAttribute("wasm-import-module", Attr->getImportModule()); + Fn->addAttributes(llvm::AttributeList::FunctionIndex, B); + } + if (const auto *Attr = FD->getAttr()) { + llvm::Function *Fn = cast(GV); + llvm::AttrBuilder B; + B.addAttribute("wasm-import-name", Attr->getImportName()); + Fn->addAttributes(llvm::AttributeList::FunctionIndex, B); + } + } + if (auto *FD = dyn_cast_or_null(D)) { llvm::Function *Fn = cast(GV); if (!FD->doesThisDeclarationHaveABody() && !FD->hasPrototype()) @@ -6774,21 +6790,19 @@ void MSP430TargetCodeGenInfo::setTargetAttributes( if (GV->isDeclaration()) return; if (const FunctionDecl *FD = dyn_cast_or_null(D)) { - if (const MSP430InterruptAttr *attr = FD->getAttr()) { - // Handle 'interrupt' attribute: - llvm::Function *F = cast(GV); + const auto *InterruptAttr = FD->getAttr(); + if (!InterruptAttr) + return; - // Step 1: Set ISR calling convention. - F->setCallingConv(llvm::CallingConv::MSP430_INTR); + // Handle 'interrupt' attribute: + llvm::Function *F = cast(GV); - // Step 2: Add attributes goodness. - F->addFnAttr(llvm::Attribute::NoInline); + // Step 1: Set ISR calling convention. + F->setCallingConv(llvm::CallingConv::MSP430_INTR); - // Step 3: Emit ISR vector alias. - unsigned Num = attr->getNumber() / 2; - llvm::GlobalAlias::create(llvm::Function::ExternalLinkage, - "__isr_" + Twine(Num), F); - } + // Step 2: Add attributes goodness. + F->addFnAttr(llvm::Attribute::NoInline); + F->addFnAttr("interrupt", llvm::utostr(InterruptAttr->getNumber())); } } diff --git a/clang/lib/Driver/ToolChains/Arch/PPC.cpp b/clang/lib/Driver/ToolChains/Arch/PPC.cpp index 791f1206cf257..e83c263d29010 100644 --- a/clang/lib/Driver/ToolChains/Arch/PPC.cpp +++ b/clang/lib/Driver/ToolChains/Arch/PPC.cpp @@ -116,7 +116,7 @@ ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const llvm::Tripl const ArgList &Args) { if (Args.getLastArg(options::OPT_msecure_plt)) return ppc::ReadGOTPtrMode::SecurePlt; - if (Triple.isOSOpenBSD()) + if (Triple.isOSNetBSD() || Triple.isOSOpenBSD()) return ppc::ReadGOTPtrMode::SecurePlt; else return ppc::ReadGOTPtrMode::Bss; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 75f16898dfaf6..78ee7a78176ff 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -718,8 +718,9 @@ static void appendUserToPath(SmallVectorImpl &Result) { Result.append(UID.begin(), UID.end()); } -static void addPGOAndCoverageFlags(Compilation &C, const Driver &D, - const InputInfo &Output, const ArgList &Args, +static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, + const Driver &D, const InputInfo &Output, + const ArgList &Args, ArgStringList &CmdArgs) { auto *PGOGenerateArg = Args.getLastArg(options::OPT_fprofile_generate, @@ -759,6 +760,11 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D, ProfileGenerateArg->getValue())); // The default is to use Clang Instrumentation. CmdArgs.push_back("-fprofile-instrument=clang"); + if (TC.getTriple().isWindowsMSVCEnvironment()) { + // Add dependent lib for clang_rt.profile + CmdArgs.push_back(Args.MakeArgString("--dependent-lib=" + + TC.getCompilerRT(Args, "profile"))); + } } if (PGOGenerateArg) { @@ -1716,6 +1722,14 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args, } else D.Diag(diag::warn_target_unsupported_compact_branches) << CPUName; } + + if (Arg *A = Args.getLastArg(options::OPT_mrelax_pic_calls, + options::OPT_mno_relax_pic_calls)) { + if (A->getOption().matches(options::OPT_mno_relax_pic_calls)) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-mips-jalr-reloc=0"); + } + } } void Clang::AddPPCTargetArgs(const ArgList &Args, @@ -4110,7 +4124,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // sampling, overhead of call arc collection is way too high and there's no // way to collect the output. if (!Triple.isNVPTX()) - addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs); + addPGOAndCoverageFlags(TC, C, D, Output, Args, CmdArgs); if (auto *ABICompatArg = Args.getLastArg(options::OPT_fclang_abi_compat_EQ)) ABICompatArg->render(Args, CmdArgs); diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index 65ab9b2daf549..dfdfb18319abe 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -45,6 +45,7 @@ static std::string getMultiarchTriple(const Driver &D, TargetTriple.getEnvironment(); bool IsAndroid = TargetTriple.isAndroid(); bool IsMipsR6 = TargetTriple.getSubArch() == llvm::Triple::MipsSubArch_r6; + bool IsMipsN32Abi = TargetTriple.getEnvironment() == llvm::Triple::GNUABIN32; // For most architectures, just use whatever we have rather than trying to be // clever. @@ -103,33 +104,37 @@ static std::string getMultiarchTriple(const Driver &D, return "aarch64_be-linux-gnu"; break; case llvm::Triple::mips: { - std::string Arch = IsMipsR6 ? "mipsisa32r6" : "mips"; - if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-gnu")) - return Arch + "-linux-gnu"; + std::string MT = IsMipsR6 ? "mipsisa32r6-linux-gnu" : "mips-linux-gnu"; + if (D.getVFS().exists(SysRoot + "/lib/" + MT)) + return MT; break; } case llvm::Triple::mipsel: { if (IsAndroid) return "mipsel-linux-android"; - std::string Arch = IsMipsR6 ? "mipsisa32r6el" : "mipsel"; - if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-gnu")) - return Arch + "-linux-gnu"; + std::string MT = IsMipsR6 ? "mipsisa32r6el-linux-gnu" : "mipsel-linux-gnu"; + if (D.getVFS().exists(SysRoot + "/lib/" + MT)) + return MT; break; } case llvm::Triple::mips64: { - std::string Arch = IsMipsR6 ? "mipsisa64r6" : "mips64"; - std::string ABI = llvm::Triple::getEnvironmentTypeName(TargetEnvironment); - if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-" + ABI)) - return Arch + "-linux-" + ABI; + std::string MT = std::string(IsMipsR6 ? "mipsisa64r6" : "mips64") + + "-linux-" + (IsMipsN32Abi ? "gnuabin32" : "gnuabi64"); + if (D.getVFS().exists(SysRoot + "/lib/" + MT)) + return MT; + if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnu")) + return "mips64-linux-gnu"; break; } case llvm::Triple::mips64el: { if (IsAndroid) return "mips64el-linux-android"; - std::string Arch = IsMipsR6 ? "mipsisa64r6el" : "mips64el"; - std::string ABI = llvm::Triple::getEnvironmentTypeName(TargetEnvironment); - if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-" + ABI)) - return Arch + "-linux-" + ABI; + std::string MT = std::string(IsMipsR6 ? "mipsisa64r6el" : "mips64el") + + "-linux-" + (IsMipsN32Abi ? "gnuabin32" : "gnuabi64"); + if (D.getVFS().exists(SysRoot + "/lib/" + MT)) + return MT; + if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnu")) + return "mips64el-linux-gnu"; break; } case llvm::Triple::ppc: diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index 7e34b0df5c8cf..a164fd68e22e7 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -1408,10 +1408,10 @@ static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL, DAL.AddFlagArg( A, Opts.getOption(options::OPT_fno_omit_frame_pointer)); } else { - // Don't warn about /Oy- in 64-bit builds (where + // Don't warn about /Oy- in x86-64 builds (where // SupportsForcingFramePointer is false). The flag having no effect // there is a compiler-internal optimization, and people shouldn't have - // to special-case their build files for 64-bit clang-cl. + // to special-case their build files for x86-64 clang-cl. A->claim(); } break; @@ -1442,8 +1442,8 @@ MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); const OptTable &Opts = getDriver().getOpts(); - // /Oy and /Oy- only has an effect under X86-32. - bool SupportsForcingFramePointer = getArch() == llvm::Triple::x86; + // /Oy and /Oy- don't have an effect on X86-64 + bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64; // The -O[12xd] flag actually expands to several flags. We must desugar the // flags so that options embedded can be negated. For example, the '-O2' flag diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp index b1321cacaf7a3..c1eae5b05acec 100644 --- a/clang/lib/Driver/ToolChains/NetBSD.cpp +++ b/clang/lib/Driver/ToolChains/NetBSD.cpp @@ -256,6 +256,13 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); + const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(); + if (SanArgs.needsSharedRt()) { + CmdArgs.push_back("-rpath"); + CmdArgs.push_back(Args.MakeArgString( + ToolChain.getCompilerRTPath().c_str())); + } + unsigned Major, Minor, Micro; ToolChain.getTriple().getOSVersion(Major, Minor, Micro); bool useLibgcc = true; diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp index 3d35d37b7db32..6b02e68965df1 100644 --- a/clang/lib/Driver/ToolChains/OpenBSD.cpp +++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp @@ -227,9 +227,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend))); } - const char *Exec = Args.MakeArgString( - !NeedsSanitizerDeps ? ToolChain.GetLinkerPath() - : ToolChain.GetProgramPath("ld.lld")); + const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); } diff --git a/clang/lib/Frontend/InitHeaderSearch.cpp b/clang/lib/Frontend/InitHeaderSearch.cpp index ac3bb713ddccc..67842b5dca296 100644 --- a/clang/lib/Frontend/InitHeaderSearch.cpp +++ b/clang/lib/Frontend/InitHeaderSearch.cpp @@ -433,14 +433,6 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths( case llvm::Triple::DragonFly: AddPath("/usr/include/c++/5.0", CXXSystem, false); break; - case llvm::Triple::OpenBSD: { - std::string t = triple.getTriple(); - if (t.substr(0, 6) == "x86_64") - t.replace(0, 6, "amd64"); - AddGnuCPlusPlusIncludePaths("/usr/include/g++", - t, "", "", triple); - break; - } case llvm::Triple::Minix: AddGnuCPlusPlusIncludePaths("/usr/gnu/include/c++/4.4.3", "", "", "", triple); diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 66807b097d407..4cde22ce9aa44 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -1059,10 +1059,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI, // OpenCL definitions. if (LangOpts.OpenCL) { -#define OPENCLEXT(Ext) \ - if (TI.getSupportedOpenCLOpts().isSupported(#Ext, \ - LangOpts.OpenCLVersion)) \ - Builder.defineMacro(#Ext); +#define OPENCLEXT(Ext) \ + if (TI.getSupportedOpenCLOpts().isSupported(#Ext, LangOpts)) \ + Builder.defineMacro(#Ext); #include "clang/Basic/OpenCLExtensions.def" auto Arch = TI.getTriple().getArch(); diff --git a/clang/lib/Frontend/TextDiagnostic.cpp b/clang/lib/Frontend/TextDiagnostic.cpp index 35b99b10f94a4..8b18fcccb4623 100644 --- a/clang/lib/Frontend/TextDiagnostic.cpp +++ b/clang/lib/Frontend/TextDiagnostic.cpp @@ -838,7 +838,7 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, if (LangOpts.MSCompatibilityVersion && !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015)) OS << ' '; - OS << ": "; + OS << ':'; break; } diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h index c86f41faeb88a..966258bab4b32 100644 --- a/clang/lib/Headers/intrin.h +++ b/clang/lib/Headers/intrin.h @@ -564,8 +564,8 @@ __nop(void) { #if defined(__aarch64__) unsigned __int64 __getReg(int); long _InterlockedAdd(long volatile *Addend, long Value); -int _ReadStatusReg(int); -void _WriteStatusReg(int, int); +__int64 _ReadStatusReg(int); +void _WriteStatusReg(int, __int64); static inline unsigned short _byteswap_ushort (unsigned short val) { return __builtin_bswap16(val); diff --git a/clang/lib/Headers/opencl-c.h b/clang/lib/Headers/opencl-c.h index 160bae807174c..3d3dfb74905f6 100644 --- a/clang/lib/Headers/opencl-c.h +++ b/clang/lib/Headers/opencl-c.h @@ -14470,7 +14470,7 @@ half16 __ovld __cnfn shuffle2(half16 x, half16 y, ushort16 mask); #if __OPENCL_C_VERSION__ >= CL_VERSION_1_2 // OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf -int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2))); +int printf(__constant const char* st, ...); #endif // OpenCL v1.1 s6.11.3, v1.2 s6.12.14, v2.0 s6.13.14 - Image Read and Write Functions diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index fa0815eb9c6c5..3c1da075b0e26 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -617,10 +617,11 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, if (isHalf || isFloat || isLong || isFloat128) break; // HF, FF, LF, QF invalid. - if (s + 2 < ThisTokEnd && s[1] == '1' && s[2] == '6') { - s += 2; // success, eat up 2 characters. - isFloat16 = true; - continue; + if (PP.getTargetInfo().hasFloat16Type() && s + 2 < ThisTokEnd && + s[1] == '1' && s[2] == '6') { + s += 2; // success, eat up 2 characters. + isFloat16 = true; + continue; } isFloat = true; diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index bd55f71793995..c8d7bda3d6e91 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -2741,7 +2741,7 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) { // Otherwise, eat the semicolon. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - return Actions.ActOnExprStmt(Res, isExprValueDiscarded()); + return Actions.ActOnExprStmt(Res); } ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index dd2a8aae9f2fb..17c3fa3cf2aa5 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -314,7 +314,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); ExprResult CombinerResult = Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(), - D->getLocation(), /*DiscardedValue*/ false); + D->getLocation(), /*DiscardedValue=*/true); Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && @@ -356,7 +356,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { if (Actions.getLangOpts().CPlusPlus) { InitializerResult = Actions.ActOnFinishFullExpr( ParseAssignmentExpression().get(), D->getLocation(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); } else { ConsumeToken(); ParseOpenMPReductionInitializerForDecl(OmpPrivParm); @@ -364,7 +364,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { } else { InitializerResult = Actions.ActOnFinishFullExpr( ParseAssignmentExpression().get(), D->getLocation(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); } Actions.ActOnOpenMPDeclareReductionInitializerEnd( D, InitializerResult.get(), OmpPrivParm); @@ -1455,7 +1455,7 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, ExprResult LHS(ParseCastExpression( /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast)); ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); - Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); + Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); // Parse ')'. RLoc = Tok.getLocation(); @@ -1711,8 +1711,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, SourceLocation ELoc = Tok.getLocation(); ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); - Val = - Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); + Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); } // Parse ')'. @@ -1997,8 +1996,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Data.ColonLoc = Tok.getLocation(); SourceLocation ELoc = ConsumeToken(); ExprResult Tail = ParseAssignmentExpression(); - Tail = - Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); + Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc); if (Tail.isUsable()) Data.TailExpr = Tail.get(); else diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 380eb64997a71..7e9b1011e81af 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -693,13 +693,12 @@ void Parser::HandlePragmaOpenCLExtension() { if (Name == "all") { if (State == Disable) { Opt.disableAll(); - Opt.enableSupportedCore(getLangOpts().OpenCLVersion); + Opt.enableSupportedCore(getLangOpts()); } else { PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1; } } else if (State == Begin) { - if (!Opt.isKnown(Name) || - !Opt.isSupported(Name, getLangOpts().OpenCLVersion)) { + if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) { Opt.support(Name); } Actions.setCurrentOpenCLExtension(Name); @@ -709,9 +708,9 @@ void Parser::HandlePragmaOpenCLExtension() { Actions.setCurrentOpenCLExtension(""); } else if (!Opt.isKnown(Name)) PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident; - else if (Opt.isSupportedExtension(Name, getLangOpts().OpenCLVersion)) + else if (Opt.isSupportedExtension(Name, getLangOpts())) Opt.enable(Name, State == Enable); - else if (Opt.isSupportedCore(Name, getLangOpts().OpenCLVersion)) + else if (Opt.isSupportedCore(Name, getLangOpts())) PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident; else PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident; diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 2974e6a245b0e..313793c3e8fb8 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -439,7 +439,7 @@ StmtResult Parser::ParseExprStatement() { // Otherwise, eat the semicolon. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - return Actions.ActOnExprStmt(Expr, isExprValueDiscarded()); + return Actions.ActOnExprStmt(Expr); } /// ParseSEHTryBlockCommon @@ -958,16 +958,6 @@ bool Parser::ConsumeNullStmt(StmtVector &Stmts) { return true; } -bool Parser::isExprValueDiscarded() { - if (Actions.isCurCompoundStmtAStmtExpr()) { - // Look to see if the next two tokens close the statement expression; - // if so, this expression statement is the last statement in a - // statment expression. - return Tok.isNot(tok::r_brace) || NextToken().isNot(tok::r_paren); - } - return true; -} - /// ParseCompoundStatementBody - Parse a sequence of statements and invoke the /// ActOnCompoundStmt action. This expects the '{' to be the current token, and /// consume the '}' at the end of the block. It does not manipulate the scope @@ -1072,7 +1062,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { // Eat the semicolon at the end of stmt and convert the expr into a // statement. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - R = Actions.ActOnExprStmt(Res, isExprValueDiscarded()); + R = Actions.ActOnExprStmt(Res); } } @@ -1708,16 +1698,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { if (!Value.isInvalid()) { if (ForEach) FirstPart = Actions.ActOnForEachLValueExpr(Value.get()); - else { - // We already know this is not an init-statement within a for loop, so - // if we are parsing a C++11 range-based for loop, we should treat this - // expression statement as being a discarded value expression because - // we will err below. This way we do not warn on an unused expression - // that was an error in the first place, like with: for (expr : expr); - bool IsRangeBasedFor = - getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon); - FirstPart = Actions.ActOnExprStmt(Value, !IsRangeBasedFor); - } + else + FirstPart = Actions.ActOnExprStmt(Value); } if (Tok.is(tok::semi)) { diff --git a/clang/lib/Parse/ParseStmtAsm.cpp b/clang/lib/Parse/ParseStmtAsm.cpp index 9b96c5150e569..3f5af7d44f36c 100644 --- a/clang/lib/Parse/ParseStmtAsm.cpp +++ b/clang/lib/Parse/ParseStmtAsm.cpp @@ -637,7 +637,7 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { // Filter out "fpsw" and "mxcsr". They aren't valid GCC asm clobber // constraints. Clang always adds fpsr to the clobber list anyway. llvm::erase_if(Clobbers, [](const std::string &C) { - return C == "fpsw" || C == "mxcsr"; + return C == "fpsr" || C == "mxcsr"; }); // Build the vector of clobber StringRefs. diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 9fa39968625a6..9d33ec5190924 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -256,11 +256,12 @@ void Sema::Initialize() { // Initialize predefined OpenCL types and supported extensions and (optional) // core features. if (getLangOpts().OpenCL) { - getOpenCLOptions().addSupport(Context.getTargetInfo().getSupportedOpenCLOpts()); - getOpenCLOptions().enableSupportedCore(getLangOpts().OpenCLVersion); + getOpenCLOptions().addSupport( + Context.getTargetInfo().getSupportedOpenCLOpts()); + getOpenCLOptions().enableSupportedCore(getLangOpts()); addImplicitTypedef("sampler_t", Context.OCLSamplerTy); addImplicitTypedef("event_t", Context.OCLEventTy); - if (getLangOpts().OpenCLVersion >= 200) { + if (getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) { addImplicitTypedef("clk_event_t", Context.OCLClkEventTy); addImplicitTypedef("queue_t", Context.OCLQueueTy); addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 8dc1fdb76988d..b2c727b5c483b 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -10622,16 +10622,16 @@ static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) { // The below checks assume source is floating point. if (!ResultBT || !RBT || !RBT->isFloatingPoint()) return; - // If source is floating point but target is not. - if (!ResultBT->isFloatingPoint()) - return DiagnoseFloatingImpCast(S, E, E->getRHS()->getType(), - E->getExprLoc()); - - // If both source and target are floating points. - // Builtin FP kinds are ordered by increasing FP rank. - if (ResultBT->getKind() < RBT->getKind() && - // We don't want to warn for system macro. - !S.SourceMgr.isInSystemMacro(E->getOperatorLoc())) + // If source is floating point but target is an integer. + if (ResultBT->isInteger()) + DiagnoseImpCast(S, E, E->getRHS()->getType(), E->getLHS()->getType(), + E->getExprLoc(), diag::warn_impcast_float_integer); + // If both source and target are floating points. Builtin FP kinds are ordered + // by increasing FP rank. FIXME: except _Float16, we currently emit a bogus + // warning. + else if (ResultBT->isFloatingPoint() && ResultBT->getKind() < RBT->getKind() && + // We don't want to warn for system macro. + !S.SourceMgr.isInSystemMacro(E->getOperatorLoc())) // warn about dropping FP rank. DiagnoseImpCast(S, E->getRHS(), E->getLHS()->getType(), E->getOperatorLoc(), diag::warn_impcast_float_result_precision); diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index d9f007a46da5e..980d7b455ecec 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -681,7 +681,8 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { T = Property->getType(); else if (const auto *Value = dyn_cast(ND)) T = Value->getType(); - else + + if (T.isNull()) return QualType(); // Dig through references, function pointers, and block pointers to diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 181efa6d3dd09..e282bb62f0326 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -646,7 +646,7 @@ bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc, return StmtError(); Suspend = BuildResolvedCoawaitExpr(Loc, Suspend.get(), /*IsImplicit*/ true); - Suspend = ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ false); + Suspend = ActOnFinishFullExpr(Suspend.get()); if (Suspend.isInvalid()) { Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required) << ((Name == "initial_suspend") ? 0 : 1); @@ -867,7 +867,7 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E, if (PC.isInvalid()) return StmtError(); - Expr *PCE = ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get(); + Expr *PCE = ActOnFinishFullExpr(PC.get()).get(); Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit); return Res; @@ -1236,7 +1236,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { ExprResult NewExpr = S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc); - NewExpr = S.ActOnFinishFullExpr(NewExpr.get(), /*DiscardedValue*/ false); + NewExpr = S.ActOnFinishFullExpr(NewExpr.get()); if (NewExpr.isInvalid()) return false; @@ -1262,8 +1262,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { ExprResult DeleteExpr = S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc); - DeleteExpr = - S.ActOnFinishFullExpr(DeleteExpr.get(), /*DiscardedValue*/ false); + DeleteExpr = S.ActOnFinishFullExpr(DeleteExpr.get()); if (DeleteExpr.isInvalid()) return false; @@ -1348,8 +1347,7 @@ bool CoroutineStmtBuilder::makeOnException() { ExprResult UnhandledException = buildPromiseCall(S, Fn.CoroutinePromise, Loc, "unhandled_exception", None); - UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc, - /*DiscardedValue*/ false); + UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc); if (UnhandledException.isInvalid()) return false; @@ -1402,8 +1400,7 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() { "get_return_object type must no longer be dependent"); if (FnRetType->isVoidType()) { - ExprResult Res = - S.ActOnFinishFullExpr(this->ReturnValue, Loc, /*DiscardedValue*/ false); + ExprResult Res = S.ActOnFinishFullExpr(this->ReturnValue, Loc); if (Res.isInvalid()) return false; @@ -1435,7 +1432,7 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() { if (Res.isInvalid()) return false; - Res = S.ActOnFinishFullExpr(Res.get(), /*DiscardedValue*/ false); + Res = S.ActOnFinishFullExpr(Res.get()); if (Res.isInvalid()) return false; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 23c99d45a78d4..7ddf2e88b7871 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11200,9 +11200,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // struct T { S a, b; } t = { Temp(), Temp() } // // we should destroy the first Temp before constructing the second. - ExprResult Result = - ActOnFinishFullExpr(Init, VDecl->getLocation(), - /*DiscardedValue*/ false, VDecl->isConstexpr()); + ExprResult Result = ActOnFinishFullExpr(Init, VDecl->getLocation(), + false, + VDecl->isConstexpr()); if (Result.isInvalid()) { VDecl->setInvalidDecl(); return; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 0e10804a2ec76..c4c3598ee7f3c 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5116,11 +5116,22 @@ static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D, static void handleObjCDesignatedInitializer(Sema &S, Decl *D, const ParsedAttr &AL) { + DeclContext *Ctx = D->getDeclContext(); + + // This attribute can only be applied to methods in interfaces or class + // extensions. + if (!isa(Ctx) && + !(isa(Ctx) && + cast(Ctx)->IsClassExtension())) { + S.Diag(D->getLocation(), diag::err_designated_init_attr_non_init); + return; + } + ObjCInterfaceDecl *IFace; - if (auto *CatDecl = dyn_cast(D->getDeclContext())) + if (auto *CatDecl = dyn_cast(Ctx)) IFace = CatDecl->getClassInterface(); else - IFace = cast(D->getDeclContext()); + IFace = cast(Ctx); if (!IFace) return; @@ -5377,6 +5388,27 @@ static void handleARMInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + // MSP430 'interrupt' attribute is applied to + // a function with no parameters and void return type. + if (!isFunctionOrMethod(D)) { + S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) + << "'interrupt'" << ExpectedFunctionOrMethod; + return; + } + + if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) { + S.Diag(D->getLocation(), diag::warn_msp430_interrupt_attribute) + << 0; + return; + } + + if (!getFunctionOrMethodResultType(D)->isVoidType()) { + S.Diag(D->getLocation(), diag::warn_msp430_interrupt_attribute) + << 1; + return; + } + + // The attribute takes one integer argument. if (!checkAttributeNumArgs(S, AL, 1)) return; @@ -5386,8 +5418,6 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } - // FIXME: Check for decl - it should be void ()(void). - Expr *NumParamsExpr = static_cast(AL.getArgAsExpr(0)); llvm::APSInt NumParams(32); if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { @@ -5396,9 +5426,9 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { << NumParamsExpr->getSourceRange(); return; } - + // The argument should be in range 0..63. unsigned Num = NumParams.getLimitedValue(255); - if ((Num & 1) || Num > 30) { + if (Num > 63) { S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) << AL << (int)NumParams.getSExtValue() << NumParamsExpr->getSourceRange(); @@ -5558,6 +5588,51 @@ static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) { handleSimpleAttribute(S, D, AL); } +static void handleWebAssemblyImportModuleAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (!isFunctionOrMethod(D)) { + S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) + << "'import_module'" << ExpectedFunction; + return; + } + + auto *FD = cast(D); + if (FD->isThisDeclarationADefinition()) { + S.Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0; + return; + } + + StringRef Str; + SourceLocation ArgLoc; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc)) + return; + + FD->addAttr(::new (S.Context) WebAssemblyImportModuleAttr( + AL.getRange(), S.Context, Str, + AL.getAttributeSpellingListIndex())); +} + +static void handleWebAssemblyImportNameAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (!isFunctionOrMethod(D)) { + S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) + << "'import_name'" << ExpectedFunction; + return; + } + + auto *FD = cast(D); + if (FD->isThisDeclarationADefinition()) { + S.Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0; + return; + } + + StringRef Str; + SourceLocation ArgLoc; + if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc)) + return; + + FD->addAttr(::new (S.Context) WebAssemblyImportNameAttr( + AL.getRange(), S.Context, Str, + AL.getAttributeSpellingListIndex())); +} static void handleRISCVInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { @@ -6311,6 +6386,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_AVRSignal: handleAVRSignalAttr(S, D, AL); break; + case ParsedAttr::AT_WebAssemblyImportModule: + handleWebAssemblyImportModuleAttr(S, D, AL); + break; + case ParsedAttr::AT_WebAssemblyImportName: + handleWebAssemblyImportNameAttr(S, D, AL); + break; case ParsedAttr::AT_IBAction: handleSimpleAttribute(S, D, AL); break; @@ -6997,6 +7078,17 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, } } } + + // Do this check after processing D's attributes because the attribute + // objc_method_family can change whether the given method is in the init + // family, and it can be applied after objc_designated_initializer. This is a + // bit of a hack, but we need it to be compatible with versions of clang that + // processed the attribute list in the wrong order. + if (D->hasAttr() && + cast(D)->getMethodFamily() != OMF_init) { + Diag(D->getLocation(), diag::err_designated_init_attr_non_init); + D->dropAttr(); + } } // Helper for delayed processing TransparentUnion attribute. @@ -7346,13 +7438,11 @@ ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K, return true; } else if (K == AR_Unavailable) { // It is perfectly fine to refer to an 'unavailable' Objective-C method - // when it's actually defined and is referenced from within the - // @implementation itself. In this context, we interpret unavailable as a - // form of access control. + // when it is referenced from within the @implementation itself. In this + // context, we interpret unavailable as a form of access control. if (const auto *MD = dyn_cast(OffendingDecl)) { if (const auto *Impl = dyn_cast(C)) { - if (MD->getClassInterface() == Impl->getClassInterface() && - MD->isDefined()) + if (MD->getClassInterface() == Impl->getClassInterface()) return true; } } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 43b289d8d0de1..950a63aa451be 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1205,7 +1205,7 @@ static bool checkTupleLikeDecomposition(Sema &S, E = Seq.Perform(S, Entity, Kind, Init); if (E.isInvalid()) return true; - E = S.ActOnFinishFullExpr(E.get(), Loc, /*DiscardedValue*/ false); + E = S.ActOnFinishFullExpr(E.get(), Loc); if (E.isInvalid()) return true; RefVD->setInit(E.get()); @@ -1301,6 +1301,10 @@ static DeclAccessPair findDecomposableBaseClass(Sema &S, SourceLocation Loc, static bool checkMemberDecomposition(Sema &S, ArrayRef Bindings, ValueDecl *Src, QualType DecompType, const CXXRecordDecl *OrigRD) { + if (S.RequireCompleteType(Src->getLocation(), DecompType, + diag::err_incomplete_type)) + return true; + CXXCastPath BasePath; DeclAccessPair BasePair = findDecomposableBaseClass(S, Src->getLocation(), OrigRD, BasePath); @@ -3682,7 +3686,7 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - Init = ActOnFinishFullExpr(Init.get(), InitLoc, /*DiscardedValue*/ false); + Init = ActOnFinishFullExpr(Init.get(), InitLoc); if (Init.isInvalid()) { FD->setInvalidDecl(); return; @@ -4040,8 +4044,7 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin(), - /*DiscardedValue*/ false); + MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin()); if (MemberInit.isInvalid()) return true; @@ -4096,8 +4099,8 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - DelegationInit = ActOnFinishFullExpr( - DelegationInit.get(), InitRange.getBegin(), /*DiscardedValue*/ false); + DelegationInit = ActOnFinishFullExpr(DelegationInit.get(), + InitRange.getBegin()); if (DelegationInit.isInvalid()) return true; @@ -4226,8 +4229,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin(), - /*DiscardedValue*/ false); + BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin()); if (BaseInit.isInvalid()) return true; @@ -5886,9 +5888,6 @@ static bool canPassInRegisters(Sema &S, CXXRecordDecl *D, if (D->isDependentType() || D->isInvalidDecl()) return false; - if (D->hasAttr()) - return true; - // Clang <= 4 used the pre-C++11 rule, which ignores move operations. // The PS4 platform ABI follows the behavior of Clang 3.2. if (CCK == TargetInfo::CCK_ClangABI4OrPS4) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d5416d4d057c7..ff9393a56b9cb 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -738,33 +738,20 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) { return ExprError(); E = Res.get(); - QualType ScalarTy = Ty; - unsigned NumElts = 0; - if (const ExtVectorType *VecTy = Ty->getAs()) { - NumElts = VecTy->getNumElements(); - ScalarTy = VecTy->getElementType(); - } - // If this is a 'float' or '__fp16' (CVR qualified or typedef) // promote to double. // Note that default argument promotion applies only to float (and // half/fp16); it does not apply to _Float16. - const BuiltinType *BTy = ScalarTy->getAs(); + const BuiltinType *BTy = Ty->getAs(); if (BTy && (BTy->getKind() == BuiltinType::Half || BTy->getKind() == BuiltinType::Float)) { if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp64")) { - if (BTy->getKind() == BuiltinType::Half) { - QualType Ty = Context.FloatTy; - if (NumElts != 0) - Ty = Context.getExtVectorType(Ty, NumElts); - E = ImpCastExprToType(E, Ty, CK_FloatingCast).get(); - } + if (BTy->getKind() == BuiltinType::Half) { + E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get(); + } } else { - QualType Ty = Context.DoubleTy; - if (NumElts != 0) - Ty = Context.getExtVectorType(Ty, NumElts); - E = ImpCastExprToType(E, Ty, CK_FloatingCast).get(); + E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get(); } } @@ -4736,9 +4723,8 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, if (Result.isInvalid()) return true; - Result = - ActOnFinishFullExpr(Result.getAs(), Param->getOuterLocStart(), - /*DiscardedValue*/ false); + Result = ActOnFinishFullExpr(Result.getAs(), + Param->getOuterLocStart()); if (Result.isInvalid()) return true; @@ -5690,18 +5676,36 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, } if (!getLangOpts().CPlusPlus) { + // Forget about the nulled arguments since typo correction + // do not handle them well. + TheCall->shrinkNumArgs(Args.size()); // C cannot always handle TypoExpr nodes in builtin calls and direct // function calls as their argument checking don't necessarily handle // dependent types properly, so make sure any TypoExprs have been // dealt with. ExprResult Result = CorrectDelayedTyposInExpr(TheCall); if (!Result.isUsable()) return ExprError(); + CallExpr *TheOldCall = TheCall; TheCall = dyn_cast(Result.get()); + bool CorrectedTypos = TheCall != TheOldCall; if (!TheCall) return Result; - // TheCall at this point has max(Args.size(), NumParams) arguments, - // with extra arguments nulled. We don't want to introduce nulled - // arguments in Args and so we only take the first Args.size() arguments. - Args = llvm::makeArrayRef(TheCall->getArgs(), Args.size()); + Args = llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs()); + + // A new call expression node was created if some typos were corrected. + // However it may not have been constructed with enough storage. In this + // case, rebuild the node with enough storage. The waste of space is + // immaterial since this only happens when some typos were corrected. + if (CorrectedTypos && Args.size() < NumParams) { + if (Config) + TheCall = CUDAKernelCallExpr::Create( + Context, Fn, cast(Config), Args, ResultTy, VK_RValue, + RParenLoc, NumParams); + else + TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, + RParenLoc, NumParams, UsesADL); + } + // We can now handle the nulled arguments for the default arguments. + TheCall->setNumArgsUnsafe(std::max(Args.size(), NumParams)); } // Bail out early if calling a builtin with custom type checking. diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 8c89a3cee3dbb..cce7a216548ff 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7815,8 +7815,6 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC, FullExpr = IgnoredValueConversions(FullExpr.get()); if (FullExpr.isInvalid()) return ExprError(); - - DiagnoseUnusedExprResult(FullExpr.get()); } FullExpr = CorrectDelayedTyposInExpr(FullExpr.get()); diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index af233b96d69b4..4e002a853dc21 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1724,7 +1724,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, /*NRVO=*/false), CurrentLocation, Src); if (!Init.isInvalid()) - Init = ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false); + Init = ActOnFinishFullExpr(Init.get()); if (Init.isInvalid()) return ExprError(); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 36048a38b999c..8a0be0c472de9 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -4602,8 +4602,7 @@ DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar( Captures.insert(std::make_pair(LCRef, Ref)); return Ref; } - return buildDeclRefExpr(SemaRef, VD, VD->getType().getNonReferenceType(), - DefaultLoc); + return cast(LCRef); } Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const { @@ -5367,7 +5366,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, LastIteration.get(), UB.get()); EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(), CondOp.get()); - EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false); + EUB = SemaRef.ActOnFinishFullExpr(EUB.get()); // If we have a combined directive that combines 'distribute', 'for' or // 'simd' we need to be able to access the bounds of the schedule of the @@ -5396,8 +5395,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, LastIteration.get(), CombUB.get()); CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(), CombCondOp.get()); - CombEUB = - SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false); + CombEUB = SemaRef.ActOnFinishFullExpr(CombEUB.get()); const CapturedDecl *CD = cast(AStmt)->getCapturedDecl(); // We expect to have at least 2 more parameters than the 'parallel' @@ -5431,7 +5429,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, ? LB.get() : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS); - Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false); + Init = SemaRef.ActOnFinishFullExpr(Init.get()); if (isOpenMPLoopBoundSharingDirective(DKind)) { Expr *CombRHS = @@ -5442,8 +5440,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); CombInit = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS); - CombInit = - SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false); + CombInit = SemaRef.ActOnFinishFullExpr(CombInit.get()); } } @@ -5475,7 +5472,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, if (!Inc.isUsable()) return 0; Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get()); - Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false); + Inc = SemaRef.ActOnFinishFullExpr(Inc.get()); if (!Inc.isUsable()) return 0; @@ -5493,8 +5490,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // LB = LB + ST NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get()); - NextLB = - SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false); + NextLB = SemaRef.ActOnFinishFullExpr(NextLB.get()); if (!NextLB.isUsable()) return 0; // UB + ST @@ -5504,8 +5500,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // UB = UB + ST NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get()); - NextUB = - SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false); + NextUB = SemaRef.ActOnFinishFullExpr(NextUB.get()); if (!NextUB.isUsable()) return 0; if (isOpenMPLoopBoundSharingDirective(DKind)) { @@ -5516,8 +5511,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // LB = LB + ST CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(), CombNextLB.get()); - CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(), - /*DiscardedValue*/ false); + CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get()); if (!CombNextLB.isUsable()) return 0; // UB + ST @@ -5528,8 +5522,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // UB = UB + ST CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(), CombNextUB.get()); - CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(), - /*DiscardedValue*/ false); + CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get()); if (!CombNextUB.isUsable()) return 0; } @@ -5550,8 +5543,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, assert(DistInc.isUsable() && "distribute inc expr was not built"); DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(), DistInc.get()); - DistInc = - SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false); + DistInc = SemaRef.ActOnFinishFullExpr(DistInc.get()); assert(DistInc.isUsable() && "distribute inc expr was not built"); // Build expression: UB = min(UB, prevUB) for #for in composite or combined @@ -5563,8 +5555,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, DistEUBLoc, DistEUBLoc, IsUBGreater.get(), PrevUB.get(), UB.get()); PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(), CondOp.get()); - PrevEUB = - SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false); + PrevEUB = SemaRef.ActOnFinishFullExpr(PrevEUB.get()); // Build IV <= PrevUB to be used in parallel for is in combination with // a distribute directive with schedule(static, 1) @@ -5680,10 +5671,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.IterationVarRef = IV.get(); Built.LastIteration = LastIteration.get(); Built.NumIterations = NumIterations.get(); - Built.CalcLastIteration = SemaRef - .ActOnFinishFullExpr(CalcLastIteration.get(), - /*DiscardedValue*/ false) - .get(); + Built.CalcLastIteration = + SemaRef.ActOnFinishFullExpr(CalcLastIteration.get()).get(); Built.PreCond = PreCond.get(); Built.PreInits = buildPreInits(C, Captures); Built.Cond = Cond.get(); @@ -10358,8 +10347,8 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef VarList, PseudoDstExpr, PseudoSrcExpr); if (AssignmentOp.isInvalid()) continue; - AssignmentOp = - ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false); + AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc, + /*DiscardedValue=*/true); if (AssignmentOp.isInvalid()) continue; @@ -11357,8 +11346,7 @@ static bool actOnOMPReductionKindClause( BO_Assign, LHSDRE, ConditionalOp); } if (ReductionOp.isUsable()) - ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(), - /*DiscardedValue*/ false); + ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get()); } if (!ReductionOp.isUsable()) continue; @@ -11688,7 +11676,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause( buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc); ExprResult CalcStep = BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr); - CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false); + CalcStep = ActOnFinishFullExpr(CalcStep.get()); // Warn about zero linear step (it would be probably better specified as // making corresponding variables 'const'). @@ -11776,7 +11764,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, else Update = *CurPrivate; Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); // Build final: Var = InitExpr + NumIterations * Step ExprResult Final; @@ -11787,7 +11775,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, else Final = *CurPrivate; Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); if (!Update.isUsable() || !Final.isUsable()) { Updates.push_back(nullptr); @@ -11955,7 +11943,7 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef VarList, if (AssignmentOp.isInvalid()) continue; AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); if (AssignmentOp.isInvalid()) continue; @@ -12063,8 +12051,8 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef VarList, DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr); if (AssignmentOp.isInvalid()) continue; - AssignmentOp = - ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false); + AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc, + /*DiscardedValue=*/true); if (AssignmentOp.isInvalid()) continue; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 9e30c9a396c0a..dacf8d0cf4e7f 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -42,11 +42,12 @@ using namespace clang; using namespace sema; -StmtResult Sema::ActOnExprStmt(ExprResult FE, bool DiscardedValue) { +StmtResult Sema::ActOnExprStmt(ExprResult FE) { if (FE.isInvalid()) return StmtError(); - FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(), DiscardedValue); + FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(), + /*DiscardedValue*/ true); if (FE.isInvalid()) return StmtError(); @@ -347,10 +348,6 @@ sema::CompoundScopeInfo &Sema::getCurCompoundScope() const { return getCurFunction()->CompoundScopes.back(); } -bool Sema::isCurCompoundStmtAStmtExpr() const { - return getCurCompoundScope().IsStmtExpr; -} - StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef Elts, bool isStmtExpr) { const unsigned NumElts = Elts.size(); @@ -373,6 +370,14 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, Diag(D->getLocation(), diag::ext_mixed_decls_code); } } + // Warn about unused expressions in statements. + for (unsigned i = 0; i != NumElts; ++i) { + // Ignore statements that are last in a statement expression. + if (isStmtExpr && i == NumElts - 1) + continue; + + DiagnoseUnusedExprResult(Elts[i]); + } // Check for suspicious empty body (null statement) in `for' and `while' // statements. Don't do anything for template instantiations, this just adds @@ -464,12 +469,15 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHSVal, /// ActOnCaseStmtBody - This installs a statement as the body of a case. void Sema::ActOnCaseStmtBody(Stmt *S, Stmt *SubStmt) { + DiagnoseUnusedExprResult(SubStmt); cast(S)->setSubStmt(SubStmt); } StmtResult Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, Stmt *SubStmt, Scope *CurScope) { + DiagnoseUnusedExprResult(SubStmt); + if (getCurFunction()->SwitchStack.empty()) { Diag(DefaultLoc, diag::err_default_not_in_switch); return SubStmt; @@ -563,6 +571,9 @@ StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, if (IsConstexpr || isa(Cond.get().second)) setFunctionHasBranchProtectedScope(); + DiagnoseUnusedExprResult(thenStmt); + DiagnoseUnusedExprResult(elseStmt); + return IfStmt::Create(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first, Cond.get().second, thenStmt, ElseLoc, elseStmt); } @@ -1290,6 +1301,8 @@ StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond, !Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc())) CommaVisitor(*this).Visit(CondVal.second); + DiagnoseUnusedExprResult(Body); + if (isa(Body)) getCurCompoundScope().setHasEmptyLoopBodies(); @@ -1309,7 +1322,7 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, return StmtError(); Cond = CondResult.get(); - CondResult = ActOnFinishFullExpr(Cond, DoLoc, /*DiscardedValue*/ false); + CondResult = ActOnFinishFullExpr(Cond, DoLoc); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.get(); @@ -1319,6 +1332,8 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, !Diags.isIgnored(diag::warn_comma_operator, Cond->getExprLoc())) CommaVisitor(*this).Visit(Cond); + DiagnoseUnusedExprResult(Body); + return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen); } @@ -1763,6 +1778,11 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, CommaVisitor(*this).Visit(Second.get().second); Expr *Third = third.release().getAs(); + + DiagnoseUnusedExprResult(First); + DiagnoseUnusedExprResult(Third); + DiagnoseUnusedExprResult(Body); + if (isa(Body)) getCurCompoundScope().setHasEmptyLoopBodies(); @@ -1782,7 +1802,7 @@ StmtResult Sema::ActOnForEachLValueExpr(Expr *E) { if (result.isInvalid()) return StmtError(); E = result.get(); - ExprResult FullExpr = ActOnFinishFullExpr(E, /*DiscardedValue*/ false); + ExprResult FullExpr = ActOnFinishFullExpr(E); if (FullExpr.isInvalid()) return StmtError(); return StmtResult(static_cast(FullExpr.get())); @@ -1936,8 +1956,7 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, if (CollectionExprResult.isInvalid()) return StmtError(); - CollectionExprResult = - ActOnFinishFullExpr(CollectionExprResult.get(), /*DiscardedValue*/ false); + CollectionExprResult = ActOnFinishFullExpr(CollectionExprResult.get()); if (CollectionExprResult.isInvalid()) return StmtError(); @@ -2574,8 +2593,7 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, if (!NotEqExpr.isInvalid()) NotEqExpr = CheckBooleanCondition(ColonLoc, NotEqExpr.get()); if (!NotEqExpr.isInvalid()) - NotEqExpr = - ActOnFinishFullExpr(NotEqExpr.get(), /*DiscardedValue*/ false); + NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get()); if (NotEqExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) << RangeLoc << 0 << BeginRangeRef.get()->getType(); @@ -2598,7 +2616,7 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, // co_await during the initial parse. IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get()); if (!IncrExpr.isInvalid()) - IncrExpr = ActOnFinishFullExpr(IncrExpr.get(), /*DiscardedValue*/ false); + IncrExpr = ActOnFinishFullExpr(IncrExpr.get()); if (IncrExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) << RangeLoc << 2 << BeginRangeRef.get()->getType() ; @@ -2853,7 +2871,7 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, return StmtError(); } - ExprResult ExprRes = ActOnFinishFullExpr(E, /*DiscardedValue*/ false); + ExprResult ExprRes = ActOnFinishFullExpr(E); if (ExprRes.isInvalid()) return StmtError(); E = ExprRes.get(); @@ -3203,8 +3221,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { ExpressionEvaluationContext::DiscardedStatement && (HasDeducedReturnType || CurCap->HasImplicitReturnType)) { if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3331,8 +3348,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3562,8 +3578,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { ExpressionEvaluationContext::DiscardedStatement && FnRetType->getContainedAutoType()) { if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3657,8 +3672,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3737,8 +3751,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3791,7 +3804,7 @@ StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) { if (Result.isInvalid()) return StmtError(); - Result = ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false); + Result = ActOnFinishFullExpr(Result.get()); if (Result.isInvalid()) return StmtError(); Throw = Result.get(); @@ -3863,7 +3876,7 @@ Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) { } // The operand to @synchronized is a full-expression. - return ActOnFinishFullExpr(operand, /*DiscardedValue*/ false); + return ActOnFinishFullExpr(operand); } StmtResult diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index 9e084c99d0dd4..2d8864bab171d 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -383,11 +383,20 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, return StmtError( Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected) << Info.getConstraintStr() << InputExpr->getSourceRange()); - llvm::APSInt Result = EVResult.Val.getInt(); - if (!Info.isValidAsmImmediate(Result)) + + // For compatibility with GCC, we also allow pointers that would be + // integral constant expressions if they were cast to int. + llvm::APSInt IntResult; + if (!EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(), + Context)) + return StmtError( + Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected) + << Info.getConstraintStr() << InputExpr->getSourceRange()); + + if (!Info.isValidAsmImmediate(IntResult)) return StmtError(Diag(InputExpr->getBeginLoc(), diag::err_invalid_asm_value_for_constraint) - << Result.toString(10) << Info.getConstraintStr() + << IntResult.toString(10) << Info.getConstraintStr() << InputExpr->getSourceRange()); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 3f9dc989103fa..f974bedffe005 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -6309,7 +6309,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // -- a predefined __func__ variable if (auto *E = Value.getLValueBase().dyn_cast()) { if (isa(E)) { - Converted = TemplateArgument(ArgResult.get()); + Converted = TemplateArgument(ArgResult.get()->IgnoreImpCasts()); break; } Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index b4c075e9c46d4..1ae94c8aec999 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1442,7 +1442,12 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { else Result = Context.Int128Ty; break; - case DeclSpec::TST_float16: Result = Context.Float16Ty; break; + case DeclSpec::TST_float16: + if (!S.Context.getTargetInfo().hasFloat16Type()) + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) + << "_Float16"; + Result = Context.Float16Ty; + break; case DeclSpec::TST_half: Result = Context.HalfTy; break; case DeclSpec::TST_float: Result = Context.FloatTy; break; case DeclSpec::TST_double: diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index df14768cbe812..9de4e8d654f96 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -328,7 +328,7 @@ class TreeTransform { /// other mechanism. /// /// \returns the transformed statement. - StmtResult TransformStmt(Stmt *S, bool DiscardedValue = false); + StmtResult TransformStmt(Stmt *S); /// Transform the given statement. /// @@ -3269,8 +3269,8 @@ class TreeTransform { bool DeducibleTSTContext); }; -template -StmtResult TreeTransform::TransformStmt(Stmt *S, bool DiscardedValue) { +template +StmtResult TreeTransform::TransformStmt(Stmt *S) { if (!S) return S; @@ -3294,7 +3294,7 @@ StmtResult TreeTransform::TransformStmt(Stmt *S, bool DiscardedValue) { if (E.isInvalid()) return StmtError(); - return getSema().ActOnExprStmt(E, DiscardedValue); + return getSema().ActOnExprStmt(E); } } @@ -4715,8 +4715,7 @@ TreeTransform::TransformVariableArrayType(TypeLocBuilder &TLB, } if (SizeResult.isInvalid()) return QualType(); - SizeResult = - SemaRef.ActOnFinishFullExpr(SizeResult.get(), /*DiscardedValue*/ false); + SizeResult = SemaRef.ActOnFinishFullExpr(SizeResult.get()); if (SizeResult.isInvalid()) return QualType(); @@ -6521,9 +6520,7 @@ TreeTransform::TransformCompoundStmt(CompoundStmt *S, bool SubStmtChanged = false; SmallVector Statements; for (auto *B : S->body()) { - StmtResult Result = - getDerived().TransformStmt(B, !IsStmtExpr || B != S->body_back()); - + StmtResult Result = getDerived().TransformStmt(B); if (Result.isInvalid()) { // Immediately fail if this was a DeclStmt, since it's very // likely that this will cause problems for future statements. diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index da94b6eb21e9b..ea695c4736a3e 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -154,6 +154,32 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) { return E; } +/// Comparing internal representations of symbolic values (via +/// SVal::operator==()) is a valid way to check if the value was updated, +/// unless it's a LazyCompoundVal that may have a different internal +/// representation every time it is loaded from the state. In this function we +/// do an approximate comparison for lazy compound values, checking that they +/// are the immediate snapshots of the tracked region's bindings within the +/// node's respective states but not really checking that these snapshots +/// actually contain the same set of bindings. +bool hasVisibleUpdate(const ExplodedNode *LeftNode, SVal LeftVal, + const ExplodedNode *RightNode, SVal RightVal) { + if (LeftVal == RightVal) + return true; + + const auto LLCV = LeftVal.getAs(); + if (!LLCV) + return false; + + const auto RLCV = RightVal.getAs(); + if (!RLCV) + return false; + + return LLCV->getRegion() == RLCV->getRegion() && + LLCV->getStore() == LeftNode->getState()->getStore() && + RLCV->getStore() == RightNode->getState()->getStore(); +} + //===----------------------------------------------------------------------===// // Definitions for bug reporter visitors. //===----------------------------------------------------------------------===// @@ -1188,7 +1214,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, if (Succ->getState()->getSVal(R) != V) return nullptr; - if (Pred->getState()->getSVal(R) == V) { + if (hasVisibleUpdate(Pred, Pred->getState()->getSVal(R), Succ, V)) { Optional PS = Succ->getLocationAs(); if (!PS || PS->getLocationValue() != R) return nullptr; @@ -1209,6 +1235,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, // UndefinedVal.) if (Optional CE = Succ->getLocationAs()) { if (const auto *VR = dyn_cast(R)) { + const auto *Param = cast(VR->getDecl()); ProgramStateManager &StateMgr = BRC.getStateManager(); diff --git a/clang/lib/Tooling/ArgumentsAdjusters.cpp b/clang/lib/Tooling/ArgumentsAdjusters.cpp index c8e9c167422e8..f5040b8a09d57 100644 --- a/clang/lib/Tooling/ArgumentsAdjusters.cpp +++ b/clang/lib/Tooling/ArgumentsAdjusters.cpp @@ -108,5 +108,27 @@ ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First, }; } +ArgumentsAdjuster getStripPluginsAdjuster() { + return [](const CommandLineArguments &Args, StringRef /*unused*/) { + CommandLineArguments AdjustedArgs; + for (size_t I = 0, E = Args.size(); I != E; I++) { + // According to https://clang.llvm.org/docs/ClangPlugins.html + // plugin arguments are in the form: + // -Xclang {-load, -plugin, -plugin-arg-, -add-plugin} + // -Xclang + if (I + 4 < E && Args[I] == "-Xclang" && + (Args[I + 1] == "-load" || Args[I + 1] == "-plugin" || + llvm::StringRef(Args[I + 1]).startswith("-plugin-arg-") || + Args[I + 1] == "-add-plugin") && + Args[I + 2] == "-Xclang") { + I += 3; + continue; + } + AdjustedArgs.push_back(Args[I]); + } + return AdjustedArgs; + }; +} + } // end namespace tooling } // end namespace clang diff --git a/clang/test/AST/float16.cpp b/clang/test/AST/float16.cpp index aa65270c75d4c..2f428e7085ff1 100644 --- a/clang/test/AST/float16.cpp +++ b/clang/test/AST/float16.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s --strict-whitespace -// RUN: %clang_cc1 -std=c++11 -ast-dump -fnative-half-type %s | FileCheck %s --check-prefix=CHECK-NATIVE --strict-whitespace +// RUN: %clang_cc1 -std=c++11 -ast-dump -triple aarch64-linux-gnu %s | FileCheck %s --strict-whitespace +// RUN: %clang_cc1 -std=c++11 -ast-dump -triple aarch64-linux-gnu -fnative-half-type %s | FileCheck %s --check-prefix=CHECK-NATIVE --strict-whitespace /* Various contexts where type _Float16 can appear. */ diff --git a/clang/test/Analysis/PR40625.cpp b/clang/test/Analysis/PR40625.cpp new file mode 100644 index 0000000000000..6cc27d39b6c08 --- /dev/null +++ b/clang/test/Analysis/PR40625.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,alpha.core.CallAndMessageUnInitRefArg %s -verify + +void f(const int *end); + +void g(const int (&arrr)[10]) { + f(arrr+sizeof(arrr)); // expected-warning{{1st function call argument is a pointer to uninitialized value}} + // FIXME: This is a false positive that should be fixed. Until then this + // tests the crash fix in FindLastStoreBRVisitor (beside + // uninit-vals.m). +} + +void h() { + int arr[10]; + + g(arr); +} diff --git a/clang/test/Analysis/uninit-vals.m b/clang/test/Analysis/uninit-vals.m index f97af1a6633cc..33352122ca5aa 100644 --- a/clang/test/Analysis/uninit-vals.m +++ b/clang/test/Analysis/uninit-vals.m @@ -394,11 +394,11 @@ void testSmallStructBitfieldsFirstUnnamed() { struct { int : 4; int y : 4; - } a, b, c; + } a, b, c; // expected-note{{'c' initialized here}} a.y = 2; - b = a; // expected-note{{Value assigned to 'c'}} + b = a; clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} @@ -411,11 +411,11 @@ void testSmallStructBitfieldsSecondUnnamed() { struct { int x : 4; int : 4; - } a, b, c; + } a, b, c; // expected-note{{'c' initialized here}} a.x = 1; - b = a; // expected-note{{Value assigned to 'c'}} + b = a; clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p8.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p8.cpp index 686aac2802ada..e435bee2c88ee 100644 --- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p8.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p8.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -verify %s +// RUN: %clang_cc1 -std=c++11 -verify %s -triple x86_64-linux-gnu alignas(double) void f(); // expected-error {{'alignas' attribute only applies to variables, data members and tag types}} alignas(double) unsigned char c[sizeof(double)]; // expected-note {{previous}} diff --git a/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp b/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp index 4804cc559d007..7a6a408ec955b 100644 --- a/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp +++ b/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify %s -// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -std=c++1z -Wc++14-compat -verify %s -DCPP17 +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++1z -Wc++14-compat -verify %s -DCPP17 int f(); @@ -71,6 +71,7 @@ void whileInitStatement() { // last loop above. It would be nice to remove this. void whileInitStatement2() { while (; false) {} // expected-error {{expected expression}} - // expected-error@-1 {{expected ';' after expression}} - // expected-error@-2 {{expected expression}} + // expected-warning@-1 {{expression result unused}} + // expected-error@-2 {{expected ';' after expression}} + // expected-error@-3 {{expected expression}} } diff --git a/clang/test/CodeCompletion/crash-null-type.cpp b/clang/test/CodeCompletion/crash-null-type.cpp new file mode 100644 index 0000000000000..c5b3d1e79390c --- /dev/null +++ b/clang/test/CodeCompletion/crash-null-type.cpp @@ -0,0 +1,8 @@ +void test() { + for (auto [loopVar] : y) { // y has to be unresolved + loopVa + } +} +// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:3:11 %s -o - \ +// RUN: | FileCheck %s +// CHECK: COMPLETION: loopVar diff --git a/clang/test/CodeCompletion/pragma-macro-token-caching.c b/clang/test/CodeCompletion/pragma-macro-token-caching.c index 59b6621b56ad4..432706e85ceb9 100644 --- a/clang/test/CodeCompletion/pragma-macro-token-caching.c +++ b/clang/test/CodeCompletion/pragma-macro-token-caching.c @@ -12,7 +12,7 @@ void completeParam(int param) { void completeParamPragmaError(int param) { Outer(__extension__({ _Pragma(2) })); // expected-error {{_Pragma takes a parenthesized string literal}} - param; // expected-warning {{expression result unused}} + param; } // RUN: %clang_cc1 -fsyntax-only -verify -code-completion-at=%s:16:1 %s | FileCheck %s diff --git a/clang/test/CodeGen/arm64-crc32.c b/clang/test/CodeGen/arm64-crc32.c index 2d913fb123b7c..26d69a23b6a1a 100644 --- a/clang/test/CodeGen/arm64-crc32.c +++ b/clang/test/CodeGen/arm64-crc32.c @@ -1,54 +1,57 @@ // REQUIRES: aarch64-registered-target // RUN: %clang_cc1 -triple arm64-none-linux-gnu \ // RUN: -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-windows \ +// RUN: -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +#include -int crc32b(int a, char b) +uint32_t crc32b(uint32_t a, uint8_t b) { return __builtin_arm_crc32b(a,b); // CHECK: [[T0:%[0-9]+]] = zext i8 %b to i32 // CHECK: call i32 @llvm.aarch64.crc32b(i32 %a, i32 [[T0]]) } -int crc32cb(int a, char b) +uint32_t crc32cb(uint32_t a, uint8_t b) { return __builtin_arm_crc32cb(a,b); // CHECK: [[T0:%[0-9]+]] = zext i8 %b to i32 // CHECK: call i32 @llvm.aarch64.crc32cb(i32 %a, i32 [[T0]]) } -int crc32h(int a, short b) +uint32_t crc32h(uint32_t a, uint16_t b) { return __builtin_arm_crc32h(a,b); // CHECK: [[T0:%[0-9]+]] = zext i16 %b to i32 // CHECK: call i32 @llvm.aarch64.crc32h(i32 %a, i32 [[T0]]) } -int crc32ch(int a, short b) +uint32_t crc32ch(uint32_t a, uint16_t b) { return __builtin_arm_crc32ch(a,b); // CHECK: [[T0:%[0-9]+]] = zext i16 %b to i32 // CHECK: call i32 @llvm.aarch64.crc32ch(i32 %a, i32 [[T0]]) } -int crc32w(int a, int b) +uint32_t crc32w(uint32_t a, uint32_t b) { return __builtin_arm_crc32w(a,b); // CHECK: call i32 @llvm.aarch64.crc32w(i32 %a, i32 %b) } -int crc32cw(int a, int b) +uint32_t crc32cw(uint32_t a, uint32_t b) { return __builtin_arm_crc32cw(a,b); // CHECK: call i32 @llvm.aarch64.crc32cw(i32 %a, i32 %b) } -int crc32d(int a, long b) +uint32_t crc32d(uint32_t a, uint64_t b) { return __builtin_arm_crc32d(a,b); // CHECK: call i32 @llvm.aarch64.crc32x(i32 %a, i64 %b) } -int crc32cd(int a, long b) +uint32_t crc32cd(uint32_t a, uint64_t b) { return __builtin_arm_crc32cd(a,b); // CHECK: call i32 @llvm.aarch64.crc32cx(i32 %a, i64 %b) diff --git a/clang/test/CodeGen/arm64-microsoft-status-reg.cpp b/clang/test/CodeGen/arm64-microsoft-status-reg.cpp index eb59bae50f0ae..524b5af120c52 100644 --- a/clang/test/CodeGen/arm64-microsoft-status-reg.cpp +++ b/clang/test/CodeGen/arm64-microsoft-status-reg.cpp @@ -23,88 +23,112 @@ #define ARM64_TPIDRRO_EL0 ARM64_SYSREG(3,3,13, 0,3) // Thread ID Register, User Read Only [CP15_TPIDRURO] #define ARM64_TPIDR_EL1 ARM64_SYSREG(3,0,13, 0,4) // Thread ID Register, Privileged Only [CP15_TPIDRPRW] -void check_ReadWriteStatusReg(int v) { - int ret; +// From intrin.h +__int64 _ReadStatusReg(int); +void _WriteStatusReg(int, __int64); + +void check_ReadWriteStatusReg(__int64 v) { + __int64 ret; ret = _ReadStatusReg(ARM64_CNTVCT); -// CHECK-ASM: mrs x8, CNTVCT_EL0 -// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD2:.*]]) +// CHECK-ASM: mrs x0, CNTVCT_EL0 +// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD2:.*]]) +// CHECK-IR-NEXT: store i64 %[[VAR]] ret = _ReadStatusReg(ARM64_PMCCNTR_EL0); -// CHECK-ASM: mrs x8, PMCCNTR_EL0 -// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD3:.*]]) +// CHECK-ASM: mrs x0, PMCCNTR_EL0 +// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD3:.*]]) +// CHECK-IR-NEXT: store i64 %[[VAR]] ret = _ReadStatusReg(ARM64_PMSELR_EL0); -// CHECK-ASM: mrs x8, PMSELR_EL0 -// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD4:.*]]) +// CHECK-ASM: mrs x0, PMSELR_EL0 +// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD4:.*]]) +// CHECK-IR-NEXT: store i64 %[[VAR]] ret = _ReadStatusReg(ARM64_PMXEVCNTR_EL0); -// CHECK-ASM: mrs x8, PMXEVCNTR_EL0 -// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD5:.*]]) +// CHECK-ASM: mrs x0, PMXEVCNTR_EL0 +// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD5:.*]]) +// CHECK-IR-NEXT: store i64 %[[VAR]] ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(0)); -// CHECK-ASM: mrs x8, PMEVCNTR0_EL0 -// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD6:.*]]) +// CHECK-ASM: mrs x0, PMEVCNTR0_EL0 +// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD6:.*]]) +// CHECK-IR-NEXT: store i64 %[[VAR]] ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(1)); -// CHECK-ASM: mrs x8, PMEVCNTR1_EL0 -// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD7:.*]]) +// CHECK-ASM: mrs x0, PMEVCNTR1_EL0 +// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD7:.*]]) +// CHECK-IR-NEXT: store i64 %[[VAR]] ret = _ReadStatusReg(ARM64_PMXEVCNTRn_EL0(30)); -// CHECK-ASM: mrs x8, PMEVCNTR30_EL0 -// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD8:.*]]) +// CHECK-ASM: mrs x0, PMEVCNTR30_EL0 +// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD8:.*]]) +// CHECK-IR-NEXT: store i64 %[[VAR]] ret = _ReadStatusReg(ARM64_TPIDR_EL0); -// CHECK-ASM: mrs x8, TPIDR_EL0 -// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD9:.*]]) +// CHECK-ASM: mrs x0, TPIDR_EL0 +// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD9:.*]]) +// CHECK-IR-NEXT: store i64 %[[VAR]] ret = _ReadStatusReg(ARM64_TPIDRRO_EL0); -// CHECK-ASM: mrs x8, TPIDRRO_EL0 -// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD10:.*]]) +// CHECK-ASM: mrs x0, TPIDRRO_EL0 +// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD10:.*]]) +// CHECK-IR-NEXT: store i64 %[[VAR]] ret = _ReadStatusReg(ARM64_TPIDR_EL1); -// CHECK-ASM: mrs x8, TPIDR_EL1 -// CHECK-IR: call i64 @llvm.read_register.i64(metadata ![[MD11:.*]]) +// CHECK-ASM: mrs x0, TPIDR_EL1 +// CHECK-IR: %[[VAR:.*]] = call i64 @llvm.read_register.i64(metadata ![[MD11:.*]]) +// CHECK-IR-NEXT: store i64 %[[VAR]] _WriteStatusReg(ARM64_CNTVCT, v); -// CHECK-ASM: msr S3_3_C14_C0_2, x8 -// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD2:.*]], i64 {{%.*}}) +// CHECK-ASM: msr S3_3_C14_C0_2, x0 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD2:.*]], i64 %[[VAR]]) _WriteStatusReg(ARM64_PMCCNTR_EL0, v); -// CHECK-ASM: msr PMCCNTR_EL0, x8 -// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD3:.*]], i64 {{%.*}}) +// CHECK-ASM: msr PMCCNTR_EL0, x0 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD3:.*]], i64 %[[VAR]]) _WriteStatusReg(ARM64_PMSELR_EL0, v); -// CHECK-ASM: msr PMSELR_EL0, x8 -// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD4:.*]], i64 {{%.*}}) +// CHECK-ASM: msr PMSELR_EL0, x0 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD4:.*]], i64 %[[VAR]]) _WriteStatusReg(ARM64_PMXEVCNTR_EL0, v); -// CHECK-ASM: msr PMXEVCNTR_EL0, x8 -// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD5:.*]], i64 {{%.*}}) +// CHECK-ASM: msr PMXEVCNTR_EL0, x0 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD5:.*]], i64 %[[VAR]]) _WriteStatusReg(ARM64_PMXEVCNTRn_EL0(0), v); -// CHECK-ASM: msr PMEVCNTR0_EL0, x8 -// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD6:.*]], i64 {{%.*}}) +// CHECK-ASM: msr PMEVCNTR0_EL0, x0 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD6:.*]], i64 %[[VAR]]) _WriteStatusReg(ARM64_PMXEVCNTRn_EL0(1), v); -// CHECK-ASM: msr PMEVCNTR1_EL0, x8 -// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD7:.*]], i64 {{%.*}}) +// CHECK-ASM: msr PMEVCNTR1_EL0, x0 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD7:.*]], i64 %[[VAR]]) _WriteStatusReg(ARM64_PMXEVCNTRn_EL0(30), v); -// CHECK-ASM: msr PMEVCNTR30_EL0, x8 -// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD8:.*]], i64 {{%.*}}) +// CHECK-ASM: msr PMEVCNTR30_EL0, x0 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD8:.*]], i64 %[[VAR]]) _WriteStatusReg(ARM64_TPIDR_EL0, v); -// CHECK-ASM: msr TPIDR_EL0, x8 -// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD9:.*]], i64 {{%.*}}) +// CHECK-ASM: msr TPIDR_EL0, x0 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD9:.*]], i64 %[[VAR]]) _WriteStatusReg(ARM64_TPIDRRO_EL0, v); -// CHECK-ASM: msr TPIDRRO_EL0, x8 -// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD10:.*]], i64 {{%.*}}) +// CHECK-ASM: msr TPIDRRO_EL0, x0 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD10:.*]], i64 %[[VAR]]) _WriteStatusReg(ARM64_TPIDR_EL1, v); -// CHECK-ASM: msr TPIDR_EL1, x8 -// CHECK-IR: call void @llvm.write_register.i64(metadata ![[MD11:.*]], i64 {{%.*}}) +// CHECK-ASM: msr TPIDR_EL1, x0 +// CHECK-IR: %[[VAR:.*]] = load i64, +// CHECK-IR-NEXT: call void @llvm.write_register.i64(metadata ![[MD11:.*]], i64 %[[VAR]]) } // CHECK-IR: ![[MD2]] = !{!"3:3:14:0:2"} diff --git a/clang/test/CodeGen/attr-msp430.c b/clang/test/CodeGen/attr-msp430.c new file mode 100644 index 0000000000000..e8b6d0d0fa3ea --- /dev/null +++ b/clang/test/CodeGen/attr-msp430.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple msp430-unknown-unknown -emit-llvm < %s| FileCheck %s + +__attribute__((interrupt(1))) void foo(void) {} +// CHECK: @llvm.used +// CHECK-SAME: @foo + +// CHECK: define msp430_intrcc void @foo() #0 +// CHECK: attributes #0 +// CHECK-SAME: noinline +// CHECK-SAME: "interrupt"="1" diff --git a/clang/test/CodeGen/builtins-arm64.c b/clang/test/CodeGen/builtins-arm64.c index 7027a6e220f3d..f164c2f6f3647 100644 --- a/clang/test/CodeGen/builtins-arm64.c +++ b/clang/test/CodeGen/builtins-arm64.c @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -triple arm64-unknown-linux -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple arm64-unknown-linux -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LINUX +// RUN: %clang_cc1 -triple aarch64-windows -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-WIN +#include void f0(void *a, void *b) { __clear_cache(a,b); @@ -15,8 +17,15 @@ unsigned rbit(unsigned a) { return __builtin_arm_rbit(a); } +// CHECK-WIN: [[A64:%[^ ]+]] = zext i32 %a to i64 +// CHECK-WIN: call i64 @llvm.bitreverse.i64(i64 [[A64]]) +// CHECK-LINUX: call i64 @llvm.bitreverse.i64(i64 %a) +unsigned long rbitl(unsigned long a) { + return __builtin_arm_rbit64(a); +} + // CHECK: call {{.*}} @llvm.bitreverse.i64(i64 %a) -unsigned long long rbit64(unsigned long long a) { +uint64_t rbit64(uint64_t a) { return __builtin_arm_rbit64(a); } @@ -49,13 +58,17 @@ void prefetch() { // CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 0, i32 3, i32 0) } -unsigned rsr() { +__typeof__(__builtin_arm_rsr("1:2:3:4:5")) rsr(void); + +uint32_t rsr() { // CHECK: [[V0:[%A-Za-z0-9.]+]] = call i64 @llvm.read_register.i64(metadata ![[M0:[0-9]]]) // CHECK-NEXT: trunc i64 [[V0]] to i32 return __builtin_arm_rsr("1:2:3:4:5"); } -unsigned long rsr64() { +__typeof__(__builtin_arm_rsr64("1:2:3:4:5")) rsr64(void); + +uint64_t rsr64(void) { // CHECK: call i64 @llvm.read_register.i64(metadata ![[M0:[0-9]]]) return __builtin_arm_rsr64("1:2:3:4:5"); } @@ -66,13 +79,17 @@ void *rsrp() { return __builtin_arm_rsrp("1:2:3:4:5"); } +__typeof__(__builtin_arm_wsr("1:2:3:4:5", 0)) wsr(unsigned); + void wsr(unsigned v) { // CHECK: [[V0:[%A-Za-z0-9.]+]] = zext i32 %v to i64 // CHECK-NEXT: call void @llvm.write_register.i64(metadata ![[M0:[0-9]]], i64 [[V0]]) __builtin_arm_wsr("1:2:3:4:5", v); } -void wsr64(unsigned long v) { +__typeof__(__builtin_arm_wsr64("1:2:3:4:5", 0)) wsr64(uint64_t); + +void wsr64(uint64_t v) { // CHECK: call void @llvm.write_register.i64(metadata ![[M0:[0-9]]], i64 %v) __builtin_arm_wsr64("1:2:3:4:5", v); } diff --git a/clang/test/CodeGen/microsoft-no-common-align.c b/clang/test/CodeGen/microsoft-no-common-align.c index fc46946c00ed2..a7a27a062704f 100644 --- a/clang/test/CodeGen/microsoft-no-common-align.c +++ b/clang/test/CodeGen/microsoft-no-common-align.c @@ -6,3 +6,6 @@ TooLargeAlignment TooBig; // CHECK: @TooBig = dso_local global <16 x float> zeroinitializer, align 64 NormalAlignment JustRight; // CHECK: @JustRight = common dso_local global <1 x float> zeroinitializer, align 4 + +TooLargeAlignment *IsAPointer; +// CHECK: @IsAPointer = common dso_local global <16 x float>* null, align 8 diff --git a/clang/test/CodeGen/powerpc_types.c b/clang/test/CodeGen/powerpc_types.c index b7d0f5de49859..86eb7f8356801 100644 --- a/clang/test/CodeGen/powerpc_types.c +++ b/clang/test/CodeGen/powerpc_types.c @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -triple powerpc-unknown-freebsd -emit-llvm -o - %s| FileCheck -check-prefix=SVR4-CHECK %s +// RUN: %clang_cc1 -triple powerpc-unknown-netbsd -emit-llvm -o - %s| FileCheck -check-prefix=SVR4-CHECK %s +// RUN: %clang_cc1 -triple powerpc-unknown-openbsd -emit-llvm -o - %s| FileCheck -check-prefix=SVR4-CHECK %s #include diff --git a/clang/test/CodeGen/wasm-import-module.c b/clang/test/CodeGen/wasm-import-module.c new file mode 100644 index 0000000000000..866a3a459949b --- /dev/null +++ b/clang/test/CodeGen/wasm-import-module.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple wasm32-unknown-unknown-wasm -emit-llvm -o - %s | FileCheck %s + +void __attribute__((import_module("bar"))) foo(void); + +void call(void) { + foo(); +} + +// CHECK: declare void @foo() [[A:#[0-9]+]] + +// CHECK: attributes [[A]] = {{{.*}} "wasm-import-module"="bar" {{.*}}} diff --git a/clang/test/CodeGen/wasm-import-name.c b/clang/test/CodeGen/wasm-import-name.c new file mode 100644 index 0000000000000..7c3b094b9e435 --- /dev/null +++ b/clang/test/CodeGen/wasm-import-name.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple wasm32-unknown-unknown-wasm -emit-llvm -o - %s | FileCheck %s + +void __attribute__((import_name("bar"))) foo(void); + +void call(void) { + foo(); +} + +// CHECK: declare void @foo() [[A:#[0-9]+]] + +// CHECK: attributes [[A]] = {{{.*}} "wasm-import-name"="bar" {{.*}}} diff --git a/clang/test/CodeGen/x86-64-inline-asm.c b/clang/test/CodeGen/x86-64-inline-asm.c index bb46eda633b70..79c1bd95f38b5 100644 --- a/clang/test/CodeGen/x86-64-inline-asm.c +++ b/clang/test/CodeGen/x86-64-inline-asm.c @@ -1,6 +1,7 @@ // REQUIRES: x86-registered-target // RUN: %clang_cc1 -triple x86_64 %s -S -o /dev/null -DWARN -verify // RUN: %clang_cc1 -triple x86_64 %s -S -o /dev/null -Werror -verify +// RUN: %clang_cc1 -triple x86_64-linux-gnu %s -S -o - | FileCheck %s void f() { asm("movaps %xmm3, (%esi, 2)"); // expected-note@1 {{instantiated into assembly here}} @@ -15,3 +16,17 @@ static unsigned var[1] = {}; void g(void) { asm volatile("movd %%xmm0, %0" : : "m"(var)); } + +void pr40890(void) { + struct s { + int a, b; + } s; + __asm__ __volatile__("\n#define S_A abcd%0\n" : : "n"(&((struct s*)0)->a)); + __asm__ __volatile__("\n#define S_B abcd%0\n" : : "n"(&((struct s*)0)->b)); + __asm__ __volatile__("\n#define BEEF abcd%0\n" : : "n"((int*)0xdeadbeeeeeef)); + +// CHECK-LABEL: pr40890 +// CHECK: #define S_A abcd$0 +// CHECK: #define S_B abcd$4 +// CHECK: #define BEEF abcd$244837814038255 +} diff --git a/clang/test/CodeGenCXX/char8_t.cpp b/clang/test/CodeGenCXX/char8_t.cpp index f24f12d6df404..1016d6346ba27 100644 --- a/clang/test/CodeGenCXX/char8_t.cpp +++ b/clang/test/CodeGenCXX/char8_t.cpp @@ -1,9 +1,11 @@ -// RUN: %clang_cc1 -std=c++17 -emit-llvm -fchar8_t -triple x86_64-linux %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c++17 -emit-llvm -fchar8_t -triple x86_64-windows %s -o - -verify +// RUN: %clang_cc1 -std=c++17 -emit-llvm -fchar8_t -triple x86_64-linux %s -o - | FileCheck %s --check-prefix=ITANIUM +// RUN: %clang_cc1 -std=c++17 -emit-llvm -fchar8_t -triple x86_64-windows %s -o - | FileCheck %s --check-prefix=MSABI -// CHECK: define void @_Z1fDu( -void f(char8_t c) {} // expected-error {{cannot mangle this built-in char8_t type yet}} +// ITANIUM: define void @_Z1fDu( +// MSABI: define {{.*}}void @"?f@@YAX_Q@Z"( +void f(char8_t c) {} -// CHECK: define weak_odr void @_Z1gIiEvDTplplcvT__ELA4_KDuELDu114EE +// ITANIUM: define weak_odr void @_Z1gIiEvDTplplcvT__ELA4_KDuELDu114EE( +// MSABI: define weak_odr {{.*}}void @"??$g@H@@YAXPEB_Q@Z"( template void g(decltype(T() + u8"foo" + u8'r')) {} template void g(const char8_t*); diff --git a/clang/test/CodeGenCXX/cxx11-thread-local-visibility.cpp b/clang/test/CodeGenCXX/cxx11-thread-local-visibility.cpp new file mode 100644 index 0000000000000..b46d41d7c9604 --- /dev/null +++ b/clang/test/CodeGenCXX/cxx11-thread-local-visibility.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck --check-prefix=LINUX %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-apple-darwin12 | FileCheck --check-prefix=DARWIN %s + +// Regression test for PR40327 + +// LINUX: @default_tls = thread_local global i32 +// LINUX: @hidden_tls = hidden thread_local global i32 +// LINUX: define weak_odr hidden i32* @_ZTW11default_tls() +// LINUX: define weak_odr hidden i32* @_ZTW10hidden_tls() +// +// DARWIN: @default_tls = internal thread_local global i32 +// DARWIN: @hidden_tls = internal thread_local global i32 +// DARWIN: define cxx_fast_tlscc i32* @_ZTW11default_tls() +// DARWIN: define hidden cxx_fast_tlscc i32* @_ZTW10hidden_tls() + +__attribute__((visibility("default"))) thread_local int default_tls; +__attribute__((visibility("hidden"))) thread_local int hidden_tls; diff --git a/clang/test/CodeGenCXX/cxx11-thread-local.cpp b/clang/test/CodeGenCXX/cxx11-thread-local.cpp index 156c4f591908b..de941af1afb87 100644 --- a/clang/test/CodeGenCXX/cxx11-thread-local.cpp +++ b/clang/test/CodeGenCXX/cxx11-thread-local.cpp @@ -318,7 +318,7 @@ void set_anon_i() { // CHECK-NOT: call void @[[V_M_INIT]]() -// LIUNX: define weak_odr hidden i32* @_ZTW1a() { +// LINUX: define weak_odr hidden i32* @_ZTW1a() // DARWIN: define cxx_fast_tlscc i32* @_ZTW1a() // LINUX: call void @_ZTH1a() // DARWIN: call cxx_fast_tlscc void @_ZTH1a() diff --git a/clang/test/CodeGenCXX/debug-info-template-member.cpp b/clang/test/CodeGenCXX/debug-info-template-member.cpp index db6006cab8205..3d5b04d164142 100644 --- a/clang/test/CodeGenCXX/debug-info-template-member.cpp +++ b/clang/test/CodeGenCXX/debug-info-template-member.cpp @@ -30,7 +30,7 @@ inline int add3(int x) { // CHECK: {{![0-9]+}} = distinct !DIGlobalVariable( // CHECK-SAME: name: "var" // CHECK-SAME: templateParams: {{![0-9]+}} -// CHECK: !DITemplateTypeParameter(name: "P", type: {{![0-9]+}}) +// CHECK: !DITemplateTypeParameter(name: "T", type: {{![0-9]+}}) // CHECK: {{![0-9]+}} = distinct !DIGlobalVariable( // CHECK-SAME: name: "varray" // CHECK-SAME: templateParams: {{![0-9]+}} diff --git a/clang/test/CodeGenCXX/debug-info-var-template-partial.cpp b/clang/test/CodeGenCXX/debug-info-var-template-partial.cpp new file mode 100644 index 0000000000000..16c5f82c72e18 --- /dev/null +++ b/clang/test/CodeGenCXX/debug-info-var-template-partial.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu %s -o - -debug-info-kind=limited | FileCheck %s + +template constexpr bool is_same_v = false; +template constexpr bool is_same_v = true; + +template constexpr bool is_same_v; +static_assert(is_same_v, "should get partial spec"); + +// Note that the template arguments for the instantiated variable use the +// parameter names from the primary template. The partial specialization might +// not have enough parameters. + +// CHECK: distinct !DIGlobalVariable(name: "is_same_v", linkageName: "_ZL9is_same_vIiiE", {{.*}} templateParams: ![[PARAMS:[0-9]+]]) +// CHECK: ![[PARAMS]] = !{![[LHS:[0-9]+]], ![[RHS:[0-9]+]]} +// CHECK: ![[LHS]] = !DITemplateTypeParameter(name: "LHS", type: ![[INT:[0-9]+]]) +// CHECK: ![[INT]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +// CHECK: ![[RHS]] = !DITemplateTypeParameter(name: "RHS", type: ![[INT]]) diff --git a/clang/test/CodeGenCXX/float16-declarations.cpp b/clang/test/CodeGenCXX/float16-declarations.cpp index 7e1c1e8db93ca..7d07eac48111f 100644 --- a/clang/test/CodeGenCXX/float16-declarations.cpp +++ b/clang/test/CodeGenCXX/float16-declarations.cpp @@ -1,5 +1,4 @@ // RUN: %clang -std=c++11 --target=aarch64-arm--eabi -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH64 -// RUN: %clang -std=c++11 --target=x86_64 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X86 /* Various contexts where type _Float16 can appear. */ @@ -15,7 +14,6 @@ namespace { _Float16 arr1n[10]; // CHECK-AARCH64-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x half] zeroinitializer, align 2 -// CHECK-X86-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x half] zeroinitializer, align 16 _Float16 arr2n[] = { 1.2, 3.0, 3.e4 }; // CHECK-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x half] [half 0xH3CCD, half 0xH4200, half 0xH7753], align 2 @@ -30,14 +28,12 @@ namespace { _Float16 f1f; // CHECK-AARCH64-DAG: @f1f = dso_local global half 0xH0000, align 2 -// CHECK-X86-DAG: @f1f = dso_local global half 0xH0000, align 2 _Float16 f2f = 32.4; // CHECK-DAG: @f2f = dso_local global half 0xH500D, align 2 _Float16 arr1f[10]; // CHECK-AARCH64-DAG: @arr1f = dso_local global [10 x half] zeroinitializer, align 2 -// CHECK-X86-DAG: @arr1f = dso_local global [10 x half] zeroinitializer, align 16 _Float16 arr2f[] = { -1.2, -3.0, -3.e4 }; // CHECK-DAG: @arr2f = dso_local global [3 x half] [half 0xHBCCD, half 0xHC200, half 0xHF753], align 2 @@ -137,8 +133,6 @@ int main(void) { long double cvtld = f2n; //CHECK-AARCh64-DAG: [[H2LD:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to fp128 //CHECK-AARCh64-DAG: store fp128 [[H2LD]], fp128* %{{.*}}, align 16 -//CHECK-X86-DAG: [[H2LD:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to x86_fp80 -//CHECK-X86-DAG: store x86_fp80 [[H2LD]], x86_fp80* %{{.*}}, align 16 _Float16 f2h = 42.0f; //CHECK-DAG: store half 0xH5140, half* %{{.*}}, align 2 diff --git a/clang/test/CodeGenCXX/mangle-ms.cpp b/clang/test/CodeGenCXX/mangle-ms.cpp index e128c94431532..0175b961e5e90 100644 --- a/clang/test/CodeGenCXX/mangle-ms.cpp +++ b/clang/test/CodeGenCXX/mangle-ms.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=i386-pc-win32 -std=c++98 | FileCheck %s // RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=x86_64-pc-win32 -std=c++98| FileCheck -check-prefix X64 %s +// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=aarch64-pc-win32 -std=c++98 -DARM | FileCheck -check-prefixes=X64,ARM %s int a; // CHECK-DAG: @"?a@@3HA" @@ -466,10 +467,12 @@ namespace Complex { // CHECK-DAG: define dso_local void @"?f@Complex@@YAXU?$_Complex@H@__clang@@@Z"( void f(_Complex int) {} } +#ifdef ARM namespace Float16 { -// CHECK-DAG: define dso_local void @"?f@Float16@@YAXU_Float16@__clang@@@Z"( +// ARM-DAG: define dso_local void @"?f@Float16@@YAXU_Float16@__clang@@@Z"( void f(_Float16) {} } +#endif // ARM namespace PR26029 { template diff --git a/clang/test/CodeGenCXX/trivial-auto-var-init.cpp b/clang/test/CodeGenCXX/trivial-auto-var-init.cpp index b795c0755bd41..0a9ad86c7e2fe 100644 --- a/clang/test/CodeGenCXX/trivial-auto-var-init.cpp +++ b/clang/test/CodeGenCXX/trivial-auto-var-init.cpp @@ -30,6 +30,53 @@ void test_block() { used(block); } +// Using the variable being initialized is typically UB in C, but for blocks we +// can be nice: they imply extra book-keeping and we can do the auto-init before +// any of said book-keeping. +// +// UNINIT-LABEL: test_block_self_init( +// ZERO-LABEL: test_block_self_init( +// ZERO: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8 +// ZERO: %captured1 = getelementptr inbounds %struct.__block_byref_captured, %struct.__block_byref_captured* %captured, i32 0, i32 4 +// ZERO-NEXT: store %struct.XYZ* null, %struct.XYZ** %captured1, align 8 +// ZERO: %call = call %struct.XYZ* @create( +// PATTERN-LABEL: test_block_self_init( +// PATTERN: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8 +// PATTERN: %captured1 = getelementptr inbounds %struct.__block_byref_captured, %struct.__block_byref_captured* %captured, i32 0, i32 4 +// PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8 +// PATTERN: %call = call %struct.XYZ* @create( +using Block = void (^)(); +typedef struct XYZ { + Block block; +} * xyz_t; +void test_block_self_init() { + extern xyz_t create(Block block); + __block xyz_t captured = create(^() { + used(captured); + }); +} + +// Capturing with escape after initialization is also an edge case. +// +// UNINIT-LABEL: test_block_captures_self_after_init( +// ZERO-LABEL: test_block_captures_self_after_init( +// ZERO: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8 +// ZERO: %captured1 = getelementptr inbounds %struct.__block_byref_captured.1, %struct.__block_byref_captured.1* %captured, i32 0, i32 4 +// ZERO-NEXT: store %struct.XYZ* null, %struct.XYZ** %captured1, align 8 +// ZERO: %call = call %struct.XYZ* @create( +// PATTERN-LABEL: test_block_captures_self_after_init( +// PATTERN: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8 +// PATTERN: %captured1 = getelementptr inbounds %struct.__block_byref_captured.1, %struct.__block_byref_captured.1* %captured, i32 0, i32 4 +// PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8 +// PATTERN: %call = call %struct.XYZ* @create( +void test_block_captures_self_after_init() { + extern xyz_t create(Block block); + __block xyz_t captured; + captured = create(^() { + used(captured); + }); +} + // This type of code is currently not handled by zero / pattern initialization. // The test will break when that is fixed. // UNINIT-LABEL: test_goto_unreachable_value( diff --git a/clang/test/CodeGenCXX/trivial_abi.cpp b/clang/test/CodeGenCXX/trivial_abi.cpp index e37c8ff615a26..2cf07b22581a2 100644 --- a/clang/test/CodeGenCXX/trivial_abi.cpp +++ b/clang/test/CodeGenCXX/trivial_abi.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++17 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++17 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s // CHECK: %[[STRUCT_SMALL:.*]] = type { i32* } // CHECK: %[[STRUCT_LARGE:.*]] = type { i32*, [128 x i32] } @@ -43,13 +43,6 @@ struct HasNonTrivial { NonTrivial m; }; -struct __attribute__((trivial_abi)) CopyMoveDeleted { - CopyMoveDeleted(int); - CopyMoveDeleted(const CopyMoveDeleted &) = delete; - CopyMoveDeleted(CopyMoveDeleted &&) = delete; - int a; -}; - // CHECK: define void @_Z14testParamSmall5Small(i64 %[[A_COERCE:.*]]) // CHECK: %[[A:.*]] = alloca %[[STRUCT_SMALL]], align 8 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[A]], i32 0, i32 0 @@ -244,11 +237,3 @@ void calleeExceptionLarge(Large, Large); void testExceptionLarge() { calleeExceptionLarge(Large(), Large()); } - -// A class with deleted copy and move constructors can still be passed or -// returned in registers if the class is annotated with trivial_abi. - -// CHECK: define i64 @_Z19testCopyMoveDeletedi(i32 % -CopyMoveDeleted testCopyMoveDeleted(int a) { - return a; -} diff --git a/clang/test/CodeGenOpenCL/printf.cl b/clang/test/CodeGenOpenCL/printf.cl index 346f6c35bae46..fc139d776db6e 100644 --- a/clang/test/CodeGenOpenCL/printf.cl +++ b/clang/test/CodeGenOpenCL/printf.cl @@ -12,28 +12,26 @@ int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2))) // ALL-LABEL: @test_printf_float2( -// FP64: %conv = fpext <2 x float> %0 to <2 x double> -// FP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x double> %conv) +// FP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([7 x i8], [7 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x float> %0) -// NOFP64: call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x float> %0) + +// NOFP64: call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([7 x i8], [7 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x float> %0) kernel void test_printf_float2(float2 arg) { - printf("%v2f", arg); + printf("%v2hlf", arg); } // ALL-LABEL: @test_printf_half2( -// FP64: %conv = fpext <2 x half> %0 to <2 x double> -// FP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x double> %conv) #2 +// FP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(2)* @.str.1, i32 0, i32 0), <2 x half> %0) -// NOFP64: %conv = fpext <2 x half> %0 to <2 x float> -// NOFP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x float> %conv) #2 +// NOFP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(2)* @.str.1, i32 0, i32 0), <2 x half> %0) kernel void test_printf_half2(half2 arg) { - printf("%v2f", arg); + printf("%v2hf", arg); } #ifdef cl_khr_fp64 // FP64-LABEL: @test_printf_double2( -// FP64: call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x double> %0) #2 +// FP64: call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(2)* @.str.2, i32 0, i32 0), <2 x double> %0) kernel void test_printf_double2(double2 arg) { - printf("%v2f", arg); + printf("%v2lf", arg); } #endif diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c index f5171d5c040c5..5048fd25c4a7d 100644 --- a/clang/test/Driver/cl-options.c +++ b/clang/test/Driver/cl-options.c @@ -66,7 +66,7 @@ // RUN: %clang_cl -### /FA -fprofile-instr-generate=/tmp/somefile.profraw -- %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-FILE %s // RUN: %clang_cl -### /FA -fprofile-instr-generate -fprofile-instr-use -- %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MIX-GEN-USE %s // RUN: %clang_cl -### /FA -fprofile-instr-generate -fprofile-instr-use=file -- %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MIX-GEN-USE %s -// CHECK-PROFILE-GENERATE: "-fprofile-instrument=clang" +// CHECK-PROFILE-GENERATE: "-fprofile-instrument=clang" "--dependent-lib={{[^"]*}}clang_rt.profile-{{[^"]*}}.lib" // CHECK-PROFILE-GENERATE-FILE: "-fprofile-instrument-path=/tmp/somefile.profraw" // CHECK-NO-MIX-GEN-USE: '{{[a-z=-]*}}' not allowed with '{{[a-z=-]*}}' @@ -178,6 +178,10 @@ // Oy_2: -momit-leaf-frame-pointer // Oy_2: -O2 +// RUN: %clang_cl --target=aarch64-pc-windows-msvc -Werror /Oy- /O2 -### -- %s 2>&1 | FileCheck -check-prefix=Oy_aarch64 %s +// Oy_aarch64: -mdisable-fp-elim +// Oy_aarch64: -O2 + // RUN: %clang_cl --target=i686-pc-win32 -Werror /O2 /O2 -### -- %s 2>&1 | FileCheck -check-prefix=O2O2 %s // O2O2: "-O2" @@ -386,7 +390,10 @@ // Unsupported but parsed options. Check that we don't error on them. // (/Zs is for syntax-only) // RUN: %clang_cl /Zs \ +// RUN: /await \ +// RUN: /constexpr:depth1000 /constexpr:backtrace1000 /constexpr:steps1000 \ // RUN: /AIfoo \ +// RUN: /AI foo_does_not_exist \ // RUN: /Bt \ // RUN: /Bt+ \ // RUN: /clr:pure \ @@ -438,6 +445,9 @@ // RUN: /QIfist \ // RUN: /Qimprecise_fwaits \ // RUN: /Qpar \ +// RUN: /Qpar-report:1 \ +// RUN: /Qsafe_fp_loads \ +// RUN: /Qspectre \ // RUN: /Qvec-report:2 \ // RUN: /u \ // RUN: /V \ diff --git a/clang/test/Driver/instrprof-ld.c b/clang/test/Driver/instrprof-ld.c index ea20105699758..1ac3f9650ff3e 100644 --- a/clang/test/Driver/instrprof-ld.c +++ b/clang/test/Driver/instrprof-ld.c @@ -121,3 +121,17 @@ // // CHECK-WINDOWS-X86-64: "{{.*}}link{{(.exe)?}}" // CHECK-WINDOWS-X86-64: "{{.*}}clang_rt.profile-x86_64.lib" + +// Test instrumented profiling dependent-lib flags +// +// RUN: %clang %s -### -o %t.o -target x86_64-pc-win32 \ +// RUN: -fprofile-instr-generate 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-WINDOWS-X86-64-DEPENDENT-LIB %s +// +// CHECK-WINDOWS-X86-64-DEPENDENT-LIB: "--dependent-lib={{[^"]*}}clang_rt.profile-{{[^"]*}}.lib" +// +// RUN: %clang %s -### -o %t.o -target x86_64-mingw32 \ +// RUN: -fprofile-instr-generate 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-MINGW-X86-64-DEPENDENT-LIB %s +// +// CHECK-MINGW-X86-64-DEPENDENT-LIB-NOT: "--dependent-lib={{[^"]*}}clang_rt.profile-{{[^"]*}}.a" diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c index 3ab81be4906aa..a817347802932 100644 --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -1632,6 +1632,11 @@ // CHECK-DEBIAN-ML-MIPS64EL-N32: "-L[[SYSROOT]]/usr/lib" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=mips64-unknown-linux-gnu \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ +// RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64-GNUABI %s +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: --target=mips64-linux-gnuabi64 -mabi=n64 \ // RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ @@ -1652,6 +1657,11 @@ // CHECK-DEBIAN-ML-MIPS64-GNUABI: "{{.*}}/usr/lib/gcc/mips64-linux-gnuabi64/4.9/../../../mips64-linux-gnuabi64{{/|\\\\}}crtn.o" // // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=mips64el-unknown-linux-gnu \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ +// RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64EL-GNUABI %s +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: --target=mips64el-linux-gnuabi64 -mabi=n64 \ // RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ diff --git a/clang/test/Driver/mips-features.c b/clang/test/Driver/mips-features.c index f63fb8de55d6c..19725bc096b5d 100644 --- a/clang/test/Driver/mips-features.c +++ b/clang/test/Driver/mips-features.c @@ -444,3 +444,15 @@ // RUN: -mginv -mno-ginv 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-GINV %s // CHECK-NO-GINV: "-target-feature" "-ginv" +// +// -mrelax-pic-calls +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -mno-relax-pic-calls -mrelax-pic-calls 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-RELAX-PIC-CALLS %s +// CHECK-RELAX-PIC-CALLS-NOT: "-mllvm" "-mips-jalr-reloc=0" +// +// -mno-relax-pic-calls +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -mrelax-pic-calls -mno-relax-pic-calls 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-RELAX-PIC-CALLS %s +// CHECK-NO-RELAX-PIC-CALLS: "-mllvm" "-mips-jalr-reloc=0" diff --git a/clang/test/Driver/msp430-toolchain.c b/clang/test/Driver/msp430-toolchain.c index ae5ed9189c828..62ef1c0c1f150 100644 --- a/clang/test/Driver/msp430-toolchain.c +++ b/clang/test/Driver/msp430-toolchain.c @@ -8,44 +8,44 @@ // RUN: --gcc-toolchain=%S/Inputs/basic_msp430_tree 2>&1 \ // RUN: | FileCheck -check-prefix=MSP430 %s -// MSP430: "{{.*}}Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../bin/msp430-elf-ld" +// MSP430: "{{.*}}Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../..{{/|\\\\}}..{{/|\\\\}}bin{{/|\\\\}}msp430-elf-ld" // MSP430: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430" -// MSP430: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430" -// MSP430: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430/crt0.o" -// MSP430: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtbegin.o" +// MSP430: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../..{{/|\\\\}}..{{/|\\\\}}msp430-elf{{/|\\\\}}lib/430" +// MSP430: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../..{{/|\\\\}}..{{/|\\\\}}msp430-elf{{/|\\\\}}lib/430{{/|\\\\}}crt0.o" +// MSP430: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430{{/|\\\\}}crtbegin.o" // MSP430: "--start-group" "-lmul_none" "-lgcc" "-lc" "-lcrt" "-lnosys" "--end-group" -// MSP430: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtend.o" -// MSP430: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430/crtn.o" +// MSP430: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430{{/|\\\\}}crtend.o" +// MSP430: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../..{{/|\\\\}}..{{/|\\\\}}msp430-elf{{/|\\\\}}lib/430{{/|\\\\}}crtn.o" // RUN: %clang %s -### -no-canonical-prefixes -target msp430 -nodefaultlibs \ // RUN: --gcc-toolchain=%S/Inputs/basic_msp430_tree 2>&1 \ // RUN: | FileCheck -check-prefix=MSP430-NO-DFT-LIB %s -// MSP430-NO-DFT-LIB: "{{.*}}Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../bin/msp430-elf-ld" +// MSP430-NO-DFT-LIB: "{{.*}}Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../..{{/|\\\\}}..{{/|\\\\}}bin{{/|\\\\}}msp430-elf-ld" // MSP430-NO-DFT-LIB: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430" -// MSP430-NO-DFT-LIB: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430" -// MSP430-NO-DFT-LIB: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430/crt0.o" -// MSP430-NO-DFT-LIB: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtbegin.o" +// MSP430-NO-DFT-LIB: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../..{{/|\\\\}}..{{/|\\\\}}msp430-elf{{/|\\\\}}lib/430" +// MSP430-NO-DFT-LIB: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../..{{/|\\\\}}..{{/|\\\\}}msp430-elf{{/|\\\\}}lib/430{{/|\\\\}}crt0.o" +// MSP430-NO-DFT-LIB: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430{{/|\\\\}}crtbegin.o" // MSP430-NO-DFT-LIB: "--start-group" "-lmul_none" "-lgcc" "--end-group" -// MSP430-NO-DFT-LIB: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430/crtend.o" -// MSP430-NO-DFT-LIB: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430/crtn.o" +// MSP430-NO-DFT-LIB: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430{{/|\\\\}}crtend.o" +// MSP430-NO-DFT-LIB: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../..{{/|\\\\}}..{{/|\\\\}}msp430-elf{{/|\\\\}}lib/430{{/|\\\\}}crtn.o" // RUN: %clang %s -### -no-canonical-prefixes -target msp430 -nostartfiles \ // RUN: --gcc-toolchain=%S/Inputs/basic_msp430_tree 2>&1 \ // RUN: | FileCheck -check-prefix=MSP430-NO-START %s -// MSP430-NO-START: "{{.*}}Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../bin/msp430-elf-ld" +// MSP430-NO-START: "{{.*}}Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../..{{/|\\\\}}..{{/|\\\\}}bin{{/|\\\\}}msp430-elf-ld" // MSP430-NO-START: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430" -// MSP430-NO-START: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430" +// MSP430-NO-START: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../..{{/|\\\\}}..{{/|\\\\}}msp430-elf{{/|\\\\}}lib/430" // MSP430-NO-START: "--start-group" "-lmul_none" "-lgcc" "-lc" "-lcrt" "-lnosys" "--end-group" // RUN: %clang %s -### -no-canonical-prefixes -target msp430 -nostdlib \ // RUN: --gcc-toolchain=%S/Inputs/basic_msp430_tree 2>&1 \ // RUN: | FileCheck -check-prefix=MSP430-NO-STD-LIB %s -// MSP430-NO-STD-LIB: "{{.*}}Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../bin/msp430-elf-ld" +// MSP430-NO-STD-LIB: "{{.*}}Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../..{{/|\\\\}}..{{/|\\\\}}bin{{/|\\\\}}msp430-elf-ld" // MSP430-NO-STD-LIB: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/430" -// MSP430-NO-STD-LIB: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../../../msp430-elf/lib/430" +// MSP430-NO-STD-LIB: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/7.3.1/../../..{{/|\\\\}}..{{/|\\\\}}msp430-elf{{/|\\\\}}lib/430" // MSP430-NO-STD-LIB: "--start-group" "-lmul_none" "-lgcc" "--end-group" // RUN: %clang %s -### -no-canonical-prefixes -target msp430 -mmcu=msp430f147 2>&1 \ diff --git a/clang/test/Driver/netbsd.c b/clang/test/Driver/netbsd.c index f5352e2486f06..221264a525976 100644 --- a/clang/test/Driver/netbsd.c +++ b/clang/test/Driver/netbsd.c @@ -446,3 +446,8 @@ // PTHREAD-NOT: _POSIX_THREADS // PTHREAD: _REENTRANT // PTHREAD-NOT: _POSIX_THREADS + +// Check PowerPC for Secure PLT +// RUN: %clang -target powerpc-unknown-netbsd -### -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix=POWERPC-SECUREPLT %s +// POWERPC-SECUREPLT: "-target-feature" "+secure-plt" diff --git a/clang/test/Lexer/half-literal.cpp b/clang/test/Lexer/half-literal.cpp index 8e0034d491dd7..2f1cf9589fab0 100644 --- a/clang/test/Lexer/half-literal.cpp +++ b/clang/test/Lexer/half-literal.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic -triple aarch64-linux-gnu %s float a = 1.0h; // expected-error{{no matching literal operator for call to 'operator""h' with argument of type 'long double' or 'const char *', and no matching literal operator template}} float b = 1.0H; // expected-error{{invalid suffix 'H' on floating constant}} diff --git a/clang/test/Misc/diag-format.c b/clang/test/Misc/diag-format.c index bc29894ad03e2..b24aeb9356ae3 100644 --- a/clang/test/Misc/diag-format.c +++ b/clang/test/Misc/diag-format.c @@ -1,30 +1,30 @@ -// RUN: %clang -fsyntax-only %s 2>&1 | FileCheck %s -check-prefix=DEFAULT -// RUN: %clang -fsyntax-only -fdiagnostics-format=clang %s 2>&1 | FileCheck %s -check-prefix=DEFAULT -// RUN: %clang -fsyntax-only -fdiagnostics-format=clang -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=DEFAULT +// RUN: %clang -fsyntax-only %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=DEFAULT +// RUN: %clang -fsyntax-only -fdiagnostics-format=clang %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=DEFAULT +// RUN: %clang -fsyntax-only -fdiagnostics-format=clang -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=DEFAULT // -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2013 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2015 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2013 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2015 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2013 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2013 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015 // -// RUN: %clang -fsyntax-only -fdiagnostics-format=vi %s 2>&1 | FileCheck %s -check-prefix=VI +// RUN: %clang -fsyntax-only -fdiagnostics-format=vi %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=VI // -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fno-show-column -fmsc-version=1900 %s 2>&1 | FileCheck %s -check-prefix=MSVC2015_ORIG +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fno-show-column -fmsc-version=1900 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015_ORIG // -// RUN: %clang -fsyntax-only -fno-show-column %s 2>&1 | FileCheck %s -check-prefix=NO_COLUMN +// RUN: %clang -fsyntax-only -fno-show-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=NO_COLUMN // -// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1300 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010-FALLBACK -// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010-FALLBACK -// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1800 %s 2>&1 | FileCheck %s -check-prefix=MSVC2013-FALLBACK -// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1900 %s 2>&1 | FileCheck %s -check-prefix=MSVC2015-FALLBACK +// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1300 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010-FALLBACK +// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010-FALLBACK +// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1800 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2013-FALLBACK +// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1900 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015-FALLBACK diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 9a6bcca1bd36b..5ae4a7ca7bbe9 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -94,6 +94,7 @@ // CHECK-NEXT: ObjCBridge (SubjectMatchRule_record, SubjectMatchRule_type_alias) // CHECK-NEXT: ObjCBridgeMutable (SubjectMatchRule_record) // CHECK-NEXT: ObjCBridgeRelated (SubjectMatchRule_record) +// CHECK-NEXT: ObjCDesignatedInitializer (SubjectMatchRule_objc_method) // CHECK-NEXT: ObjCException (SubjectMatchRule_objc_interface) // CHECK-NEXT: ObjCExplicitProtocolImpl (SubjectMatchRule_objc_protocol) // CHECK-NEXT: ObjCExternallyRetained (SubjectMatchRule_variable_not_is_parameter, SubjectMatchRule_function, SubjectMatchRule_block, SubjectMatchRule_objc_method) @@ -136,6 +137,8 @@ // CHECK-NEXT: WarnUnusedResult (SubjectMatchRule_objc_method, SubjectMatchRule_enum, SubjectMatchRule_record, SubjectMatchRule_hasType_functionType) // CHECK-NEXT: Weak (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record) // CHECK-NEXT: WeakRef (SubjectMatchRule_variable, SubjectMatchRule_function) +// CHECK-NEXT: WebAssemblyImportModule (SubjectMatchRule_function) +// CHECK-NEXT: WebAssemblyImportName (SubjectMatchRule_function) // CHECK-NEXT: WorkGroupSizeHint (SubjectMatchRule_function) // CHECK-NEXT: XRayInstrument (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: XRayLogArgs (SubjectMatchRule_function, SubjectMatchRule_objc_method) diff --git a/clang/test/OpenMP/ordered_doacross_codegen.cpp b/clang/test/OpenMP/ordered_doacross_codegen.cpp index 2f19e9c2d5ef9..a3abf248d7617 100644 --- a/clang/test/OpenMP/ordered_doacross_codegen.cpp +++ b/clang/test/OpenMP/ordered_doacross_codegen.cpp @@ -16,6 +16,17 @@ extern int n; int a[10], b[10], c[10], d[10]; void foo(); +// CHECK-LABEL:bar +void bar() { + int i,j; +// CHECK: call void @__kmpc_doacross_init( +// CHECK: call void @__kmpc_doacross_fini( +#pragma omp parallel for ordered(2) + for (i = 0; i < n; ++i) + for (j = 0; j < n; ++j) + a[i] = b[i] + 1; +} + // CHECK-LABEL: @main() int main() { int i; @@ -35,7 +46,7 @@ int main() { // CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 1, i8* [[CAST]]) // CHECK: call void @__kmpc_for_static_init_4( #pragma omp for ordered(1) - for (i = 0; i < n; ++i) { + for (int i = 0; i < n; ++i) { a[i] = b[i] + 1; foo(); // CHECK: invoke void [[FOO:.+]]( diff --git a/clang/test/PCH/leakfiles b/clang/test/PCH/leakfiles new file mode 100644 index 0000000000000..90b279026bc1a --- /dev/null +++ b/clang/test/PCH/leakfiles @@ -0,0 +1,29 @@ +// Test that compiling using a PCH doesn't leak file descriptors. +// https://bugs.chromium.org/p/chromium/issues/detail?id=924225 +// +// This test requires bash loops and ulimit. +// REQUIRES: shell +// UNSUPPORTED: win32 +// +// Set up source files. lib/lib.h includes lots of lib*.h files in that dir. +// client.c includes lib/lib.h, and also the individual files directly. +// +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: cd %t +// RUN: mkdir lib +// RUN: for i in {1..300}; do touch lib/lib$i.h; done +// RUN: for i in {1..300}; do echo "#include \"lib$i.h\"" >> lib/lib.h; done +// RUN: echo "#include \"lib/lib.h\"" > client.c +// RUN: for i in {1..300}; do echo "#include \"lib/lib$i.h\"" >> client.c; done +// +// We want to verify that we don't hold all the files open at the same time. +// This is important e.g. on mac, which has a low default FD limit. +// RUN: ulimit -n 100 +// +// Test without PCH. +// RUN: %clang_cc1 -fsyntax-only -Ilib/ client.c +// +// Test with PCH. +// RUN: %clang_cc1 -emit-pch -o pch -Ilib/ client.c +// RUN: %clang_cc1 -include-pch pch -Ilib/ client.c -fsyntax-only diff --git a/clang/test/Parser/cxx1z-init-statement.cpp b/clang/test/Parser/cxx1z-init-statement.cpp index ade60dc762d5c..3d119ef8e709c 100644 --- a/clang/test/Parser/cxx1z-init-statement.cpp +++ b/clang/test/Parser/cxx1z-init-statement.cpp @@ -13,9 +13,9 @@ int f() { if (T(n) = 0; n) {} // init-statement expressions - if (T{f()}; f()) {} // expected-warning {{expression result unused}} - if (T{f()}, g, h; f()) {} // expected-warning 2{{unused}} expected-warning {{expression result unused}} - if (T(f()), g, h + 1; f()) {} // expected-warning 2{{unused}} expected-warning {{expression result unused}} + if (T{f()}; f()) {} + if (T{f()}, g, h; f()) {} // expected-warning 2{{unused}} + if (T(f()), g, h + 1; f()) {} // expected-warning 2{{unused}} // condition declarations if (T(n){g}) {} @@ -35,7 +35,7 @@ int f() { // Likewise for 'switch' switch (int n; n) {} - switch (g; int g = 5) {} // expected-warning {{expression result unused}} + switch (g; int g = 5) {} if (int a, b; int c = a) { // expected-note 6{{previous}} int a; // expected-error {{redefinition}} diff --git a/clang/test/Parser/switch-recovery.cpp b/clang/test/Parser/switch-recovery.cpp index eacd017ab2364..a3a0178cd10b6 100644 --- a/clang/test/Parser/switch-recovery.cpp +++ b/clang/test/Parser/switch-recovery.cpp @@ -105,7 +105,7 @@ void test9(int x) { // expected-note {{'x' declared here}} expected-error {{expected expression}} 8:: x; // expected-error {{expected ';' after expression}} \ expected-error {{no member named 'x' in the global namespace; did you mean simply 'x'?}} \ - expected-warning {{expression result unused}} + expected-warning 2 {{expression result unused}} 9:: :y; // expected-error {{expected ';' after expression}} \ expected-error {{expected unqualified-id}} \ expected-warning {{expression result unused}} diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c index 940dddade3378..770e52cc78435 100644 --- a/clang/test/Preprocessor/init.c +++ b/clang/test/Preprocessor/init.c @@ -9110,667 +9110,383 @@ // // RUN: %clang_cc1 -E -dM -ffreestanding -triple=wasm32-unknown-unknown \ // RUN: < /dev/null \ -// RUN: | FileCheck -match-full-lines -check-prefix=WEBASSEMBLY32 %s +// RUN: | FileCheck -match-full-lines -check-prefixes=WEBASSEMBLY,WEBASSEMBLY32 %s +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=wasm64-unknown-unknown \ +// RUN: < /dev/null \ +// RUN: | FileCheck -match-full-lines -check-prefixes=WEBASSEMBLY,WEBASSEMBLY64 %s +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=wasm32-unknown-wasi \ +// RUN: < /dev/null \ +// RUN: | FileCheck -match-full-lines -check-prefixes=WEBASSEMBLY,WEBASSEMBLY32,WEBASSEMBLY-WASI %s +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=wasm64-unknown-wasi \ +// RUN: < /dev/null \ +// RUN: | FileCheck -match-full-lines -check-prefixes=WEBASSEMBLY,WEBASSEMBLY64,WEBASSEMBLY-WASI %s // // WEBASSEMBLY32:#define _ILP32 1 // WEBASSEMBLY32-NOT:#define _LP64 -// WEBASSEMBLY32-NEXT:#define __ATOMIC_ACQUIRE 2 -// WEBASSEMBLY32-NEXT:#define __ATOMIC_ACQ_REL 4 -// WEBASSEMBLY32-NEXT:#define __ATOMIC_CONSUME 1 -// WEBASSEMBLY32-NEXT:#define __ATOMIC_RELAXED 0 -// WEBASSEMBLY32-NEXT:#define __ATOMIC_RELEASE 3 -// WEBASSEMBLY32-NEXT:#define __ATOMIC_SEQ_CST 5 -// WEBASSEMBLY32-NEXT:#define __BIGGEST_ALIGNMENT__ 16 -// WEBASSEMBLY32-NEXT:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ -// WEBASSEMBLY32-NEXT:#define __CHAR16_TYPE__ unsigned short -// WEBASSEMBLY32-NEXT:#define __CHAR32_TYPE__ unsigned int -// WEBASSEMBLY32-NEXT:#define __CHAR_BIT__ 8 -// WEBASSEMBLY32-NOT:#define __CHAR_UNSIGNED__ -// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_BOOL_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_CHAR_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_INT_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_LLONG_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_LONG_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_POINTER_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_SHORT_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __CONSTANT_CFSTRINGS__ 1 -// WEBASSEMBLY32-NEXT:#define __DBL_DECIMAL_DIG__ 17 -// WEBASSEMBLY32-NEXT:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324 -// WEBASSEMBLY32-NEXT:#define __DBL_DIG__ 15 -// WEBASSEMBLY32-NEXT:#define __DBL_EPSILON__ 2.2204460492503131e-16 -// WEBASSEMBLY32-NEXT:#define __DBL_HAS_DENORM__ 1 -// WEBASSEMBLY32-NEXT:#define __DBL_HAS_INFINITY__ 1 -// WEBASSEMBLY32-NEXT:#define __DBL_HAS_QUIET_NAN__ 1 -// WEBASSEMBLY32-NEXT:#define __DBL_MANT_DIG__ 53 -// WEBASSEMBLY32-NEXT:#define __DBL_MAX_10_EXP__ 308 -// WEBASSEMBLY32-NEXT:#define __DBL_MAX_EXP__ 1024 -// WEBASSEMBLY32-NEXT:#define __DBL_MAX__ 1.7976931348623157e+308 -// WEBASSEMBLY32-NEXT:#define __DBL_MIN_10_EXP__ (-307) -// WEBASSEMBLY32-NEXT:#define __DBL_MIN_EXP__ (-1021) -// WEBASSEMBLY32-NEXT:#define __DBL_MIN__ 2.2250738585072014e-308 -// WEBASSEMBLY32-NEXT:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ -// WEBASSEMBLY32-NOT:#define __ELF__ -// WEBASSEMBLY32-NEXT:#define __FINITE_MATH_ONLY__ 0 -// WEBASSEMBLY32:#define __FLT_DECIMAL_DIG__ 9 -// WEBASSEMBLY32-NEXT:#define __FLT_DENORM_MIN__ 1.40129846e-45F -// WEBASSEMBLY32-NEXT:#define __FLT_DIG__ 6 -// WEBASSEMBLY32-NEXT:#define __FLT_EPSILON__ 1.19209290e-7F -// WEBASSEMBLY32-NEXT:#define __FLT_EVAL_METHOD__ 0 -// WEBASSEMBLY32-NEXT:#define __FLT_HAS_DENORM__ 1 -// WEBASSEMBLY32-NEXT:#define __FLT_HAS_INFINITY__ 1 -// WEBASSEMBLY32-NEXT:#define __FLT_HAS_QUIET_NAN__ 1 -// WEBASSEMBLY32-NEXT:#define __FLT_MANT_DIG__ 24 -// WEBASSEMBLY32-NEXT:#define __FLT_MAX_10_EXP__ 38 -// WEBASSEMBLY32-NEXT:#define __FLT_MAX_EXP__ 128 -// WEBASSEMBLY32-NEXT:#define __FLT_MAX__ 3.40282347e+38F -// WEBASSEMBLY32-NEXT:#define __FLT_MIN_10_EXP__ (-37) -// WEBASSEMBLY32-NEXT:#define __FLT_MIN_EXP__ (-125) -// WEBASSEMBLY32-NEXT:#define __FLT_MIN__ 1.17549435e-38F -// WEBASSEMBLY32-NEXT:#define __FLT_RADIX__ 2 -// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_BOOL_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_CHAR_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_INT_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_LLONG_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_LONG_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_POINTER_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_SHORT_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1 -// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2 -// WEBASSEMBLY32-NEXT:#define __GNUC_MINOR__ {{.*}} -// WEBASSEMBLY32-NEXT:#define __GNUC_PATCHLEVEL__ {{.*}} -// WEBASSEMBLY32-NEXT:#define __GNUC_STDC_INLINE__ 1 -// WEBASSEMBLY32-NEXT:#define __GNUC__ {{.*}} -// WEBASSEMBLY32-NEXT:#define __GXX_ABI_VERSION 1002 +// WEBASSEMBLY64-NOT:#define _ILP32 +// WEBASSEMBLY64:#define _LP64 1 +// WEBASSEMBLY-NEXT:#define __ATOMIC_ACQUIRE 2 +// WEBASSEMBLY-NEXT:#define __ATOMIC_ACQ_REL 4 +// WEBASSEMBLY-NEXT:#define __ATOMIC_CONSUME 1 +// WEBASSEMBLY-NEXT:#define __ATOMIC_RELAXED 0 +// WEBASSEMBLY-NEXT:#define __ATOMIC_RELEASE 3 +// WEBASSEMBLY-NEXT:#define __ATOMIC_SEQ_CST 5 +// WEBASSEMBLY-NEXT:#define __BIGGEST_ALIGNMENT__ 16 +// WEBASSEMBLY-NEXT:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ +// WEBASSEMBLY-NEXT:#define __CHAR16_TYPE__ unsigned short +// WEBASSEMBLY-NEXT:#define __CHAR32_TYPE__ unsigned int +// WEBASSEMBLY-NEXT:#define __CHAR_BIT__ 8 +// WEBASSEMBLY-NOT:#define __CHAR_UNSIGNED__ +// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_BOOL_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_CHAR_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_INT_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_LLONG_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_LONG_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_POINTER_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_SHORT_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __CONSTANT_CFSTRINGS__ 1 +// WEBASSEMBLY-NEXT:#define __DBL_DECIMAL_DIG__ 17 +// WEBASSEMBLY-NEXT:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324 +// WEBASSEMBLY-NEXT:#define __DBL_DIG__ 15 +// WEBASSEMBLY-NEXT:#define __DBL_EPSILON__ 2.2204460492503131e-16 +// WEBASSEMBLY-NEXT:#define __DBL_HAS_DENORM__ 1 +// WEBASSEMBLY-NEXT:#define __DBL_HAS_INFINITY__ 1 +// WEBASSEMBLY-NEXT:#define __DBL_HAS_QUIET_NAN__ 1 +// WEBASSEMBLY-NEXT:#define __DBL_MANT_DIG__ 53 +// WEBASSEMBLY-NEXT:#define __DBL_MAX_10_EXP__ 308 +// WEBASSEMBLY-NEXT:#define __DBL_MAX_EXP__ 1024 +// WEBASSEMBLY-NEXT:#define __DBL_MAX__ 1.7976931348623157e+308 +// WEBASSEMBLY-NEXT:#define __DBL_MIN_10_EXP__ (-307) +// WEBASSEMBLY-NEXT:#define __DBL_MIN_EXP__ (-1021) +// WEBASSEMBLY-NEXT:#define __DBL_MIN__ 2.2250738585072014e-308 +// WEBASSEMBLY-NEXT:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ +// WEBASSEMBLY-NOT:#define __ELF__ +// WEBASSEMBLY-NEXT:#define __FINITE_MATH_ONLY__ 0 +// WEBASSEMBLY-NEXT:#define __FLT16_DECIMAL_DIG__ 5 +// WEBASSEMBLY-NEXT:#define __FLT16_DENORM_MIN__ 5.9604644775390625e-8F16 +// WEBASSEMBLY-NEXT:#define __FLT16_DIG__ 3 +// WEBASSEMBLY-NEXT:#define __FLT16_EPSILON__ 9.765625e-4F16 +// WEBASSEMBLY-NEXT:#define __FLT16_HAS_DENORM__ 1 +// WEBASSEMBLY-NEXT:#define __FLT16_HAS_INFINITY__ 1 +// WEBASSEMBLY-NEXT:#define __FLT16_HAS_QUIET_NAN__ 1 +// WEBASSEMBLY-NEXT:#define __FLT16_MANT_DIG__ 11 +// WEBASSEMBLY-NEXT:#define __FLT16_MAX_10_EXP__ 4 +// WEBASSEMBLY-NEXT:#define __FLT16_MAX_EXP__ 15 +// WEBASSEMBLY-NEXT:#define __FLT16_MAX__ 6.5504e+4F16 +// WEBASSEMBLY-NEXT:#define __FLT16_MIN_10_EXP__ (-13) +// WEBASSEMBLY-NEXT:#define __FLT16_MIN_EXP__ (-14) +// WEBASSEMBLY-NEXT:#define __FLT16_MIN__ 6.103515625e-5F16 +// WEBASSEMBLY-NEXT:#define __FLT_DECIMAL_DIG__ 9 +// WEBASSEMBLY-NEXT:#define __FLT_DENORM_MIN__ 1.40129846e-45F +// WEBASSEMBLY-NEXT:#define __FLT_DIG__ 6 +// WEBASSEMBLY-NEXT:#define __FLT_EPSILON__ 1.19209290e-7F +// WEBASSEMBLY-NEXT:#define __FLT_EVAL_METHOD__ 0 +// WEBASSEMBLY-NEXT:#define __FLT_HAS_DENORM__ 1 +// WEBASSEMBLY-NEXT:#define __FLT_HAS_INFINITY__ 1 +// WEBASSEMBLY-NEXT:#define __FLT_HAS_QUIET_NAN__ 1 +// WEBASSEMBLY-NEXT:#define __FLT_MANT_DIG__ 24 +// WEBASSEMBLY-NEXT:#define __FLT_MAX_10_EXP__ 38 +// WEBASSEMBLY-NEXT:#define __FLT_MAX_EXP__ 128 +// WEBASSEMBLY-NEXT:#define __FLT_MAX__ 3.40282347e+38F +// WEBASSEMBLY-NEXT:#define __FLT_MIN_10_EXP__ (-37) +// WEBASSEMBLY-NEXT:#define __FLT_MIN_EXP__ (-125) +// WEBASSEMBLY-NEXT:#define __FLT_MIN__ 1.17549435e-38F +// WEBASSEMBLY-NEXT:#define __FLT_RADIX__ 2 +// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_BOOL_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_CHAR_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_INT_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_LLONG_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_LONG_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_POINTER_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_SHORT_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1 +// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2 +// WEBASSEMBLY-NEXT:#define __GNUC_MINOR__ {{.*}} +// WEBASSEMBLY-NEXT:#define __GNUC_PATCHLEVEL__ {{.*}} +// WEBASSEMBLY-NEXT:#define __GNUC_STDC_INLINE__ 1 +// WEBASSEMBLY-NEXT:#define __GNUC__ {{.*}} +// WEBASSEMBLY-NEXT:#define __GXX_ABI_VERSION 1002 // WEBASSEMBLY32-NEXT:#define __ILP32__ 1 -// WEBASSEMBLY32-NEXT:#define __INT16_C_SUFFIX__ -// WEBASSEMBLY32-NEXT:#define __INT16_FMTd__ "hd" -// WEBASSEMBLY32-NEXT:#define __INT16_FMTi__ "hi" -// WEBASSEMBLY32-NEXT:#define __INT16_MAX__ 32767 -// WEBASSEMBLY32-NEXT:#define __INT16_TYPE__ short -// WEBASSEMBLY32-NEXT:#define __INT32_C_SUFFIX__ -// WEBASSEMBLY32-NEXT:#define __INT32_FMTd__ "d" -// WEBASSEMBLY32-NEXT:#define __INT32_FMTi__ "i" -// WEBASSEMBLY32-NEXT:#define __INT32_MAX__ 2147483647 -// WEBASSEMBLY32-NEXT:#define __INT32_TYPE__ int -// WEBASSEMBLY32-NEXT:#define __INT64_C_SUFFIX__ LL -// WEBASSEMBLY32-NEXT:#define __INT64_FMTd__ "lld" -// WEBASSEMBLY32-NEXT:#define __INT64_FMTi__ "lli" -// WEBASSEMBLY32-NEXT:#define __INT64_MAX__ 9223372036854775807LL -// WEBASSEMBLY32-NEXT:#define __INT64_TYPE__ long long int -// WEBASSEMBLY32-NEXT:#define __INT8_C_SUFFIX__ -// WEBASSEMBLY32-NEXT:#define __INT8_FMTd__ "hhd" -// WEBASSEMBLY32-NEXT:#define __INT8_FMTi__ "hhi" -// WEBASSEMBLY32-NEXT:#define __INT8_MAX__ 127 -// WEBASSEMBLY32-NEXT:#define __INT8_TYPE__ signed char -// WEBASSEMBLY32-NEXT:#define __INTMAX_C_SUFFIX__ LL -// WEBASSEMBLY32-NEXT:#define __INTMAX_FMTd__ "lld" -// WEBASSEMBLY32-NEXT:#define __INTMAX_FMTi__ "lli" -// WEBASSEMBLY32-NEXT:#define __INTMAX_MAX__ 9223372036854775807LL -// WEBASSEMBLY32-NEXT:#define __INTMAX_TYPE__ long long int -// WEBASSEMBLY32-NEXT:#define __INTMAX_WIDTH__ 64 -// WEBASSEMBLY32-NEXT:#define __INTPTR_FMTd__ "ld" -// WEBASSEMBLY32-NEXT:#define __INTPTR_FMTi__ "li" +// WEBASSEMBLY64-NOT:#define __ILP32__ +// WEBASSEMBLY-NEXT:#define __INT16_C_SUFFIX__ +// WEBASSEMBLY-NEXT:#define __INT16_FMTd__ "hd" +// WEBASSEMBLY-NEXT:#define __INT16_FMTi__ "hi" +// WEBASSEMBLY-NEXT:#define __INT16_MAX__ 32767 +// WEBASSEMBLY-NEXT:#define __INT16_TYPE__ short +// WEBASSEMBLY-NEXT:#define __INT32_C_SUFFIX__ +// WEBASSEMBLY-NEXT:#define __INT32_FMTd__ "d" +// WEBASSEMBLY-NEXT:#define __INT32_FMTi__ "i" +// WEBASSEMBLY-NEXT:#define __INT32_MAX__ 2147483647 +// WEBASSEMBLY-NEXT:#define __INT32_TYPE__ int +// WEBASSEMBLY-NEXT:#define __INT64_C_SUFFIX__ LL +// WEBASSEMBLY-NEXT:#define __INT64_FMTd__ "lld" +// WEBASSEMBLY-NEXT:#define __INT64_FMTi__ "lli" +// WEBASSEMBLY-NEXT:#define __INT64_MAX__ 9223372036854775807LL +// WEBASSEMBLY-NEXT:#define __INT64_TYPE__ long long int +// WEBASSEMBLY-NEXT:#define __INT8_C_SUFFIX__ +// WEBASSEMBLY-NEXT:#define __INT8_FMTd__ "hhd" +// WEBASSEMBLY-NEXT:#define __INT8_FMTi__ "hhi" +// WEBASSEMBLY-NEXT:#define __INT8_MAX__ 127 +// WEBASSEMBLY-NEXT:#define __INT8_TYPE__ signed char +// WEBASSEMBLY-NEXT:#define __INTMAX_C_SUFFIX__ LL +// WEBASSEMBLY-NEXT:#define __INTMAX_FMTd__ "lld" +// WEBASSEMBLY-NEXT:#define __INTMAX_FMTi__ "lli" +// WEBASSEMBLY-NEXT:#define __INTMAX_MAX__ 9223372036854775807LL +// WEBASSEMBLY-NEXT:#define __INTMAX_TYPE__ long long int +// WEBASSEMBLY-NEXT:#define __INTMAX_WIDTH__ 64 +// WEBASSEMBLY-NEXT:#define __INTPTR_FMTd__ "ld" +// WEBASSEMBLY-NEXT:#define __INTPTR_FMTi__ "li" // WEBASSEMBLY32-NEXT:#define __INTPTR_MAX__ 2147483647L -// WEBASSEMBLY32-NEXT:#define __INTPTR_TYPE__ long int +// WEBASSEMBLY64-NEXT:#define __INTPTR_MAX__ 9223372036854775807L +// WEBASSEMBLY-NEXT:#define __INTPTR_TYPE__ long int // WEBASSEMBLY32-NEXT:#define __INTPTR_WIDTH__ 32 -// WEBASSEMBLY32-NEXT:#define __INT_FAST16_FMTd__ "hd" -// WEBASSEMBLY32-NEXT:#define __INT_FAST16_FMTi__ "hi" -// WEBASSEMBLY32-NEXT:#define __INT_FAST16_MAX__ 32767 -// WEBASSEMBLY32-NEXT:#define __INT_FAST16_TYPE__ short -// WEBASSEMBLY32-NEXT:#define __INT_FAST32_FMTd__ "d" -// WEBASSEMBLY32-NEXT:#define __INT_FAST32_FMTi__ "i" -// WEBASSEMBLY32-NEXT:#define __INT_FAST32_MAX__ 2147483647 -// WEBASSEMBLY32-NEXT:#define __INT_FAST32_TYPE__ int -// WEBASSEMBLY32-NEXT:#define __INT_FAST64_FMTd__ "lld" -// WEBASSEMBLY32-NEXT:#define __INT_FAST64_FMTi__ "lli" -// WEBASSEMBLY32-NEXT:#define __INT_FAST64_MAX__ 9223372036854775807LL -// WEBASSEMBLY32-NEXT:#define __INT_FAST64_TYPE__ long long int -// WEBASSEMBLY32-NEXT:#define __INT_FAST8_FMTd__ "hhd" -// WEBASSEMBLY32-NEXT:#define __INT_FAST8_FMTi__ "hhi" -// WEBASSEMBLY32-NEXT:#define __INT_FAST8_MAX__ 127 -// WEBASSEMBLY32-NEXT:#define __INT_FAST8_TYPE__ signed char -// WEBASSEMBLY32-NEXT:#define __INT_LEAST16_FMTd__ "hd" -// WEBASSEMBLY32-NEXT:#define __INT_LEAST16_FMTi__ "hi" -// WEBASSEMBLY32-NEXT:#define __INT_LEAST16_MAX__ 32767 -// WEBASSEMBLY32-NEXT:#define __INT_LEAST16_TYPE__ short -// WEBASSEMBLY32-NEXT:#define __INT_LEAST32_FMTd__ "d" -// WEBASSEMBLY32-NEXT:#define __INT_LEAST32_FMTi__ "i" -// WEBASSEMBLY32-NEXT:#define __INT_LEAST32_MAX__ 2147483647 -// WEBASSEMBLY32-NEXT:#define __INT_LEAST32_TYPE__ int -// WEBASSEMBLY32-NEXT:#define __INT_LEAST64_FMTd__ "lld" -// WEBASSEMBLY32-NEXT:#define __INT_LEAST64_FMTi__ "lli" -// WEBASSEMBLY32-NEXT:#define __INT_LEAST64_MAX__ 9223372036854775807LL -// WEBASSEMBLY32-NEXT:#define __INT_LEAST64_TYPE__ long long int -// WEBASSEMBLY32-NEXT:#define __INT_LEAST8_FMTd__ "hhd" -// WEBASSEMBLY32-NEXT:#define __INT_LEAST8_FMTi__ "hhi" -// WEBASSEMBLY32-NEXT:#define __INT_LEAST8_MAX__ 127 -// WEBASSEMBLY32-NEXT:#define __INT_LEAST8_TYPE__ signed char -// WEBASSEMBLY32-NEXT:#define __INT_MAX__ 2147483647 -// WEBASSEMBLY32-NEXT:#define __LDBL_DECIMAL_DIG__ 36 -// WEBASSEMBLY32-NEXT:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L -// WEBASSEMBLY32-NEXT:#define __LDBL_DIG__ 33 -// WEBASSEMBLY32-NEXT:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L -// WEBASSEMBLY32-NEXT:#define __LDBL_HAS_DENORM__ 1 -// WEBASSEMBLY32-NEXT:#define __LDBL_HAS_INFINITY__ 1 -// WEBASSEMBLY32-NEXT:#define __LDBL_HAS_QUIET_NAN__ 1 -// WEBASSEMBLY32-NEXT:#define __LDBL_MANT_DIG__ 113 -// WEBASSEMBLY32-NEXT:#define __LDBL_MAX_10_EXP__ 4932 -// WEBASSEMBLY32-NEXT:#define __LDBL_MAX_EXP__ 16384 -// WEBASSEMBLY32-NEXT:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L -// WEBASSEMBLY32-NEXT:#define __LDBL_MIN_10_EXP__ (-4931) -// WEBASSEMBLY32-NEXT:#define __LDBL_MIN_EXP__ (-16381) -// WEBASSEMBLY32-NEXT:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L -// WEBASSEMBLY32-NEXT:#define __LITTLE_ENDIAN__ 1 -// WEBASSEMBLY32-NEXT:#define __LONG_LONG_MAX__ 9223372036854775807LL +// WEBASSEMBLY64-NEXT:#define __INTPTR_WIDTH__ 64 +// WEBASSEMBLY-NEXT:#define __INT_FAST16_FMTd__ "hd" +// WEBASSEMBLY-NEXT:#define __INT_FAST16_FMTi__ "hi" +// WEBASSEMBLY-NEXT:#define __INT_FAST16_MAX__ 32767 +// WEBASSEMBLY-NEXT:#define __INT_FAST16_TYPE__ short +// WEBASSEMBLY-NEXT:#define __INT_FAST32_FMTd__ "d" +// WEBASSEMBLY-NEXT:#define __INT_FAST32_FMTi__ "i" +// WEBASSEMBLY-NEXT:#define __INT_FAST32_MAX__ 2147483647 +// WEBASSEMBLY-NEXT:#define __INT_FAST32_TYPE__ int +// WEBASSEMBLY-NEXT:#define __INT_FAST64_FMTd__ "lld" +// WEBASSEMBLY-NEXT:#define __INT_FAST64_FMTi__ "lli" +// WEBASSEMBLY-NEXT:#define __INT_FAST64_MAX__ 9223372036854775807LL +// WEBASSEMBLY-NEXT:#define __INT_FAST64_TYPE__ long long int +// WEBASSEMBLY-NEXT:#define __INT_FAST8_FMTd__ "hhd" +// WEBASSEMBLY-NEXT:#define __INT_FAST8_FMTi__ "hhi" +// WEBASSEMBLY-NEXT:#define __INT_FAST8_MAX__ 127 +// WEBASSEMBLY-NEXT:#define __INT_FAST8_TYPE__ signed char +// WEBASSEMBLY-NEXT:#define __INT_LEAST16_FMTd__ "hd" +// WEBASSEMBLY-NEXT:#define __INT_LEAST16_FMTi__ "hi" +// WEBASSEMBLY-NEXT:#define __INT_LEAST16_MAX__ 32767 +// WEBASSEMBLY-NEXT:#define __INT_LEAST16_TYPE__ short +// WEBASSEMBLY-NEXT:#define __INT_LEAST32_FMTd__ "d" +// WEBASSEMBLY-NEXT:#define __INT_LEAST32_FMTi__ "i" +// WEBASSEMBLY-NEXT:#define __INT_LEAST32_MAX__ 2147483647 +// WEBASSEMBLY-NEXT:#define __INT_LEAST32_TYPE__ int +// WEBASSEMBLY-NEXT:#define __INT_LEAST64_FMTd__ "lld" +// WEBASSEMBLY-NEXT:#define __INT_LEAST64_FMTi__ "lli" +// WEBASSEMBLY-NEXT:#define __INT_LEAST64_MAX__ 9223372036854775807LL +// WEBASSEMBLY-NEXT:#define __INT_LEAST64_TYPE__ long long int +// WEBASSEMBLY-NEXT:#define __INT_LEAST8_FMTd__ "hhd" +// WEBASSEMBLY-NEXT:#define __INT_LEAST8_FMTi__ "hhi" +// WEBASSEMBLY-NEXT:#define __INT_LEAST8_MAX__ 127 +// WEBASSEMBLY-NEXT:#define __INT_LEAST8_TYPE__ signed char +// WEBASSEMBLY-NEXT:#define __INT_MAX__ 2147483647 +// WEBASSEMBLY-NEXT:#define __LDBL_DECIMAL_DIG__ 36 +// WEBASSEMBLY-NEXT:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L +// WEBASSEMBLY-NEXT:#define __LDBL_DIG__ 33 +// WEBASSEMBLY-NEXT:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L +// WEBASSEMBLY-NEXT:#define __LDBL_HAS_DENORM__ 1 +// WEBASSEMBLY-NEXT:#define __LDBL_HAS_INFINITY__ 1 +// WEBASSEMBLY-NEXT:#define __LDBL_HAS_QUIET_NAN__ 1 +// WEBASSEMBLY-NEXT:#define __LDBL_MANT_DIG__ 113 +// WEBASSEMBLY-NEXT:#define __LDBL_MAX_10_EXP__ 4932 +// WEBASSEMBLY-NEXT:#define __LDBL_MAX_EXP__ 16384 +// WEBASSEMBLY-NEXT:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L +// WEBASSEMBLY-NEXT:#define __LDBL_MIN_10_EXP__ (-4931) +// WEBASSEMBLY-NEXT:#define __LDBL_MIN_EXP__ (-16381) +// WEBASSEMBLY-NEXT:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L +// WEBASSEMBLY-NEXT:#define __LITTLE_ENDIAN__ 1 +// WEBASSEMBLY-NEXT:#define __LONG_LONG_MAX__ 9223372036854775807LL // WEBASSEMBLY32-NEXT:#define __LONG_MAX__ 2147483647L // WEBASSEMBLY32-NOT:#define __LP64__ -// WEBASSEMBLY32-NEXT:#define __NO_INLINE__ 1 -// WEBASSEMBLY32-NEXT:#define __OBJC_BOOL_IS_BOOL 0 -// WEBASSEMBLY32-NEXT:#define __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES 3 -// WEBASSEMBLY32-NEXT:#define __OPENCL_MEMORY_SCOPE_DEVICE 2 -// WEBASSEMBLY32-NEXT:#define __OPENCL_MEMORY_SCOPE_SUB_GROUP 4 -// WEBASSEMBLY32-NEXT:#define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1 -// WEBASSEMBLY32-NEXT:#define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0 -// WEBASSEMBLY32-NEXT:#define __ORDER_BIG_ENDIAN__ 4321 -// WEBASSEMBLY32-NEXT:#define __ORDER_LITTLE_ENDIAN__ 1234 -// WEBASSEMBLY32-NEXT:#define __ORDER_PDP_ENDIAN__ 3412 +// WEBASSEMBLY64-NEXT:#define __LONG_MAX__ 9223372036854775807L +// WEBASSEMBLY64-NEXT:#define __LP64__ 1 +// WEBASSEMBLY-NEXT:#define __NO_INLINE__ 1 +// WEBASSEMBLY-NEXT:#define __OBJC_BOOL_IS_BOOL 0 +// WEBASSEMBLY-NEXT:#define __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES 3 +// WEBASSEMBLY-NEXT:#define __OPENCL_MEMORY_SCOPE_DEVICE 2 +// WEBASSEMBLY-NEXT:#define __OPENCL_MEMORY_SCOPE_SUB_GROUP 4 +// WEBASSEMBLY-NEXT:#define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1 +// WEBASSEMBLY-NEXT:#define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0 +// WEBASSEMBLY-NEXT:#define __ORDER_BIG_ENDIAN__ 4321 +// WEBASSEMBLY-NEXT:#define __ORDER_LITTLE_ENDIAN__ 1234 +// WEBASSEMBLY-NEXT:#define __ORDER_PDP_ENDIAN__ 3412 // WEBASSEMBLY32-NEXT:#define __POINTER_WIDTH__ 32 -// WEBASSEMBLY32-NEXT:#define __PRAGMA_REDEFINE_EXTNAME 1 -// WEBASSEMBLY32-NEXT:#define __PTRDIFF_FMTd__ "ld" -// WEBASSEMBLY32-NEXT:#define __PTRDIFF_FMTi__ "li" +// WEBASSEMBLY64-NEXT:#define __POINTER_WIDTH__ 64 +// WEBASSEMBLY-NEXT:#define __PRAGMA_REDEFINE_EXTNAME 1 +// WEBASSEMBLY-NEXT:#define __PTRDIFF_FMTd__ "ld" +// WEBASSEMBLY-NEXT:#define __PTRDIFF_FMTi__ "li" // WEBASSEMBLY32-NEXT:#define __PTRDIFF_MAX__ 2147483647L -// WEBASSEMBLY32-NEXT:#define __PTRDIFF_TYPE__ long int +// WEBASSEMBLY64-NEXT:#define __PTRDIFF_MAX__ 9223372036854775807L +// WEBASSEMBLY-NEXT:#define __PTRDIFF_TYPE__ long int // WEBASSEMBLY32-NEXT:#define __PTRDIFF_WIDTH__ 32 -// WEBASSEMBLY32-NOT:#define __REGISTER_PREFIX__ -// WEBASSEMBLY32-NEXT:#define __SCHAR_MAX__ 127 -// WEBASSEMBLY32-NEXT:#define __SHRT_MAX__ 32767 +// WEBASSEMBLY64-NEXT:#define __PTRDIFF_WIDTH__ 64 +// WEBASSEMBLY-NOT:#define __REGISTER_PREFIX__ +// WEBASSEMBLY-NEXT:#define __SCHAR_MAX__ 127 +// WEBASSEMBLY-NEXT:#define __SHRT_MAX__ 32767 // WEBASSEMBLY32-NEXT:#define __SIG_ATOMIC_MAX__ 2147483647L // WEBASSEMBLY32-NEXT:#define __SIG_ATOMIC_WIDTH__ 32 -// WEBASSEMBLY32-NEXT:#define __SIZEOF_DOUBLE__ 8 -// WEBASSEMBLY32-NEXT:#define __SIZEOF_FLOAT__ 4 -// WEBASSEMBLY32-NEXT:#define __SIZEOF_INT128__ 16 -// WEBASSEMBLY32-NEXT:#define __SIZEOF_INT__ 4 -// WEBASSEMBLY32-NEXT:#define __SIZEOF_LONG_DOUBLE__ 16 -// WEBASSEMBLY32-NEXT:#define __SIZEOF_LONG_LONG__ 8 +// WEBASSEMBLY64-NEXT:#define __SIG_ATOMIC_MAX__ 9223372036854775807L +// WEBASSEMBLY64-NEXT:#define __SIG_ATOMIC_WIDTH__ 64 +// WEBASSEMBLY-NEXT:#define __SIZEOF_DOUBLE__ 8 +// WEBASSEMBLY-NEXT:#define __SIZEOF_FLOAT__ 4 +// WEBASSEMBLY-NEXT:#define __SIZEOF_INT128__ 16 +// WEBASSEMBLY-NEXT:#define __SIZEOF_INT__ 4 +// WEBASSEMBLY-NEXT:#define __SIZEOF_LONG_DOUBLE__ 16 +// WEBASSEMBLY-NEXT:#define __SIZEOF_LONG_LONG__ 8 // WEBASSEMBLY32-NEXT:#define __SIZEOF_LONG__ 4 // WEBASSEMBLY32-NEXT:#define __SIZEOF_POINTER__ 4 // WEBASSEMBLY32-NEXT:#define __SIZEOF_PTRDIFF_T__ 4 -// WEBASSEMBLY32-NEXT:#define __SIZEOF_SHORT__ 2 -// WEBASSEMBLY32-NEXT:#define __SIZEOF_SIZE_T__ 4 -// WEBASSEMBLY32-NEXT:#define __SIZEOF_WCHAR_T__ 4 -// WEBASSEMBLY32-NEXT:#define __SIZEOF_WINT_T__ 4 -// WEBASSEMBLY32-NEXT:#define __SIZE_FMTX__ "lX" -// WEBASSEMBLY32-NEXT:#define __SIZE_FMTo__ "lo" -// WEBASSEMBLY32-NEXT:#define __SIZE_FMTu__ "lu" -// WEBASSEMBLY32-NEXT:#define __SIZE_FMTx__ "lx" -// WEBASSEMBLY32-NEXT:#define __SIZE_MAX__ 4294967295UL -// WEBASSEMBLY32-NEXT:#define __SIZE_TYPE__ long unsigned int -// WEBASSEMBLY32-NEXT:#define __SIZE_WIDTH__ 32 -// WEBASSEMBLY32-NEXT:#define __STDC_HOSTED__ 0 -// WEBASSEMBLY32-NOT:#define __STDC_MB_MIGHT_NEQ_WC__ -// WEBASSEMBLY32-NOT:#define __STDC_NO_ATOMICS__ -// WEBASSEMBLY32-NOT:#define __STDC_NO_COMPLEX__ -// WEBASSEMBLY32-NOT:#define __STDC_NO_VLA__ -// WEBASSEMBLY32-NOT:#define __STDC_NO_THREADS__ -// WEBASSEMBLY32-NEXT:#define __STDC_UTF_16__ 1 -// WEBASSEMBLY32-NEXT:#define __STDC_UTF_32__ 1 -// WEBASSEMBLY32-NEXT:#define __STDC_VERSION__ 201112L -// WEBASSEMBLY32-NEXT:#define __STDC__ 1 -// WEBASSEMBLY32-NEXT:#define __UINT16_C_SUFFIX__ -// WEBASSEMBLY32-NEXT:#define __UINT16_FMTX__ "hX" -// WEBASSEMBLY32-NEXT:#define __UINT16_FMTo__ "ho" -// WEBASSEMBLY32-NEXT:#define __UINT16_FMTu__ "hu" -// WEBASSEMBLY32-NEXT:#define __UINT16_FMTx__ "hx" -// WEBASSEMBLY32-NEXT:#define __UINT16_MAX__ 65535 -// WEBASSEMBLY32-NEXT:#define __UINT16_TYPE__ unsigned short -// WEBASSEMBLY32-NEXT:#define __UINT32_C_SUFFIX__ U -// WEBASSEMBLY32-NEXT:#define __UINT32_FMTX__ "X" -// WEBASSEMBLY32-NEXT:#define __UINT32_FMTo__ "o" -// WEBASSEMBLY32-NEXT:#define __UINT32_FMTu__ "u" -// WEBASSEMBLY32-NEXT:#define __UINT32_FMTx__ "x" -// WEBASSEMBLY32-NEXT:#define __UINT32_MAX__ 4294967295U -// WEBASSEMBLY32-NEXT:#define __UINT32_TYPE__ unsigned int -// WEBASSEMBLY32-NEXT:#define __UINT64_C_SUFFIX__ ULL -// WEBASSEMBLY32-NEXT:#define __UINT64_FMTX__ "llX" -// WEBASSEMBLY32-NEXT:#define __UINT64_FMTo__ "llo" -// WEBASSEMBLY32-NEXT:#define __UINT64_FMTu__ "llu" -// WEBASSEMBLY32-NEXT:#define __UINT64_FMTx__ "llx" -// WEBASSEMBLY32-NEXT:#define __UINT64_MAX__ 18446744073709551615ULL -// WEBASSEMBLY32-NEXT:#define __UINT64_TYPE__ long long unsigned int -// WEBASSEMBLY32-NEXT:#define __UINT8_C_SUFFIX__ -// WEBASSEMBLY32-NEXT:#define __UINT8_FMTX__ "hhX" -// WEBASSEMBLY32-NEXT:#define __UINT8_FMTo__ "hho" -// WEBASSEMBLY32-NEXT:#define __UINT8_FMTu__ "hhu" -// WEBASSEMBLY32-NEXT:#define __UINT8_FMTx__ "hhx" -// WEBASSEMBLY32-NEXT:#define __UINT8_MAX__ 255 -// WEBASSEMBLY32-NEXT:#define __UINT8_TYPE__ unsigned char -// WEBASSEMBLY32-NEXT:#define __UINTMAX_C_SUFFIX__ ULL -// WEBASSEMBLY32-NEXT:#define __UINTMAX_FMTX__ "llX" -// WEBASSEMBLY32-NEXT:#define __UINTMAX_FMTo__ "llo" -// WEBASSEMBLY32-NEXT:#define __UINTMAX_FMTu__ "llu" -// WEBASSEMBLY32-NEXT:#define __UINTMAX_FMTx__ "llx" -// WEBASSEMBLY32-NEXT:#define __UINTMAX_MAX__ 18446744073709551615ULL -// WEBASSEMBLY32-NEXT:#define __UINTMAX_TYPE__ long long unsigned int -// WEBASSEMBLY32-NEXT:#define __UINTMAX_WIDTH__ 64 -// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTX__ "lX" -// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTo__ "lo" -// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTu__ "lu" -// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTx__ "lx" -// WEBASSEMBLY32-NEXT:#define __UINTPTR_MAX__ 4294967295UL -// WEBASSEMBLY32-NEXT:#define __UINTPTR_TYPE__ long unsigned int -// WEBASSEMBLY32-NEXT:#define __UINTPTR_WIDTH__ 32 -// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_FMTX__ "hX" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_FMTo__ "ho" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_FMTu__ "hu" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_FMTx__ "hx" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_MAX__ 65535 -// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_TYPE__ unsigned short -// WEBASSEMBLY32-NEXT:#define __UINT_FAST32_FMTX__ "X" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST32_FMTo__ "o" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST32_FMTu__ "u" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST32_FMTx__ "x" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST32_MAX__ 4294967295U -// WEBASSEMBLY32-NEXT:#define __UINT_FAST32_TYPE__ unsigned int -// WEBASSEMBLY32-NEXT:#define __UINT_FAST64_FMTX__ "llX" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST64_FMTo__ "llo" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST64_FMTu__ "llu" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST64_FMTx__ "llx" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST64_MAX__ 18446744073709551615ULL -// WEBASSEMBLY32-NEXT:#define __UINT_FAST64_TYPE__ long long unsigned int -// WEBASSEMBLY32-NEXT:#define __UINT_FAST8_FMTX__ "hhX" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST8_FMTo__ "hho" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST8_FMTu__ "hhu" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST8_FMTx__ "hhx" -// WEBASSEMBLY32-NEXT:#define __UINT_FAST8_MAX__ 255 -// WEBASSEMBLY32-NEXT:#define __UINT_FAST8_TYPE__ unsigned char -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST16_FMTX__ "hX" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST16_FMTo__ "ho" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST16_FMTu__ "hu" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST16_FMTx__ "hx" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST16_MAX__ 65535 -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST16_TYPE__ unsigned short -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST32_FMTX__ "X" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST32_FMTo__ "o" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST32_FMTu__ "u" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST32_FMTx__ "x" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST32_MAX__ 4294967295U -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST32_TYPE__ unsigned int -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST64_FMTX__ "llX" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST64_FMTo__ "llo" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST64_FMTu__ "llu" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST64_FMTx__ "llx" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST64_TYPE__ long long unsigned int -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST8_FMTX__ "hhX" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST8_FMTo__ "hho" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST8_FMTu__ "hhu" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST8_FMTx__ "hhx" -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST8_MAX__ 255 -// WEBASSEMBLY32-NEXT:#define __UINT_LEAST8_TYPE__ unsigned char -// WEBASSEMBLY32-NEXT:#define __USER_LABEL_PREFIX__ -// WEBASSEMBLY32-NEXT:#define __VERSION__ "{{.*}}" -// WEBASSEMBLY32-NEXT:#define __WCHAR_MAX__ 2147483647 -// WEBASSEMBLY32-NEXT:#define __WCHAR_TYPE__ int -// WEBASSEMBLY32-NOT:#define __WCHAR_UNSIGNED__ -// WEBASSEMBLY32-NEXT:#define __WCHAR_WIDTH__ 32 -// WEBASSEMBLY32-NEXT:#define __WINT_MAX__ 2147483647 -// WEBASSEMBLY32-NEXT:#define __WINT_TYPE__ int -// WEBASSEMBLY32-NOT:#define __WINT_UNSIGNED__ -// WEBASSEMBLY32-NEXT:#define __WINT_WIDTH__ 32 -// WEBASSEMBLY32-NEXT:#define __clang__ 1 -// WEBASSEMBLY32-NEXT:#define __clang_major__ {{.*}} -// WEBASSEMBLY32-NEXT:#define __clang_minor__ {{.*}} -// WEBASSEMBLY32-NEXT:#define __clang_patchlevel__ {{.*}} -// WEBASSEMBLY32-NEXT:#define __clang_version__ "{{.*}}" -// WEBASSEMBLY32-NEXT:#define __llvm__ 1 -// WEBASSEMBLY32-NOT:#define __wasm_simd128__ -// WEBASSEMBLY32-NOT:#define __wasm_simd256__ -// WEBASSEMBLY32-NOT:#define __wasm_simd512__ -// WEBASSEMBLY32-NOT:#define __unix -// WEBASSEMBLY32-NOT:#define __unix__ -// WEBASSEMBLY32-NEXT:#define __wasm 1 -// WEBASSEMBLY32-NEXT:#define __wasm32 1 -// WEBASSEMBLY32-NEXT:#define __wasm32__ 1 -// WEBASSEMBLY32-NOT:#define __wasm64 -// WEBASSEMBLY32-NOT:#define __wasm64__ -// WEBASSEMBLY32-NEXT:#define __wasm__ 1 -// -// RUN: %clang_cc1 -E -dM -ffreestanding -triple=wasm64-unknown-unknown \ -// RUN: < /dev/null \ -// RUN: | FileCheck -match-full-lines -check-prefix=WEBASSEMBLY64 %s -// -// WEBASSEMBLY64-NOT:#define _ILP32 -// WEBASSEMBLY64:#define _LP64 1 -// WEBASSEMBLY64-NEXT:#define __ATOMIC_ACQUIRE 2 -// WEBASSEMBLY64-NEXT:#define __ATOMIC_ACQ_REL 4 -// WEBASSEMBLY64-NEXT:#define __ATOMIC_CONSUME 1 -// WEBASSEMBLY64-NEXT:#define __ATOMIC_RELAXED 0 -// WEBASSEMBLY64-NEXT:#define __ATOMIC_RELEASE 3 -// WEBASSEMBLY64-NEXT:#define __ATOMIC_SEQ_CST 5 -// WEBASSEMBLY64-NEXT:#define __BIGGEST_ALIGNMENT__ 16 -// WEBASSEMBLY64-NEXT:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ -// WEBASSEMBLY64-NEXT:#define __CHAR16_TYPE__ unsigned short -// WEBASSEMBLY64-NEXT:#define __CHAR32_TYPE__ unsigned int -// WEBASSEMBLY64-NEXT:#define __CHAR_BIT__ 8 -// WEBASSEMBLY64-NOT:#define __CHAR_UNSIGNED__ -// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_BOOL_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_CHAR_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_INT_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_LLONG_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_LONG_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_POINTER_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_SHORT_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __CONSTANT_CFSTRINGS__ 1 -// WEBASSEMBLY64-NEXT:#define __DBL_DECIMAL_DIG__ 17 -// WEBASSEMBLY64-NEXT:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324 -// WEBASSEMBLY64-NEXT:#define __DBL_DIG__ 15 -// WEBASSEMBLY64-NEXT:#define __DBL_EPSILON__ 2.2204460492503131e-16 -// WEBASSEMBLY64-NEXT:#define __DBL_HAS_DENORM__ 1 -// WEBASSEMBLY64-NEXT:#define __DBL_HAS_INFINITY__ 1 -// WEBASSEMBLY64-NEXT:#define __DBL_HAS_QUIET_NAN__ 1 -// WEBASSEMBLY64-NEXT:#define __DBL_MANT_DIG__ 53 -// WEBASSEMBLY64-NEXT:#define __DBL_MAX_10_EXP__ 308 -// WEBASSEMBLY64-NEXT:#define __DBL_MAX_EXP__ 1024 -// WEBASSEMBLY64-NEXT:#define __DBL_MAX__ 1.7976931348623157e+308 -// WEBASSEMBLY64-NEXT:#define __DBL_MIN_10_EXP__ (-307) -// WEBASSEMBLY64-NEXT:#define __DBL_MIN_EXP__ (-1021) -// WEBASSEMBLY64-NEXT:#define __DBL_MIN__ 2.2250738585072014e-308 -// WEBASSEMBLY64-NEXT:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ -// WEBASSEMBLY64-NOT:#define __ELF__ -// WEBASSEMBLY64-NEXT:#define __FINITE_MATH_ONLY__ 0 -// WEBASSEMBLY64:#define __FLT_DECIMAL_DIG__ 9 -// WEBASSEMBLY64-NEXT:#define __FLT_DENORM_MIN__ 1.40129846e-45F -// WEBASSEMBLY64-NEXT:#define __FLT_DIG__ 6 -// WEBASSEMBLY64-NEXT:#define __FLT_EPSILON__ 1.19209290e-7F -// WEBASSEMBLY64-NEXT:#define __FLT_EVAL_METHOD__ 0 -// WEBASSEMBLY64-NEXT:#define __FLT_HAS_DENORM__ 1 -// WEBASSEMBLY64-NEXT:#define __FLT_HAS_INFINITY__ 1 -// WEBASSEMBLY64-NEXT:#define __FLT_HAS_QUIET_NAN__ 1 -// WEBASSEMBLY64-NEXT:#define __FLT_MANT_DIG__ 24 -// WEBASSEMBLY64-NEXT:#define __FLT_MAX_10_EXP__ 38 -// WEBASSEMBLY64-NEXT:#define __FLT_MAX_EXP__ 128 -// WEBASSEMBLY64-NEXT:#define __FLT_MAX__ 3.40282347e+38F -// WEBASSEMBLY64-NEXT:#define __FLT_MIN_10_EXP__ (-37) -// WEBASSEMBLY64-NEXT:#define __FLT_MIN_EXP__ (-125) -// WEBASSEMBLY64-NEXT:#define __FLT_MIN__ 1.17549435e-38F -// WEBASSEMBLY64-NEXT:#define __FLT_RADIX__ 2 -// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_BOOL_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_CHAR_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_INT_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_LLONG_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_LONG_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_POINTER_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_SHORT_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1 -// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2 -// WEBASSEMBLY64-NEXT:#define __GNUC_MINOR__ {{.*}} -// WEBASSEMBLY64-NEXT:#define __GNUC_PATCHLEVEL__ {{.*}} -// WEBASSEMBLY64-NEXT:#define __GNUC_STDC_INLINE__ 1 -// WEBASSEMBLY64-NEXT:#define __GNUC__ {{.}} -// WEBASSEMBLY64-NEXT:#define __GXX_ABI_VERSION 1002 -// WEBASSEMBLY64-NOT:#define __ILP32__ -// WEBASSEMBLY64-NEXT:#define __INT16_C_SUFFIX__ -// WEBASSEMBLY64-NEXT:#define __INT16_FMTd__ "hd" -// WEBASSEMBLY64-NEXT:#define __INT16_FMTi__ "hi" -// WEBASSEMBLY64-NEXT:#define __INT16_MAX__ 32767 -// WEBASSEMBLY64-NEXT:#define __INT16_TYPE__ short -// WEBASSEMBLY64-NEXT:#define __INT32_C_SUFFIX__ -// WEBASSEMBLY64-NEXT:#define __INT32_FMTd__ "d" -// WEBASSEMBLY64-NEXT:#define __INT32_FMTi__ "i" -// WEBASSEMBLY64-NEXT:#define __INT32_MAX__ 2147483647 -// WEBASSEMBLY64-NEXT:#define __INT32_TYPE__ int -// WEBASSEMBLY64-NEXT:#define __INT64_C_SUFFIX__ LL -// WEBASSEMBLY64-NEXT:#define __INT64_FMTd__ "lld" -// WEBASSEMBLY64-NEXT:#define __INT64_FMTi__ "lli" -// WEBASSEMBLY64-NEXT:#define __INT64_MAX__ 9223372036854775807LL -// WEBASSEMBLY64-NEXT:#define __INT64_TYPE__ long long int -// WEBASSEMBLY64-NEXT:#define __INT8_C_SUFFIX__ -// WEBASSEMBLY64-NEXT:#define __INT8_FMTd__ "hhd" -// WEBASSEMBLY64-NEXT:#define __INT8_FMTi__ "hhi" -// WEBASSEMBLY64-NEXT:#define __INT8_MAX__ 127 -// WEBASSEMBLY64-NEXT:#define __INT8_TYPE__ signed char -// WEBASSEMBLY64-NEXT:#define __INTMAX_C_SUFFIX__ LL -// WEBASSEMBLY64-NEXT:#define __INTMAX_FMTd__ "lld" -// WEBASSEMBLY64-NEXT:#define __INTMAX_FMTi__ "lli" -// WEBASSEMBLY64-NEXT:#define __INTMAX_MAX__ 9223372036854775807LL -// WEBASSEMBLY64-NEXT:#define __INTMAX_TYPE__ long long int -// WEBASSEMBLY64-NEXT:#define __INTMAX_WIDTH__ 64 -// WEBASSEMBLY64-NEXT:#define __INTPTR_FMTd__ "ld" -// WEBASSEMBLY64-NEXT:#define __INTPTR_FMTi__ "li" -// WEBASSEMBLY64-NEXT:#define __INTPTR_MAX__ 9223372036854775807L -// WEBASSEMBLY64-NEXT:#define __INTPTR_TYPE__ long int -// WEBASSEMBLY64-NEXT:#define __INTPTR_WIDTH__ 64 -// WEBASSEMBLY64-NEXT:#define __INT_FAST16_FMTd__ "hd" -// WEBASSEMBLY64-NEXT:#define __INT_FAST16_FMTi__ "hi" -// WEBASSEMBLY64-NEXT:#define __INT_FAST16_MAX__ 32767 -// WEBASSEMBLY64-NEXT:#define __INT_FAST16_TYPE__ short -// WEBASSEMBLY64-NEXT:#define __INT_FAST32_FMTd__ "d" -// WEBASSEMBLY64-NEXT:#define __INT_FAST32_FMTi__ "i" -// WEBASSEMBLY64-NEXT:#define __INT_FAST32_MAX__ 2147483647 -// WEBASSEMBLY64-NEXT:#define __INT_FAST32_TYPE__ int -// WEBASSEMBLY64-NEXT:#define __INT_FAST64_FMTd__ "lld" -// WEBASSEMBLY64-NEXT:#define __INT_FAST64_FMTi__ "lli" -// WEBASSEMBLY64-NEXT:#define __INT_FAST64_MAX__ 9223372036854775807LL -// WEBASSEMBLY64-NEXT:#define __INT_FAST64_TYPE__ long long int -// WEBASSEMBLY64-NEXT:#define __INT_FAST8_FMTd__ "hhd" -// WEBASSEMBLY64-NEXT:#define __INT_FAST8_FMTi__ "hhi" -// WEBASSEMBLY64-NEXT:#define __INT_FAST8_MAX__ 127 -// WEBASSEMBLY64-NEXT:#define __INT_FAST8_TYPE__ signed char -// WEBASSEMBLY64-NEXT:#define __INT_LEAST16_FMTd__ "hd" -// WEBASSEMBLY64-NEXT:#define __INT_LEAST16_FMTi__ "hi" -// WEBASSEMBLY64-NEXT:#define __INT_LEAST16_MAX__ 32767 -// WEBASSEMBLY64-NEXT:#define __INT_LEAST16_TYPE__ short -// WEBASSEMBLY64-NEXT:#define __INT_LEAST32_FMTd__ "d" -// WEBASSEMBLY64-NEXT:#define __INT_LEAST32_FMTi__ "i" -// WEBASSEMBLY64-NEXT:#define __INT_LEAST32_MAX__ 2147483647 -// WEBASSEMBLY64-NEXT:#define __INT_LEAST32_TYPE__ int -// WEBASSEMBLY64-NEXT:#define __INT_LEAST64_FMTd__ "lld" -// WEBASSEMBLY64-NEXT:#define __INT_LEAST64_FMTi__ "lli" -// WEBASSEMBLY64-NEXT:#define __INT_LEAST64_MAX__ 9223372036854775807LL -// WEBASSEMBLY64-NEXT:#define __INT_LEAST64_TYPE__ long long int -// WEBASSEMBLY64-NEXT:#define __INT_LEAST8_FMTd__ "hhd" -// WEBASSEMBLY64-NEXT:#define __INT_LEAST8_FMTi__ "hhi" -// WEBASSEMBLY64-NEXT:#define __INT_LEAST8_MAX__ 127 -// WEBASSEMBLY64-NEXT:#define __INT_LEAST8_TYPE__ signed char -// WEBASSEMBLY64-NEXT:#define __INT_MAX__ 2147483647 -// WEBASSEMBLY64-NEXT:#define __LDBL_DECIMAL_DIG__ 36 -// WEBASSEMBLY64-NEXT:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L -// WEBASSEMBLY64-NEXT:#define __LDBL_DIG__ 33 -// WEBASSEMBLY64-NEXT:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L -// WEBASSEMBLY64-NEXT:#define __LDBL_HAS_DENORM__ 1 -// WEBASSEMBLY64-NEXT:#define __LDBL_HAS_INFINITY__ 1 -// WEBASSEMBLY64-NEXT:#define __LDBL_HAS_QUIET_NAN__ 1 -// WEBASSEMBLY64-NEXT:#define __LDBL_MANT_DIG__ 113 -// WEBASSEMBLY64-NEXT:#define __LDBL_MAX_10_EXP__ 4932 -// WEBASSEMBLY64-NEXT:#define __LDBL_MAX_EXP__ 16384 -// WEBASSEMBLY64-NEXT:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L -// WEBASSEMBLY64-NEXT:#define __LDBL_MIN_10_EXP__ (-4931) -// WEBASSEMBLY64-NEXT:#define __LDBL_MIN_EXP__ (-16381) -// WEBASSEMBLY64-NEXT:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L -// WEBASSEMBLY64-NEXT:#define __LITTLE_ENDIAN__ 1 -// WEBASSEMBLY64-NEXT:#define __LONG_LONG_MAX__ 9223372036854775807LL -// WEBASSEMBLY64-NEXT:#define __LONG_MAX__ 9223372036854775807L -// WEBASSEMBLY64-NEXT:#define __LP64__ 1 -// WEBASSEMBLY64-NEXT:#define __NO_INLINE__ 1 -// WEBASSEMBLY64-NEXT:#define __OBJC_BOOL_IS_BOOL 0 -// WEBASSEMBLY64-NEXT:#define __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES 3 -// WEBASSEMBLY64-NEXT:#define __OPENCL_MEMORY_SCOPE_DEVICE 2 -// WEBASSEMBLY64-NEXT:#define __OPENCL_MEMORY_SCOPE_SUB_GROUP 4 -// WEBASSEMBLY64-NEXT:#define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1 -// WEBASSEMBLY64-NEXT:#define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0 -// WEBASSEMBLY64-NEXT:#define __ORDER_BIG_ENDIAN__ 4321 -// WEBASSEMBLY64-NEXT:#define __ORDER_LITTLE_ENDIAN__ 1234 -// WEBASSEMBLY64-NEXT:#define __ORDER_PDP_ENDIAN__ 3412 -// WEBASSEMBLY64-NEXT:#define __POINTER_WIDTH__ 64 -// WEBASSEMBLY64-NEXT:#define __PRAGMA_REDEFINE_EXTNAME 1 -// WEBASSEMBLY64-NEXT:#define __PTRDIFF_FMTd__ "ld" -// WEBASSEMBLY64-NEXT:#define __PTRDIFF_FMTi__ "li" -// WEBASSEMBLY64-NEXT:#define __PTRDIFF_MAX__ 9223372036854775807L -// WEBASSEMBLY64-NEXT:#define __PTRDIFF_TYPE__ long int -// WEBASSEMBLY64-NEXT:#define __PTRDIFF_WIDTH__ 64 -// WEBASSEMBLY64-NOT:#define __REGISTER_PREFIX__ -// WEBASSEMBLY64-NEXT:#define __SCHAR_MAX__ 127 -// WEBASSEMBLY64-NEXT:#define __SHRT_MAX__ 32767 -// WEBASSEMBLY64-NEXT:#define __SIG_ATOMIC_MAX__ 9223372036854775807L -// WEBASSEMBLY64-NEXT:#define __SIG_ATOMIC_WIDTH__ 64 -// WEBASSEMBLY64-NEXT:#define __SIZEOF_DOUBLE__ 8 -// WEBASSEMBLY64-NEXT:#define __SIZEOF_FLOAT__ 4 -// WEBASSEMBLY64-NEXT:#define __SIZEOF_INT128__ 16 -// WEBASSEMBLY64-NEXT:#define __SIZEOF_INT__ 4 -// WEBASSEMBLY64-NEXT:#define __SIZEOF_LONG_DOUBLE__ 16 -// WEBASSEMBLY64-NEXT:#define __SIZEOF_LONG_LONG__ 8 // WEBASSEMBLY64-NEXT:#define __SIZEOF_LONG__ 8 // WEBASSEMBLY64-NEXT:#define __SIZEOF_POINTER__ 8 // WEBASSEMBLY64-NEXT:#define __SIZEOF_PTRDIFF_T__ 8 -// WEBASSEMBLY64-NEXT:#define __SIZEOF_SHORT__ 2 +// WEBASSEMBLY-NEXT:#define __SIZEOF_SHORT__ 2 +// WEBASSEMBLY32-NEXT:#define __SIZEOF_SIZE_T__ 4 // WEBASSEMBLY64-NEXT:#define __SIZEOF_SIZE_T__ 8 -// WEBASSEMBLY64-NEXT:#define __SIZEOF_WCHAR_T__ 4 -// WEBASSEMBLY64-NEXT:#define __SIZEOF_WINT_T__ 4 -// WEBASSEMBLY64-NEXT:#define __SIZE_FMTX__ "lX" -// WEBASSEMBLY64-NEXT:#define __SIZE_FMTo__ "lo" -// WEBASSEMBLY64-NEXT:#define __SIZE_FMTu__ "lu" -// WEBASSEMBLY64-NEXT:#define __SIZE_FMTx__ "lx" +// WEBASSEMBLY-NEXT:#define __SIZEOF_WCHAR_T__ 4 +// WEBASSEMBLY-NEXT:#define __SIZEOF_WINT_T__ 4 +// WEBASSEMBLY-NEXT:#define __SIZE_FMTX__ "lX" +// WEBASSEMBLY-NEXT:#define __SIZE_FMTo__ "lo" +// WEBASSEMBLY-NEXT:#define __SIZE_FMTu__ "lu" +// WEBASSEMBLY-NEXT:#define __SIZE_FMTx__ "lx" +// WEBASSEMBLY32-NEXT:#define __SIZE_MAX__ 4294967295UL // WEBASSEMBLY64-NEXT:#define __SIZE_MAX__ 18446744073709551615UL -// WEBASSEMBLY64-NEXT:#define __SIZE_TYPE__ long unsigned int +// WEBASSEMBLY-NEXT:#define __SIZE_TYPE__ long unsigned int +// WEBASSEMBLY32-NEXT:#define __SIZE_WIDTH__ 32 // WEBASSEMBLY64-NEXT:#define __SIZE_WIDTH__ 64 -// WEBASSEMBLY64-NEXT:#define __STDC_HOSTED__ 0 -// WEBASSEMBLY64-NOT:#define __STDC_MB_MIGHT_NEQ_WC__ -// WEBASSEMBLY64-NOT:#define __STDC_NO_ATOMICS__ -// WEBASSEMBLY64-NOT:#define __STDC_NO_COMPLEX__ -// WEBASSEMBLY64-NOT:#define __STDC_NO_VLA__ -// WEBASSEMBLY64-NOT:#define __STDC_NO_THREADS__ -// WEBASSEMBLY64-NEXT:#define __STDC_UTF_16__ 1 -// WEBASSEMBLY64-NEXT:#define __STDC_UTF_32__ 1 -// WEBASSEMBLY64-NEXT:#define __STDC_VERSION__ 201112L -// WEBASSEMBLY64-NEXT:#define __STDC__ 1 -// WEBASSEMBLY64-NEXT:#define __UINT16_C_SUFFIX__ -// WEBASSEMBLY64-NEXT:#define __UINT16_FMTX__ "hX" -// WEBASSEMBLY64-NEXT:#define __UINT16_FMTo__ "ho" -// WEBASSEMBLY64-NEXT:#define __UINT16_FMTu__ "hu" -// WEBASSEMBLY64-NEXT:#define __UINT16_FMTx__ "hx" -// WEBASSEMBLY64-NEXT:#define __UINT16_MAX__ 65535 -// WEBASSEMBLY64-NEXT:#define __UINT16_TYPE__ unsigned short -// WEBASSEMBLY64-NEXT:#define __UINT32_C_SUFFIX__ U -// WEBASSEMBLY64-NEXT:#define __UINT32_FMTX__ "X" -// WEBASSEMBLY64-NEXT:#define __UINT32_FMTo__ "o" -// WEBASSEMBLY64-NEXT:#define __UINT32_FMTu__ "u" -// WEBASSEMBLY64-NEXT:#define __UINT32_FMTx__ "x" -// WEBASSEMBLY64-NEXT:#define __UINT32_MAX__ 4294967295U -// WEBASSEMBLY64-NEXT:#define __UINT32_TYPE__ unsigned int -// WEBASSEMBLY64-NEXT:#define __UINT64_C_SUFFIX__ ULL -// WEBASSEMBLY64-NEXT:#define __UINT64_FMTX__ "llX" -// WEBASSEMBLY64-NEXT:#define __UINT64_FMTo__ "llo" -// WEBASSEMBLY64-NEXT:#define __UINT64_FMTu__ "llu" -// WEBASSEMBLY64-NEXT:#define __UINT64_FMTx__ "llx" -// WEBASSEMBLY64-NEXT:#define __UINT64_MAX__ 18446744073709551615ULL -// WEBASSEMBLY64-NEXT:#define __UINT64_TYPE__ long long unsigned int -// WEBASSEMBLY64-NEXT:#define __UINT8_C_SUFFIX__ -// WEBASSEMBLY64-NEXT:#define __UINT8_FMTX__ "hhX" -// WEBASSEMBLY64-NEXT:#define __UINT8_FMTo__ "hho" -// WEBASSEMBLY64-NEXT:#define __UINT8_FMTu__ "hhu" -// WEBASSEMBLY64-NEXT:#define __UINT8_FMTx__ "hhx" -// WEBASSEMBLY64-NEXT:#define __UINT8_MAX__ 255 -// WEBASSEMBLY64-NEXT:#define __UINT8_TYPE__ unsigned char -// WEBASSEMBLY64-NEXT:#define __UINTMAX_C_SUFFIX__ ULL -// WEBASSEMBLY64-NEXT:#define __UINTMAX_FMTX__ "llX" -// WEBASSEMBLY64-NEXT:#define __UINTMAX_FMTo__ "llo" -// WEBASSEMBLY64-NEXT:#define __UINTMAX_FMTu__ "llu" -// WEBASSEMBLY64-NEXT:#define __UINTMAX_FMTx__ "llx" -// WEBASSEMBLY64-NEXT:#define __UINTMAX_MAX__ 18446744073709551615ULL -// WEBASSEMBLY64-NEXT:#define __UINTMAX_TYPE__ long long unsigned int -// WEBASSEMBLY64-NEXT:#define __UINTMAX_WIDTH__ 64 -// WEBASSEMBLY64-NEXT:#define __UINTPTR_FMTX__ "lX" -// WEBASSEMBLY64-NEXT:#define __UINTPTR_FMTo__ "lo" -// WEBASSEMBLY64-NEXT:#define __UINTPTR_FMTu__ "lu" -// WEBASSEMBLY64-NEXT:#define __UINTPTR_FMTx__ "lx" +// WEBASSEMBLY-NEXT:#define __STDC_HOSTED__ 0 +// WEBASSEMBLY-NOT:#define __STDC_MB_MIGHT_NEQ_WC__ +// WEBASSEMBLY-NOT:#define __STDC_NO_ATOMICS__ +// WEBASSEMBLY-NOT:#define __STDC_NO_COMPLEX__ +// WEBASSEMBLY-NOT:#define __STDC_NO_VLA__ +// WEBASSEMBLY-NOT:#define __STDC_NO_THREADS__ +// WEBASSEMBLY-NEXT:#define __STDC_UTF_16__ 1 +// WEBASSEMBLY-NEXT:#define __STDC_UTF_32__ 1 +// WEBASSEMBLY-NEXT:#define __STDC_VERSION__ 201112L +// WEBASSEMBLY-NEXT:#define __STDC__ 1 +// WEBASSEMBLY-NEXT:#define __UINT16_C_SUFFIX__ +// WEBASSEMBLY-NEXT:#define __UINT16_FMTX__ "hX" +// WEBASSEMBLY-NEXT:#define __UINT16_FMTo__ "ho" +// WEBASSEMBLY-NEXT:#define __UINT16_FMTu__ "hu" +// WEBASSEMBLY-NEXT:#define __UINT16_FMTx__ "hx" +// WEBASSEMBLY-NEXT:#define __UINT16_MAX__ 65535 +// WEBASSEMBLY-NEXT:#define __UINT16_TYPE__ unsigned short +// WEBASSEMBLY-NEXT:#define __UINT32_C_SUFFIX__ U +// WEBASSEMBLY-NEXT:#define __UINT32_FMTX__ "X" +// WEBASSEMBLY-NEXT:#define __UINT32_FMTo__ "o" +// WEBASSEMBLY-NEXT:#define __UINT32_FMTu__ "u" +// WEBASSEMBLY-NEXT:#define __UINT32_FMTx__ "x" +// WEBASSEMBLY-NEXT:#define __UINT32_MAX__ 4294967295U +// WEBASSEMBLY-NEXT:#define __UINT32_TYPE__ unsigned int +// WEBASSEMBLY-NEXT:#define __UINT64_C_SUFFIX__ ULL +// WEBASSEMBLY-NEXT:#define __UINT64_FMTX__ "llX" +// WEBASSEMBLY-NEXT:#define __UINT64_FMTo__ "llo" +// WEBASSEMBLY-NEXT:#define __UINT64_FMTu__ "llu" +// WEBASSEMBLY-NEXT:#define __UINT64_FMTx__ "llx" +// WEBASSEMBLY-NEXT:#define __UINT64_MAX__ 18446744073709551615ULL +// WEBASSEMBLY-NEXT:#define __UINT64_TYPE__ long long unsigned int +// WEBASSEMBLY-NEXT:#define __UINT8_C_SUFFIX__ +// WEBASSEMBLY-NEXT:#define __UINT8_FMTX__ "hhX" +// WEBASSEMBLY-NEXT:#define __UINT8_FMTo__ "hho" +// WEBASSEMBLY-NEXT:#define __UINT8_FMTu__ "hhu" +// WEBASSEMBLY-NEXT:#define __UINT8_FMTx__ "hhx" +// WEBASSEMBLY-NEXT:#define __UINT8_MAX__ 255 +// WEBASSEMBLY-NEXT:#define __UINT8_TYPE__ unsigned char +// WEBASSEMBLY-NEXT:#define __UINTMAX_C_SUFFIX__ ULL +// WEBASSEMBLY-NEXT:#define __UINTMAX_FMTX__ "llX" +// WEBASSEMBLY-NEXT:#define __UINTMAX_FMTo__ "llo" +// WEBASSEMBLY-NEXT:#define __UINTMAX_FMTu__ "llu" +// WEBASSEMBLY-NEXT:#define __UINTMAX_FMTx__ "llx" +// WEBASSEMBLY-NEXT:#define __UINTMAX_MAX__ 18446744073709551615ULL +// WEBASSEMBLY-NEXT:#define __UINTMAX_TYPE__ long long unsigned int +// WEBASSEMBLY-NEXT:#define __UINTMAX_WIDTH__ 64 +// WEBASSEMBLY-NEXT:#define __UINTPTR_FMTX__ "lX" +// WEBASSEMBLY-NEXT:#define __UINTPTR_FMTo__ "lo" +// WEBASSEMBLY-NEXT:#define __UINTPTR_FMTu__ "lu" +// WEBASSEMBLY-NEXT:#define __UINTPTR_FMTx__ "lx" +// WEBASSEMBLY32-NEXT:#define __UINTPTR_MAX__ 4294967295UL // WEBASSEMBLY64-NEXT:#define __UINTPTR_MAX__ 18446744073709551615UL -// WEBASSEMBLY64-NEXT:#define __UINTPTR_TYPE__ long unsigned int +// WEBASSEMBLY-NEXT:#define __UINTPTR_TYPE__ long unsigned int +// WEBASSEMBLY32-NEXT:#define __UINTPTR_WIDTH__ 32 // WEBASSEMBLY64-NEXT:#define __UINTPTR_WIDTH__ 64 -// WEBASSEMBLY64-NEXT:#define __UINT_FAST16_FMTX__ "hX" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST16_FMTo__ "ho" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST16_FMTu__ "hu" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST16_FMTx__ "hx" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST16_MAX__ 65535 -// WEBASSEMBLY64-NEXT:#define __UINT_FAST16_TYPE__ unsigned short -// WEBASSEMBLY64-NEXT:#define __UINT_FAST32_FMTX__ "X" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST32_FMTo__ "o" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST32_FMTu__ "u" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST32_FMTx__ "x" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST32_MAX__ 4294967295U -// WEBASSEMBLY64-NEXT:#define __UINT_FAST32_TYPE__ unsigned int -// WEBASSEMBLY64-NEXT:#define __UINT_FAST64_FMTX__ "llX" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST64_FMTo__ "llo" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST64_FMTu__ "llu" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST64_FMTx__ "llx" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST64_MAX__ 18446744073709551615ULL -// WEBASSEMBLY64-NEXT:#define __UINT_FAST64_TYPE__ long long unsigned int -// WEBASSEMBLY64-NEXT:#define __UINT_FAST8_FMTX__ "hhX" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST8_FMTo__ "hho" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST8_FMTu__ "hhu" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST8_FMTx__ "hhx" -// WEBASSEMBLY64-NEXT:#define __UINT_FAST8_MAX__ 255 -// WEBASSEMBLY64-NEXT:#define __UINT_FAST8_TYPE__ unsigned char -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST16_FMTX__ "hX" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST16_FMTo__ "ho" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST16_FMTu__ "hu" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST16_FMTx__ "hx" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST16_MAX__ 65535 -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST16_TYPE__ unsigned short -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST32_FMTX__ "X" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST32_FMTo__ "o" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST32_FMTu__ "u" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST32_FMTx__ "x" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST32_MAX__ 4294967295U -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST32_TYPE__ unsigned int -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST64_FMTX__ "llX" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST64_FMTo__ "llo" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST64_FMTu__ "llu" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST64_FMTx__ "llx" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST64_TYPE__ long long unsigned int -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST8_FMTX__ "hhX" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST8_FMTo__ "hho" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST8_FMTu__ "hhu" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST8_FMTx__ "hhx" -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST8_MAX__ 255 -// WEBASSEMBLY64-NEXT:#define __UINT_LEAST8_TYPE__ unsigned char -// WEBASSEMBLY64-NEXT:#define __USER_LABEL_PREFIX__ -// WEBASSEMBLY64-NEXT:#define __VERSION__ "{{.*}}" -// WEBASSEMBLY64-NEXT:#define __WCHAR_MAX__ 2147483647 -// WEBASSEMBLY64-NEXT:#define __WCHAR_TYPE__ int -// WEBASSEMBLY64-NOT:#define __WCHAR_UNSIGNED__ -// WEBASSEMBLY64-NEXT:#define __WCHAR_WIDTH__ 32 -// WEBASSEMBLY64-NEXT:#define __WINT_MAX__ 2147483647 -// WEBASSEMBLY64-NEXT:#define __WINT_TYPE__ int -// WEBASSEMBLY64-NOT:#define __WINT_UNSIGNED__ -// WEBASSEMBLY64-NEXT:#define __WINT_WIDTH__ 32 -// WEBASSEMBLY64-NEXT:#define __clang__ 1 -// WEBASSEMBLY64-NEXT:#define __clang_major__ {{.*}} -// WEBASSEMBLY64-NEXT:#define __clang_minor__ {{.*}} -// WEBASSEMBLY64-NEXT:#define __clang_patchlevel__ {{.*}} -// WEBASSEMBLY64-NEXT:#define __clang_version__ "{{.*}}" -// WEBASSEMBLY64-NEXT:#define __llvm__ 1 -// WEBASSEMBLY64-NOT:#define __wasm_simd128__ -// WEBASSEMBLY64-NOT:#define __wasm_simd256__ -// WEBASSEMBLY64-NOT:#define __wasm_simd512__ -// WEBASSEMBLY64-NOT:#define __unix -// WEBASSEMBLY64-NOT:#define __unix__ -// WEBASSEMBLY64-NEXT:#define __wasm 1 +// WEBASSEMBLY-NEXT:#define __UINT_FAST16_FMTX__ "hX" +// WEBASSEMBLY-NEXT:#define __UINT_FAST16_FMTo__ "ho" +// WEBASSEMBLY-NEXT:#define __UINT_FAST16_FMTu__ "hu" +// WEBASSEMBLY-NEXT:#define __UINT_FAST16_FMTx__ "hx" +// WEBASSEMBLY-NEXT:#define __UINT_FAST16_MAX__ 65535 +// WEBASSEMBLY-NEXT:#define __UINT_FAST16_TYPE__ unsigned short +// WEBASSEMBLY-NEXT:#define __UINT_FAST32_FMTX__ "X" +// WEBASSEMBLY-NEXT:#define __UINT_FAST32_FMTo__ "o" +// WEBASSEMBLY-NEXT:#define __UINT_FAST32_FMTu__ "u" +// WEBASSEMBLY-NEXT:#define __UINT_FAST32_FMTx__ "x" +// WEBASSEMBLY-NEXT:#define __UINT_FAST32_MAX__ 4294967295U +// WEBASSEMBLY-NEXT:#define __UINT_FAST32_TYPE__ unsigned int +// WEBASSEMBLY-NEXT:#define __UINT_FAST64_FMTX__ "llX" +// WEBASSEMBLY-NEXT:#define __UINT_FAST64_FMTo__ "llo" +// WEBASSEMBLY-NEXT:#define __UINT_FAST64_FMTu__ "llu" +// WEBASSEMBLY-NEXT:#define __UINT_FAST64_FMTx__ "llx" +// WEBASSEMBLY-NEXT:#define __UINT_FAST64_MAX__ 18446744073709551615ULL +// WEBASSEMBLY-NEXT:#define __UINT_FAST64_TYPE__ long long unsigned int +// WEBASSEMBLY-NEXT:#define __UINT_FAST8_FMTX__ "hhX" +// WEBASSEMBLY-NEXT:#define __UINT_FAST8_FMTo__ "hho" +// WEBASSEMBLY-NEXT:#define __UINT_FAST8_FMTu__ "hhu" +// WEBASSEMBLY-NEXT:#define __UINT_FAST8_FMTx__ "hhx" +// WEBASSEMBLY-NEXT:#define __UINT_FAST8_MAX__ 255 +// WEBASSEMBLY-NEXT:#define __UINT_FAST8_TYPE__ unsigned char +// WEBASSEMBLY-NEXT:#define __UINT_LEAST16_FMTX__ "hX" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST16_FMTo__ "ho" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST16_FMTu__ "hu" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST16_FMTx__ "hx" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST16_MAX__ 65535 +// WEBASSEMBLY-NEXT:#define __UINT_LEAST16_TYPE__ unsigned short +// WEBASSEMBLY-NEXT:#define __UINT_LEAST32_FMTX__ "X" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST32_FMTo__ "o" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST32_FMTu__ "u" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST32_FMTx__ "x" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST32_MAX__ 4294967295U +// WEBASSEMBLY-NEXT:#define __UINT_LEAST32_TYPE__ unsigned int +// WEBASSEMBLY-NEXT:#define __UINT_LEAST64_FMTX__ "llX" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST64_FMTo__ "llo" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST64_FMTu__ "llu" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST64_FMTx__ "llx" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL +// WEBASSEMBLY-NEXT:#define __UINT_LEAST64_TYPE__ long long unsigned int +// WEBASSEMBLY-NEXT:#define __UINT_LEAST8_FMTX__ "hhX" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST8_FMTo__ "hho" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST8_FMTu__ "hhu" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST8_FMTx__ "hhx" +// WEBASSEMBLY-NEXT:#define __UINT_LEAST8_MAX__ 255 +// WEBASSEMBLY-NEXT:#define __UINT_LEAST8_TYPE__ unsigned char +// WEBASSEMBLY-NEXT:#define __USER_LABEL_PREFIX__ +// WEBASSEMBLY-NEXT:#define __VERSION__ "{{.*}}" +// WEBASSEMBLY-NEXT:#define __WCHAR_MAX__ 2147483647 +// WEBASSEMBLY-NEXT:#define __WCHAR_TYPE__ int +// WEBASSEMBLY-NOT:#define __WCHAR_UNSIGNED__ +// WEBASSEMBLY-NEXT:#define __WCHAR_WIDTH__ 32 +// WEBASSEMBLY-NEXT:#define __WINT_MAX__ 2147483647 +// WEBASSEMBLY-NEXT:#define __WINT_TYPE__ int +// WEBASSEMBLY-NOT:#define __WINT_UNSIGNED__ +// WEBASSEMBLY-NEXT:#define __WINT_WIDTH__ 32 +// WEBASSEMBLY-NEXT:#define __clang__ 1 +// WEBASSEMBLY-NEXT:#define __clang_major__ {{.*}} +// WEBASSEMBLY-NEXT:#define __clang_minor__ {{.*}} +// WEBASSEMBLY-NEXT:#define __clang_patchlevel__ {{.*}} +// WEBASSEMBLY-NEXT:#define __clang_version__ "{{.*}}" +// WEBASSEMBLY-NEXT:#define __llvm__ 1 +// WEBASSEMBLY-NOT:#define __unix +// WEBASSEMBLY-NOT:#define __unix__ +// WEBASSEMBLY-WASI-NEXT:#define __wasi__ 1 +// WEBASSEMBLY-NOT:#define __wasm_simd128__ +// WEBASSEMBLY-NOT:#define __wasm_simd256__ +// WEBASSEMBLY-NOT:#define __wasm_simd512__ +// WEBASSEMBLY-NEXT:#define __wasm 1 +// WEBASSEMBLY32-NEXT:#define __wasm32 1 // WEBASSEMBLY64-NOT:#define __wasm32 +// WEBASSEMBLY32-NEXT:#define __wasm32__ 1 // WEBASSEMBLY64-NOT:#define __wasm32__ +// WEBASSEMBLY32-NOT:#define __wasm64__ +// WEBASSEMBLY32-NOT:#define __wasm64 // WEBASSEMBLY64-NEXT:#define __wasm64 1 // WEBASSEMBLY64-NEXT:#define __wasm64__ 1 -// WEBASSEMBLY64-NEXT:#define __wasm__ 1 +// WEBASSEMBLY-NEXT:#define __wasm__ 1 // RUN: %clang_cc1 -E -dM -ffreestanding -triple i686-windows-cygnus < /dev/null | FileCheck -match-full-lines -check-prefix CYGWIN-X32 %s // CYGWIN-X32: #define __USER_LABEL_PREFIX__ _ diff --git a/clang/test/Sema/Float16.c b/clang/test/Sema/Float16.c new file mode 100644 index 0000000000000..bdfb01702c371 --- /dev/null +++ b/clang/test/Sema/Float16.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux-pc %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple spir-unknown-unknown %s -DHAVE +// RUN: %clang_cc1 -fsyntax-only -verify -triple armv7a-linux-gnu %s -DHAVE +// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-linux-gnu %s -DHAVE + +#ifdef HAVE +// expected-no-diagnostics +#else +// expected-error@+2{{_Float16 is not supported on this target}} +#endif // HAVE +_Float16 f; diff --git a/clang/test/Sema/attr-msp430.c b/clang/test/Sema/attr-msp430.c index 26b2d8fcfd653..4b38d09b86757 100644 --- a/clang/test/Sema/attr-msp430.c +++ b/clang/test/Sema/attr-msp430.c @@ -1,6 +1,13 @@ // RUN: %clang_cc1 -triple msp430-unknown-unknown -fsyntax-only -verify %s +__attribute__((interrupt(1))) int t; // expected-warning {{'interrupt' attribute only applies to functions}} + int i; -void f(void) __attribute__((interrupt(i))); /* expected-error {{'interrupt' attribute requires an integer constant}} */ +__attribute__((interrupt(i))) void f(void); // expected-error {{'interrupt' attribute requires an integer constant}} +__attribute__((interrupt(1, 2))) void f2(void); // expected-error {{'interrupt' attribute takes one argument}} +__attribute__((interrupt(1))) int f3(void); // expected-warning {{MSP430 'interrupt' attribute only applies to functions that have a 'void' return type}} +__attribute__((interrupt(1))) void f4(int a); // expected-warning {{MSP430 'interrupt' attribute only applies to functions that have no parameters}} +__attribute__((interrupt(64))) void f5(void); // expected-error {{'interrupt' attribute parameter 64 is out of bounds}} -void f2(void) __attribute__((interrupt(12))); +__attribute__((interrupt(0))) void f6(void); +__attribute__((interrupt(63))) void f7(void); diff --git a/clang/test/Sema/inline-asm-validate-x86.c b/clang/test/Sema/inline-asm-validate-x86.c index f21ef6940a6da..5ea20eec05995 100644 --- a/clang/test/Sema/inline-asm-validate-x86.c +++ b/clang/test/Sema/inline-asm-validate-x86.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple i686 -fsyntax-only -verify %s -// RUN: %clang_cc1 -triple x86_64 -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple x86_64 -fsyntax-only -verify -DAMD64 %s void I(int i, int j) { static const int BelowMin = -1; @@ -55,6 +55,7 @@ void K(int i, int j) { void L(int i, int j) { static const int Invalid1 = 1; static const int Invalid2 = 42; + static const int Invalid3 = 0; static const int Valid1 = 0xff; static const int Valid2 = 0xffff; static const int Valid3 = 0xffffffff; @@ -67,6 +68,9 @@ void L(int i, int j) { __asm__("xorl %0,%2" : "=r"(i) : "0"(i), "L"(Invalid2)); // expected-error{{value '42' out of range for constraint 'L'}} + __asm__("xorl %0,%2" + : "=r"(i) + : "0"(i), "L"(Invalid3)); // expected-error{{value '0' out of range for constraint 'L'}} __asm__("xorl %0,%2" : "=r"(i) : "0"(i), "L"(Valid1)); // expected-no-error @@ -129,3 +133,21 @@ void O(int i, int j) { : "0"(i), "O"(64)); // expected-no-error } +void pr40890(void) { + struct s { + int a, b; + }; + static struct s s; + // This null pointer can be used as an integer constant expression. + __asm__ __volatile__("\n#define S_A abcd%0\n" : : "n"(&((struct s*)0)->a)); + // This offset-from-null pointer can be used as an integer constant expression. + __asm__ __volatile__("\n#define S_B abcd%0\n" : : "n"(&((struct s*)0)->b)); + // This pointer cannot be used as an integer constant expression. + __asm__ __volatile__("\n#define GLOBAL_A abcd%0\n" : : "n"(&s.a)); // expected-error{{constraint 'n' expects an integer constant expression}} + // Floating-point is also not okay. + __asm__ __volatile__("\n#define PI abcd%0\n" : : "n"(3.14f)); // expected-error{{constraint 'n' expects an integer constant expression}} +#ifdef AMD64 + // This arbitrary pointer is fine. + __asm__ __volatile__("\n#define BEEF abcd%0\n" : : "n"((int*)0xdeadbeeeeeef)); +#endif +} diff --git a/clang/test/Sema/typo-correction.c b/clang/test/Sema/typo-correction.c index e7992ac90bb3d..73ba265509e4c 100644 --- a/clang/test/Sema/typo-correction.c +++ b/clang/test/Sema/typo-correction.c @@ -100,3 +100,18 @@ void rdar38642201_caller() { structVar1.fieldName1.member1, //expected-error{{use of undeclared identifier 'structVar1'}} structVar2.fieldName2.member2); //expected-error{{use of undeclared identifier 'structVar2'}} } + +void PR40286_g(int x, int y); +void PR40286_h(int x, int y, int z); +void PR40286_1(int the_value) { + PR40286_g(the_walue); // expected-error {{use of undeclared identifier 'the_walue'}} +} +void PR40286_2(int the_value) { + PR40286_h(the_value, the_walue); // expected-error {{use of undeclared identifier 'the_walue'}} +} +void PR40286_3(int the_value) { + PR40286_h(the_walue); // expected-error {{use of undeclared identifier 'the_walue'}} +} +void PR40286_4(int the_value) { // expected-note {{'the_value' declared here}} + PR40286_h(the_value, the_value, the_walue); // expected-error {{use of undeclared identifier 'the_walue'; did you mean 'the_value'?}} +} diff --git a/clang/test/SemaCXX/Float16.cpp b/clang/test/SemaCXX/Float16.cpp new file mode 100644 index 0000000000000..f27c3839854e1 --- /dev/null +++ b/clang/test/SemaCXX/Float16.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux-pc %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple spir-unknown-unknown %s -DHAVE +// RUN: %clang_cc1 -fsyntax-only -verify -triple armv7a-linux-gnu %s -DHAVE +// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-linux-gnu %s -DHAVE + +#ifdef HAVE +// expected-no-diagnostics +#endif // HAVE + +#ifndef HAVE +// expected-error@+2{{_Float16 is not supported on this target}} +#endif // !HAVE +_Float16 f; + +#ifndef HAVE +// expected-error@+2{{invalid suffix 'F16' on floating constant}} +#endif // !HAVE +const auto g = 1.1F16; diff --git a/clang/test/SemaCXX/PR40395.cpp b/clang/test/SemaCXX/PR40395.cpp new file mode 100644 index 0000000000000..469c86d56209c --- /dev/null +++ b/clang/test/SemaCXX/PR40395.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++17 -fms-extensions -triple=x86_64-pc-win32 -verify %s +// expected-no-diagnostics + +// PR40395 - ConstantExpr shouldn't cause the template object to infinitely +// expand. +struct _GUID {}; +struct __declspec(uuid("{AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA}")) B {}; + +template +struct A { + virtual void baz() { A(); } +}; + +void f() { + A<&__uuidof(B)>(); +} diff --git a/clang/test/SemaCXX/constant-expression-cxx1y.cpp b/clang/test/SemaCXX/constant-expression-cxx1y.cpp index 3c57ac573f2cb..ed51cca82ecac 100644 --- a/clang/test/SemaCXX/constant-expression-cxx1y.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx1y.cpp @@ -1135,3 +1135,27 @@ constexpr bool indirect_builtin_constant_p(const char *__s) { return __builtin_constant_p(*__s); } constexpr bool n = indirect_builtin_constant_p("a"); + +__attribute__((enable_if(indirect_builtin_constant_p("a") == n, "OK"))) +int test_in_enable_if() { return 0; } +int n2 = test_in_enable_if(); + +template +int test_in_template_param() { return 0; } +int n3 = test_in_template_param(); + +void test_in_case(int n) { + switch (n) { + case indirect_builtin_constant_p("abc"): + break; + } +} +enum InEnum1 { + ONE = indirect_builtin_constant_p("abc") +}; +enum InEnum2 : int { + TWO = indirect_builtin_constant_p("abc") +}; +enum class InEnum3 { + THREE = indirect_builtin_constant_p("abc") +}; diff --git a/clang/test/SemaCXX/cxx1z-decomposition.cpp b/clang/test/SemaCXX/cxx1z-decomposition.cpp index 3c9b181f1c8f0..8b5fd6809bb4c 100644 --- a/clang/test/SemaCXX/cxx1z-decomposition.cpp +++ b/clang/test/SemaCXX/cxx1z-decomposition.cpp @@ -81,4 +81,21 @@ struct PR37352 { void f() { static auto [a] = *this; } // expected-error {{cannot be declared 'static'}} }; +namespace instantiate_template { + +template +struct pair { + T1 a; + T2 b; +}; + +const pair &f1(); + +int f2() { + const auto &[a, b] = f1(); + return a + b; +} + +} // namespace instantiate_template + // FIXME: by-value array copies diff --git a/clang/test/SemaCXX/cxx1z-init-statement.cpp b/clang/test/SemaCXX/cxx1z-init-statement.cpp index eea2589ab7c62..d37acd08ce77d 100644 --- a/clang/test/SemaCXX/cxx1z-init-statement.cpp +++ b/clang/test/SemaCXX/cxx1z-init-statement.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++1z -Wno-unused-value -verify %s -// RUN: %clang_cc1 -std=c++17 -Wno-unused-value -verify %s +// RUN: %clang_cc1 -std=c++1z -verify %s +// RUN: %clang_cc1 -std=c++17 -verify %s void testIf() { int x = 0; @@ -12,7 +12,7 @@ void testIf() { int x = 0; // expected-error {{redefinition of 'x'}} if (x; int a = 0) ++a; - if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} + if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} expected-warning {{unused}} int a = 0; // expected-error {{redefinition of 'a'}} else int a = 0; // expected-error {{redefinition of 'a'}} @@ -48,7 +48,7 @@ void testSwitch() { ++a; } - switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} + switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} expected-warning {{unused}} case 0: int a = 0; // expected-error {{redefinition of 'a'}} // expected-note {{previous definition is here}} case 1: diff --git a/clang/test/SemaCXX/enable_if.cpp b/clang/test/SemaCXX/enable_if.cpp index ba520b047a324..4bc974dafc289 100644 --- a/clang/test/SemaCXX/enable_if.cpp +++ b/clang/test/SemaCXX/enable_if.cpp @@ -514,3 +514,11 @@ namespace TypeOfFn { static_assert(is_same<__typeof__(foo)*, decltype(&foo)>::value, ""); } + +namespace InConstantContext { +void foo(const char *s) __attribute__((enable_if(((void)__builtin_constant_p(*s), true), "trap"))) {} + +void test() { + InConstantContext::foo("abc"); +} +} // namespace InConstantContext diff --git a/clang/test/SemaCXX/for-range-examples.cpp b/clang/test/SemaCXX/for-range-examples.cpp index 5424b7a8ee797..477789b56c142 100644 --- a/clang/test/SemaCXX/for-range-examples.cpp +++ b/clang/test/SemaCXX/for-range-examples.cpp @@ -244,7 +244,7 @@ void foo () { int b = 1, a[b]; a[0] = 0; - [&] { for (int c : a) 0; } (); // expected-warning {{expression result unused}} + [&] { for (int c : a) 0; } (); } diff --git a/clang/test/SemaCXX/warn-float-conversion.cpp b/clang/test/SemaCXX/warn-float-conversion.cpp index 7dec4844b062e..fad1ff147e492 100644 --- a/clang/test/SemaCXX/warn-float-conversion.cpp +++ b/clang/test/SemaCXX/warn-float-conversion.cpp @@ -44,17 +44,17 @@ void Convert(float f, double d, long double ld) { void CompoundAssignment() { int x = 3; - x += 1.234; //expected-warning{{conversion}} - x -= -0.0; //expected-warning{{conversion}} - x *= 1.1f; //expected-warning{{conversion}} - x /= -2.2f; //expected-warning{{conversion}} + x += 1.234; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} + x -= -0.0; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} + x *= 1.1f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} + x /= -2.2f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} - int y = x += 1.4f; //expected-warning{{conversion}} + int y = x += 1.4f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} float z = 1.1f; double w = -2.2; - y += z + w; //expected-warning{{conversion}} + y += z + w; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} } # 1 "foo.h" 3 diff --git a/clang/test/SemaCXX/warn-unused-result.cpp b/clang/test/SemaCXX/warn-unused-result.cpp index f1de4618a741a..88f5ab1e85c06 100644 --- a/clang/test/SemaCXX/warn-unused-result.cpp +++ b/clang/test/SemaCXX/warn-unused-result.cpp @@ -33,36 +33,6 @@ void test() { const S &s4 = g1(); } -void testSubstmts(int i) { - switch (i) { - case 0: - f(); // expected-warning {{ignoring return value}} - default: - f(); // expected-warning {{ignoring return value}} - } - - if (i) - f(); // expected-warning {{ignoring return value}} - else - f(); // expected-warning {{ignoring return value}} - - while (i) - f(); // expected-warning {{ignoring return value}} - - do - f(); // expected-warning {{ignoring return value}} - while (i); - - for (f(); // expected-warning {{ignoring return value}} - ; - f() // expected-warning {{ignoring return value}} - ) - f(); // expected-warning {{ignoring return value}} - - f(), // expected-warning {{ignoring return value}} - (void)f(); -} - struct X { int foo() __attribute__((warn_unused_result)); }; @@ -236,13 +206,3 @@ void f() { (void)++p; } } // namespace - -namespace PR39837 { -[[clang::warn_unused_result]] int f(int); - -void g() { - int a[2]; - for (int b : a) - f(b); // expected-warning {{ignoring return value}} -} -} // namespace PR39837 diff --git a/clang/test/SemaObjC/attr-designated-init.m b/clang/test/SemaObjC/attr-designated-init.m index 05085884784b0..3558916dbe54a 100644 --- a/clang/test/SemaObjC/attr-designated-init.m +++ b/clang/test/SemaObjC/attr-designated-init.m @@ -3,7 +3,7 @@ #define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) #define NS_UNAVAILABLE __attribute__((unavailable)) -void fnfoo(void) NS_DESIGNATED_INITIALIZER; // expected-error {{only applies to init methods of interface or class extension declarations}} +void fnfoo(void) NS_DESIGNATED_INITIALIZER; // expected-error {{'objc_designated_initializer' attribute only applies to Objective-C methods}} @protocol P1 -(id)init NS_DESIGNATED_INITIALIZER; // expected-error {{only applies to init methods of interface or class extension declarations}} @@ -428,3 +428,16 @@ - (instancetype)init NS_DESIGNATED_INITIALIZER; @interface CategoryForMissingInterface(Cat) // expected-error{{cannot find interface declaration}} - (instancetype)init NS_DESIGNATED_INITIALIZER; // expected-error{{only applies to init methods of interface or class extension declarations}} @end + +@interface TwoAttrs +-(instancetype)foo + __attribute__((objc_designated_initializer)) + __attribute__((objc_method_family(init))); +-(instancetype)bar + __attribute__((objc_method_family(init))) + __attribute__((objc_designated_initializer)); +-(instancetype)baz + __attribute__((objc_designated_initializer, objc_method_family(init))); +-(instancetype)quux + __attribute__((objc_method_family(init), objc_designated_initializer)); +@end diff --git a/clang/test/SemaObjC/call-unavailable-init-in-self.m b/clang/test/SemaObjC/call-unavailable-init-in-self.m index fa6f670cc997f..48fc2326af457 100644 --- a/clang/test/SemaObjC/call-unavailable-init-in-self.m +++ b/clang/test/SemaObjC/call-unavailable-init-in-self.m @@ -5,13 +5,24 @@ @interface NSObject + (instancetype)new; + (instancetype)alloc; +- (void)declaredInSuper; + +@end + +@interface NSObject (Category) + +- (void)declaredInSuperCategory; + @end @interface Sub: NSObject - (instancetype)init __attribute__((unavailable)); // expected-note 4 {{'init' has been explicitly marked unavailable here}} -- (void)notImplemented __attribute__((unavailable)); // expected-note {{'notImplemented' has been explicitly marked unavailable here}} +- (void)notImplemented __attribute__((unavailable)); + +- (void)declaredInSuper __attribute__((unavailable)); +- (void)declaredInSuperCategory __attribute__((unavailable)); @end @@ -34,7 +45,14 @@ - (instancetype) init { } - (void)reportUseOfUnimplemented { - [self notImplemented]; // expected-error {{'notImplemented' is unavailable}} + [self notImplemented]; +} + +- (void)allowSuperCallUsingSelf { + [self declaredInSuper]; + [[Sub alloc] declaredInSuper]; + [self declaredInSuperCategory]; + [[Sub alloc] declaredInSuperCategory]; } @end diff --git a/clang/test/SemaObjC/conversion.m b/clang/test/SemaObjC/conversion.m index 88a1a44b2177b..743f7440e2e43 100644 --- a/clang/test/SemaObjC/conversion.m +++ b/clang/test/SemaObjC/conversion.m @@ -14,4 +14,11 @@ void radar14415662(RDar14415662 *f, char x, int y) { x = y; // expected-warning {{implicit conversion loses integer precision: 'int' to 'char'}} } +__attribute__((objc_root_class)) @interface DoubleProp +@property double d; +@end +void use_double_prop(DoubleProp *dp) { + double local = 42; + dp.d += local; // no warning +} diff --git a/clang/test/SemaObjC/enum-fixed-type.m b/clang/test/SemaObjC/enum-fixed-type.m index 88c895a33982d..b4135a555a23e 100644 --- a/clang/test/SemaObjC/enum-fixed-type.m +++ b/clang/test/SemaObjC/enum-fixed-type.m @@ -1,9 +1,11 @@ // RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s // RUN: %clang_cc1 -fsyntax-only -verify -xc %s +#ifdef __OBJC__ #if !__has_feature(objc_fixed_enum) # error Enumerations with a fixed underlying type are not supported #endif +#endif #if !__has_extension(cxx_fixed_enum) # error Enumerations with a fixed underlying type are not supported diff --git a/clang/test/SemaObjC/infer-availability-from-init.m b/clang/test/SemaObjC/infer-availability-from-init.m index f9996ec70877e..7aa1e53c09109 100644 --- a/clang/test/SemaObjC/infer-availability-from-init.m +++ b/clang/test/SemaObjC/infer-availability-from-init.m @@ -47,12 +47,12 @@ void usenotmyobject() { } @interface FromSelf : NSObject --(instancetype)init __attribute__((unavailable)); // expected-note {{'init' has been explicitly marked unavailable here}} +-(instancetype)init __attribute__((unavailable)); +(FromSelf*)another_one; @end @implementation FromSelf +(FromSelf*)another_one { - [self new]; // expected-error{{'new' is unavailable}} + [self new]; } @end diff --git a/clang/test/SemaOpenCL/extension-version.cl b/clang/test/SemaOpenCL/extension-version.cl index a587f1db99af2..d976cfb3a4354 100644 --- a/clang/test/SemaOpenCL/extension-version.cl +++ b/clang/test/SemaOpenCL/extension-version.cl @@ -2,12 +2,14 @@ // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple spir-unknown-unknown // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple spir-unknown-unknown // RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple spir-unknown-unknown +// RUN: %clang_cc1 -x cl -cl-std=c++ %s -verify -triple spir-unknown-unknown // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES // RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES +// RUN: %clang_cc1 -x cl -cl-std=c++ %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -#if __OPENCL_C_VERSION__ >= 200 && ! defined TEST_CORE_FEATURES +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) && !defined(TEST_CORE_FEATURES) // expected-no-diagnostics #endif @@ -47,44 +49,44 @@ #ifndef cl_khr_byte_addressable_store #error "Missing cl_khr_byte_addressable_store define" #endif -#pragma OPENCL EXTENSION cl_khr_byte_addressable_store: enable -#if (__OPENCL_C_VERSION__ >= 110) && defined TEST_CORE_FEATURES +#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 110) && defined TEST_CORE_FEATURES // expected-warning@-2{{OpenCL extension 'cl_khr_byte_addressable_store' is core feature or supported optional core feature - ignoring}} #endif #ifndef cl_khr_global_int32_base_atomics #error "Missing cl_khr_global_int32_base_atomics define" #endif -#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics: enable -#if (__OPENCL_C_VERSION__ >= 110) && defined TEST_CORE_FEATURES +#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 110) && defined TEST_CORE_FEATURES // expected-warning@-2{{OpenCL extension 'cl_khr_global_int32_base_atomics' is core feature or supported optional core feature - ignoring}} #endif #ifndef cl_khr_global_int32_extended_atomics #error "Missing cl_khr_global_int32_extended_atomics define" #endif -#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics: enable -#if (__OPENCL_C_VERSION__ >= 110) && defined TEST_CORE_FEATURES +#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 110) && defined TEST_CORE_FEATURES // expected-warning@-2{{OpenCL extension 'cl_khr_global_int32_extended_atomics' is core feature or supported optional core feature - ignoring}} #endif #ifndef cl_khr_local_int32_base_atomics #error "Missing cl_khr_local_int32_base_atomics define" #endif -#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics: enable -#if (__OPENCL_C_VERSION__ >= 110) && defined TEST_CORE_FEATURES +#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 110) && defined TEST_CORE_FEATURES // expected-warning@-2{{OpenCL extension 'cl_khr_local_int32_base_atomics' is core feature or supported optional core feature - ignoring}} #endif #ifndef cl_khr_local_int32_extended_atomics #error "Missing cl_khr_local_int32_extended_atomics define" #endif -#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics: enable -#if (__OPENCL_C_VERSION__ >= 110) && defined TEST_CORE_FEATURES +#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 110) && defined TEST_CORE_FEATURES // expected-warning@-2{{OpenCL extension 'cl_khr_local_int32_extended_atomics' is core feature or supported optional core feature - ignoring}} #endif -#if (__OPENCL_C_VERSION__ < 110) +#if (defined(__OPENCL_C_VERSION__) && __OPENCL_C_VERSION__ < 110) // Deprecated abvoe 1.0 #ifndef cl_khr_select_fprounding_mode #error "Missing cl_khr_select_fp_rounding_mode define" @@ -97,8 +99,8 @@ #ifndef cl_khr_fp64 #error "Missing cl_khr_fp64 define" #endif -#pragma OPENCL EXTENSION cl_khr_fp64: enable -#if (__OPENCL_C_VERSION__ >= 120) && defined TEST_CORE_FEATURES +#pragma OPENCL EXTENSION cl_khr_fp64 : enable +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 120) && defined TEST_CORE_FEATURES // expected-warning@-2{{OpenCL extension 'cl_khr_fp64' is core feature or supported optional core feature - ignoring}} #endif @@ -106,131 +108,129 @@ #ifndef cl_khr_3d_image_writes #error "Missing cl_khr_3d_image_writes define" #endif -#pragma OPENCL EXTENSION cl_khr_3d_image_writes: enable -#if (__OPENCL_C_VERSION__ >= 200) && defined TEST_CORE_FEATURES +#pragma OPENCL EXTENSION cl_khr_3d_image_writes : enable +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) && defined TEST_CORE_FEATURES // expected-warning@-2{{OpenCL extension 'cl_khr_3d_image_writes' is core feature or supported optional core feature - ignoring}} #endif - - -#if (__OPENCL_C_VERSION__ >= 110) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 110) #ifndef cl_khr_gl_event #error "Missing cl_khr_gl_event define" #endif #else // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_gl_event' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_gl_event: enable +#pragma OPENCL EXTENSION cl_khr_gl_event : enable -#if (__OPENCL_C_VERSION__ >= 110) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 110) #ifndef cl_khr_d3d10_sharing #error "Missing cl_khr_d3d10_sharing define" #endif #else // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_d3d10_sharing' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_d3d10_sharing: enable +#pragma OPENCL EXTENSION cl_khr_d3d10_sharing : enable -#if (__OPENCL_C_VERSION__ >= 110) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 110) #ifndef cles_khr_int64 #error "Missing cles_khr_int64 define" #endif #else // expected-warning@+2{{unsupported OpenCL extension 'cles_khr_int64' - ignoring}} #endif -#pragma OPENCL EXTENSION cles_khr_int64: enable +#pragma OPENCL EXTENSION cles_khr_int64 : enable -#if (__OPENCL_C_VERSION__ >= 120) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 120) #ifndef cl_khr_context_abort #error "Missing cl_context_abort define" #endif #else // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_context_abort' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_context_abort: enable +#pragma OPENCL EXTENSION cl_khr_context_abort : enable -#if (__OPENCL_C_VERSION__ >= 120) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 120) #ifndef cl_khr_d3d11_sharing #error "Missing cl_khr_d3d11_sharing define" #endif #else // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_d3d11_sharing' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_d3d11_sharing: enable +#pragma OPENCL EXTENSION cl_khr_d3d11_sharing : enable -#if (__OPENCL_C_VERSION__ >= 120) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 120) #ifndef cl_khr_dx9_media_sharing #error "Missing cl_khr_dx9_media_sharing define" #endif #else // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_dx9_media_sharing' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_dx9_media_sharing: enable +#pragma OPENCL EXTENSION cl_khr_dx9_media_sharing : enable -#if (__OPENCL_C_VERSION__ >= 120) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 120) #ifndef cl_khr_image2d_from_buffer #error "Missing cl_khr_image2d_from_buffer define" #endif #else // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_image2d_from_buffer' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_image2d_from_buffer: enable +#pragma OPENCL EXTENSION cl_khr_image2d_from_buffer : enable -#if (__OPENCL_C_VERSION__ >= 120) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 120) #ifndef cl_khr_initialize_memory #error "Missing cl_khr_initialize_memory define" #endif #else // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_initialize_memory' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_initialize_memory: enable +#pragma OPENCL EXTENSION cl_khr_initialize_memory : enable -#if (__OPENCL_C_VERSION__ >= 120) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 120) #ifndef cl_khr_gl_depth_images #error "Missing cl_khr_gl_depth_images define" #endif #else // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_gl_depth_images' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_gl_depth_images: enable +#pragma OPENCL EXTENSION cl_khr_gl_depth_images : enable -#if (__OPENCL_C_VERSION__ >= 120) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 120) #ifndef cl_khr_gl_msaa_sharing #error "Missing cl_khr_gl_msaa_sharing define" #endif #else // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_gl_msaa_sharing' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_gl_msaa_sharing: enable +#pragma OPENCL EXTENSION cl_khr_gl_msaa_sharing : enable -#if (__OPENCL_C_VERSION__ >= 120) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 120) #ifndef cl_khr_spir #error "Missing cl_khr_spir define" #endif #else // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_spir' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_spir: enable +#pragma OPENCL EXTENSION cl_khr_spir : enable -#if (__OPENCL_C_VERSION__ >= 200) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) #ifndef cl_khr_egl_event #error "Missing cl_khr_egl_event define" #endif #else // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_egl_event' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_egl_event: enable +#pragma OPENCL EXTENSION cl_khr_egl_event : enable -#if (__OPENCL_C_VERSION__ >= 200) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) #ifndef cl_khr_egl_image #error "Missing cl_khr_egl_image define" #endif #else // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_egl_image' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_egl_image: enable +#pragma OPENCL EXTENSION cl_khr_egl_image : enable -#if (__OPENCL_C_VERSION__ >= 200) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) #ifndef cl_khr_mipmap_image #error "Missing cl_khr_mipmap_image define" #endif @@ -240,18 +240,18 @@ #endif // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_mipmap_image' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_mipmap_image: enable +#pragma OPENCL EXTENSION cl_khr_mipmap_image : enable -#if (__OPENCL_C_VERSION__ >= 200) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) #ifndef cl_khr_srgb_image_writes #error "Missing cl_khr_srgb_image_writes define" #endif #else // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_srgb_image_writes' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_srgb_image_writes: enable +#pragma OPENCL EXTENSION cl_khr_srgb_image_writes : enable -#if (__OPENCL_C_VERSION__ >= 200) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) #ifndef cl_khr_subgroups #error "Missing cl_khr_subgroups define" #endif @@ -261,9 +261,9 @@ #endif // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_subgroups' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_subgroups: enable +#pragma OPENCL EXTENSION cl_khr_subgroups : enable -#if (__OPENCL_C_VERSION__ >= 200) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) #ifndef cl_khr_terminate_context #error "Missing cl_khr_terminate_context define" #endif @@ -280,9 +280,9 @@ #ifndef cl_amd_media_ops2 #error "Missing cl_amd_media_ops2 define" #endif -#pragma OPENCL EXTENSION cl_amd_media_ops2: enable +#pragma OPENCL EXTENSION cl_amd_media_ops2 : enable -#if (__OPENCL_C_VERSION__ >= 120) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 120) #ifndef cl_khr_depth_images #error "Missing cl_khr_depth_images define" #endif @@ -292,9 +292,9 @@ #endif // expected-warning@+2{{unsupported OpenCL extension 'cl_khr_depth_images' - ignoring}} #endif -#pragma OPENCL EXTENSION cl_khr_depth_images: enable +#pragma OPENCL EXTENSION cl_khr_depth_images : enable -#if (__OPENCL_C_VERSION__ >= 120) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 120) #ifndef cl_intel_subgroups #error "Missing cl_intel_subgroups define" #endif @@ -303,7 +303,7 @@ #endif #pragma OPENCL EXTENSION cl_intel_subgroups : enable -#if (__OPENCL_C_VERSION__ >= 120) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 120) #ifndef cl_intel_subgroups_short #error "Missing cl_intel_subgroups_short define" #endif @@ -312,7 +312,7 @@ #endif #pragma OPENCL EXTENSION cl_intel_subgroups_short : enable -#if (__OPENCL_C_VERSION__ >= 120) +#if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 120) #ifndef cl_intel_device_side_avc_motion_estimation #error "Missing cl_intel_device_side_avc_motion_estimation define" #endif diff --git a/clang/test/SemaOpenCL/extensions.cl b/clang/test/SemaOpenCL/extensions.cl index 5f95e32d4a549..e9dba69ecd7c9 100644 --- a/clang/test/SemaOpenCL/extensions.cl +++ b/clang/test/SemaOpenCL/extensions.cl @@ -28,6 +28,7 @@ // enabled by default with -cl-std=CL2.0). // // RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL2.0 -finclude-default-header +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=c++ #ifdef _OPENCL_H_ // expected-no-diagnostics @@ -37,7 +38,11 @@ // expected-no-diagnostics #endif -#if __OPENCL_C_VERSION__ < 120 +#ifdef __OPENCL_CPP_VERSION__ +// expected-no-diagnostics +#endif + +#if (defined(__OPENCL_C_VERSION__) && __OPENCL_C_VERSION__ < 120) void f1(double da) { // expected-error {{type 'double' requires cl_khr_fp64 extension}} double d; // expected-error {{type 'double' requires cl_khr_fp64 extension}} (void) 1.0; // expected-warning {{double precision constant requires cl_khr_fp64}} @@ -89,7 +94,7 @@ void f2(void) { // expected-warning@-2{{unsupported OpenCL extension 'cl_khr_fp64' - ignoring}} #endif -#if __OPENCL_C_VERSION__ < 120 +#if (defined(__OPENCL_C_VERSION__) && __OPENCL_C_VERSION__ < 120) void f3(void) { double d; // expected-error {{type 'double' requires cl_khr_fp64 extension}} } diff --git a/clang/test/SemaOpenCL/printf-format-string-warnings.cl b/clang/test/SemaOpenCL/printf-format-string-warnings.cl index 2b9c5cc3f319f..39b859402702f 100644 --- a/clang/test/SemaOpenCL/printf-format-string-warnings.cl +++ b/clang/test/SemaOpenCL/printf-format-string-warnings.cl @@ -1,13 +1,14 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0 -finclude-default-header -// Make sure warnings are produced based on printf format strings. +// FIXME: Make sure warnings are produced based on printf format strings. +// expected-no-diagnostics kernel void format_string_warnings(__constant char* arg) { - printf("%d", arg); // expected-warning {{format specifies type 'int' but the argument has type '__constant char *'}} + printf("%d", arg); - printf("not enough arguments %d %d", 4); // expected-warning {{more '%' conversions than data arguments}} + printf("not enough arguments %d %d", 4); - printf("too many arguments", 4); // expected-warning {{data argument not used by format string}} + printf("too many arguments", 4); } diff --git a/clang/test/SemaOpenCL/printf-format-strings.cl b/clang/test/SemaOpenCL/printf-format-strings.cl index 079a83495685e..212e1f8981cbe 100644 --- a/clang/test/SemaOpenCL/printf-format-strings.cl +++ b/clang/test/SemaOpenCL/printf-format-strings.cl @@ -13,10 +13,10 @@ int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2))) kernel void format_v4f32(float4 arg) { #ifdef cl_khr_fp64 - printf("%v4f\n", arg); + printf("%v4f\n", arg); // expected-warning{{format specifies type 'double __attribute__((ext_vector_type(4)))' but the argument has type 'float4' (vector of 4 'float' values)}} // Precision modifier - printf("%.2v4f\n", arg); + printf("%.2v4f\n", arg); // expected-warning{{format specifies type 'double __attribute__((ext_vector_type(4)))' but the argument has type 'float4' (vector of 4 'float' values)}} #else // FIXME: These should not warn, and the type should be expected to be float. printf("%v4f\n", arg); // expected-warning {{double __attribute__((ext_vector_type(4)))' but the argument has type 'float4' (vector of 4 'float' values)}} diff --git a/clang/test/Tooling/clang-check-mac-libcxx-fixed-compilation-db.cpp b/clang/test/Tooling/clang-check-mac-libcxx-fixed-compilation-db.cpp index 035155c96c925..8c59a2f07f698 100644 --- a/clang/test/Tooling/clang-check-mac-libcxx-fixed-compilation-db.cpp +++ b/clang/test/Tooling/clang-check-mac-libcxx-fixed-compilation-db.cpp @@ -10,7 +10,7 @@ // // RUN: cp $(which clang-check) %t/mock-libcxx/bin/ // RUN: cp "%s" "%t/test.cpp" -// RUN: %t/mock-libcxx/bin/clang-check -p "%t" "%t/test.cpp" -- -stdlib=libc++ - +// RUN: %t/mock-libcxx/bin/clang-check -p "%t" "%t/test.cpp" -- -stdlib=libc++ -target x86_64-apple-darwin +// REQUIRES: system-darwin #include vector v; diff --git a/clang/unittests/Basic/FileManagerTest.cpp b/clang/unittests/Basic/FileManagerTest.cpp index 746d9ad5e89bb..8e98f44fa46d8 100644 --- a/clang/unittests/Basic/FileManagerTest.cpp +++ b/clang/unittests/Basic/FileManagerTest.cpp @@ -222,33 +222,6 @@ TEST_F(FileManagerTest, getFileReturnsNULLForNonexistentFile) { EXPECT_EQ(nullptr, file); } -// When calling getFile(OpenFile=false); getFile(OpenFile=true) the file is -// opened for the second call. -TEST_F(FileManagerTest, getFileDefersOpen) { - llvm::IntrusiveRefCntPtr FS( - new llvm::vfs::InMemoryFileSystem()); - FS->addFile("/tmp/test", 0, llvm::MemoryBuffer::getMemBufferCopy("test")); - FS->addFile("/tmp/testv", 0, llvm::MemoryBuffer::getMemBufferCopy("testv")); - FileManager manager(options, FS); - - const FileEntry *file = manager.getFile("/tmp/test", /*OpenFile=*/false); - ASSERT_TRUE(file != nullptr); - ASSERT_TRUE(file->isValid()); - // "real path name" reveals whether the file was actually opened. - EXPECT_FALSE(file->isOpenForTests()); - - file = manager.getFile("/tmp/test", /*OpenFile=*/true); - ASSERT_TRUE(file != nullptr); - ASSERT_TRUE(file->isValid()); - EXPECT_TRUE(file->isOpenForTests()); - - // However we should never try to open a file previously opened as virtual. - ASSERT_TRUE(manager.getVirtualFile("/tmp/testv", 5, 0)); - ASSERT_TRUE(manager.getFile("/tmp/testv", /*OpenFile=*/false)); - file = manager.getFile("/tmp/testv", /*OpenFile=*/true); - EXPECT_FALSE(file->isOpenForTests()); -} - // The following tests apply to Unix-like system only. #ifndef _WIN32 diff --git a/clang/unittests/Tooling/ToolingTest.cpp b/clang/unittests/Tooling/ToolingTest.cpp index 186463f80af73..5813552a6cd32 100644 --- a/clang/unittests/Tooling/ToolingTest.cpp +++ b/clang/unittests/Tooling/ToolingTest.cpp @@ -450,6 +450,37 @@ TEST(ClangToolTest, StripDependencyFileAdjuster) { EXPECT_TRUE(HasFlag("-w")); } +// Check getClangStripPluginsAdjuster strips plugin related args. +TEST(ClangToolTest, StripPluginsAdjuster) { + FixedCompilationDatabase Compilations( + "/", {"-Xclang", "-add-plugin", "-Xclang", "random-plugin"}); + + ClangTool Tool(Compilations, std::vector(1, "/a.cc")); + Tool.mapVirtualFile("/a.cc", "void a() {}"); + + std::unique_ptr Action( + newFrontendActionFactory()); + + CommandLineArguments FinalArgs; + ArgumentsAdjuster CheckFlagsAdjuster = + [&FinalArgs](const CommandLineArguments &Args, StringRef /*unused*/) { + FinalArgs = Args; + return Args; + }; + Tool.clearArgumentsAdjusters(); + Tool.appendArgumentsAdjuster(getStripPluginsAdjuster()); + Tool.appendArgumentsAdjuster(CheckFlagsAdjuster); + Tool.run(Action.get()); + + auto HasFlag = [&FinalArgs](const std::string &Flag) { + return std::find(FinalArgs.begin(), FinalArgs.end(), Flag) != + FinalArgs.end(); + }; + EXPECT_FALSE(HasFlag("-Xclang")); + EXPECT_FALSE(HasFlag("-add-plugin")); + EXPECT_FALSE(HasFlag("-random-plugin")); +} + namespace { /// Find a target name such that looking for it in TargetRegistry by that name /// returns the same target. We expect that there is at least one target diff --git a/compiler-rt/cmake/base-config-ix.cmake b/compiler-rt/cmake/base-config-ix.cmake index 6684d7371d68f..aeabf17653f5e 100644 --- a/compiler-rt/cmake/base-config-ix.cmake +++ b/compiler-rt/cmake/base-config-ix.cmake @@ -195,10 +195,10 @@ macro(test_targets) # clang's default CPU's. In the 64-bit case, we must also specify the ABI # since the default ABI differs between gcc and clang. # FIXME: Ideally, we would build the N32 library too. - test_target_arch(mipsel "" "-mips32r2" "-mabi=32") + test_target_arch(mipsel "" "-mips32r2" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64") test_target_arch(mips64el "" "-mips64r2" "-mabi=64") elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "mips") - test_target_arch(mips "" "-mips32r2" "-mabi=32") + test_target_arch(mips "" "-mips32r2" "-mabi=32" "-D_LARGEFILE_SOURCE" "-D_FILE_OFFSET_BITS=64") test_target_arch(mips64 "" "-mips64r2" "-mabi=64") elseif("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "arm") if(WIN32) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index db5c4645dc0a5..5b94338771780 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -118,6 +118,7 @@ check_library_exists(dl dlopen "" COMPILER_RT_HAS_LIBDL) check_library_exists(rt shm_open "" COMPILER_RT_HAS_LIBRT) check_library_exists(m pow "" COMPILER_RT_HAS_LIBM) check_library_exists(pthread pthread_create "" COMPILER_RT_HAS_LIBPTHREAD) +check_library_exists(execinfo backtrace "" COMPILER_RT_HAS_LIBEXECINFO) # Look for terminfo library, used in unittests that depend on LLVMSupport. if(LLVM_ENABLE_TERMINFO) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc b/compiler-rt/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc index 86cb440476069..bddc26d20019d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc @@ -25,7 +25,7 @@ struct ioctl_desc { const char *name; }; -const unsigned ioctl_table_max = 1202; +const unsigned ioctl_table_max = 1200; static ioctl_desc ioctl_table[ioctl_table_max]; static unsigned ioctl_table_size = 0; @@ -298,9 +298,6 @@ static void ioctl_table_fill() { _(IRFRAMETTY_GET_DEVICE, WRITE, sizeof(unsigned int)); _(IRFRAMETTY_GET_DONGLE, WRITE, sizeof(unsigned int)); _(IRFRAMETTY_SET_DONGLE, READ, sizeof(unsigned int)); - /* Entries from file: dev/isa/satlinkio.h */ - _(SATIORESET, NONE, 0); - _(SATIOGID, WRITE, struct_satlink_id_sz); /* Entries from file: dev/isa/isvio.h */ _(ISV_CMD, READWRITE, struct_isv_cmd_sz); /* Entries from file: dev/isa/wtreg.h */ @@ -649,8 +646,8 @@ static void ioctl_table_fill() { _(SPKRTUNE, NONE, 0); _(SPKRGETVOL, WRITE, sizeof(unsigned int)); _(SPKRSETVOL, READ, sizeof(unsigned int)); - /* Entries from file: dev/nvmm/nvmm_ioctl.h */ #if 0 /* WIP */ + /* Entries from file: dev/nvmm/nvmm_ioctl.h */ _(NVMM_IOC_CAPABILITY, WRITE, struct_nvmm_ioc_capability_sz); _(NVMM_IOC_MACHINE_CREATE, READWRITE, struct_nvmm_ioc_machine_create_sz); _(NVMM_IOC_MACHINE_DESTROY, READ, struct_nvmm_ioc_machine_destroy_sz); @@ -659,7 +656,7 @@ static void ioctl_table_fill() { _(NVMM_IOC_VCPU_DESTROY, READ, struct_nvmm_ioc_vcpu_destroy_sz); _(NVMM_IOC_VCPU_SETSTATE, READ, struct_nvmm_ioc_vcpu_setstate_sz); _(NVMM_IOC_VCPU_GETSTATE, READ, struct_nvmm_ioc_vcpu_getstate_sz); - _(NVMM_IOC_VCPU_INJECT, READWRITE, struct_nvmm_ioc_vcpu_inject_sz); + _(NVMM_IOC_VCPU_INJECT, READ, struct_nvmm_ioc_vcpu_inject_sz); _(NVMM_IOC_VCPU_RUN, READWRITE, struct_nvmm_ioc_vcpu_run_sz); _(NVMM_IOC_GPA_MAP, READ, struct_nvmm_ioc_gpa_map_sz); _(NVMM_IOC_GPA_UNMAP, READ, struct_nvmm_ioc_gpa_unmap_sz); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc index b23b430d9e5bc..c32c80b3e48be 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc @@ -122,10 +122,11 @@ #include #include #include -#include #include #include +#if 0 #include +#endif #include #include #include @@ -639,7 +640,6 @@ unsigned struct_rf_recon_req_sz = sizeof(rf_recon_req); unsigned struct_rio_conf_sz = sizeof(rio_conf); unsigned struct_rio_interface_sz = sizeof(rio_interface); unsigned struct_rio_stats_sz = sizeof(rio_stats); -unsigned struct_satlink_id_sz = sizeof(satlink_id); unsigned struct_scan_io_sz = sizeof(scan_io); unsigned struct_scbusaccel_args_sz = sizeof(scbusaccel_args); unsigned struct_scbusiodetach_args_sz = sizeof(scbusiodetach_args); @@ -1105,9 +1105,6 @@ unsigned IOCTL_IRDA_GET_TURNAROUNDMASK = IRDA_GET_TURNAROUNDMASK; unsigned IOCTL_IRFRAMETTY_GET_DEVICE = IRFRAMETTY_GET_DEVICE; unsigned IOCTL_IRFRAMETTY_GET_DONGLE = IRFRAMETTY_GET_DONGLE; unsigned IOCTL_IRFRAMETTY_SET_DONGLE = IRFRAMETTY_SET_DONGLE; -unsigned IOCTL_SATIORESET = SATIORESET; -unsigned IOCTL_SATIOGID = SATIOGID; -unsigned IOCTL_SATIOSBUFSIZE = SATIOSBUFSIZE; unsigned IOCTL_ISV_CMD = ISV_CMD; unsigned IOCTL_WTQICMD = WTQICMD; unsigned IOCTL_ISCSI_GET_VERSION = ISCSI_GET_VERSION; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h index 0c0c8a837b8b3..594cfa6c0d47b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h @@ -803,7 +803,6 @@ extern unsigned struct_rf_recon_req_sz; extern unsigned struct_rio_conf_sz; extern unsigned struct_rio_interface_sz; extern unsigned struct_rio_stats_sz; -extern unsigned struct_satlink_id_sz; extern unsigned struct_scan_io_sz; extern unsigned struct_scbusaccel_args_sz; extern unsigned struct_scbusiodetach_args_sz; @@ -1266,9 +1265,6 @@ extern unsigned IOCTL_IRDA_GET_TURNAROUNDMASK; extern unsigned IOCTL_IRFRAMETTY_GET_DEVICE; extern unsigned IOCTL_IRFRAMETTY_GET_DONGLE; extern unsigned IOCTL_IRFRAMETTY_SET_DONGLE; -extern unsigned IOCTL_SATIORESET; -extern unsigned IOCTL_SATIOGID; -extern unsigned IOCTL_SATIOSBUFSIZE; extern unsigned IOCTL_ISV_CMD; extern unsigned IOCTL_WTQICMD; extern unsigned IOCTL_ISCSI_GET_VERSION; diff --git a/compiler-rt/lib/xray/tests/CMakeLists.txt b/compiler-rt/lib/xray/tests/CMakeLists.txt index 89a2b3b01ed8a..145852904549b 100644 --- a/compiler-rt/lib/xray/tests/CMakeLists.txt +++ b/compiler-rt/lib/xray/tests/CMakeLists.txt @@ -48,8 +48,7 @@ endfunction() set(XRAY_TEST_ARCH ${XRAY_SUPPORTED_ARCH}) set(XRAY_UNITTEST_LINK_FLAGS - ${CMAKE_THREAD_LIBS_INIT} - -l${SANITIZER_CXX_ABI_LIBRARY}) + ${CMAKE_THREAD_LIBS_INIT}) if (NOT APPLE) # Needed by LLVMSupport. @@ -71,15 +70,18 @@ if (NOT APPLE) endforeach() # We also add the actual libraries to link as dependencies. - list(APPEND XRAY_UNITTEST_LINK_FLAGS -lLLVMXRay -lLLVMSupport -lLLVMTestingSupport) + list(APPEND XRAY_UNITTEST_LINK_FLAGS -lLLVMXRay -lLLVMSupport -lLLVMDemangle -lLLVMTestingSupport) endif() append_list_if(COMPILER_RT_HAS_LIBM -lm XRAY_UNITTEST_LINK_FLAGS) append_list_if(COMPILER_RT_HAS_LIBRT -lrt XRAY_UNITTEST_LINK_FLAGS) append_list_if(COMPILER_RT_HAS_LIBDL -ldl XRAY_UNITTEST_LINK_FLAGS) append_list_if(COMPILER_RT_HAS_LIBPTHREAD -pthread XRAY_UNITTEST_LINK_FLAGS) + append_list_if(COMPILER_RT_HAS_LIBEXECINFO -lexecinfo XRAY_UNITTEST_LINK_FLAGS) endif() +list(APPEND XRAY_UNITTEST_LINK_FLAGS -l${SANITIZER_CXX_ABI_LIBRARY}) + macro(add_xray_unittest testname) cmake_parse_arguments(TEST "" "" "SOURCES;HEADERS" ${ARGN}) if(UNIX AND NOT APPLE) diff --git a/compiler-rt/test/CMakeLists.txt b/compiler-rt/test/CMakeLists.txt index 2e239d54e29c8..7070fb789520c 100644 --- a/compiler-rt/test/CMakeLists.txt +++ b/compiler-rt/test/CMakeLists.txt @@ -14,10 +14,6 @@ if(COMPILER_RT_BUILD_PROFILE AND COMPILER_RT_HAS_PROFILE) list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS profile) endif() -if(COMPILER_RT_STANDALONE_BUILD) - list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS FileCheck) -endif() - # When ANDROID, we build tests with the host compiler (i.e. CMAKE_C_COMPILER), # and run tests with tools from the host toolchain. if(NOT ANDROID) diff --git a/compiler-rt/test/builtins/Unit/compiler_rt_logb_test.c b/compiler-rt/test/builtins/Unit/compiler_rt_logb_test.c index 79676598089c6..9625881316bb8 100644 --- a/compiler-rt/test/builtins/Unit/compiler_rt_logb_test.c +++ b/compiler-rt/test/builtins/Unit/compiler_rt_logb_test.c @@ -37,6 +37,10 @@ double cases[] = { }; int main() { + // Do not the run the compiler-rt logb test case if using GLIBC version + // < 2.23. Older versions might not compute to the same value as the + // compiler-rt value. +#if !defined(__GLIBC__) || (defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 23)) const unsigned N = sizeof(cases) / sizeof(cases[0]); unsigned i; for (i = 0; i < N; ++i) { @@ -58,6 +62,9 @@ int main() { if (test__compiler_rt_logb(fromRep(signBit ^ x))) return 1; x >>= 1; } +#else + printf("skipped\n"); +#endif return 0; } diff --git a/compiler-rt/test/msan/Linux/name_to_handle_at.cc b/compiler-rt/test/msan/Linux/name_to_handle_at.cc index 0ff8d982f4f77..a8bc75fa2ae5c 100644 --- a/compiler-rt/test/msan/Linux/name_to_handle_at.cc +++ b/compiler-rt/test/msan/Linux/name_to_handle_at.cc @@ -14,7 +14,7 @@ int main(void) { handle->handle_bytes = MAX_HANDLE_SZ; int mount_id; - int res = name_to_handle_at(AT_FDCWD, "/bin/cat", handle, &mount_id, 0); + int res = name_to_handle_at(AT_FDCWD, "/dev/null", handle, &mount_id, 0); assert(!res); __msan_check_mem_is_initialized(&mount_id, sizeof(mount_id)); __msan_check_mem_is_initialized(&handle->handle_bytes, diff --git a/compiler-rt/utils/generate_netbsd_ioctls.awk b/compiler-rt/utils/generate_netbsd_ioctls.awk index 82b1992143772..38fe88fb0cde4 100755 --- a/compiler-rt/utils/generate_netbsd_ioctls.awk +++ b/compiler-rt/utils/generate_netbsd_ioctls.awk @@ -152,7 +152,6 @@ FNR == 1 { $0 ~ /JOY_GET_X_OFFSET/ || $0 ~ /CHIOGPICKER/ || $0 ~ /SLIOCGUNIT/ || - $0 ~ /SATIOSBUFSIZE/ || $0 ~ /TUNSLMODE/ || $0 ~ /CBQ_IF_ATTACH/ || $0 ~ /CDNR_IF_ATTACH/ || diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt index a57e36fddcde5..6b83bce1ae72d 100644 --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -27,7 +27,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) project(libcxx CXX C) set(PACKAGE_NAME libcxx) - set(PACKAGE_VERSION 8.0.0svn) + set(PACKAGE_VERSION 8.0.1) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") diff --git a/libcxx/cmake/Modules/HandleOutOfTreeLLVM.cmake b/libcxx/cmake/Modules/HandleOutOfTreeLLVM.cmake index 70eed1d70ba1b..11c13315585bf 100644 --- a/libcxx/cmake/Modules/HandleOutOfTreeLLVM.cmake +++ b/libcxx/cmake/Modules/HandleOutOfTreeLLVM.cmake @@ -116,7 +116,7 @@ macro(configure_out_of_tree_llvm) # Required LIT Configuration ------------------------------------------------ # Define the default arguments to use with 'lit', and an option for the user # to override. - set(LLVM_EXTERNAL_LIT "${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py") + set(LLVM_DEFAULT_EXTERNAL_LIT "${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py") set(LIT_ARGS_DEFAULT "-sv --show-xfail --show-unsupported") if (MSVC OR XCODE) set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst index 20be9f627ef86..ca5a534ae846e 100644 --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -1,6 +1,6 @@ -======================================== -Libc++ 8.0.0 (In-Progress) Release Notes -======================================== +========================== +Libc++ 8.0.0 Release Notes +========================== .. contents:: :local: @@ -8,12 +8,6 @@ Libc++ 8.0.0 (In-Progress) Release Notes Written by the `Libc++ Team `_ -.. warning:: - - These are in-progress notes for the upcoming libc++ 8 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ @@ -22,22 +16,14 @@ part of the LLVM Compiler Infrastructure, release 8.0.0. Here we describe the status of libc++ in some detail, including major improvements from the previous release and new feature work. For the general LLVM release notes, see `the LLVM documentation `_. All LLVM releases may -be downloaded from the `LLVM releases web site `_. +be downloaded from the `LLVM releases web site `_. For more information about libc++, please see the `Libc++ Web Site `_ or the `LLVM Web Site `_. -Note that if you are reading this file from a Subversion checkout or the -main Libc++ web page, this document applies to the *next* release, not -the current one. To see the release notes for a specific release, please -see the `releases page `_. - What's New in Libc++ 8.0.0? =========================== -New Features ------------- - API Changes ----------- - Building libc++ for Mac OSX 10.6 is not supported anymore. diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/delete_align_val_t_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/delete_align_val_t_replace.pass.cpp index 4dd9390c4fdcf..bd20e090637d0 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/delete_align_val_t_replace.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/delete_align_val_t_replace.pass.cpp @@ -17,9 +17,11 @@ // None of the current GCC compilers support this. // UNSUPPORTED: gcc-5, gcc-6 -// Aligned allocation was not provided before macosx10.12 and as a result we -// get availability errors when the deployment target is older than macosx10.13. -// However, AppleClang 10 (and older) don't trigger availability errors. +// Aligned allocation was not provided before macosx10.14 and as a result we +// get availability errors when the deployment target is older than macosx10.14. +// However, AppleClang 10 (and older) don't trigger availability errors, and +// Clang < 8.0 doesn't warn for 10.13. +// XFAIL: !(apple-clang-9 || apple-clang-10 || clang-7) && availability=macosx10.13 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.12 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.11 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.10 diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t.pass.cpp index d6194b00aa025..6b4e1c1924b4a 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t.pass.cpp @@ -15,9 +15,11 @@ // FIXME change this to XFAIL. // UNSUPPORTED: no-aligned-allocation && !gcc -// Aligned allocation was not provided before macosx10.12 and as a result we -// get availability errors when the deployment target is older than macosx10.13. -// However, AppleClang 10 (and older) don't trigger availability errors. +// Aligned allocation was not provided before macosx10.14 and as a result we +// get availability errors when the deployment target is older than macosx10.14. +// However, AppleClang 10 (and older) don't trigger availability errors, and +// Clang < 8.0 doesn't warn for 10.13. +// XFAIL: !(apple-clang-9 || apple-clang-10 || clang-7) && availability=macosx10.13 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.12 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.11 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.10 diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow.pass.cpp index 59878aefd18a2..3188cc587dde9 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow.pass.cpp @@ -15,9 +15,11 @@ // FIXME turn this into an XFAIL // UNSUPPORTED: no-aligned-allocation && !gcc -// Aligned allocation was not provided before macosx10.12 and as a result we -// get availability errors when the deployment target is older than macosx10.13. -// However, AppleClang 10 (and older) don't trigger availability errors. +// Aligned allocation was not provided before macosx10.14 and as a result we +// get availability errors when the deployment target is older than macosx10.14. +// However, AppleClang 10 (and older) don't trigger availability errors, and +// Clang < 8.0 doesn't warn for 10.13. +// XFAIL: !(apple-clang-9 || apple-clang-10 || clang-7) && availability=macosx10.13 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.12 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.11 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.10 diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow_replace.pass.cpp index fc713dbf8ed83..29d8fd06a701e 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow_replace.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_align_val_t_nothrow_replace.pass.cpp @@ -10,9 +10,11 @@ // UNSUPPORTED: c++98, c++03, c++11, c++14 // UNSUPPORTED: sanitizer-new-delete -// Aligned allocation was not provided before macosx10.12 and as a result we -// get availability errors when the deployment target is older than macosx10.13. -// However, AppleClang 10 (and older) don't trigger availability errors. +// Aligned allocation was not provided before macosx10.14 and as a result we +// get availability errors when the deployment target is older than macosx10.14. +// However, AppleClang 10 (and older) don't trigger availability errors, and +// Clang < 8.0 doesn't warn for 10.13. +// XFAIL: !(apple-clang-9 || apple-clang-10 || clang-7) && availability=macosx10.13 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.12 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.11 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.10 diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/delete_align_val_t_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/delete_align_val_t_replace.pass.cpp index 19cabcce1edd9..c01e39915ec01 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/delete_align_val_t_replace.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/delete_align_val_t_replace.pass.cpp @@ -16,9 +16,11 @@ // None of the current GCC compilers support this. // UNSUPPORTED: gcc-5, gcc-6 -// Aligned allocation was not provided before macosx10.12 and as a result we -// get availability errors when the deployment target is older than macosx10.13. -// However, AppleClang 10 (and older) don't trigger availability errors. +// Aligned allocation was not provided before macosx10.14 and as a result we +// get availability errors when the deployment target is older than macosx10.14. +// However, AppleClang 10 (and older) don't trigger availability errors, and +// Clang < 8.0 doesn't warn for 10.13 +// XFAIL: !(apple-clang-9 || apple-clang-10 || clang-7) && availability=macosx10.13 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.12 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.11 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.10 diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t.pass.cpp index 7cf1aca3b9f8e..8cb40885c466f 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t.pass.cpp @@ -9,9 +9,11 @@ // UNSUPPORTED: c++98, c++03, c++11, c++14 -// Aligned allocation was not provided before macosx10.12 and as a result we -// get availability errors when the deployment target is older than macosx10.13. -// However, AppleClang 10 (and older) don't trigger availability errors. +// Aligned allocation was not provided before macosx10.14 and as a result we +// get availability errors when the deployment target is older than macosx10.14. +// However, AppleClang 10 (and older) don't trigger availability errors, and +// Clang < 8.0 doesn't warn for 10.13. +// XFAIL: !(apple-clang-9 || apple-clang-10 || clang-7) && availability=macosx10.13 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.12 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.11 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.10 diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow.pass.cpp index dd2666e00aad4..9d7f13bee3288 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow.pass.cpp @@ -9,9 +9,11 @@ // UNSUPPORTED: c++98, c++03, c++11, c++14 -// Aligned allocation was not provided before macosx10.12 and as a result we -// get availability errors when the deployment target is older than macosx10.13. -// However, AppleClang 10 (and older) don't trigger availability errors. +// Aligned allocation was not provided before macosx10.14 and as a result we +// get availability errors when the deployment target is older than macosx10.14. +// However, AppleClang 10 (and older) don't trigger availability errors, and +// Clang < 8.0 doesn't warn for 10.13 +// XFAIL: !(apple-clang-9 || apple-clang-10 || clang-7) && availability=macosx10.13 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.12 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.11 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.10 diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow_replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow_replace.pass.cpp index 514a2b8afc8c3..82367d7de093b 100644 --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow_replace.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_align_val_t_nothrow_replace.pass.cpp @@ -10,9 +10,11 @@ // UNSUPPORTED: c++98, c++03, c++11, c++14 // UNSUPPORTED: sanitizer-new-delete -// Aligned allocation was not provided before macosx10.12 and as a result we -// get availability errors when the deployment target is older than macosx10.13. -// However, AppleClang 10 (and older) don't trigger availability errors. +// Aligned allocation was not provided before macosx10.14 and as a result we +// get availability errors when the deployment target is older than macosx10.14. +// However, AppleClang 10 (and older) don't trigger availability errors, and +// Clang < 8.0 doesn't warn for 10.13 +// XFAIL: !(apple-clang-9 || apple-clang-10 || clang-7) && availability=macosx10.13 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.12 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.11 // XFAIL: !(apple-clang-9 || apple-clang-10) && availability=macosx10.10 diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt index 0eeb4b35a236b..92c7dc5dc5576 100644 --- a/libcxxabi/CMakeLists.txt +++ b/libcxxabi/CMakeLists.txt @@ -21,7 +21,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) project(libcxxabi CXX C) set(PACKAGE_NAME libcxxabi) - set(PACKAGE_VERSION 8.0.0svn) + set(PACKAGE_VERSION 8.0.0) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") diff --git a/libcxxabi/cmake/Modules/HandleOutOfTreeLLVM.cmake b/libcxxabi/cmake/Modules/HandleOutOfTreeLLVM.cmake index e50d0262f8041..0283a59ac1db2 100644 --- a/libcxxabi/cmake/Modules/HandleOutOfTreeLLVM.cmake +++ b/libcxxabi/cmake/Modules/HandleOutOfTreeLLVM.cmake @@ -117,7 +117,7 @@ macro(configure_out_of_tree_llvm) # Required LIT Configuration ------------------------------------------------ # Define the default arguments to use with 'lit', and an option for the user # to override. - set(LLVM_EXTERNAL_LIT "${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py") + set(LLVM_DEFAULT_EXTERNAL_LIT "${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py") set(LIT_ARGS_DEFAULT "-sv --show-xfail --show-unsupported") if (MSVC OR XCODE) set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") diff --git a/libunwind/CMakeLists.txt b/libunwind/CMakeLists.txt index 8d0fc50cc451c..3d06073cfe747 100644 --- a/libunwind/CMakeLists.txt +++ b/libunwind/CMakeLists.txt @@ -81,7 +81,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) endif() set(PACKAGE_NAME libunwind) - set(PACKAGE_VERSION 8.0.0svn) + set(PACKAGE_VERSION 8.0.1) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp index 30ad35995aece..49bb360d79411 100644 --- a/libunwind/src/AddressSpace.hpp +++ b/libunwind/src/AddressSpace.hpp @@ -534,11 +534,11 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, #endif cbdata->sects->dwarf_index_section = eh_frame_hdr_start; cbdata->sects->dwarf_index_section_length = phdr->p_memsz; - EHHeaderParser::decodeEHHdr( + found_hdr = EHHeaderParser::decodeEHHdr( *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, hdrInfo); - cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; - found_hdr = true; + if (found_hdr) + cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; } } diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp index ec70c0a11f70f..4109549a911b1 100644 --- a/libunwind/src/DwarfInstructions.hpp +++ b/libunwind/src/DwarfInstructions.hpp @@ -234,6 +234,31 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, } #endif +#if defined(_LIBUNWIND_TARGET_PPC64) +#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1) +#define PPC64_ELFV1_R2_OFFSET 40 +#define PPC64_ELFV2_R2_LOAD_INST_ENCODING 0xe8410018u // ld r2,24(r1) +#define PPC64_ELFV2_R2_OFFSET 24 + // If the instruction at return address is a TOC (r2) restore, + // then r2 was saved and needs to be restored. + // ELFv2 ABI specifies that the TOC Pointer must be saved at SP + 24, + // while in ELFv1 ABI it is saved at SP + 40. + if (R::getArch() == REGISTERS_PPC64 && returnAddress != 0) { + pint_t sp = newRegisters.getRegister(UNW_REG_SP); + pint_t r2 = 0; + switch (addressSpace.get32(returnAddress)) { + case PPC64_ELFV1_R2_LOAD_INST_ENCODING: + r2 = addressSpace.get64(sp + PPC64_ELFV1_R2_OFFSET); + break; + case PPC64_ELFV2_R2_LOAD_INST_ENCODING: + r2 = addressSpace.get64(sp + PPC64_ELFV2_R2_OFFSET); + break; + } + if (r2) + newRegisters.setRegister(UNW_PPC64_R2, r2); + } +#endif + // Return address is address after call site instruction, so setting IP to // that does simualates a return. newRegisters.setIP(returnAddress); diff --git a/libunwind/src/EHHeaderParser.hpp b/libunwind/src/EHHeaderParser.hpp index 9bdaf5505ff04..6b3e7dead8664 100644 --- a/libunwind/src/EHHeaderParser.hpp +++ b/libunwind/src/EHHeaderParser.hpp @@ -36,7 +36,7 @@ template class EHHeaderParser { uint8_t table_enc; }; - static void decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd, + static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo); static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, uint32_t sectionLength, @@ -53,12 +53,14 @@ template class EHHeaderParser { }; template -void EHHeaderParser::decodeEHHdr(A &addressSpace, pint_t ehHdrStart, +bool EHHeaderParser::decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) { pint_t p = ehHdrStart; uint8_t version = addressSpace.get8(p++); - if (version != 1) - _LIBUNWIND_ABORT("Unsupported .eh_frame_hdr version"); + if (version != 1) { + _LIBUNWIND_LOG0("Unsupported .eh_frame_hdr version"); + return false; + } uint8_t eh_frame_ptr_enc = addressSpace.get8(p++); uint8_t fde_count_enc = addressSpace.get8(p++); @@ -71,6 +73,8 @@ void EHHeaderParser::decodeEHHdr(A &addressSpace, pint_t ehHdrStart, ? 0 : addressSpace.getEncodedP(p, ehHdrEnd, fde_count_enc, ehHdrStart); ehHdrInfo.table = p; + + return true; } template @@ -102,7 +106,9 @@ bool EHHeaderParser::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, pint_t ehHdrEnd = ehHdrStart + sectionLength; EHHeaderParser::EHHeaderInfo hdrInfo; - EHHeaderParser::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd, hdrInfo); + if (!EHHeaderParser::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd, + hdrInfo)) + return false; size_t tableEntrySize = getTableEntrySize(hdrInfo.table_enc); pint_t tableEntry; diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S index 389db67579cdf..a155fbe2ddf2b 100644 --- a/libunwind/src/UnwindRegistersRestore.S +++ b/libunwind/src/UnwindRegistersRestore.S @@ -396,119 +396,119 @@ Lnovec: #elif defined(__ppc__) DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) -; -; void libunwind::Registers_ppc::jumpto() -; -; On entry: -; thread_state pointer is in r3 -; - - ; restore integral registerrs - ; skip r0 for now - ; skip r1 for now - lwz r2, 16(r3) - ; skip r3 for now - ; skip r4 for now - ; skip r5 for now - lwz r6, 32(r3) - lwz r7, 36(r3) - lwz r8, 40(r3) - lwz r9, 44(r3) - lwz r10, 48(r3) - lwz r11, 52(r3) - lwz r12, 56(r3) - lwz r13, 60(r3) - lwz r14, 64(r3) - lwz r15, 68(r3) - lwz r16, 72(r3) - lwz r17, 76(r3) - lwz r18, 80(r3) - lwz r19, 84(r3) - lwz r20, 88(r3) - lwz r21, 92(r3) - lwz r22, 96(r3) - lwz r23,100(r3) - lwz r24,104(r3) - lwz r25,108(r3) - lwz r26,112(r3) - lwz r27,116(r3) - lwz r28,120(r3) - lwz r29,124(r3) - lwz r30,128(r3) - lwz r31,132(r3) - - ; restore float registers - lfd f0, 160(r3) - lfd f1, 168(r3) - lfd f2, 176(r3) - lfd f3, 184(r3) - lfd f4, 192(r3) - lfd f5, 200(r3) - lfd f6, 208(r3) - lfd f7, 216(r3) - lfd f8, 224(r3) - lfd f9, 232(r3) - lfd f10,240(r3) - lfd f11,248(r3) - lfd f12,256(r3) - lfd f13,264(r3) - lfd f14,272(r3) - lfd f15,280(r3) - lfd f16,288(r3) - lfd f17,296(r3) - lfd f18,304(r3) - lfd f19,312(r3) - lfd f20,320(r3) - lfd f21,328(r3) - lfd f22,336(r3) - lfd f23,344(r3) - lfd f24,352(r3) - lfd f25,360(r3) - lfd f26,368(r3) - lfd f27,376(r3) - lfd f28,384(r3) - lfd f29,392(r3) - lfd f30,400(r3) - lfd f31,408(r3) - - ; restore vector registers if any are in use - lwz r5,156(r3) ; test VRsave - cmpwi r5,0 - beq Lnovec - - subi r4,r1,16 - rlwinm r4,r4,0,0,27 ; mask low 4-bits - ; r4 is now a 16-byte aligned pointer into the red zone - ; the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer +// +// void libunwind::Registers_ppc::jumpto() +// +// On entry: +// thread_state pointer is in r3 +// + + // restore integral registerrs + // skip r0 for now + // skip r1 for now + lwz %r2, 16(%r3) + // skip r3 for now + // skip r4 for now + // skip r5 for now + lwz %r6, 32(%r3) + lwz %r7, 36(%r3) + lwz %r8, 40(%r3) + lwz %r9, 44(%r3) + lwz %r10, 48(%r3) + lwz %r11, 52(%r3) + lwz %r12, 56(%r3) + lwz %r13, 60(%r3) + lwz %r14, 64(%r3) + lwz %r15, 68(%r3) + lwz %r16, 72(%r3) + lwz %r17, 76(%r3) + lwz %r18, 80(%r3) + lwz %r19, 84(%r3) + lwz %r20, 88(%r3) + lwz %r21, 92(%r3) + lwz %r22, 96(%r3) + lwz %r23,100(%r3) + lwz %r24,104(%r3) + lwz %r25,108(%r3) + lwz %r26,112(%r3) + lwz %r27,116(%r3) + lwz %r28,120(%r3) + lwz %r29,124(%r3) + lwz %r30,128(%r3) + lwz %r31,132(%r3) + + // restore float registers + lfd %f0, 160(%r3) + lfd %f1, 168(%r3) + lfd %f2, 176(%r3) + lfd %f3, 184(%r3) + lfd %f4, 192(%r3) + lfd %f5, 200(%r3) + lfd %f6, 208(%r3) + lfd %f7, 216(%r3) + lfd %f8, 224(%r3) + lfd %f9, 232(%r3) + lfd %f10,240(%r3) + lfd %f11,248(%r3) + lfd %f12,256(%r3) + lfd %f13,264(%r3) + lfd %f14,272(%r3) + lfd %f15,280(%r3) + lfd %f16,288(%r3) + lfd %f17,296(%r3) + lfd %f18,304(%r3) + lfd %f19,312(%r3) + lfd %f20,320(%r3) + lfd %f21,328(%r3) + lfd %f22,336(%r3) + lfd %f23,344(%r3) + lfd %f24,352(%r3) + lfd %f25,360(%r3) + lfd %f26,368(%r3) + lfd %f27,376(%r3) + lfd %f28,384(%r3) + lfd %f29,392(%r3) + lfd %f30,400(%r3) + lfd %f31,408(%r3) + + // restore vector registers if any are in use + lwz %r5, 156(%r3) // test VRsave + cmpwi %r5, 0 + beq Lnovec + subi %r4, %r1, 16 + rlwinm %r4, %r4, 0, 0, 27 // mask low 4-bits + // r4 is now a 16-byte aligned pointer into the red zone + // the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer + #define LOAD_VECTOR_UNALIGNEDl(_index) \ - andis. r0,r5,(1<<(15-_index)) @\ - beq Ldone ## _index @\ - lwz r0, 424+_index*16(r3) @\ - stw r0, 0(r4) @\ - lwz r0, 424+_index*16+4(r3) @\ - stw r0, 4(r4) @\ - lwz r0, 424+_index*16+8(r3) @\ - stw r0, 8(r4) @\ - lwz r0, 424+_index*16+12(r3)@\ - stw r0, 12(r4) @\ - lvx v ## _index,0,r4 @\ -Ldone ## _index: + andis. %r0, %r5, (1<<(15-_index)) SEPARATOR \ + beq Ldone ## _index SEPARATOR \ + lwz %r0, 424+_index*16(%r3) SEPARATOR \ + stw %r0, 0(%r4) SEPARATOR \ + lwz %r0, 424+_index*16+4(%r3) SEPARATOR \ + stw %r0, 4(%r4) SEPARATOR \ + lwz %r0, 424+_index*16+8(%r3) SEPARATOR \ + stw %r0, 8(%r4) SEPARATOR \ + lwz %r0, 424+_index*16+12(%r3) SEPARATOR \ + stw %r0, 12(%r4) SEPARATOR \ + lvx %v ## _index, 0, %r4 SEPARATOR \ + Ldone ## _index: #define LOAD_VECTOR_UNALIGNEDh(_index) \ - andi. r0,r5,(1<<(31-_index)) @\ - beq Ldone ## _index @\ - lwz r0, 424+_index*16(r3) @\ - stw r0, 0(r4) @\ - lwz r0, 424+_index*16+4(r3) @\ - stw r0, 4(r4) @\ - lwz r0, 424+_index*16+8(r3) @\ - stw r0, 8(r4) @\ - lwz r0, 424+_index*16+12(r3)@\ - stw r0, 12(r4) @\ - lvx v ## _index,0,r4 @\ - Ldone ## _index: + andi. %r0, %r5, (1<<(31-_index)) SEPARATOR \ + beq Ldone ## _index SEPARATOR \ + lwz %r0, 424+_index*16(%r3) SEPARATOR \ + stw %r0, 0(%r4) SEPARATOR \ + lwz %r0, 424+_index*16+4(%r3) SEPARATOR \ + stw %r0, 4(%r4) SEPARATOR \ + lwz %r0, 424+_index*16+8(%r3) SEPARATOR \ + stw %r0, 8(%r4) SEPARATOR \ + lwz %r0, 424+_index*16+12(%r3) SEPARATOR \ + stw %r0, 12(%r4) SEPARATOR \ + lvx %v ## _index, 0, %r4 SEPARATOR \ + Ldone ## _index: LOAD_VECTOR_UNALIGNEDl(0) @@ -545,17 +545,17 @@ Ldone ## _index: LOAD_VECTOR_UNALIGNEDh(31) Lnovec: - lwz r0, 136(r3) ; __cr - mtocrf 255,r0 - lwz r0, 148(r3) ; __ctr - mtctr r0 - lwz r0, 0(r3) ; __ssr0 - mtctr r0 - lwz r0, 8(r3) ; do r0 now - lwz r5,28(r3) ; do r5 now - lwz r4,24(r3) ; do r4 now - lwz r1,12(r3) ; do sp now - lwz r3,20(r3) ; do r3 last + lwz %r0, 136(%r3) // __cr + mtcr %r0 + lwz %r0, 148(%r3) // __ctr + mtctr %r0 + lwz %r0, 0(%r3) // __ssr0 + mtctr %r0 + lwz %r0, 8(%r3) // do r0 now + lwz %r5, 28(%r3) // do r5 now + lwz %r4, 24(%r3) // do r4 now + lwz %r1, 12(%r3) // do sp now + lwz %r3, 20(%r3) // do r3 last bctr #elif defined(__arm64__) || defined(__aarch64__) diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S index 48ecb0aec70f1..4b674afc6bdc8 100644 --- a/libunwind/src/UnwindRegistersSave.S +++ b/libunwind/src/UnwindRegistersSave.S @@ -557,144 +557,144 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) #elif defined(__ppc__) -; -; extern int unw_getcontext(unw_context_t* thread_state) -; -; On entry: -; thread_state pointer is in r3 -; +// +// extern int unw_getcontext(unw_context_t* thread_state) +// +// On entry: +// thread_state pointer is in r3 +// DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - stw r0, 8(r3) - mflr r0 - stw r0, 0(r3) ; store lr as ssr0 - stw r1, 12(r3) - stw r2, 16(r3) - stw r3, 20(r3) - stw r4, 24(r3) - stw r5, 28(r3) - stw r6, 32(r3) - stw r7, 36(r3) - stw r8, 40(r3) - stw r9, 44(r3) - stw r10, 48(r3) - stw r11, 52(r3) - stw r12, 56(r3) - stw r13, 60(r3) - stw r14, 64(r3) - stw r15, 68(r3) - stw r16, 72(r3) - stw r17, 76(r3) - stw r18, 80(r3) - stw r19, 84(r3) - stw r20, 88(r3) - stw r21, 92(r3) - stw r22, 96(r3) - stw r23,100(r3) - stw r24,104(r3) - stw r25,108(r3) - stw r26,112(r3) - stw r27,116(r3) - stw r28,120(r3) - stw r29,124(r3) - stw r30,128(r3) - stw r31,132(r3) - - ; save VRSave register - mfspr r0,256 - stw r0,156(r3) - ; save CR registers - mfcr r0 - stw r0,136(r3) - ; save CTR register - mfctr r0 - stw r0,148(r3) - - ; save float registers - stfd f0, 160(r3) - stfd f1, 168(r3) - stfd f2, 176(r3) - stfd f3, 184(r3) - stfd f4, 192(r3) - stfd f5, 200(r3) - stfd f6, 208(r3) - stfd f7, 216(r3) - stfd f8, 224(r3) - stfd f9, 232(r3) - stfd f10,240(r3) - stfd f11,248(r3) - stfd f12,256(r3) - stfd f13,264(r3) - stfd f14,272(r3) - stfd f15,280(r3) - stfd f16,288(r3) - stfd f17,296(r3) - stfd f18,304(r3) - stfd f19,312(r3) - stfd f20,320(r3) - stfd f21,328(r3) - stfd f22,336(r3) - stfd f23,344(r3) - stfd f24,352(r3) - stfd f25,360(r3) - stfd f26,368(r3) - stfd f27,376(r3) - stfd f28,384(r3) - stfd f29,392(r3) - stfd f30,400(r3) - stfd f31,408(r3) - - - ; save vector registers - - subi r4,r1,16 - rlwinm r4,r4,0,0,27 ; mask low 4-bits - ; r4 is now a 16-byte aligned pointer into the red zone + stw %r0, 8(%r3) + mflr %r0 + stw %r0, 0(%r3) // store lr as ssr0 + stw %r1, 12(%r3) + stw %r2, 16(%r3) + stw %r3, 20(%r3) + stw %r4, 24(%r3) + stw %r5, 28(%r3) + stw %r6, 32(%r3) + stw %r7, 36(%r3) + stw %r8, 40(%r3) + stw %r9, 44(%r3) + stw %r10, 48(%r3) + stw %r11, 52(%r3) + stw %r12, 56(%r3) + stw %r13, 60(%r3) + stw %r14, 64(%r3) + stw %r15, 68(%r3) + stw %r16, 72(%r3) + stw %r17, 76(%r3) + stw %r18, 80(%r3) + stw %r19, 84(%r3) + stw %r20, 88(%r3) + stw %r21, 92(%r3) + stw %r22, 96(%r3) + stw %r23,100(%r3) + stw %r24,104(%r3) + stw %r25,108(%r3) + stw %r26,112(%r3) + stw %r27,116(%r3) + stw %r28,120(%r3) + stw %r29,124(%r3) + stw %r30,128(%r3) + stw %r31,132(%r3) + + // save VRSave register + mfspr %r0, 256 + stw %r0, 156(%r3) + // save CR registers + mfcr %r0 + stw %r0, 136(%r3) + // save CTR register + mfctr %r0 + stw %r0, 148(%r3) + + // save float registers + stfd %f0, 160(%r3) + stfd %f1, 168(%r3) + stfd %f2, 176(%r3) + stfd %f3, 184(%r3) + stfd %f4, 192(%r3) + stfd %f5, 200(%r3) + stfd %f6, 208(%r3) + stfd %f7, 216(%r3) + stfd %f8, 224(%r3) + stfd %f9, 232(%r3) + stfd %f10,240(%r3) + stfd %f11,248(%r3) + stfd %f12,256(%r3) + stfd %f13,264(%r3) + stfd %f14,272(%r3) + stfd %f15,280(%r3) + stfd %f16,288(%r3) + stfd %f17,296(%r3) + stfd %f18,304(%r3) + stfd %f19,312(%r3) + stfd %f20,320(%r3) + stfd %f21,328(%r3) + stfd %f22,336(%r3) + stfd %f23,344(%r3) + stfd %f24,352(%r3) + stfd %f25,360(%r3) + stfd %f26,368(%r3) + stfd %f27,376(%r3) + stfd %f28,384(%r3) + stfd %f29,392(%r3) + stfd %f30,400(%r3) + stfd %f31,408(%r3) + + + // save vector registers + + subi %r4, %r1, 16 + rlwinm %r4, %r4, 0, 0, 27 // mask low 4-bits + // r4 is now a 16-byte aligned pointer into the red zone #define SAVE_VECTOR_UNALIGNED(_vec, _offset) \ - stvx _vec,0,r4 @\ - lwz r5, 0(r4) @\ - stw r5, _offset(r3) @\ - lwz r5, 4(r4) @\ - stw r5, _offset+4(r3) @\ - lwz r5, 8(r4) @\ - stw r5, _offset+8(r3) @\ - lwz r5, 12(r4) @\ - stw r5, _offset+12(r3) - - SAVE_VECTOR_UNALIGNED( v0, 424+0x000) - SAVE_VECTOR_UNALIGNED( v1, 424+0x010) - SAVE_VECTOR_UNALIGNED( v2, 424+0x020) - SAVE_VECTOR_UNALIGNED( v3, 424+0x030) - SAVE_VECTOR_UNALIGNED( v4, 424+0x040) - SAVE_VECTOR_UNALIGNED( v5, 424+0x050) - SAVE_VECTOR_UNALIGNED( v6, 424+0x060) - SAVE_VECTOR_UNALIGNED( v7, 424+0x070) - SAVE_VECTOR_UNALIGNED( v8, 424+0x080) - SAVE_VECTOR_UNALIGNED( v9, 424+0x090) - SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0) - SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0) - SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0) - SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0) - SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0) - SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0) - SAVE_VECTOR_UNALIGNED(v16, 424+0x100) - SAVE_VECTOR_UNALIGNED(v17, 424+0x110) - SAVE_VECTOR_UNALIGNED(v18, 424+0x120) - SAVE_VECTOR_UNALIGNED(v19, 424+0x130) - SAVE_VECTOR_UNALIGNED(v20, 424+0x140) - SAVE_VECTOR_UNALIGNED(v21, 424+0x150) - SAVE_VECTOR_UNALIGNED(v22, 424+0x160) - SAVE_VECTOR_UNALIGNED(v23, 424+0x170) - SAVE_VECTOR_UNALIGNED(v24, 424+0x180) - SAVE_VECTOR_UNALIGNED(v25, 424+0x190) - SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0) - SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0) - SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0) - SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0) - SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0) - SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0) - - li r3, 0 ; return UNW_ESUCCESS + stvx _vec, 0, %r4 SEPARATOR \ + lwz %r5, 0(%r4) SEPARATOR \ + stw %r5, _offset(%r3) SEPARATOR \ + lwz %r5, 4(%r4) SEPARATOR \ + stw %r5, _offset+4(%r3) SEPARATOR \ + lwz %r5, 8(%r4) SEPARATOR \ + stw %r5, _offset+8(%r3) SEPARATOR \ + lwz %r5, 12(%r4) SEPARATOR \ + stw %r5, _offset+12(%r3) + + SAVE_VECTOR_UNALIGNED( %v0, 424+0x000) + SAVE_VECTOR_UNALIGNED( %v1, 424+0x010) + SAVE_VECTOR_UNALIGNED( %v2, 424+0x020) + SAVE_VECTOR_UNALIGNED( %v3, 424+0x030) + SAVE_VECTOR_UNALIGNED( %v4, 424+0x040) + SAVE_VECTOR_UNALIGNED( %v5, 424+0x050) + SAVE_VECTOR_UNALIGNED( %v6, 424+0x060) + SAVE_VECTOR_UNALIGNED( %v7, 424+0x070) + SAVE_VECTOR_UNALIGNED( %v8, 424+0x080) + SAVE_VECTOR_UNALIGNED( %v9, 424+0x090) + SAVE_VECTOR_UNALIGNED(%v10, 424+0x0A0) + SAVE_VECTOR_UNALIGNED(%v11, 424+0x0B0) + SAVE_VECTOR_UNALIGNED(%v12, 424+0x0C0) + SAVE_VECTOR_UNALIGNED(%v13, 424+0x0D0) + SAVE_VECTOR_UNALIGNED(%v14, 424+0x0E0) + SAVE_VECTOR_UNALIGNED(%v15, 424+0x0F0) + SAVE_VECTOR_UNALIGNED(%v16, 424+0x100) + SAVE_VECTOR_UNALIGNED(%v17, 424+0x110) + SAVE_VECTOR_UNALIGNED(%v18, 424+0x120) + SAVE_VECTOR_UNALIGNED(%v19, 424+0x130) + SAVE_VECTOR_UNALIGNED(%v20, 424+0x140) + SAVE_VECTOR_UNALIGNED(%v21, 424+0x150) + SAVE_VECTOR_UNALIGNED(%v22, 424+0x160) + SAVE_VECTOR_UNALIGNED(%v23, 424+0x170) + SAVE_VECTOR_UNALIGNED(%v24, 424+0x180) + SAVE_VECTOR_UNALIGNED(%v25, 424+0x190) + SAVE_VECTOR_UNALIGNED(%v26, 424+0x1A0) + SAVE_VECTOR_UNALIGNED(%v27, 424+0x1B0) + SAVE_VECTOR_UNALIGNED(%v28, 424+0x1C0) + SAVE_VECTOR_UNALIGNED(%v29, 424+0x1D0) + SAVE_VECTOR_UNALIGNED(%v30, 424+0x1E0) + SAVE_VECTOR_UNALIGNED(%v31, 424+0x1F0) + + li %r3, 0 // return UNW_ESUCCESS blr diff --git a/libunwind/src/assembly.h b/libunwind/src/assembly.h index 2df930214fae5..0b7d24389a40b 100644 --- a/libunwind/src/assembly.h +++ b/libunwind/src/assembly.h @@ -29,14 +29,26 @@ #ifdef _ARCH_PWR8 #define PPC64_HAS_VMX #endif -#elif defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__) -#define SEPARATOR @ #elif defined(__arm64__) #define SEPARATOR %% #else #define SEPARATOR ; #endif +#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1) +#define PPC64_OPD1 .section .opd,"aw",@progbits SEPARATOR +#define PPC64_OPD2 SEPARATOR \ + .p2align 3 SEPARATOR \ + .quad .Lfunc_begin0 SEPARATOR \ + .quad .TOC.@tocbase SEPARATOR \ + .quad 0 SEPARATOR \ + .text SEPARATOR \ +.Lfunc_begin0: +#else +#define PPC64_OPD1 +#define PPC64_OPD2 +#endif + #define GLUE2(a, b) a ## b #define GLUE(a, b) GLUE2(a, b) #define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name) @@ -97,13 +109,17 @@ .globl SYMBOL_NAME(name) SEPARATOR \ EXPORT_SYMBOL(name) SEPARATOR \ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ - SYMBOL_NAME(name): + PPC64_OPD1 \ + SYMBOL_NAME(name): \ + PPC64_OPD2 #define DEFINE_LIBUNWIND_PRIVATE_FUNCTION(name) \ .globl SYMBOL_NAME(name) SEPARATOR \ HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \ SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ - SYMBOL_NAME(name): + PPC64_OPD1 \ + SYMBOL_NAME(name): \ + PPC64_OPD2 #if defined(__arm__) #if !defined(__ARM_ARCH) diff --git a/libunwind/test/lit.cfg b/libunwind/test/lit.cfg index 272bc163bb37b..1d284bdfd771a 100644 --- a/libunwind/test/lit.cfg +++ b/libunwind/test/lit.cfg @@ -23,6 +23,9 @@ config.suffixes = ['.cpp', '.s'] # test_source_root: The root path where tests are located. config.test_source_root = os.path.dirname(__file__) +# needed to test libunwind with code that throws exceptions +config.enable_exceptions = True + # Infer the libcxx_test_source_root for configuration import. # If libcxx_source_root isn't specified in the config, assume that the libcxx # and libunwind source directories are sibling directories. diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index 29131d7eb8db4..2bb9aa01e5399 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -669,18 +669,38 @@ const uint8_t ArmThunk[] = { 0xe7, 0x44, // L1: add pc, ip }; -size_t RangeExtensionThunk::getSize() const { +size_t RangeExtensionThunkARM::getSize() const { assert(Config->Machine == ARMNT); return sizeof(ArmThunk); } -void RangeExtensionThunk::writeTo(uint8_t *Buf) const { +void RangeExtensionThunkARM::writeTo(uint8_t *Buf) const { assert(Config->Machine == ARMNT); uint64_t Offset = Target->getRVA() - RVA - 12; memcpy(Buf + OutputSectionOff, ArmThunk, sizeof(ArmThunk)); applyMOV32T(Buf + OutputSectionOff, uint32_t(Offset)); } +// A position independent ARM64 adrp+add thunk, with a maximum range of +// +/- 4 GB, which is enough for any PE-COFF. +const uint8_t Arm64Thunk[] = { + 0x10, 0x00, 0x00, 0x90, // adrp x16, Dest + 0x10, 0x02, 0x00, 0x91, // add x16, x16, :lo12:Dest + 0x00, 0x02, 0x1f, 0xd6, // br x16 +}; + +size_t RangeExtensionThunkARM64::getSize() const { + assert(Config->Machine == ARM64); + return sizeof(Arm64Thunk); +} + +void RangeExtensionThunkARM64::writeTo(uint8_t *Buf) const { + assert(Config->Machine == ARM64); + memcpy(Buf + OutputSectionOff, Arm64Thunk, sizeof(Arm64Thunk)); + applyArm64Addr(Buf + OutputSectionOff + 0, Target->getRVA(), RVA, 12); + applyArm64Imm(Buf + OutputSectionOff + 4, Target->getRVA() & 0xfff, 0); +} + void LocalImportChunk::getBaserels(std::vector *Res) { Res->emplace_back(getRVA()); } diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h index f8a0ddd8ef3b2..e132fdf8adfaf 100644 --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -355,9 +355,18 @@ class ImportThunkChunkARM64 : public Chunk { Defined *ImpSymbol; }; -class RangeExtensionThunk : public Chunk { +class RangeExtensionThunkARM : public Chunk { public: - explicit RangeExtensionThunk(Defined *T) : Target(T) {} + explicit RangeExtensionThunkARM(Defined *T) : Target(T) {} + size_t getSize() const override; + void writeTo(uint8_t *Buf) const override; + + Defined *Target; +}; + +class RangeExtensionThunkARM64 : public Chunk { +public: + explicit RangeExtensionThunkARM64(Defined *T) : Target(T) {} size_t getSize() const override; void writeTo(uint8_t *Buf) const override; diff --git a/lld/COFF/DLL.cpp b/lld/COFF/DLL.cpp index 599cc5892a16f..c06027d3e5c34 100644 --- a/lld/COFF/DLL.cpp +++ b/lld/COFF/DLL.cpp @@ -47,6 +47,7 @@ class HintNameChunk : public Chunk { } void writeTo(uint8_t *Buf) const override { + memset(Buf + OutputSectionOff, 0, getSize()); write16le(Buf + OutputSectionOff, Hint); memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size()); } @@ -63,7 +64,10 @@ class LookupChunk : public Chunk { size_t getSize() const override { return Config->Wordsize; } void writeTo(uint8_t *Buf) const override { - write32le(Buf + OutputSectionOff, HintName->getRVA()); + if (Config->is64()) + write64le(Buf + OutputSectionOff, HintName->getRVA()); + else + write32le(Buf + OutputSectionOff, HintName->getRVA()); } Chunk *HintName; @@ -99,6 +103,8 @@ class ImportDirectoryChunk : public Chunk { size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); } void writeTo(uint8_t *Buf) const override { + memset(Buf + OutputSectionOff, 0, getSize()); + auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff); E->ImportLookupTableRVA = LookupTab->getRVA(); E->NameRVA = DLLName->getRVA(); @@ -118,6 +124,10 @@ class NullChunk : public Chunk { bool hasData() const override { return false; } size_t getSize() const override { return Size; } + void writeTo(uint8_t *Buf) const override { + memset(Buf + OutputSectionOff, 0, Size); + } + private: size_t Size; }; @@ -160,6 +170,8 @@ class DelayDirectoryChunk : public Chunk { } void writeTo(uint8_t *Buf) const override { + memset(Buf + OutputSectionOff, 0, getSize()); + auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff); E->Attributes = 1; E->Name = DLLName->getRVA(); @@ -392,6 +404,8 @@ class ExportDirectoryChunk : public Chunk { } void writeTo(uint8_t *Buf) const override { + memset(Buf + OutputSectionOff, 0, getSize()); + auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff); E->NameRVA = DLLName->getRVA(); E->OrdinalBase = 0; diff --git a/lld/COFF/ICF.cpp b/lld/COFF/ICF.cpp index 34ea360fa9258..f6904eb7d24f2 100644 --- a/lld/COFF/ICF.cpp +++ b/lld/COFF/ICF.cpp @@ -263,19 +263,21 @@ void ICF::run(ArrayRef Vec) { // Initially, we use hash values to partition sections. parallelForEach(Chunks, [&](SectionChunk *SC) { - SC->Class[1] = xxHash64(SC->getContents()); + SC->Class[0] = xxHash64(SC->getContents()); }); // Combine the hashes of the sections referenced by each section into its // hash. - parallelForEach(Chunks, [&](SectionChunk *SC) { - uint32_t Hash = SC->Class[1]; - for (Symbol *B : SC->symbols()) - if (auto *Sym = dyn_cast_or_null(B)) - Hash ^= Sym->getChunk()->Class[1]; - // Set MSB to 1 to avoid collisions with non-hash classs. - SC->Class[0] = Hash | (1U << 31); - }); + for (unsigned Cnt = 0; Cnt != 2; ++Cnt) { + parallelForEach(Chunks, [&](SectionChunk *SC) { + uint32_t Hash = SC->Class[Cnt % 2]; + for (Symbol *B : SC->symbols()) + if (auto *Sym = dyn_cast_or_null(B)) + Hash += Sym->getChunk()->Class[Cnt % 2]; + // Set MSB to 1 to avoid collisions with non-hash classs. + SC->Class[(Cnt + 1) % 2] = Hash | (1U << 31); + }); + } // From now on, sections in Chunks are ordered so that sections in // the same group are consecutive in the vector. diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp index 7862b6ce4cc5a..7757b89e2b36d 100644 --- a/lld/COFF/PDB.cpp +++ b/lld/COFF/PDB.cpp @@ -288,18 +288,24 @@ static void pdbMakeAbsolute(SmallVectorImpl &FileName) { // It's not absolute in any path syntax. Relative paths necessarily refer to // the local file system, so we can make it native without ending up with a // nonsensical path. - sys::path::native(FileName); if (Config->PDBSourcePath.empty()) { + sys::path::native(FileName); sys::fs::make_absolute(FileName); return; } - // Only apply native and dot removal to the relative file path. We want to - // leave the path the user specified untouched since we assume they specified - // it for a reason. - sys::path::remove_dots(FileName, /*remove_dot_dots=*/true); + // Try to guess whether /PDBSOURCEPATH is a unix path or a windows path. + // Since PDB's are more of a Windows thing, we make this conservative and only + // decide that it's a unix path if we're fairly certain. Specifically, if + // it starts with a forward slash. SmallString<128> AbsoluteFileName = Config->PDBSourcePath; - sys::path::append(AbsoluteFileName, FileName); + sys::path::Style GuessedStyle = AbsoluteFileName.startswith("/") + ? sys::path::Style::posix + : sys::path::Style::windows; + sys::path::append(AbsoluteFileName, GuessedStyle, FileName); + sys::path::native(AbsoluteFileName, GuessedStyle); + sys::path::remove_dots(AbsoluteFileName, true, GuessedStyle); + FileName = std::move(AbsoluteFileName); } diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 258796ea6057b..56b797451cfc7 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -306,16 +306,31 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) { // Check whether the target address S is in range from a relocation // of type RelType at address P. static bool isInRange(uint16_t RelType, uint64_t S, uint64_t P, int Margin) { - assert(Config->Machine == ARMNT); - int64_t Diff = AbsoluteDifference(S, P + 4) + Margin; - switch (RelType) { - case IMAGE_REL_ARM_BRANCH20T: - return isInt<21>(Diff); - case IMAGE_REL_ARM_BRANCH24T: - case IMAGE_REL_ARM_BLX23T: - return isInt<25>(Diff); - default: - return true; + if (Config->Machine == ARMNT) { + int64_t Diff = AbsoluteDifference(S, P + 4) + Margin; + switch (RelType) { + case IMAGE_REL_ARM_BRANCH20T: + return isInt<21>(Diff); + case IMAGE_REL_ARM_BRANCH24T: + case IMAGE_REL_ARM_BLX23T: + return isInt<25>(Diff); + default: + return true; + } + } else if (Config->Machine == ARM64) { + int64_t Diff = AbsoluteDifference(S, P) + Margin; + switch (RelType) { + case IMAGE_REL_ARM64_BRANCH26: + return isInt<28>(Diff); + case IMAGE_REL_ARM64_BRANCH19: + return isInt<21>(Diff); + case IMAGE_REL_ARM64_BRANCH14: + return isInt<16>(Diff); + default: + return true; + } + } else { + llvm_unreachable("Unexpected architecture"); } } @@ -327,7 +342,17 @@ getThunk(DenseMap &LastThunks, Defined *Target, uint64_t P, Defined *&LastThunk = LastThunks[Target->getRVA()]; if (LastThunk && isInRange(Type, LastThunk->getRVA(), P, Margin)) return {LastThunk, false}; - RangeExtensionThunk *C = make(Target); + Chunk *C; + switch (Config->Machine) { + case ARMNT: + C = make(Target); + break; + case ARM64: + C = make(Target); + break; + default: + llvm_unreachable("Unexpected architecture"); + } Defined *D = make("", C); LastThunk = D; return {D, true}; @@ -344,14 +369,14 @@ getThunk(DenseMap &LastThunks, Defined *Target, uint64_t P, // After adding thunks, we verify that all relocations are in range (with // no extra margin requirements). If this failed, we restart (throwing away // the previously created thunks) and retry with a wider margin. -static bool createThunks(std::vector &Chunks, int Margin) { +static bool createThunks(OutputSection *OS, int Margin) { bool AddressesChanged = false; DenseMap LastThunks; size_t ThunksSize = 0; // Recheck Chunks.size() each iteration, since we can insert more // elements into it. - for (size_t I = 0; I != Chunks.size(); ++I) { - SectionChunk *SC = dyn_cast_or_null(Chunks[I]); + for (size_t I = 0; I != OS->Chunks.size(); ++I) { + SectionChunk *SC = dyn_cast_or_null(OS->Chunks[I]); if (!SC) continue; size_t ThunkInsertionSpot = I + 1; @@ -388,7 +413,8 @@ static bool createThunks(std::vector &Chunks, int Margin) { Chunk *ThunkChunk = Thunk->getChunk(); ThunkChunk->setRVA( ThunkInsertionRVA); // Estimate of where it will be located. - Chunks.insert(Chunks.begin() + ThunkInsertionSpot, ThunkChunk); + ThunkChunk->setOutputSection(OS); + OS->Chunks.insert(OS->Chunks.begin() + ThunkInsertionSpot, ThunkChunk); ThunkInsertionSpot++; ThunksSize += ThunkChunk->getSize(); ThunkInsertionRVA += ThunkChunk->getSize(); @@ -428,7 +454,7 @@ static bool verifyRanges(const std::vector Chunks) { // Assign addresses and add thunks if necessary. void Writer::finalizeAddresses() { assignAddresses(); - if (Config->Machine != ARMNT) + if (Config->Machine != ARMNT && Config->Machine != ARM64) return; size_t OrigNumChunks = 0; @@ -477,7 +503,7 @@ void Writer::finalizeAddresses() { // to avoid things going out of range due to the added thunks. bool AddressesChanged = false; for (OutputSection *Sec : OutputSections) - AddressesChanged |= createThunks(Sec->Chunks, Margin); + AddressesChanged |= createThunks(Sec, Margin); // If the verification above thought we needed thunks, we should have // added some. assert(AddressesChanged); @@ -1325,19 +1351,47 @@ static void addSymbolToRVASet(SymbolRVASet &RVASet, Defined *S) { // symbol in an executable section. static void maybeAddAddressTakenFunction(SymbolRVASet &AddressTakenSyms, Symbol *S) { - auto *D = dyn_cast_or_null(S); - - // Ignore undefined symbols and references to non-functions (e.g. globals and - // labels). - if (!D || - D->getCOFFSymbol().getComplexType() != COFF::IMAGE_SYM_DTYPE_FUNCTION) + if (!S) return; - // Mark the symbol as address taken if it's in an executable section. - Chunk *RefChunk = D->getChunk(); - OutputSection *OS = RefChunk ? RefChunk->getOutputSection() : nullptr; - if (OS && OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE) - addSymbolToRVASet(AddressTakenSyms, D); + switch (S->kind()) { + case Symbol::DefinedLocalImportKind: + case Symbol::DefinedImportDataKind: + // Defines an __imp_ pointer, so it is data, so it is ignored. + break; + case Symbol::DefinedCommonKind: + // Common is always data, so it is ignored. + break; + case Symbol::DefinedAbsoluteKind: + case Symbol::DefinedSyntheticKind: + // Absolute is never code, synthetic generally isn't and usually isn't + // determinable. + break; + case Symbol::LazyKind: + case Symbol::UndefinedKind: + // Undefined symbols resolve to zero, so they don't have an RVA. Lazy + // symbols shouldn't have relocations. + break; + + case Symbol::DefinedImportThunkKind: + // Thunks are always code, include them. + addSymbolToRVASet(AddressTakenSyms, cast(S)); + break; + + case Symbol::DefinedRegularKind: { + // This is a regular, defined, symbol from a COFF file. Mark the symbol as + // address taken if the symbol type is function and it's in an executable + // section. + auto *D = cast(S); + if (D->getCOFFSymbol().getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { + Chunk *RefChunk = D->getChunk(); + OutputSection *OS = RefChunk ? RefChunk->getOutputSection() : nullptr; + if (OS && OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE) + addSymbolToRVASet(AddressTakenSyms, D); + } + break; + } + } } // Visit all relocations from all section contributions of this object file and diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index 8a320c9a4e9ef..f02e818daee53 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -113,6 +113,7 @@ class PPC64 final : public TargetInfo { void writeGotHeader(uint8_t *Buf) const override; bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, uint64_t BranchAddr, const Symbol &S) const override; + uint32_t getThunkSectionSpacing() const override; bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, RelExpr Expr) const override; @@ -756,7 +757,18 @@ bool PPC64::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, // If the offset exceeds the range of the branch type then it will need // a range-extending thunk. - return !inBranchRange(Type, BranchAddr, S.getVA()); + // See the comment in getRelocTargetVA() about R_PPC64_CALL. + return !inBranchRange(Type, BranchAddr, + S.getVA() + + getPPC64GlobalEntryToLocalEntryOffset(S.StOther)); +} + +uint32_t PPC64::getThunkSectionSpacing() const { + // See comment in Arch/ARM.cpp for a more detailed explanation of + // getThunkSectionSpacing(). For PPC64 we pick the constant here based on + // R_PPC64_REL24, which is used by unconditional branch instructions. + // 0x2000000 = (1 << 24-1) * 4 + return 0x2000000; } bool PPC64::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp index 06314155dcc92..a000eeb079d9e 100644 --- a/lld/ELF/Arch/X86_64.cpp +++ b/lld/ELF/Arch/X86_64.cpp @@ -264,15 +264,6 @@ void X86_64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, template void X86_64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { - // Convert - // leaq bar@tlsld(%rip), %rdi - // callq __tls_get_addr@PLT - // leaq bar@dtpoff(%rax), %rcx - // to - // .word 0x6666 - // .byte 0x66 - // mov %fs:0,%rax - // leaq bar@tpoff(%rax), %rcx if (Type == R_X86_64_DTPOFF64) { write64le(Loc, Val); return; @@ -287,7 +278,37 @@ void X86_64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, 0x66, // .byte 0x66 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax }; - memcpy(Loc - 3, Inst, sizeof(Inst)); + + if (Loc[4] == 0xe8) { + // Convert + // leaq bar@tlsld(%rip), %rdi # 48 8d 3d + // callq __tls_get_addr@PLT # e8 + // leaq bar@dtpoff(%rax), %rcx + // to + // .word 0x6666 + // .byte 0x66 + // mov %fs:0,%rax + // leaq bar@tpoff(%rax), %rcx + memcpy(Loc - 3, Inst, sizeof(Inst)); + return; + } + + if (Loc[4] == 0xff && Loc[5] == 0x15) { + // Convert + // leaq x@tlsld(%rip),%rdi # 48 8d 3d + // call *__tls_get_addr@GOTPCREL(%rip) # ff 15 + // to + // .long 0x66666666 + // movq %fs:0,%rax + // See "Table 11.9: LD -> LE Code Transition (LP64)" in + // https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf + Loc[-3] = 0x66; + memcpy(Loc - 2, Inst, sizeof(Inst)); + return; + } + + error(getErrorLocation(Loc - 3) + + "expected R_X86_64_PLT32 or R_X86_64_GOTPCRELX after R_X86_64_TLSLD"); } template diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 8fb760e592eb1..60555f188fed3 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -159,6 +159,7 @@ struct Configuration { bool OFormatBinary; bool Omagic; bool OptRemarksWithHotness; + bool PicThunk; bool Pie; bool PrintGcSections; bool PrintIcfSections; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 13b6119e2dc91..bce9d944a4a64 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -130,7 +130,7 @@ static std::tuple parseEmulation(StringRef Emul) { .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS}) .Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS}) .Case("elf32lriscv", {ELF32LEKind, EM_RISCV}) - .Case("elf32ppc", {ELF32BEKind, EM_PPC}) + .Cases("elf32ppc", "elf32ppclinux", {ELF32BEKind, EM_PPC}) .Case("elf64btsmip", {ELF64BEKind, EM_MIPS}) .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS}) .Case("elf64lriscv", {ELF64LEKind, EM_RISCV}) @@ -1006,6 +1006,7 @@ static void setConfigs(opt::InputArgList &Args) { Config->Endianness = Config->IsLE ? endianness::little : endianness::big; Config->IsMips64EL = (K == ELF64LEKind && M == EM_MIPS); Config->Pic = Config->Pie || Config->Shared; + Config->PicThunk = Args.hasArg(OPT_pic_veneer, Config->Pic); Config->Wordsize = Config->Is64 ? 8 : 4; // ELF defines two different ways to store relocation addends as shown below: diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp index e917ae76a689e..d08ac73ded80e 100644 --- a/lld/ELF/ICF.cpp +++ b/lld/ELF/ICF.cpp @@ -426,16 +426,17 @@ void ICF::forEachClass(llvm::function_ref Fn) { // Combine the hashes of the sections referenced by the given section into its // hash. template -static void combineRelocHashes(InputSection *IS, ArrayRef Rels) { - uint32_t Hash = IS->Class[1]; +static void combineRelocHashes(unsigned Cnt, InputSection *IS, + ArrayRef Rels) { + uint32_t Hash = IS->Class[Cnt % 2]; for (RelTy Rel : Rels) { Symbol &S = IS->template getFile()->getRelocTargetSym(Rel); if (auto *D = dyn_cast(&S)) if (auto *RelSec = dyn_cast_or_null(D->Section)) - Hash ^= RelSec->Class[1]; + Hash += RelSec->Class[Cnt % 2]; } // Set MSB to 1 to avoid collisions with non-hash IDs. - IS->Class[0] = Hash | (1U << 31); + IS->Class[(Cnt + 1) % 2] = Hash | (1U << 31); } static void print(const Twine &S) { @@ -453,15 +454,17 @@ template void ICF::run() { // Initially, we use hash values to partition sections. parallelForEach(Sections, [&](InputSection *S) { - S->Class[1] = xxHash64(S->data()); + S->Class[0] = xxHash64(S->data()); }); - parallelForEach(Sections, [&](InputSection *S) { - if (S->AreRelocsRela) - combineRelocHashes(S, S->template relas()); - else - combineRelocHashes(S, S->template rels()); - }); + for (unsigned Cnt = 0; Cnt != 2; ++Cnt) { + parallelForEach(Sections, [&](InputSection *S) { + if (S->AreRelocsRela) + combineRelocHashes(Cnt, S, S->template relas()); + else + combineRelocHashes(Cnt, S, S->template rels()); + }); + } // From now on, sections in Sections vector are ordered so that sections // in the same equivalence class are consecutive in the vector. diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index e4d1dec7cbcbd..bc7e61072e642 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -320,17 +320,6 @@ StringRef ObjFile::getShtGroupSignature(ArrayRef Sections, return Signature; } -template -ArrayRef::Elf_Word> -ObjFile::getShtGroupEntries(const Elf_Shdr &Sec) { - const ELFFile &Obj = this->getObj(); - ArrayRef Entries = - CHECK(Obj.template getSectionContentsAsArray(&Sec), this); - if (Entries.empty() || Entries[0] != GRP_COMDAT) - fatal(toString(this) + ": unsupported SHT_GROUP format"); - return Entries.slice(1); -} - template bool ObjFile::shouldMerge(const Elf_Shdr &Sec) { // On a regular link we don't merge sections if -O0 (default is -O1). This // sometimes makes the linker significantly faster, although the output will @@ -440,26 +429,34 @@ void ObjFile::initializeSections( case SHT_GROUP: { // De-duplicate section groups by their signatures. StringRef Signature = getShtGroupSignature(ObjSections, Sec); - bool IsNew = ComdatGroups.insert(CachedHashStringRef(Signature)).second; this->Sections[I] = &InputSection::Discarded; - // We only support GRP_COMDAT type of group. Get the all entries of the - // section here to let getShtGroupEntries to check the type early for us. - ArrayRef Entries = getShtGroupEntries(Sec); - // If it is a new section group, we want to keep group members. - // Group leader sections, which contain indices of group members, are - // discarded because they are useless beyond this point. The only - // exception is the -r option because in order to produce re-linkable - // object files, we want to pass through basically everything. + ArrayRef Entries = + CHECK(Obj.template getSectionContentsAsArray(&Sec), this); + if (Entries.empty()) + fatal(toString(this) + ": empty SHT_GROUP"); + + // The first word of a SHT_GROUP section contains flags. Currently, + // the standard defines only "GRP_COMDAT" flag for the COMDAT group. + // An group with the empty flag doesn't define anything; such sections + // are just skipped. + if (Entries[0] == 0) + continue; + + if (Entries[0] != GRP_COMDAT) + fatal(toString(this) + ": unsupported SHT_GROUP format"); + + bool IsNew = ComdatGroups.insert(CachedHashStringRef(Signature)).second; if (IsNew) { if (Config->Relocatable) this->Sections[I] = createInputSection(Sec); - continue; + continue; } + // Otherwise, discard group members. - for (uint32_t SecIndex : Entries) { + for (uint32_t SecIndex : Entries.slice(1)) { if (SecIndex >= Size) fatal(toString(this) + ": invalid section index in group: " + Twine(SecIndex)); @@ -739,7 +736,8 @@ InputSectionBase *ObjFile::createInputSection(const Elf_Shdr &Sec) { // sections. Drop those sections to avoid duplicate symbol errors. // FIXME: This is glibc PR20543, we should remove this hack once that has been // fixed for a while. - if (Name.startswith(".gnu.linkonce.")) + if (Name == ".gnu.linkonce.t.__x86.get_pc_thunk.bx" || + Name == ".gnu.linkonce.t.__i686.get_pc_thunk.bx") return &InputSection::Discarded; // If we are creating a new .build-id section, strip existing .build-id diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 5094ddd804a5f..d7cbbc67a3656 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -175,7 +175,6 @@ template class ObjFile : public ELFFileBase { StringRef getShtGroupSignature(ArrayRef Sections, const Elf_Shdr &Sec); - ArrayRef getShtGroupEntries(const Elf_Shdr &Sec); public: static bool classof(const InputFile *F) { return F->kind() == Base::ObjKind; } diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 839bff7011eb8..ca2f49c07bb71 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -248,6 +248,7 @@ void InputSectionBase::parseCompressedHeader() { } UncompressedSize = Hdr->ch_size; + Alignment = std::max(Hdr->ch_addralign, 1); RawData = RawData.slice(sizeof(*Hdr)); return; } @@ -265,6 +266,7 @@ void InputSectionBase::parseCompressedHeader() { } UncompressedSize = Hdr->ch_size; + Alignment = std::max(Hdr->ch_addralign, 1); RawData = RawData.slice(sizeof(*Hdr)); } @@ -578,10 +580,6 @@ static int64_t getTlsTpOffset() { // Variant 1. The thread pointer points to a TCB with a fixed 2-word size, // followed by a variable amount of alignment padding, followed by the TLS // segment. - // - // NB: While the ARM/AArch64 ABI formally has a 2-word TCB size, lld - // effectively increases the TCB size to 8 words for Android compatibility. - // It accomplishes this by increasing the segment's alignment. return alignTo(Config->Wordsize * 2, Out::TlsPhdr->p_align); case EM_386: case EM_X86_64: diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index e43a21b923d33..439fe341644c8 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -30,7 +30,7 @@ def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">; def build_id: F<"build-id">, HelpText<"Alias for --build-id=fast">; def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">, - MetaVarName<"[fast,md5,sha,uuid,0x]">; + MetaVarName<"[fast,md5,sha1,uuid,0x]">; defm check_sections: B<"check-sections", "Check section addresses for overlaps (default)", @@ -255,6 +255,9 @@ defm use_android_relr_tags: B<"use-android-relr-tags", "Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*", "Use SHT_RELR / DT_RELR* tags (default)">; +def pic_veneer: F<"pic-veneer">, + HelpText<"Always generate position independent thunks (veneers)">; + defm pie: B<"pie", "Create a position independent executable", "Do not create a position independent executable (default)">; diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 812468896f0d0..9ffe8a9cc72e7 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -356,7 +356,7 @@ static bool needsGot(RelExpr Expr) { static bool isRelExpr(RelExpr Expr) { return isRelExprOneOf(Expr); + R_AARCH64_PLT_PAGE_PC, R_RELAX_GOT_PC>(Expr); } // Returns true if a given relocation can be computed at link-time. diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index eee3f0e330cc3..7dbe1641622b6 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -94,7 +94,6 @@ class ScriptParser final : ScriptLexer { SortSectionPolicy readSortKind(); SymbolAssignment *readProvideHidden(bool Provide, bool Hidden); SymbolAssignment *readAssignment(StringRef Tok); - std::tuple readBfdName(); void readSort(); Expr readAssert(); Expr readConstant(); @@ -385,39 +384,25 @@ void ScriptParser::readOutputArch() { skip(); } -std::tuple ScriptParser::readBfdName() { - StringRef S = unquote(next()); - if (S == "elf32-i386") - return std::make_tuple(ELF32LEKind, EM_386, false); - if (S == "elf32-iamcu") - return std::make_tuple(ELF32LEKind, EM_IAMCU, false); - if (S == "elf32-littlearm") - return std::make_tuple(ELF32LEKind, EM_ARM, false); - if (S == "elf32-x86-64") - return std::make_tuple(ELF32LEKind, EM_X86_64, false); - if (S == "elf64-littleaarch64") - return std::make_tuple(ELF64LEKind, EM_AARCH64, false); - if (S == "elf64-powerpc") - return std::make_tuple(ELF64BEKind, EM_PPC64, false); - if (S == "elf64-powerpcle") - return std::make_tuple(ELF64LEKind, EM_PPC64, false); - if (S == "elf64-x86-64") - return std::make_tuple(ELF64LEKind, EM_X86_64, false); - if (S == "elf32-tradbigmips") - return std::make_tuple(ELF32BEKind, EM_MIPS, false); - if (S == "elf32-ntradbigmips") - return std::make_tuple(ELF32BEKind, EM_MIPS, true); - if (S == "elf32-tradlittlemips") - return std::make_tuple(ELF32LEKind, EM_MIPS, false); - if (S == "elf32-ntradlittlemips") - return std::make_tuple(ELF32LEKind, EM_MIPS, true); - if (S == "elf64-tradbigmips") - return std::make_tuple(ELF64BEKind, EM_MIPS, false); - if (S == "elf64-tradlittlemips") - return std::make_tuple(ELF64LEKind, EM_MIPS, false); - - setError("unknown output format name: " + S); - return std::make_tuple(ELFNoneKind, EM_NONE, false); +static std::pair parseBfdName(StringRef S) { + return StringSwitch>(S) + .Case("elf32-i386", {ELF32LEKind, EM_386}) + .Case("elf32-iamcu", {ELF32LEKind, EM_IAMCU}) + .Case("elf32-littlearm", {ELF32LEKind, EM_ARM}) + .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64}) + .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64}) + .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64}) + .Case("elf32-powerpc", {ELF32BEKind, EM_PPC}) + .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64}) + .Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64}) + .Case("elf64-x86-64", {ELF64LEKind, EM_X86_64}) + .Cases("elf32-tradbigmips", "elf32-bigmips", {ELF32BEKind, EM_MIPS}) + .Case("elf32-ntradbigmips", {ELF32BEKind, EM_MIPS}) + .Case("elf32-tradlittlemips", {ELF32LEKind, EM_MIPS}) + .Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS}) + .Case("elf64-tradbigmips", {ELF64BEKind, EM_MIPS}) + .Case("elf64-tradlittlemips", {ELF64LEKind, EM_MIPS}) + .Default({ELFNoneKind, EM_NONE}); } // Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(bfdname, big, little). @@ -425,9 +410,16 @@ std::tuple ScriptParser::readBfdName() { void ScriptParser::readOutputFormat() { expect("("); - std::tuple BfdTuple = readBfdName(); - if (Config->EKind == ELFNoneKind) - std::tie(Config->EKind, Config->EMachine, Config->MipsN32Abi) = BfdTuple; + StringRef Name = unquote(next()); + StringRef S = Name; + if (S.consume_back("-freebsd")) + Config->OSABI = ELFOSABI_FREEBSD; + + std::tie(Config->EKind, Config->EMachine) = parseBfdName(S); + if (Config->EMachine == EM_NONE) + setError("unknown output format name: " + Name); + if (S == "elf32-ntradlittlemips" || S == "elf32-ntradbigmips") + Config->MipsN32Abi = true; if (consume(")")) return; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index f459c1b6b4792..10675588ebe2e 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1513,8 +1513,10 @@ void RelocationBaseSection::finalizeContents() { else getParent()->Link = 0; - if (In.RelaIplt == this || In.RelaPlt == this) + if (In.RelaPlt == this) getParent()->Info = In.GotPlt->getParent()->SectionIndex; + if (In.RelaIplt == this) + getParent()->Info = In.IgotPlt->getParent()->SectionIndex; } RelrBaseSection::RelrBaseSection() @@ -1999,6 +2001,11 @@ template void SymbolTableSection::writeTo(uint8_t *Buf) { ESym->setVisibility(Sym->Visibility); } + // The 3 most significant bits of st_other are used by OpenPOWER ABI. + // See getPPC64GlobalEntryToLocalEntryOffset() for more details. + if (Config->EMachine == EM_PPC64) + ESym->st_other |= Sym->StOther & 0xe0; + ESym->st_name = Ent.StrTabOffset; ESym->st_shndx = getSymSectionIndex(Ent.Sym); diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp index 95b57dc0db426..7a31d36b0e902 100644 --- a/lld/ELF/Thunks.cpp +++ b/lld/ELF/Thunks.cpp @@ -722,7 +722,7 @@ Thunk::~Thunk() = default; static Thunk *addThunkAArch64(RelType Type, Symbol &S) { if (Type != R_AARCH64_CALL26 && Type != R_AARCH64_JUMP26) fatal("unrecognized relocation type"); - if (Config->Pic) + if (Config->PicThunk) return make(S); return make(S); } @@ -739,7 +739,7 @@ static Thunk *addThunkPreArmv7(RelType Reloc, Symbol &S) { case R_ARM_JUMP24: case R_ARM_CALL: case R_ARM_THM_CALL: - if (Config->Pic) + if (Config->PicThunk) return make(S); return make(S); } @@ -794,13 +794,13 @@ static Thunk *addThunkArm(RelType Reloc, Symbol &S) { case R_ARM_PLT32: case R_ARM_JUMP24: case R_ARM_CALL: - if (Config->Pic) + if (Config->PicThunk) return make(S); return make(S); case R_ARM_THM_JUMP19: case R_ARM_THM_JUMP24: case R_ARM_THM_CALL: - if (Config->Pic) + if (Config->PicThunk) return make(S); return make(S); } @@ -820,7 +820,7 @@ static Thunk *addThunkPPC64(RelType Type, Symbol &S) { if (S.isInPlt()) return make(S); - if (Config->Pic) + if (Config->PicThunk) return make(S); return make(S); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 17f4c7961d30e..36ba025326388 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -547,6 +547,11 @@ static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName, if (Config->Discard == DiscardPolicy::None) return true; + // If -emit-reloc is given, all symbols including local ones need to be + // copied because they may be referenced by relocations. + if (Config->EmitRelocs) + return true; + // In ELF assembly .L symbols are normally discarded by the assembler. // If the assembler fails to do so, the linker discards them if // * --discard-locals is used. @@ -2192,17 +2197,6 @@ template void Writer::setPhdrs() { } if (P->p_type == PT_TLS && P->p_memsz) { - if (!Config->Shared && - (Config->EMachine == EM_ARM || Config->EMachine == EM_AARCH64)) { - // On ARM/AArch64, reserve extra space (8 words) between the thread - // pointer and an executable's TLS segment by overaligning the segment. - // This reservation is needed for backwards compatibility with Android's - // TCB, which allocates several slots after the thread pointer (e.g. - // TLS_SLOT_STACK_GUARD==5). For simplicity, this overalignment is also - // done on other operating systems. - P->p_align = std::max(P->p_align, Config->Wordsize * 8); - } - // The TLS pointer goes after PT_TLS for variant 2 targets. At least glibc // will align it, so round up the size to make sure the offsets are // correct. diff --git a/lld/MinGW/Options.td b/lld/MinGW/Options.td index 948faa6875211..0cda2447e5223 100644 --- a/lld/MinGW/Options.td +++ b/lld/MinGW/Options.td @@ -78,3 +78,9 @@ def version: F<"version">, HelpText<"Display the version number and exit">; def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias; def alias_strip_s: Flag<["-"], "s">, Alias; def alias_strip_S: Flag<["-"], "S">, Alias; + +// Ignored options +def: S<"plugin">; +def: J<"plugin=">; +def: S<"plugin-opt">; +def: J<"plugin-opt=">; diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index dc5df6795d993..aab52573d925a 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -5,18 +5,15 @@ lld 8.0.0 Release Notes .. contents:: :local: -.. warning:: - These are in-progress notes for the upcoming LLVM 8.0.0 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ -This document contains the release notes for the lld linker, release 8.0.0. -Here we describe the status of lld, including major improvements -from the previous release. All lld releases may be downloaded -from the `LLVM releases web site `_. +lld is a high-performance linker that supports ELF (Unix), COFF (Windows), +Mach-O (macOS), MinGW and WebAssembly. lld is command-line-compatible with +GNU linkers and Microsoft link.exe and is significantly faster than the +system default linkers. + +lld 8.0.0 has lots of feature improvements and bug fixes. Non-comprehensive list of changes in this release ================================================= @@ -33,12 +30,35 @@ ELF Improvements non-superpages to a superpage if they are aligned to the superpage size. (`r342746 `_) +* lld now attempts to place a ``.note`` segment in the first page of a + generated file, so that you can find some important information + (``.note.gnu.build-id`` in particular) in a core file even if a core + file is truncated by ulimit. + (`r349524 `_) + +* lld now reports an error if ``_GLOBAL_OFFSET_TABLE_`` symbol is + defined by an input object file, as the symbol is supposed to be + synthesized by the linker. + (`r347854 `_) + * lld/Hexagon can now link Linux kernel and musl libc for Qualcomm Hexagon ISA. * Initial MSP430 ISA support has landed. -* The following flags have been added: ``-z interpose``, ``-z global`` +* lld now uses the ``sigrie`` instruction as a trap instruction for + MIPS targets. + +* lld now creates a TLS segment for AArch64 with a slightly larger + alignment requirement, so that the loader makes a few bytes room + before each TLS segment at runtime. The aim of this change is to + make room to accomodate nonstandard Android TLS slots while keeping + the compatibility with the standard AArch64 ABI. + (`r350681 `_) + +* The following flags have been added: ``--call-graph-profile``, + ``--no-call-graph-profile``, ``--warn-ifunc-textrel``, + ``-z interpose``, ``-z global``, ``-z nodefaultlib`` COFF Improvements ----------------- @@ -46,11 +66,30 @@ COFF Improvements * PDB GUID is set to hash of PDB contents instead to a random byte sequence for build reproducibility. +* ``/pdbsourcepath:`` is now also used to make ``"cwd"``, ``"exe"``, ``"pdb"`` + in the env block of PDB outputs absolute if they are relative, and to make + paths to obj files referenced in PDB outputs absolute if they are relative. + Together with the previous item, this makes it possible to generate + executables and PDBs that are fully deterministic and independent of the + absolute path to the build directory, so that different machines building + the same code in different directories can produce exactly the same output. + * The following flags have been added: ``/force:multiple`` * lld now can link against import libraries produced by GNU tools. -* lld can create thunks for ARM, to allow linking images over 16 MB. +* lld can create thunks for ARM and ARM64, to allow linking larger images + (over 16 MB for ARM and over 128 MB for ARM64) + +* Several speed and memory usage improvements. + +* lld now creates debug info for typedefs. + +* lld can now link obj files produced by ``cl.exe /Z7 /Yc``. + +* lld now understands ``%_PDB%`` and ``%_EXT%`` in ``/pdbaltpath:``. + +* Undefined symbols are now printed in demangled form in addition to raw form. MinGW Improvements ------------------ @@ -66,10 +105,12 @@ MinGW Improvements linked in a different order than with GNU ld, inserting a DWARF exception table terminator too early.) -MachO Improvements ------------------- +* lld now supports COFF embedded directives for linking to nondefault + libraries, just like for the normal COFF target. -* Item 1. +* Actually generate a codeview build id signature, even if not creating a PDB. + Previously, the ``--build-id`` option did not actually generate a build id + unless ``--pdb`` was specified. WebAssembly Improvements ------------------------ diff --git a/lld/docs/index.rst b/lld/docs/index.rst index da1c894f3d833..2564e9b6310fd 100644 --- a/lld/docs/index.rst +++ b/lld/docs/index.rst @@ -173,4 +173,5 @@ document soon. AtomLLD WebAssembly windows_support + missingkeyfunction ReleaseNotes diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 index d1ce4a3517f4d..889d5feabe4d1 100644 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -311,6 +311,8 @@ Write optimization remarks in YAML format to .Ar file . .It Fl -opt-remarks-with-hotness Include hotness information in the optimization remarks file. +.It Fl -pic-veneer +Always generate position independent thunks. .It Fl -pie Create a position independent executable. .It Fl -print-gc-sections diff --git a/lld/docs/missingkeyfunction.rst b/lld/docs/missingkeyfunction.rst index 410c749c3b036..54ad3251f794e 100644 --- a/lld/docs/missingkeyfunction.rst +++ b/lld/docs/missingkeyfunction.rst @@ -1,5 +1,5 @@ -Missing Key Method -================== +Missing Key Function +==================== If your build failed with a linker error something like this:: diff --git a/lld/test/COFF/arm-thumb-thunks-pdb.s b/lld/test/COFF/arm-thumb-thunks-pdb.s new file mode 100644 index 0000000000000..9e972a78d37ff --- /dev/null +++ b/lld/test/COFF/arm-thumb-thunks-pdb.s @@ -0,0 +1,18 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -triple=thumbv7-windows %s -o %t.obj +// RUN: lld-link -entry:main -subsystem:console %t.obj -out:%t.exe -debug -pdb:%t.pdb -verbose 2>&1 | FileCheck %s --check-prefix=VERBOSE + +// VERBOSE: Added 1 thunks with margin {{.*}} in {{.*}} passes + + .syntax unified + .globl main + .globl func1 + .text +main: + bne func1 + bx lr + .section .text$a, "xr" + .space 0x100000 + .section .text$b, "xr" +func1: + bx lr diff --git a/lld/test/COFF/arm64-branch-range.test b/lld/test/COFF/arm64-branch-range.test deleted file mode 100644 index 0b581e9c464dc..0000000000000 --- a/lld/test/COFF/arm64-branch-range.test +++ /dev/null @@ -1,16 +0,0 @@ -// REQUIRES: aarch64 - -// RUN: echo -e '.globl _start\n _start:\n bl too_far26\n' > %t.main26.s -// RUN: echo -e '.globl _start\n _start:\n b.ne too_far19\n' > %t.main19.s -// RUN: echo -e '.globl _start\n _start:\n tbz x0, #0, too_far14\n' > %t.main14.s - -// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %t.main26.s -o %t.main26.obj -// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %t.main19.s -o %t.main19.obj -// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %t.main14.s -o %t.main14.obj -// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/far-arm64-abs.s -o %t.far.obj - -// RUN: not lld-link -base:0x10000 -entry:_start -subsystem:console %t.main26.obj %t.far.obj -out:%t.exe 2>&1 | FileCheck %s -// RUN: not lld-link -base:0x10000 -entry:_start -subsystem:console %t.main19.obj %t.far.obj -out:%t.exe 2>&1 | FileCheck %s -// RUN: not lld-link -base:0x10000 -entry:_start -subsystem:console %t.main14.obj %t.far.obj -out:%t.exe 2>&1 | FileCheck %s - -// CHECK: relocation out of range diff --git a/lld/test/COFF/arm64-thunks.s b/lld/test/COFF/arm64-thunks.s new file mode 100644 index 0000000000000..49004544c4389 --- /dev/null +++ b/lld/test/COFF/arm64-thunks.s @@ -0,0 +1,27 @@ +// REQUIRES: aarch64 +// RUN: llvm-mc -filetype=obj -triple=aarch64-windows %s -o %t.obj +// RUN: lld-link -entry:main -subsystem:console %t.obj -out:%t.exe -verbose 2>&1 | FileCheck -check-prefix=VERBOSE %s +// RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s + +// VERBOSE: Added 1 thunks with margin {{.*}} in 1 passes + + .globl main + .globl func1 + .text +main: + tbz w0, #0, func1 + ret + .section .text$a, "xr" + .space 0x8000 + .section .text$b, "xr" +func1: + ret + +// DISASM: 0000000140001000 .text: +// DISASM: 140001000: 40 00 00 36 tbz w0, #0, #8 <.text+0x8> +// DISASM: 140001004: c0 03 5f d6 ret +// DISASM: 140001008: 50 00 00 90 adrp x16, #32768 +// DISASM: 14000100c: 10 52 00 91 add x16, x16, #20 +// DISASM: 140001010: 00 02 1f d6 br x16 + +// DISASM: 140009014: c0 03 5f d6 ret diff --git a/lld/test/COFF/guardcf-thunk.s b/lld/test/COFF/guardcf-thunk.s new file mode 100644 index 0000000000000..0969c580ac9f6 --- /dev/null +++ b/lld/test/COFF/guardcf-thunk.s @@ -0,0 +1,43 @@ +# REQUIRES: x86 + +# Make a DLL that exports exportfn1. +# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj +# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /implib:%t.lib + +# Make an obj that takes the address of that exported function. +# RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc %s -o %t2.obj +# RUN: lld-link -entry:main -guard:cf %t2.obj %t.lib -nodefaultlib -out:%t.exe +# RUN: llvm-readobj -coff-load-config %t.exe | FileCheck %s + +# Check that the gfids table contains *exactly* two entries, one for exportfn1 +# and one for main. +# CHECK: GuardFidTable [ +# CHECK-NEXT: 0x{{[0-9A-Fa-f]+0$}} +# CHECK-NEXT: 0x{{[0-9A-Fa-f]+0$}} +# CHECK-NEXT: ] + + + .def @feat.00; + .scl 3; + .type 0; + .endef + .globl @feat.00 +@feat.00 = 0x001 + + .section .text,"rx" + .def main; .scl 2; .type 32; .endef + .global main +main: + leaq exportfn1(%rip), %rax + retq + + .section .rdata,"dr" +.globl _load_config_used +_load_config_used: + .long 256 + .fill 124, 1, 0 + .quad __guard_fids_table + .quad __guard_fids_count + .long __guard_flags + .fill 128, 1, 0 + diff --git a/lld/test/COFF/imports.test b/lld/test/COFF/imports.test index 64f3900a1c2f3..f54bdfd88dfab 100644 --- a/lld/test/COFF/imports.test +++ b/lld/test/COFF/imports.test @@ -34,3 +34,16 @@ IMPORT-NEXT: Symbol: ExitProcess (0) IMPORT-NEXT: Symbol: (50) IMPORT-NEXT: Symbol: MessageBoxA (1) IMPORT-NEXT: } + +# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /merge:.rdata=.text \ +# RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib /include:ExitProcess +# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=MERGE %s + +MERGE: Import { +MERGE-NEXT: Name: std64.dll +MERGE-NEXT: ImportLookupTableRVA: 0x1090 +MERGE-NEXT: ImportAddressTableRVA: 0x10B0 +MERGE-NEXT: Symbol: ExitProcess (0) +MERGE-NEXT: Symbol: (50) +MERGE-NEXT: Symbol: MessageBoxA (1) +MERGE-NEXT: } diff --git a/lld/test/COFF/pdb-relative-source-lines.test b/lld/test/COFF/pdb-relative-source-lines.test index 865d7a6d8a0a4..547056785962a 100644 --- a/lld/test/COFF/pdb-relative-source-lines.test +++ b/lld/test/COFF/pdb-relative-source-lines.test @@ -37,26 +37,26 @@ RUN: llvm-pdbutil pdb2yaml -modules -module-files -module-syms -subsections=line RUN: ./lld-link -debug "-pdbsourcepath:/usr/src" -entry:main -nodefaultlib -out:out.exe -pdb:out.pdb pdb_lines_1_relative.obj pdb_lines_2_relative.obj RUN: llvm-pdbutil pdb2yaml -modules -module-files -module-syms -subsections=lines,fc %t/out.pdb | FileCheck --check-prefix=POSIX %s -CHECK-LABEL: - Module: 'c:\src{{[\\/]}}pdb_lines_1_relative.obj' -CHECK-NEXT: ObjFile: 'c:\src{{[\\/]}}pdb_lines_1_relative.obj' +CHECK-LABEL: - Module: 'c:\src\pdb_lines_1_relative.obj' +CHECK-NEXT: ObjFile: 'c:\src\pdb_lines_1_relative.obj' CHECK: SourceFiles: -CHECK-NEXT: - 'c:\src{{[\\/]}}pdb_lines_1.c' -CHECK-NEXT: - 'c:\src{{[\\/]}}foo.h' +CHECK-NEXT: - 'c:\src\pdb_lines_1.c' +CHECK-NEXT: - 'c:\src\foo.h' CHECK: Subsections: -CHECK: - FileName: 'c:\src{{[\\/]}}pdb_lines_1.c' -CHECK: - FileName: 'c:\src{{[\\/]}}foo.h' +CHECK: - FileName: 'c:\src\pdb_lines_1.c' +CHECK: - FileName: 'c:\src\foo.h' CHECK: - !FileChecksums -CHECK: - FileName: 'c:\src{{[\\/]}}pdb_lines_1.c' -CHECK: - FileName: 'c:\src{{[\\/]}}foo.h' +CHECK: - FileName: 'c:\src\pdb_lines_1.c' +CHECK: - FileName: 'c:\src\foo.h' -CHECK-LABEL: - Module: 'c:\src{{[\\/]}}pdb_lines_2_relative.obj' -CHECK-NEXT: ObjFile: 'c:\src{{[\\/]}}pdb_lines_2_relative.obj' +CHECK-LABEL: - Module: 'c:\src\pdb_lines_2_relative.obj' +CHECK-NEXT: ObjFile: 'c:\src\pdb_lines_2_relative.obj' CHECK: SourceFiles: -CHECK-NEXT: - 'c:\src{{[\\/]}}pdb_lines_2.c' +CHECK-NEXT: - 'c:\src\pdb_lines_2.c' CHECK: Subsections: -CHECK: - FileName: 'c:\src{{[\\/]}}pdb_lines_2.c' +CHECK: - FileName: 'c:\src\pdb_lines_2.c' CHECK: - !FileChecksums -CHECK: - FileName: 'c:\src{{[\\/]}}pdb_lines_2.c' +CHECK: - FileName: 'c:\src\pdb_lines_2.c' CHECK-LABEL: - Kind: S_ENVBLOCK CHECK-NEXT: EnvBlockSym: @@ -64,33 +64,33 @@ CHECK-NEXT: Entries: CHECK-NEXT: - cwd CHECK-NEXT: - 'c:\src' CHECK-NEXT: - exe -CHECK-NEXT: - 'c:\src{{[\\/]}}lld-link' +CHECK-NEXT: - 'c:\src\lld-link' CHECK-NEXT: - pdb -CHECK-NEXT: - 'c:\src{{[\\/]}}out.pdb' +CHECK-NEXT: - 'c:\src\out.pdb' CHECK-NEXT: - cmd CHECK-NEXT: - '-debug -pdbsourcepath:c:\src -entry:main -nodefaultlib -out:out.exe -pdb:out.pdb pdb_lines_1_relative.obj pdb_lines_2_relative.obj' -POSIX-LABEL: - Module: '/usr/src{{[\\/]}}pdb_lines_1_relative.obj' -POSIX-NEXT: ObjFile: '/usr/src{{[\\/]}}pdb_lines_1_relative.obj' +POSIX-LABEL: - Module: '/usr/src/pdb_lines_1_relative.obj' +POSIX-NEXT: ObjFile: '/usr/src/pdb_lines_1_relative.obj' POSIX: SourceFiles: -POSIX-NEXT: - '/usr/src{{[\\/]}}pdb_lines_1.c' -POSIX-NEXT: - '/usr/src{{[\\/]}}foo.h' +POSIX-NEXT: - '/usr/src/pdb_lines_1.c' +POSIX-NEXT: - '/usr/src/foo.h' POSIX: Subsections: -POSIX: - FileName: '/usr/src{{[\\/]}}pdb_lines_1.c' -POSIX: - FileName: '/usr/src{{[\\/]}}foo.h' +POSIX: - FileName: '/usr/src/pdb_lines_1.c' +POSIX: - FileName: '/usr/src/foo.h' POSIX: - !FileChecksums -POSIX: - FileName: '/usr/src{{[\\/]}}pdb_lines_1.c' -POSIX: - FileName: '/usr/src{{[\\/]}}foo.h' +POSIX: - FileName: '/usr/src/pdb_lines_1.c' +POSIX: - FileName: '/usr/src/foo.h' -POSIX-LABEL: - Module: '/usr/src{{[\\/]}}pdb_lines_2_relative.obj' -POSIX-NEXT: ObjFile: '/usr/src{{[\\/]}}pdb_lines_2_relative.obj' +POSIX-LABEL: - Module: '/usr/src/pdb_lines_2_relative.obj' +POSIX-NEXT: ObjFile: '/usr/src/pdb_lines_2_relative.obj' POSIX: SourceFiles: -POSIX-NEXT: - '/usr/src{{[\\/]}}pdb_lines_2.c' +POSIX-NEXT: - '/usr/src/pdb_lines_2.c' POSIX: Subsections: -POSIX: - FileName: '/usr/src{{[\\/]}}pdb_lines_2.c' +POSIX: - FileName: '/usr/src/pdb_lines_2.c' POSIX: - !FileChecksums -POSIX: - FileName: '/usr/src{{[\\/]}}pdb_lines_2.c' +POSIX: - FileName: '/usr/src/pdb_lines_2.c' POSIX-LABEL: - Kind: S_ENVBLOCK POSIX-NEXT: EnvBlockSym: @@ -98,8 +98,8 @@ POSIX-NEXT: Entries: POSIX-NEXT: - cwd POSIX-NEXT: - '/usr/src' POSIX-NEXT: - exe -POSIX-NEXT: - '/usr/src{{[\\/]}}lld-link' +POSIX-NEXT: - '/usr/src/lld-link' POSIX-NEXT: - pdb -POSIX-NEXT: - '/usr/src{{[\\/]}}out.pdb' +POSIX-NEXT: - '/usr/src/out.pdb' POSIX-NEXT: - cmd POSIX-NEXT: - '-debug -pdbsourcepath:/usr/src -entry:main -nodefaultlib -out:out.exe -pdb:out.pdb pdb_lines_1_relative.obj pdb_lines_2_relative.obj' diff --git a/lld/test/ELF/aarch64-cortex-a53-843419-tlsrelax.s b/lld/test/ELF/aarch64-cortex-a53-843419-tlsrelax.s index 2db5c7e36bbce..bff72d3725f4c 100644 --- a/lld/test/ELF/aarch64-cortex-a53-843419-tlsrelax.s +++ b/lld/test/ELF/aarch64-cortex-a53-843419-tlsrelax.s @@ -26,9 +26,9 @@ _start: // CHECK: _start: // CHECK-NEXT: 210ff8: 41 d0 3b d5 mrs x1, TPIDR_EL0 // CHECK-NEXT: 210ffc: 00 00 a0 d2 movz x0, #0, lsl #16 -// CHECK-NEXT: 211000: 01 08 80 f2 movk x1, #64 +// CHECK-NEXT: 211000: 01 02 80 f2 movk x1, #16 // CHECK-NEXT: 211004: 00 00 a0 d2 movz x0, #0, lsl #16 -// CHECK-NEXT: 211008: 01 08 80 f2 movk x1, #64 +// CHECK-NEXT: 211008: 01 02 80 f2 movk x1, #16 // CHECK-NEXT: 21100c: c0 03 5f d6 ret .type v,@object diff --git a/lld/test/ELF/aarch64-gnu-ifunc-address-pie.s b/lld/test/ELF/aarch64-gnu-ifunc-address-pie.s new file mode 100644 index 0000000000000..3db9070dbd07b --- /dev/null +++ b/lld/test/ELF/aarch64-gnu-ifunc-address-pie.s @@ -0,0 +1,44 @@ +# REQUIRES: aarch64 +# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o +# RUN: ld.lld -pie %t.o -o %tout +# RUN: llvm-objdump -D %tout | FileCheck %s +# RUN: llvm-readobj -r %tout | FileCheck %s -check-prefix=CHECK-RELOCS + +# Test that when we take the address of a preemptible ifunc using -fpie, we can +# handle the case when the ifunc is in the same translation unit as the address +# taker. In this case the compiler knows that ifunc is not defined in a shared +# library so it can use a non got generating relative reference. +.text +.globl myfunc +.type myfunc,@gnu_indirect_function +myfunc: + ret + +.text +.globl main +.type main,@function +main: + adrp x8, myfunc + add x8, x8, :lo12: myfunc + ret + +# CHECK: 0000000000010000 myfunc: +# CHECK-NEXT: 10000: c0 03 5f d6 ret +# CHECK: 0000000000010004 main: +# CHECK-NEXT: 10004: 08 00 00 90 adrp x8, #0 +# x8 = 0x10000 +# CHECK-NEXT: 10008: 08 41 00 91 add x8, x8, #16 +# x8 = 0x10010 = .plt for myfunc +# CHECK-NEXT: 1000c: c0 03 5f d6 ret +# CHECK-NEXT: Disassembly of section .plt: +# CHECK-NEXT: 0000000000010010 .plt: +# CHECK-NEXT: 10010: 90 00 00 90 adrp x16, #65536 +# CHECK-NEXT: 10014: 11 02 40 f9 ldr x17, [x16] +# CHECK-NEXT: 10018: 10 02 00 91 add x16, x16, #0 +# CHECK-NEXT: 1001c: 20 02 1f d6 br x17 + +# CHECK-RELOCS: Relocations [ +# CHECK-RELOCS-NEXT: Section {{.*}} .rela.plt { +# CHECK-RELOCS-NEXT: 0x20000 R_AARCH64_IRELATIVE - 0x10000 +# CHECK-RELOCS-NEXT: } +# CHECK-RELOCS-NEXT: ] diff --git a/lld/test/ELF/aarch64-tls-gdle.s b/lld/test/ELF/aarch64-tls-gdle.s index 882ec8c1ae176..19fdc1d35c5d5 100644 --- a/lld/test/ELF/aarch64-tls-gdle.s +++ b/lld/test/ELF/aarch64-tls-gdle.s @@ -9,11 +9,11 @@ #RELOC: Relocations [ #RELOC-NEXT: ] -# TCB size = 64 and foo is first element from TLS register. +# TCB size = 0x16 and foo is first element from TLS register. # CHECK: Disassembly of section .text: # CHECK: _start: # CHECK: 210000: 00 00 a0 d2 movz x0, #0, lsl #16 -# CHECK: 210004: 00 08 80 f2 movk x0, #64 +# CHECK: 210004: 00 02 80 f2 movk x0, #16 # CHECK: 210008: 1f 20 03 d5 nop # CHECK: 21000c: 1f 20 03 d5 nop diff --git a/lld/test/ELF/aarch64-tls-iele.s b/lld/test/ELF/aarch64-tls-iele.s index 0229d6676cd59..9fec4ee7dc92a 100644 --- a/lld/test/ELF/aarch64-tls-iele.s +++ b/lld/test/ELF/aarch64-tls-iele.s @@ -9,13 +9,13 @@ # RELOC: Relocations [ # RELOC-NEXT: ] -# TCB size = 64 and foo is first element from TLS register. +# TCB size = 0x16 and foo is first element from TLS register. # CHECK: Disassembly of section .text: # CHECK: _start: # CHECK-NEXT: 210000: 00 00 a0 d2 movz x0, #0, lsl #16 -# CHECK-NEXT: 210004: 80 08 80 f2 movk x0, #68 +# CHECK-NEXT: 210004: 80 02 80 f2 movk x0, #20 # CHECK-NEXT: 210008: 00 00 a0 d2 movz x0, #0, lsl #16 -# CHECK-NEXT: 21000c: 00 08 80 f2 movk x0, #64 +# CHECK-NEXT: 21000c: 00 02 80 f2 movk x0, #16 .section .tdata .align 2 diff --git a/lld/test/ELF/aarch64-tls-le.s b/lld/test/ELF/aarch64-tls-le.s index 49c322facb128..eda1375865626 100644 --- a/lld/test/ELF/aarch64-tls-le.s +++ b/lld/test/ELF/aarch64-tls-le.s @@ -17,12 +17,12 @@ _start: add x0, x0, :tprel_hi12:v2 add x0, x0, :tprel_lo12_nc:v2 -# TCB size = 64 and foo is first element from TLS register. +# TCB size = 0x16 and foo is first element from TLS register. #CHECK: Disassembly of section .text: #CHECK: _start: #CHECK: 210000: 40 d0 3b d5 mrs x0, TPIDR_EL0 #CHECK: 210004: 00 00 40 91 add x0, x0, #0, lsl #12 -#CHECK: 210008: 00 00 01 91 add x0, x0, #64 +#CHECK: 210008: 00 40 00 91 add x0, x0, #16 #CHECK: 21000c: 40 d0 3b d5 mrs x0, TPIDR_EL0 #CHECK: 210010: 00 fc 7f 91 add x0, x0, #4095, lsl #12 #CHECK: 210014: 00 e0 3f 91 add x0, x0, #4088 @@ -36,9 +36,9 @@ v1: .word 0 .size v1, 4 -# The current offset from the thread pointer is 68. Raise it to just below the +# The current offset from the thread pointer is 20. Raise it to just below the # 24-bit limit. -.space (0xfffff8 - 68) +.space (0xfffff8 - 20) .type v2,@object .globl v2 diff --git a/lld/test/ELF/aarch64-tlsld-ldst.s b/lld/test/ELF/aarch64-tlsld-ldst.s index 8ebdc2f152a6c..3144ca5d99afd 100644 --- a/lld/test/ELF/aarch64-tlsld-ldst.s +++ b/lld/test/ELF/aarch64-tlsld-ldst.s @@ -26,27 +26,27 @@ _start: mrs x8, TPIDR_EL0 // CHECK: _start: // CHECK-NEXT: 210000: 48 d0 3b d5 mrs x8, TPIDR_EL0 -// 0x0 + c40 = 0xc40 = tcb (64-bytes) + var0 -// CHECK-NEXT: 210004: 08 01 40 91 add x8, x8, #0, lsl #12 -// CHECK-NEXT: 210008: 14 11 c3 3d ldr q20, [x8, #3136] -// 0x1000 + 0x850 = 0x1850 = tcb + var1 -// CHECK-NEXT: 21000c: 08 05 40 91 add x8, x8, #1, lsl #12 -// CHECK-NEXT: 210010: 00 29 44 f9 ldr x0, [x8, #2128] -// 0x2000 + 0x458 = 0x2458 = tcb + var2 -// CHECK-NEXT: 210014: 08 09 40 91 add x8, x8, #2, lsl #12 -// CHECK-NEXT: 210018: 00 59 44 b9 ldr w0, [x8, #1112] -// 0x3000 + 0x5c = 0x305c = tcb + var3 -// CHECK-NEXT: 21001c: 08 0d 40 91 add x8, x8, #3, lsl #12 -// CHECK-NEXT: 210020: 00 b9 40 79 ldrh w0, [x8, #92] -// 0x3000 + 0xc5e = 0x3c5e = tcb + var4 -// CHECK-NEXT: 210024: 08 0d 40 91 add x8, x8, #3, lsl #12 -// CHECK-NEXT: 210028: 00 79 71 39 ldrb w0, [x8, #3166] +// 0x0 + c10 = 0xc10 = tcb (16-bytes) + var0 +// CHECK-NEXT: 210004: 08 01 40 91 add x8, x8, #0, lsl #12 +// CHECK-NEXT: 210008: 14 05 c3 3d ldr q20, [x8, #3088] +// 0x1000 + 0x820 = 0x1820 = tcb + var1 +// CHECK-NEXT: 21000c: 08 05 40 91 add x8, x8, #1, lsl #12 +// CHECK-NEXT: 210010: 00 11 44 f9 ldr x0, [x8, #2080] +// 0x2000 + 0x428 = 0x2428 = tcb + var2 +// CHECK-NEXT: 210014: 08 09 40 91 add x8, x8, #2, lsl #12 +// CHECK-NEXT: 210018: 00 29 44 b9 ldr w0, [x8, #1064] +// 0x3000 + 0x2c = 0x302c = tcb + var3 +// CHECK-NEXT: 21001c: 08 0d 40 91 add x8, x8, #3, lsl #12 +// CHECK-NEXT: 210020: 00 59 40 79 ldrh w0, [x8, #44] +// 0x3000 + 0xc2e = 0x32ce = tcb + var4 +// CHECK-NEXT: 210024: 08 0d 40 91 add x8, x8, #3, lsl #12 +// CHECK-NEXT: 210028: 00 b9 70 39 ldrb w0, [x8, #3118] -// CHECK-SYMS: 0000000000000c00 16 TLS GLOBAL DEFAULT 2 var0 -// CHECK-SYMS-NEXT: 0000000000001810 8 TLS GLOBAL DEFAULT 2 var1 -// CHECK-SYMS-NEXT: 0000000000002418 4 TLS GLOBAL DEFAULT 2 var2 -// CHECK-SYMS-NEXT: 000000000000301c 2 TLS GLOBAL DEFAULT 2 var3 -// CHECK-SYMS-NEXT: 0000000000003c1e 1 TLS GLOBAL DEFAULT 2 var4 +// CHECK-SYMS: 0000000000000c00 0 TLS GLOBAL DEFAULT 2 var0 +// CHECK-SYMS-NEXT: 0000000000001810 4 TLS GLOBAL DEFAULT 2 var1 +// CHECK-SYMS-NEXT: 0000000000002418 2 TLS GLOBAL DEFAULT 2 var2 +// CHECK-SYMS-NEXT: 000000000000301c 1 TLS GLOBAL DEFAULT 2 var3 +// CHECK-SYMS-NEXT: 0000000000003c1e 0 TLS GLOBAL DEFAULT 2 var4 .globl var0 .globl var1 @@ -59,12 +59,12 @@ _start: mrs x8, TPIDR_EL0 .type var3,@object .section .tbss,"awT",@nobits - .balign 64 + .balign 16 .space 1024 * 3 var0: .quad 0 .quad 0 - .size var0, 16 + .size var1, 16 .space 1024 * 3 var1: .quad 0 @@ -72,14 +72,14 @@ var1: .space 1024 * 3 var2: .word 0 - .size var2, 4 + .size var1, 4 .space 1024 * 3 var3: .hword 0 - .size var3, 2 + .size var2, 2 .space 1024 * 3 var4: .byte 0 - .size var4, 1 + .size var3, 1 .space 1024 * 3 diff --git a/lld/test/ELF/arm-force-pi-thunk.s b/lld/test/ELF/arm-force-pi-thunk.s new file mode 100644 index 0000000000000..2c88de0424ee5 --- /dev/null +++ b/lld/test/ELF/arm-force-pi-thunk.s @@ -0,0 +1,87 @@ +// REQUIRES: arm +// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: echo "SECTIONS { \ +// RUN: . = SIZEOF_HEADERS; \ +// RUN: .text_low : { *(.text_low) *(.text_low2) } \ +// RUN: .text_high 0x2000000 : { *(.text_high) *(.text_high2) } \ +// RUN: } " > %t.script +// RUN: ld.lld --pic-veneer --script %t.script %t -o %t2 2>&1 +// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck %s + +// Test that we can force generation of position independent thunks even when +// inputs are not pic. + + .syntax unified + .section .text_low, "ax", %progbits + .thumb + .globl _start +_start: bx lr + .globl low_target + .type low_target, %function +low_target: + bl high_target + bl high_target2 + + .section .text_low2, "ax", %progbits + .thumb + .globl low_target2 + .type low_target2, %function +low_target2: + bl high_target + bl high_target2 + +// CHECK: Disassembly of section .text_low: +// CHECK-NEXT: _start: +// CHECK-NEXT: 94: 70 47 bx lr +// CHECK: low_target: +// CHECK-NEXT: 96: 00 f0 03 f8 bl #6 +// CHECK-NEXT: 9a: 00 f0 07 f8 bl #14 +// CHECK-NEXT: 9e: d4 d4 bmi #-88 +// CHECK: __ThumbV7PILongThunk_high_target: +// CHECK-NEXT: a0: 4f f6 55 7c movw r12, #65365 +// CHECK-NEXT: a4: c0 f2 ff 1c movt r12, #511 +// CHECK-NEXT: a8: fc 44 add r12, pc +// CHECK-NEXT: aa: 60 47 bx r12 +// CHECK: __ThumbV7PILongThunk_high_target2: +// CHECK-NEXT: ac: 4f f6 69 7c movw r12, #65385 +// CHECK-NEXT: b0: c0 f2 ff 1c movt r12, #511 +// CHECK-NEXT: b4: fc 44 add r12, pc +// CHECK-NEXT: b6: 60 47 bx r12 +// CHECK: low_target2: +// CHECK-NEXT: b8: ff f7 f2 ff bl #-28 +// CHECK-NEXT: bc: ff f7 f6 ff bl #-20 + + + .section .text_high, "ax", %progbits + .thumb + .globl high_target + .type high_target, %function +high_target: + bl low_target + bl low_target2 + + .section .text_high2, "ax", %progbits + .thumb + .globl high_target2 + .type high_target2, %function +high_target2: + bl low_target + bl low_target2 + +// CHECK: Disassembly of section .text_high: +// CHECK-NEXT: high_target: +// CHECK-NEXT: 2000000: 00 f0 02 f8 bl #4 +// CHECK-NEXT: 2000004: 00 f0 06 f8 bl #12 +// CHECK: __ThumbV7PILongThunk_low_target: +// CHECK-NEXT: 2000008: 40 f2 83 0c movw r12, #131 +// CHECK-NEXT: 200000c: cf f6 00 6c movt r12, #65024 +// CHECK-NEXT: 2000010: fc 44 add r12, pc +// CHECK-NEXT: 2000012: 60 47 bx r12 +// CHECK: __ThumbV7PILongThunk_low_target2: +// CHECK-NEXT: 2000014: 40 f2 99 0c movw r12, #153 +// CHECK-NEXT: 2000018: cf f6 00 6c movt r12, #65024 +// CHECK-NEXT: 200001c: fc 44 add r12, pc +// CHECK-NEXT: 200001e: 60 47 bx r12 +// CHECK: high_target2: +// CHECK-NEXT: 2000020: ff f7 f2 ff bl #-28 +// CHECK-NEXT: 2000024: ff f7 f6 ff bl #-20 diff --git a/lld/test/ELF/arm-gnu-ifunc.s b/lld/test/ELF/arm-gnu-ifunc.s index 8a7cb0ae237a7..92f87b5d5faef 100644 --- a/lld/test/ELF/arm-gnu-ifunc.s +++ b/lld/test/ELF/arm-gnu-ifunc.s @@ -35,6 +35,8 @@ _start: // CHECK-NEXT: Address: 0x100F4 // CHECK-NEXT: Offset: 0xF4 // CHECK-NEXT: Size: 16 +// CHECK-NEXT: Link: +// CHECK-NEXT: Info: 4 // CHECK: Name: .plt // CHECK-NEXT: Type: SHT_PROGBITS // CHECK-NEXT: Flags [ @@ -44,7 +46,8 @@ _start: // CHECK-NEXT: Address: 0x11020 // CHECK-NEXT: Offset: 0x1020 // CHECK-NEXT: Size: 32 -// CHECK: Name: .got +// CHECK: Index: 4 +// CHECK-NEXT: Name: .got // CHECK-NEXT: Type: SHT_PROGBITS // CHECK-NEXT: Flags [ // CHECK-NEXT: SHF_ALLOC diff --git a/lld/test/ELF/arm-tls-le32.s b/lld/test/ELF/arm-tls-le32.s index f9a5fa9b2fc90..7834dedf1be0f 100644 --- a/lld/test/ELF/arm-tls-le32.s +++ b/lld/test/ELF/arm-tls-le32.s @@ -69,9 +69,9 @@ x: // CHECK: Disassembly of section .text: // CHECK-NEXT: _start: -// offset of x from Thread pointer = (TcbSize + 0x0 = 0x20) -// CHECK-NEXT: 11000: 20 00 00 00 -// offset of z from Thread pointer = (TcbSize + 0x8 = 0x28) -// CHECK-NEXT: 11004: 28 00 00 00 -// offset of y from Thread pointer = (TcbSize + 0x4 = 0x24) -// CHECK-NEXT: 11008: 24 00 00 00 +// offset of x from Thread pointer = (TcbSize + 0x0 = 0x8) +// CHECK-NEXT: 11000: 08 00 00 00 +// offset of z from Thread pointer = (TcbSize + 0x8 = 0x10) +// CHECK-NEXT: 11004: 10 00 00 00 +// offset of y from Thread pointer = (TcbSize + 0x4 = 0xc) +// CHECK-NEXT: 11008: 0c 00 00 00 diff --git a/lld/test/ELF/arm-tls-norelax-ie-le.s b/lld/test/ELF/arm-tls-norelax-ie-le.s index 11c3e4f5dc1a2..4a52f547f0a93 100644 --- a/lld/test/ELF/arm-tls-norelax-ie-le.s +++ b/lld/test/ELF/arm-tls-norelax-ie-le.s @@ -37,5 +37,5 @@ x2: .type x2, %object // CHECK: Contents of section .got: -// x1 at offset 0x20 from TP, x2 at offset 0x24 from TP. Offsets include TCB size of 0x20 -// CHECK-NEXT: 13064 20000000 24000000 +// x1 at offset 8 from TP, x2 at offset 0xc from TP. Offsets include TCB size of 8 +// CHECK-NEXT: 13064 08000000 0c000000 diff --git a/lld/test/ELF/comdat-linkonce.s b/lld/test/ELF/comdat-linkonce.s index 8721f58bb20ce..8b1d4b362e86c 100644 --- a/lld/test/ELF/comdat-linkonce.s +++ b/lld/test/ELF/comdat-linkonce.s @@ -4,7 +4,12 @@ // RUN: ld.lld -shared %t.o %t2.o -o %t // RUN: ld.lld -shared %t2.o %t.o -o %t -.section .gnu.linkonce.t.zed +.section .gnu.linkonce.t.__x86.get_pc_thunk.bx .globl abc abc: nop + +.section .gnu.linkonce.t.__i686.get_pc_thunk.bx +.globl def +def: +nop diff --git a/lld/test/ELF/compressed-input-alignment.test b/lld/test/ELF/compressed-input-alignment.test new file mode 100644 index 0000000000000..a1f679034b77d --- /dev/null +++ b/lld/test/ELF/compressed-input-alignment.test @@ -0,0 +1,67 @@ +# REQUIRES: zlib, x86 + +# RUN: yaml2obj -docnum=1 %s -o %t.o +# RUN: ld.lld %t.o %t.o -o %t2 +# RUN: llvm-readobj -sections -section-data %t2 | FileCheck %s + +# RUN: yaml2obj -docnum=2 %s -o %t.o +# RUN: ld.lld %t.o %t.o -o %t2 +# RUN: llvm-readobj -sections -section-data %t2 | FileCheck %s + +# CHECK: Name: .debug_info +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x0 +# CHECK-NEXT: Offset: 0xE8 +# CHECK-NEXT: Size: 108 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 1 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: {{.*}} |ABCDEFGHIJKLMNOP| +# CHECK-NEXT: 0010: {{.*}} |QRSTUVWXYZ.ABCDE| +# CHECK-NEXT: 0020: {{.*}} |FGHIJKLMNOPQRSTU| +# CHECK-NEXT: 0030: {{.*}} |VWXYZ.ABCDEFGHIJ| +# CHECK-NEXT: 0040: {{.*}} |KLMNOPQRSTUVWXYZ| +# CHECK-NEXT: 0050: {{.*}} |.ABCDEFGHIJKLMNO| +# CHECK-NEXT: 0060: {{.*}} |PQRSTUVWXYZ.| +# CHECK-NEXT: ) +# CHECK-NEXT: } + +## YAML below is produced from the following code. AddressAlign of .debug_info is 8, +## while compressed header has ch_addralign = 1. LLD had a bug and did not use the +## value of ch_addralign at all. We produced broken section content. +## +## .section .debug_info,"",@progbits +## .string "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +## .string "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .debug_info + Type: SHT_PROGBITS + Flags: [ SHF_COMPRESSED ] + AddressAlign: 0x0000000000000008 + Content: 010000000000000036000000000000000100000000000000789C73747276717573F7F0F4F2F6F1F5F30F080C0A0E090D0B8F888C6270C42D0500ADA00FBF + +## YAML below is the same as above, with a single change: ch_addralign field of the compressed +## header was set to 0. This is allowed by the standard, we have to support it. +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .debug_info + Type: SHT_PROGBITS + Flags: [ SHF_COMPRESSED ] + AddressAlign: 0x0000000000000008 + Content: 010000000000000036000000000000000000000000000000789C73747276717573F7F0F4F2F6F1F5F30F080C0A0E090D0B8F888C6270C42D0500ADA00FBF diff --git a/lld/test/ELF/eh-frame-hdr-augmentation.s b/lld/test/ELF/eh-frame-hdr-augmentation.s index 934f9200a27ca..c51ea1c4976b9 100644 --- a/lld/test/ELF/eh-frame-hdr-augmentation.s +++ b/lld/test/ELF/eh-frame-hdr-augmentation.s @@ -11,7 +11,7 @@ // CHECK-NEXT: Code alignment factor: 1 // CHECK-NEXT: Data alignment factor: -8 // CHECK-NEXT: Return address column: 16 -// CHECK-NEXT: Personality Address: 00000dad +// CHECK-NEXT: Personality Address: 0000000000000dad // CHECK-NEXT: Augmentation data: // CHECK: DW_CFA_def_cfa: reg7 +8 @@ -20,7 +20,7 @@ // CHECK-NEXT: DW_CFA_nop: // CHECK: 00000020 00000014 00000024 FDE cie=00000024 pc=00000d98...00000d98 -// CHECK-NEXT: LSDA Address: 00000d8f +// CHECK-NEXT: LSDA Address: 0000000000000d8f // CHECK-NEXT: DW_CFA_nop: // CHECK-NEXT: DW_CFA_nop: // CHECK-NEXT: DW_CFA_nop: diff --git a/lld/test/ELF/emit-relocs-mergeable2.s b/lld/test/ELF/emit-relocs-mergeable2.s new file mode 100644 index 0000000000000..22d4cf4238af9 --- /dev/null +++ b/lld/test/ELF/emit-relocs-mergeable2.s @@ -0,0 +1,14 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: ld.lld --emit-relocs %t.o -o %t.exe +# RUN: llvm-readelf --relocations %t.exe | FileCheck %s + +# CHECK: 0000000000201004 000000010000000b R_X86_64_32S 0000000000200120 .Lfoo + 8 + +.globl _start +_start: + movq .Lfoo+8, %rax +.section .rodata.cst16,"aM",@progbits,16 +.Lfoo: + .quad 0 + .quad 0 diff --git a/lld/test/ELF/emulation-aarch64.s b/lld/test/ELF/emulation-aarch64.s index b9a6428fa953e..c0edc9a69d36d 100644 --- a/lld/test/ELF/emulation-aarch64.s +++ b/lld/test/ELF/emulation-aarch64.s @@ -30,5 +30,28 @@ # AARCH64-NEXT: Flags [ (0x0) # AARCH64-NEXT: ] +# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %taarch64fbsd +# RUN: echo 'OUTPUT_FORMAT(elf64-aarch64-freebsd)' > %taarch64fbsd.script +# RUN: ld.lld %taarch64fbsd.script %taarch64fbsd -o %t2aarch64fbsd +# RUN: llvm-readobj -file-headers %t2aarch64fbsd | FileCheck --check-prefix=AARCH64-FBSD %s +# AARCH64-FBSD: ElfHeader { +# AARCH64-FBSD-NEXT: Ident { +# AARCH64-FBSD-NEXT: Magic: (7F 45 4C 46) +# AARCH64-FBSD-NEXT: Class: 64-bit (0x2) +# AARCH64-FBSD-NEXT: DataEncoding: LittleEndian (0x1) +# AARCH64-FBSD-NEXT: FileVersion: 1 +# AARCH64-FBSD-NEXT: OS/ABI: FreeBSD (0x9) +# AARCH64-FBSD-NEXT: ABIVersion: 0 +# AARCH64-FBSD-NEXT: Unused: (00 00 00 00 00 00 00) +# AARCH64-FBSD-NEXT: } +# AARCH64-FBSD-NEXT: Type: Executable (0x2) +# AARCH64-FBSD-NEXT: Machine: EM_AARCH64 (0xB7) +# AARCH64-FBSD-NEXT: Version: 1 +# AARCH64-FBSD-NEXT: Entry: +# AARCH64-FBSD-NEXT: ProgramHeaderOffset: 0x40 +# AARCH64-FBSD-NEXT: SectionHeaderOffset: +# AARCH64-FBSD-NEXT: Flags [ (0x0) +# AARCH64-FBSD-NEXT: ] + .globl _start _start: diff --git a/lld/test/ELF/emulation-mips.s b/lld/test/ELF/emulation-mips.s index 42d0dd973eb36..6d7a1198b761f 100644 --- a/lld/test/ELF/emulation-mips.s +++ b/lld/test/ELF/emulation-mips.s @@ -7,6 +7,9 @@ # RUN: echo 'OUTPUT_FORMAT(elf32-tradbigmips)' > %tmips.script # RUN: ld.lld %tmips.script -e _start %tmips -o %t4mips # RUN: llvm-readobj -file-headers %t4mips | FileCheck --check-prefix=MIPS %s +# RUN: echo 'OUTPUT_FORMAT(elf32-bigmips)' > %tmips2.script +# RUN: ld.lld %tmips2.script -e _start %tmips -o %t5mips +# RUN: llvm-readobj -file-headers %t5mips | FileCheck --check-prefix=MIPS %s # MIPS: ElfHeader { # MIPS-NEXT: Ident { # MIPS-NEXT: Magic: (7F 45 4C 46) diff --git a/lld/test/ELF/emulation-ppc.s b/lld/test/ELF/emulation-ppc.s index 12e84782252fd..4c8beb10159e6 100644 --- a/lld/test/ELF/emulation-ppc.s +++ b/lld/test/ELF/emulation-ppc.s @@ -35,6 +35,38 @@ # PPC64-NEXT: StringTableSectionIndex: # PPC64-NEXT: } +# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-freebsd %s -o %tppc64fbsd +# RUN: echo 'OUTPUT_FORMAT(elf64-powerpc-freebsd)' > %tppc64fbsd.script +# RUN: ld.lld %tppc64fbsd.script %tppc64fbsd -o %t2ppc64fbsd +# RUN: llvm-readobj -file-headers %t2ppc64fbsd | FileCheck --check-prefix=PPC64-FBSD %s + +# PPC64-FBSD: ElfHeader { +# PPC64-FBSD-NEXT: Ident { +# PPC64-FBSD-NEXT: Magic: (7F 45 4C 46) +# PPC64-FBSD-NEXT: Class: 64-bit (0x2) +# PPC64-FBSD-NEXT: DataEncoding: BigEndian (0x2) +# PPC64-FBSD-NEXT: FileVersion: 1 +# PPC64-FBSD-NEXT: OS/ABI: FreeBSD (0x9) +# PPC64-FBSD-NEXT: ABIVersion: 0 +# PPC64-FBSD-NEXT: Unused: (00 00 00 00 00 00 00) +# PPC64-FBSD-NEXT: } +# PPC64-FBSD-NEXT: Type: Executable (0x2) +# PPC64-FBSD-NEXT: Machine: EM_PPC64 (0x15) +# PPC64-FBSD-NEXT: Version: 1 +# PPC64-FBSD-NEXT: Entry: +# PPC64-FBSD-NEXT: ProgramHeaderOffset: 0x40 +# PPC64-FBSD-NEXT: SectionHeaderOffset: +# PPC64-FBSD-NEXT: Flags [ (0x2) +# PPC64-FBSD-NEXT: 0x2 +# PPC64-FBSD-NEXT: ] +# PPC64-FBSD-NEXT: HeaderSize: 64 +# PPC64-FBSD-NEXT: ProgramHeaderEntrySize: 56 +# PPC64-FBSD-NEXT: ProgramHeaderCount: +# PPC64-FBSD-NEXT: SectionHeaderEntrySize: 64 +# PPC64-FBSD-NEXT: SectionHeaderCount: +# PPC64-FBSD-NEXT: StringTableSectionIndex: +# PPC64-FBSD-NEXT: } + # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %tppc64le # RUN: ld.lld -m elf64lppc %tppc64le -o %t2ppc64le # RUN: llvm-readobj -file-headers %t2ppc64le | FileCheck --check-prefix=PPC64LE %s @@ -71,5 +103,42 @@ # PPC64LE-NEXT: StringTableSectionIndex: # PPC64LE-NEXT: } +# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-linux %s -o %tppc32 +# RUN: ld.lld -m elf32ppc %tppc32 -o %t2ppc32 +# RUN: llvm-readobj -file-headers %t2ppc32 | FileCheck --check-prefix=PPC32 %s +# RUN: ld.lld %tppc32 -o %t3ppc32 +# RUN: llvm-readobj -file-headers %t3ppc32 | FileCheck --check-prefix=PPC32 %s +# RUN: echo 'OUTPUT_FORMAT(elf32-powerpc)' > %tppc32.script +# RUN: ld.lld %tppc32.script %tppc32 -o %t4ppc32 +# RUN: llvm-readobj -file-headers %t4ppc32 | FileCheck --check-prefix=PPC32 %s +# RUN: ld.lld -m elf32ppclinux %tppc32 -o %t5ppc32 +# RUN: llvm-readobj -file-headers %t5ppc32 | FileCheck --check-prefix=PPC32 %s + +# PPC32: ElfHeader { +# PPC32-NEXT: Ident { +# PPC32-NEXT: Magic: (7F 45 4C 46) +# PPC32-NEXT: Class: 32-bit (0x1) +# PPC32-NEXT: DataEncoding: BigEndian (0x2) +# PPC32-NEXT: FileVersion: 1 +# PPC32-NEXT: OS/ABI: SystemV (0x0) +# PPC32-NEXT: ABIVersion: 0 +# PPC32-NEXT: Unused: (00 00 00 00 00 00 00) +# PPC32-NEXT: } +# PPC32-NEXT: Type: Executable (0x2) +# PPC32-NEXT: Machine: EM_PPC (0x14) +# PPC32-NEXT: Version: 1 +# PPC32-NEXT: Entry: +# PPC32-NEXT: ProgramHeaderOffset: 0x34 +# PPC32-NEXT: SectionHeaderOffset: +# PPC32-NEXT: Flags [ (0x0) +# PPC32-NEXT: ] +# PPC32-NEXT: HeaderSize: 52 +# PPC32-NEXT: ProgramHeaderEntrySize: 32 +# PPC32-NEXT: ProgramHeaderCount: +# PPC32-NEXT: SectionHeaderEntrySize: 40 +# PPC32-NEXT: SectionHeaderCount: +# PPC32-NEXT: StringTableSectionIndex: +# PPC32-NEXT: } + .globl _start _start: diff --git a/lld/test/ELF/emulation-x86.s b/lld/test/ELF/emulation-x86.s index 65d807c67f2f0..02b8943566928 100644 --- a/lld/test/ELF/emulation-x86.s +++ b/lld/test/ELF/emulation-x86.s @@ -7,6 +7,9 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.sysv # RUN: ld.lld -m elf_amd64_fbsd %t.sysv -o %t.freebsd # RUN: llvm-readobj -file-headers %t.freebsd | FileCheck --check-prefix=AMD64 %s +# RUN: echo 'OUTPUT_FORMAT(elf64-x86-64-freebsd)' > %t4x64.script +# RUN: ld.lld %t4x64.script %tx64 -o %t4x64 +# RUN: llvm-readobj -file-headers %t4x64 | FileCheck --check-prefix=AMD64 %s # AMD64: ElfHeader { # AMD64-NEXT: Ident { # AMD64-NEXT: Magic: (7F 45 4C 46) @@ -137,10 +140,13 @@ # X86-NEXT: } # RUN: llvm-mc -filetype=obj -triple=i686-unknown-freebsd %s -o %tx86fbsd -# RUN: ld.lld -m elf_i386_fbsd %tx86fbsd -o %t2x86_fbsd -# RUN: llvm-readobj -file-headers %t2x86_fbsd | FileCheck --check-prefix=X86FBSD %s +# RUN: ld.lld -m elf_i386_fbsd %tx86fbsd -o %t2x86fbsd +# RUN: llvm-readobj -file-headers %t2x86fbsd | FileCheck --check-prefix=X86FBSD %s # RUN: ld.lld %tx86fbsd -o %t3x86fbsd # RUN: llvm-readobj -file-headers %t3x86fbsd | FileCheck --check-prefix=X86FBSD %s +# RUN: echo 'OUTPUT_FORMAT(elf32-i386-freebsd)' > %t4x86fbsd.script +# RUN: ld.lld %t4x86fbsd.script %tx86fbsd -o %t4x86fbsd +# RUN: llvm-readobj -file-headers %t4x86fbsd | FileCheck --check-prefix=X86FBSD %s # X86FBSD: ElfHeader { # X86FBSD-NEXT: Ident { # X86FBSD-NEXT: Magic: (7F 45 4C 46) diff --git a/lld/test/ELF/gc-sections-metadata-startstop.s b/lld/test/ELF/gc-sections-metadata-startstop.s index ede1899698c4f..0a1efb7e60758 100644 --- a/lld/test/ELF/gc-sections-metadata-startstop.s +++ b/lld/test/ELF/gc-sections-metadata-startstop.s @@ -11,7 +11,7 @@ # CHECK-NOT: yy # CHECK: SYMBOL TABLE: -# CHECK: xx 00000000 __start_xx +# CHECK: xx 00000000 .protected __start_xx # CHECK: w *UND* 00000000 __start_yy .weak __start_xx diff --git a/lld/test/ELF/mips-micro-relocs.s b/lld/test/ELF/mips-micro-relocs.s index b539aa9467634..566f6810f6e91 100644 --- a/lld/test/ELF/mips-micro-relocs.s +++ b/lld/test/ELF/mips-micro-relocs.s @@ -39,9 +39,9 @@ # EL-NEXT: 20028: 00 00 00 00 nop # EL-NEXT: 2002c: 00 94 e8 ff b -44 -# SYM: 00037ff0 .got 00000000 .hidden _gp -# SYM: 00020000 g F .text 00000000 foo -# SYM: 00020010 .text 00000000 __start +# SYM: 00037ff0 .got 00000000 .hidden _gp +# SYM: 00020000 g F .text 00000000 0x80 foo +# SYM: 00020010 .text 00000000 0x80 __start .text .set micromips diff --git a/lld/test/ELF/mips-micror6-relocs.s b/lld/test/ELF/mips-micror6-relocs.s index ca2c1c064f560..fb450ba5cf3c5 100644 --- a/lld/test/ELF/mips-micror6-relocs.s +++ b/lld/test/ELF/mips-micror6-relocs.s @@ -26,8 +26,8 @@ # EL-NEXT: 20014: 7f 80 f6 ff beqzc $3, -36 # EL-NEXT: 20018: ff b7 f4 ff balc -24 -# SYM: 00020000 g F .text 00000000 foo -# SYM: 00020010 .text 00000000 __start +# SYM: 00020000 g F .text 00000000 0x80 foo +# SYM: 00020010 .text 00000000 0x80 __start .text .set micromips diff --git a/lld/test/ELF/no-discard-this_module.s b/lld/test/ELF/no-discard-this_module.s new file mode 100644 index 0000000000000..3ce56d165fc1a --- /dev/null +++ b/lld/test/ELF/no-discard-this_module.s @@ -0,0 +1,41 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu -save-temp-labels %s -o %t +// RUN: ld.lld %t -o %t2 +// RUN: llvm-readobj -s -sd -t %t2 | FileCheck %s + +.global _start +_start: + +// This section and symbol is used by Linux kernel modules. Ensure it's not +// accidentally discarded. +.section .gnu.linkonce.this_module: +__this_module: +.byte 0x00 + +// CHECK: Section { +// CHECK: Index: +// CHECK: Name: .gnu.linkonce.this_module +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: ] +// CHECK-NEXT: Address: +// CHECK-NEXT: Offset: +// CHECK-NEXT: Size: +// CHECK-NEXT: Link: +// CHECK-NEXT: Info: +// CHECK-NEXT: AddressAlignment: +// CHECK-NEXT: EntrySize: +// CHECK-NEXT: SectionData ( +// CHECK-NEXT: 0000: 00 |.| +// CHECK-NEXT: ) +// CHECK-NEXT: } + +// CHECK: Symbol { +// CHECK: Name: __this_module +// CHECK-NEXT: Value: +// CHECK-NEXT: Size: +// CHECK-NEXT: Binding: Local +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other: +// CHECK-NEXT: Section: .gnu.linkonce.this_module: +// CHECK-NEXT: } diff --git a/lld/test/ELF/ppc64-bsymbolic-toc-restore.s b/lld/test/ELF/ppc64-bsymbolic-toc-restore.s index 49d347c489927..d467d22ff7b1e 100644 --- a/lld/test/ELF/ppc64-bsymbolic-toc-restore.s +++ b/lld/test/ELF/ppc64-bsymbolic-toc-restore.s @@ -53,7 +53,7 @@ caller: # CHECK-LABEL: caller # CHECK: bl .+44 # CHECK-NEXT: mr 31, 3 -# CHECK-NEXT: bl .+67108816 +# CHECK-NEXT: bl .+44 # CHECK-NEXT: ld 2, 24(1) # CHECK-NEXT: add 3, 3, 31 # CHECK-NEXT: addi 1, 1, 32 @@ -63,6 +63,6 @@ caller: # CHECK-EMPTY: # CHECK-NEXT: def: # CHECK-NEXT: addis 2, 12, 2 -# CHECK-NEXT: addi 2, 2, -32636 +# CHECK-NEXT: addi 2, 2, -32616 # CHECK-NEXT: li 3, 55 # CHECK-NEXT: blr diff --git a/lld/test/ELF/ppc64-call-reach.s b/lld/test/ELF/ppc64-call-reach.s index a02bfa8299335..b843e7e531c91 100644 --- a/lld/test/ELF/ppc64-call-reach.s +++ b/lld/test/ELF/ppc64-call-reach.s @@ -3,16 +3,16 @@ # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o # RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ # RUN: %t.o -o %t -# RUN: llvm-objdump -d %t | FileCheck %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s # RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ # RUN: %t.o -o %t -# RUN: llvm-objdump -d %t | FileCheck %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s # RUN: ld.lld --defsym callee=0xE010014 --defsym tail_callee=0xE010024 \ # RUN: %t.o -o %t -# RUN: llvm-objdump -d %t | FileCheck --check-prefix=NEGOFFSET %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=NEGOFFSET %s # RUN: ld.lld --defsym callee=0x12010018 --defsym tail_callee=0x12010028 \ # RUN: %t.o -o %t -# RUN: llvm-objdump -d %t | FileCheck --check-prefix=THUNK %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=THUNK %s # RUN: llvm-readelf --sections %t | FileCheck --check-prefix=BRANCHLT %s # RUN: not ld.lld --defsym callee=0x1001002D --defsym tail_callee=0x1001002F \ # RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s @@ -20,16 +20,16 @@ # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o # RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ # RUN: %t.o -o %t -# RUN: llvm-objdump -d %t | FileCheck %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s # RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ # RUN: %t.o -o %t -# RUN: llvm-objdump -d %t | FileCheck %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s # RUN: ld.lld --defsym callee=0xE010014 --defsym tail_callee=0xE010024 \ # RUN: %t.o -o %t -# RUN: llvm-objdump -d %t | FileCheck --check-prefix=NEGOFFSET %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=NEGOFFSET %s # RUN: ld.lld --defsym callee=0x12010018 --defsym tail_callee=0x12010028 \ # RUN: %t.o -o %t -# RUN: llvm-objdump -d %t | FileCheck --check-prefix=THUNK %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=THUNK %s # RUN: llvm-readelf --sections %t | FileCheck --check-prefix=BRANCHLT %s # RUN: not ld.lld --defsym callee=0x1001002D --defsym tail_callee=0x1001002F \ # RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s @@ -58,37 +58,33 @@ test: # Check that we are branching to the definitions, and not range-extending # thunks. # CHECK-LABEL: test -# CHECK: 10010014: {{.*}} bl .+33554428 -# CHECK: 10010024: {{.*}} b .+33554428 +# CHECK: 10010014: bl .+33554428 +# CHECK: 10010024: b .+33554428 # NEGOFFSET-LABEL: test -# NEGOFFSET: 10010014: {{.*}} bl .+33554432 -# NEGOFFSET: 10010024: {{.*}} b .+33554432 +# NEGOFFSET: 10010014: bl .-33554432 +# NEGOFFSET: 10010024: b .+33554432 + +# THUNK-LABEL: test: +# THUNK: 10010014: bl .+20 +# THUNK: 10010024: b .+20 # .branch_lt[0] # THUNK-LABEL: __long_branch_callee: -# THUNK-NEXT: 10010000: {{.*}} addis 12, 2, -1 +# THUNK-NEXT: 10010028: addis 12, 2, -1 # THUNK-NEXT: ld 12, -32768(12) # THUNK-NEXT: mtctr 12 # THUNK-NEXT: bctr # .branch_lt[1] # THUNK-LABEL: __long_branch_tail_callee: -# THUNK-NEXT: 10010010: {{.*}} addis 12, 2, -1 +# THUNK-NEXT: 10010038: addis 12, 2, -1 # THUNK-NEXT: ld 12, -32760(12) # THUNK-NEXT: mtctr 12 # THUNK-NEXT: bctr -# Each call now branches to a thunk, and although it is printed as positive -# the offset is interpreted as a signed 26 bit value so 67108812 is actually -# -52. -# THUNK-LABEL: test: -# THUNK: 10010034: {{.*}} bl .+67108812 -# THUNK: 10010044: {{.*}} b .+67108812 - # The offset from the TOC to the .branch_lt section is (-1 << 16) - 32768. # Name Type Address Off Size # BRANCHLT: .branch_lt PROGBITS 0000000010020000 020000 000010 # BRANCHLT: .got PROGBITS 0000000010030000 030000 000008 # BRANCHLT-NOT: .plt - diff --git a/lld/test/ELF/ppc64-ifunc.s b/lld/test/ELF/ppc64-ifunc.s index 6f2d3318b9c28..32e317f3c059d 100644 --- a/lld/test/ELF/ppc64-ifunc.s +++ b/lld/test/ELF/ppc64-ifunc.s @@ -1,79 +1,67 @@ # REQUIRES: ppc # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o -# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o -# RUN: ld.lld -shared %t2.o -o %t2.so -# RUN: ld.lld %t.o %t2.so -o %t -# RUN: llvm-objdump -D %t | FileCheck %s -# RUN: llvm-readelf -dynamic-table %t | FileCheck --check-prefix=DT %s -# RUN: llvm-readelf -dyn-relocations %t | FileCheck --check-prefix=DYNREL %s +# RUN: ld.lld %t.o -o %t +# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s +# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SECTIONS %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s +# RUN: llvm-readelf -r %t | FileCheck --check-prefix=DYNREL %s # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o -# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o -# RUN: ld.lld -shared %t2.o -o %t2.so -# RUN: ld.lld %t.o %t2.so -o %t -# RUN: llvm-objdump -D %t | FileCheck %s -# RUN: llvm-readelf -dynamic-table %t | FileCheck --check-prefix=DT %s -# RUN: llvm-readelf -dyn-relocations %t | FileCheck --check-prefix=DYNREL %s +# RUN: ld.lld %t.o -o %t +# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s +# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SECTIONS %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s +# RUN: llvm-readelf -r %t | FileCheck --check-prefix=DYNREL %s -# CHECK: Disassembly of section .text: +# NM-DAG: 0000000010028000 d .TOC. +# NM-DAG: 0000000010010000 T ifunc +# NM-DAG: 0000000010010004 T ifunc2 -# Tocbase + (0 << 16) + 32560 -# 0x100280e0 + 0 + 32560 = 0x10030010 (.plt[2]) -# CHECK: __plt_foo: +# SECTIONS: .plt NOBITS 0000000010030000 + +# __plt_ifunc - . = 0x10010020 - 0x10010010 = 16 +# __plt_ifunc2 - . = 0x10010044 - 0x10010018 = 28 +# CHECK: _start: +# CHECK-NEXT: addis 2, 12, 1 +# CHECK-NEXT: addi 2, 2, 32760 +# CHECK-NEXT: 10010010: bl .+16 +# CHECK-NEXT: ld 2, 24(1) +# CHECK-NEXT: 10010018: bl .+28 +# CHECK-NEXT: ld 2, 24(1) + +# .plt[0] - .TOC. = 0x10030000 - 0x10028000 = (1<<16) - 32768 +# CHECK: __plt_ifunc: # CHECK-NEXT: std 2, 24(1) -# CHECK-NEXT: addis 12, 2, 0 -# CHECK-NEXT: ld 12, 32560(12) +# CHECK-NEXT: addis 12, 2, 1 +# CHECK-NEXT: ld 12, -32768(12) # CHECK-NEXT: mtctr 12 # CHECK-NEXT: bctr -# Tocbase + (0 << 16) + 32568 -# 0x100280e0 + 0 + 32568 = 0x1003018 (.plt[3]) -# CHECK: __plt_ifunc: +# .plt[1] - .TOC. = 0x10030000+8 - 0x10028000 = (1<<16) - 32760 +# CHECK: __plt_ifunc2: # CHECK-NEXT: std 2, 24(1) -# CHECK-NEXT: addis 12, 2, 0 -# CHECK-NEXT: ld 12, 32568(12) +# CHECK-NEXT: addis 12, 2, 1 +# CHECK-NEXT: ld 12, -32760(12) # CHECK-NEXT: mtctr 12 # CHECK-NEXT: bctr -# CHECK: ifunc: -# CHECK-NEXT: 10010028: {{.*}} nop - -# CHECK: _start: -# CHECK-NEXT: addis 2, 12, 2 -# CHECK-NEXT: addi 2, 2, -32588 -# CHECK-NEXT: bl .+67108812 -# CHECK-NEXT: ld 2, 24(1) -# CHECK-NEXT: bl .+67108824 -# CHECK-NEXT: ld 2, 24(1) - -# Check tocbase -# CHECK: Disassembly of section .got: -# CHECK-NEXT: .got: -# CHECK-NEXT: 100200e0 - -# Check .plt address -# DT_PLTGOT should point to the start of the .plt section. -# DT: 0x0000000000000003 PLTGOT 0x10030000 - -# Check that we emit the correct dynamic relocation type for an ifunc -# DYNREL: 'PLT' relocation section at offset 0x{{[0-9a-f]+}} contains 48 bytes: -# 48 bytes --> 2 Elf64_Rela relocations -# DYNREL-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend -# DYNREL-NEXT: {{[0-9a-f]+}} {{[0-9a-f]+}} R_PPC64_JMP_SLOT {{0+}} foo + 0 -# DYNREL-NEXT: {{[0-9a-f]+}} {{[0-9a-f]+}} R_PPC64_IRELATIVE 10010028 - - - .text - .abiversion 2 +# Check that we emit 2 R_PPC64_IRELATIVE. +# DYNREL: R_PPC64_IRELATIVE 10010000 +# DYNREL: R_PPC64_IRELATIVE 10010004 .type ifunc STT_GNU_IFUNC .globl ifunc ifunc: - nop + nop - .global _start - .type _start,@function +.type ifunc2 STT_GNU_IFUNC +.globl ifunc2 +ifunc2: + nop + +.global _start +.type _start,@function _start: .Lfunc_gep0: @@ -81,7 +69,7 @@ _start: addi 2, 2, .TOC.-.Lfunc_gep0@l .Lfunc_lep0: .localentry _start, .Lfunc_lep0-.Lfunc_gep0 - bl foo - nop bl ifunc nop + bl ifunc2 + nop diff --git a/lld/test/ELF/ppc64-local-dynamic.s b/lld/test/ELF/ppc64-local-dynamic.s index 6ed3b0fd8f076..87e33b784b8b4 100644 --- a/lld/test/ELF/ppc64-local-dynamic.s +++ b/lld/test/ELF/ppc64-local-dynamic.s @@ -113,7 +113,7 @@ k: // Dis: test: // Dis: addis 3, 2, 0 // Dis-NEXT: addi 3, 3, -32760 -// Dis-NEXT: bl .+67108804 +// Dis-NEXT: bl .+60 // Dis-NEXT: ld 2, 24(1) // Dis-NEXT: addis 3, 3, 0 // Dis-NEXT: lwa 3, -32768(3) diff --git a/lld/test/ELF/ppc64-local-entry.s b/lld/test/ELF/ppc64-local-entry.s new file mode 100644 index 0000000000000..2a2295169b958 --- /dev/null +++ b/lld/test/ELF/ppc64-local-entry.s @@ -0,0 +1,47 @@ +# REQUIRES: ppc + +# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t +# RUN: ld.lld -r %t -o %t2 +# RUN: llvm-objdump -s -section=.symtab %t2 | FileCheck %s + +.text +.abiversion 2 +.globl _start +.p2align 2 +.type _start,@function + +_start: +.Lfunc_begin0: +.Lfunc_gep0: + addis 2, 12, .TOC.-.Lfunc_gep0@ha + addi 2, 2, .TOC.-.Lfunc_gep0@l +.Lfunc_lep0: + .localentry _start, .Lfunc_lep0-.Lfunc_gep0 + # The code below is not important, it just needs to access some + # global data or function, in order to use the TOC. + # In this case, it performs the following: + # g += 10; + # Also note that this code is not intended to be run, but only + # to check if the linker will preserve the localentry info. + addis 3, 2, g@toc@ha + addi 3, 3, g@toc@l + lwz 4, 0(3) + addi 4, 4, 10 + stw 4, 0(3) + blr + .long 0 + .quad 0 +.Lfunc_end0: + .size _start, .Lfunc_end0-.Lfunc_begin0 + + .type g,@object # @g + .lcomm g,4,4 + +// We expect the st_other byte to be 0x60: +// localentry = 011 (gep + 2 instructions), reserved = 000, +// visibility = 00 (STV_DEFAULT) +// Currently, llvm-objdump does not support displaying +// st_other's PPC64 specific flags, thus we check the +// result of the hexdump of .symtab section. + +// CHECK: 0070 00000000 00000000 00000009 12600001 diff --git a/lld/test/ELF/ppc64-long-branch-init.s b/lld/test/ELF/ppc64-long-branch-init.s new file mode 100644 index 0000000000000..80b3919cc4555 --- /dev/null +++ b/lld/test/ELF/ppc64-long-branch-init.s @@ -0,0 +1,43 @@ +# REQUIRES: ppc + +# RUN: llvm-mc -filetype=obj -triple=powerpc64-pc-freebsd13.0 %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s + +## .init consists of sections from several object files. Sections other than the +## last one do not have a terminator. Check we do not create a long branch stub +## in the middle. +## We currently use thunk section spacing to ensure the stub is in the end. This +## is not foolproof but good enough to not break in practice. + +# CHECK: Disassembly of section .init: +# CHECK-LABEL: _init: +# CHECK: blr +# CHECK-EMPTY: +# CHECK-LABEL: __long_branch_foo: + +.globl foo +foo: + .space 0x2000000 + blr + +.section .init,"ax",@progbits,unique,0 +.globl _init +_init: + stdu 1, -48(1) + mflr 0 + std 0, 64(1) + +.section .init,"ax",@progbits,unique,1 + bl foo + nop + +.section .init,"ax",@progbits,unique,2 + bl foo + nop + +.section .init,"ax",@progbits,unique,3 + ld 1, 0(1) + ld 0, 16(1) + mtlr 0 + blr diff --git a/lld/test/ELF/ppc64-long-branch-localentry-offset.s b/lld/test/ELF/ppc64-long-branch-localentry-offset.s new file mode 100644 index 0000000000000..fd37c13db6ba2 --- /dev/null +++ b/lld/test/ELF/ppc64-long-branch-localentry-offset.s @@ -0,0 +1,30 @@ +# REQUIRES: ppc + +# RUN: llvm-mc -filetype=obj -triple=ppc64le %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-nm %t | FileCheck %s + +# CHECK-DAG: 0000000010010000 t __long_branch_callee +# CHECK-DAG: 0000000010010010 T _start +# CHECK-DAG: 0000000012010008 T callee + +# The bl instruction jumps to the local entry. The distance requires a long branch stub: +# localentry(callee) - _start = 0x12010008+8 - 0x10010010 = 0x2000000 + +# We used to compute globalentry(callee) - _start and caused a "R_PPC64_REL24 +# out of range" error because we didn't create the stub. + +.globl _start +_start: + bl callee + +.space 0x1fffff4 + +.globl callee +callee: +.Lgep0: + addis 2, 12, .TOC.-.Lgep0@ha + addi 2, 2, .TOC.-.Lgep0@l +.Llep0: + .localentry callee, .Llep0-.Lgep0 + blr diff --git a/lld/test/ELF/ppc64-plt-stub.s b/lld/test/ELF/ppc64-plt-stub.s index a644f487b8bed..bf3ac09fd516d 100644 --- a/lld/test/ELF/ppc64-plt-stub.s +++ b/lld/test/ELF/ppc64-plt-stub.s @@ -4,16 +4,19 @@ // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o // RUN: ld.lld -shared %t2.o -o %t2.so // RUN: ld.lld %t.o %t2.so -o %t -// RUN: llvm-objdump -d %t | FileCheck %s +// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o // RUN: ld.lld -shared %t2.o -o %t2.so // RUN: ld.lld %t.o %t2.so -o %t -// RUN: llvm-objdump -d %t | FileCheck %s +// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s // CHECK: Disassembly of section .text: -// CHECK-NEXT: __plt_foo: +// CHECK-NEXT: _start: +// CHECK: 10010008: bl .+16 + +// CHECK-LABEL: 0000000010010018 __plt_foo: // CHECK-NEXT: std 2, 24(1) // CHECK-NEXT: addis 12, 2, 0 // CHECK-NEXT: ld 12, 32560(12) @@ -21,8 +24,6 @@ // CHECK-NEXT: bctr -// CHECK: _start: -// CHECK: bl .+67108824 .text .abiversion 2 .globl _start diff --git a/lld/test/ELF/ppc64-rel-calls.s b/lld/test/ELF/ppc64-rel-calls.s index 4c79498dc56bd..8423eb43f2199 100644 --- a/lld/test/ELF/ppc64-rel-calls.s +++ b/lld/test/ELF/ppc64-rel-calls.s @@ -30,9 +30,8 @@ bar: nop blr -# FIXME: The printing here is misleading, the branch offset here is negative. -# CHECK: 1001000c: {{.*}} bl .+67108852 +# CHECK: 1001000c: {{.*}} bl .-12 # CHECK: 10010010: {{.*}} nop -# CHECK: 10010014: {{.*}} bl .+67108844 +# CHECK: 10010014: {{.*}} bl .-20 # CHECK: 10010018: {{.*}} nop # CHECK: 1001001c: {{.*}} blr diff --git a/lld/test/ELF/ppc64-toc-restore-recursive-call.s b/lld/test/ELF/ppc64-toc-restore-recursive-call.s index 4bedcfecf3830..756a058cc5650 100644 --- a/lld/test/ELF/ppc64-toc-restore-recursive-call.s +++ b/lld/test/ELF/ppc64-toc-restore-recursive-call.s @@ -1,8 +1,8 @@ # REQUIRES: ppc -# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t1.o -# RUN: ld.lld -shared %t1.o -o %t -# RUN: llvm-objdump -d -r %t | FileCheck %s +# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o +# RUN: ld.lld -shared %t.o -o %t.so +# RUN: llvm-objdump -d --no-show-raw-insn -r %t.so | FileCheck %s # For a recursive call that is interposable the linker calls the plt-stub rather # then calling the function directly. Since the call is through a plt stub and @@ -14,12 +14,11 @@ # for recursive calls as well as keeps the logic for recursive calls consistent # with non-recursive calls. -# CHECK-LABEL: __plt_recursive_func: -# CHECK-NEXT: 10000: -# CHECK-LABEL: recursive_func -# CHECK-NEXT: 10014: -# CHECK: 1003c: {{[0-9a-fA-F ]+}} bl .+67108804 -# CHECK-NEXT: ld 2, 24(1) +# CHECK-LABEL: 0000000000010000 recursive_func: +# CHECK: 10028: bl .+32 +# CHECK-NEXT: ld 2, 24(1) + +# CHECK-LABEL: 0000000000010048 __plt_recursive_func: .abiversion 2 .section ".text" diff --git a/lld/test/ELF/ppc64-toc-restore.s b/lld/test/ELF/ppc64-toc-restore.s index d9e06ca6e5968..d65bef847a7b2 100644 --- a/lld/test/ELF/ppc64-toc-restore.s +++ b/lld/test/ELF/ppc64-toc-restore.s @@ -5,14 +5,14 @@ // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-func.s -o %t3.o // RUN: ld.lld -shared %t2.o -o %t2.so // RUN: ld.lld %t.o %t2.so %t3.o -o %t -// RUN: llvm-objdump -d %t | FileCheck %s +// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-func.s -o %t3.o // RUN: ld.lld -shared %t2.o -o %t2.so // RUN: ld.lld %t.o %t2.so %t3.o -o %t -// RUN: llvm-objdump -d %t | FileCheck %s +// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s .text .abiversion 2 @@ -28,16 +28,11 @@ _start: bl foo nop bl bar_local - - -// CHECK: Disassembly of section .text: -// CHECK: _start: -// CHECK: 1001001c: {{.*}} bl .+67108836 -// CHECK-NOT: 10010020: {{.*}} nop -// CHECK: 10010020: {{.*}} ld 2, 24(1) -// CHECK: 10010024: {{.*}} bl .+67108848 -// CHECK-NOT: 10010028: {{.*}} nop -// CHECK-NOT: 10010028: {{.*}} ld 2, 24(1) +// CHECK-LABEL: _start: +// CHECK-NEXT: 10010008: bl .+64 +// CHECK-NEXT: 1001000c: ld 2, 24(1) +// CHECK-NEXT: 10010010: bl .-16 +// CHECK-EMPTY: # Calling a function in another object file which will have same # TOC base does not need a nop. If nop present, do not rewrite to @@ -47,26 +42,24 @@ _diff_object: bl foo_not_shared bl foo_not_shared nop - -// CHECK: _diff_object: -// CHECK-NEXT: 10010028: {{.*}} bl .+24 -// CHECK-NEXT: 1001002c: {{.*}} bl .+20 -// CHECK-NEXT: 10010030: {{.*}} nop +// CHECK-LABEL: _diff_object: +// CHECK-NEXT: 10010014: bl .+28 +// CHECK-NEXT: 10010018: bl .+24 +// CHECK-NEXT: 1001001c: nop # Branching to a local function does not need a nop .global noretbranch noretbranch: b bar_local -// CHECK: noretbranch: -// CHECK: 10010034: {{.*}} b .+67108832 -// CHECK-NOT: 10010038: {{.*}} nop -// CHECK-NOT: 1001003c: {{.*}} ld 2, 24(1) +// CHECK-LABEL: noretbranch: +// CHECK: 10010020: b .+67108832 +// CHECK-EMPTY: // This should come last to check the end-of-buffer condition. .global last last: bl foo nop -// CHECK: last: -// CHECK: 10010038: {{.*}} bl .+67108808 -// CHECK-NEXT: 1001003c: {{.*}} ld 2, 24(1) +// CHECK-LABEL: last: +// CHECK-NEXT: 10010024: bl .+36 +// CHECK-NEXT: 10010028: ld 2, 24(1) diff --git a/lld/test/ELF/sht-group-empty.test b/lld/test/ELF/sht-group-empty.test new file mode 100644 index 0000000000000..46c77f332e7e7 --- /dev/null +++ b/lld/test/ELF/sht-group-empty.test @@ -0,0 +1,55 @@ +# RUN: yaml2obj %s -o %t.o +# RUN: ld.lld %t.o %t.o -o %t -r +# RUN: llvm-readobj -s %t | FileCheck %s + +# CHECK: Name: .text.foo +# CHECK: Name: .rela.text.foo + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .group + Type: SHT_GROUP + Link: .symtab + Info: foo + Members: + - SectionOrType: GRP_COMDAT + - SectionOrType: .text.foo + - SectionOrType: .text.bar + - SectionOrType: .note + - Name: .note + Type: SHT_NOTE + Flags: [ SHF_GROUP ] + - Name: .text.foo + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ] + - Name: .text.bar + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ] + - Name: .rela.text.foo + Type: SHT_RELA + Flags: [ SHF_INFO_LINK, SHF_GROUP ] + Link: .symtab + Info: .text.foo + Relocations: + - Offset: 0x0000000000000000 + Symbol: foo + Type: R_X86_64_64 + - Name: .rela.text.bar + Type: SHT_RELA + Flags: [ SHF_INFO_LINK, SHF_GROUP ] + Link: .symtab + Info: .text.bar + Relocations: + - Offset: 0x0000000000000000 + Symbol: bar + Type: R_X86_64_64 +Symbols: + Global: + - Name: foo + - Name: bar + diff --git a/lld/test/ELF/tls-opt-x86_64-noplt.s b/lld/test/ELF/tls-opt-x86_64-noplt.s new file mode 100644 index 0000000000000..69ec49871210e --- /dev/null +++ b/lld/test/ELF/tls-opt-x86_64-noplt.s @@ -0,0 +1,88 @@ +// REQUIRES: x86 + +// Checks whether the TLS optimizations match the cases in Chapter 11 of +// https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf + +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-opt-gdie.s -o %tso.o +// RUN: ld.lld -shared %tso.o -o %t.so +// RUN: ld.lld %t.o %t.so -o %t1 +// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=RELOC %s +// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s + +// RELOC: Relocations [ +// RELOC-NEXT: Section {{.*}} .rela.dyn { +// RELOC-NEXT: 0x2020C0 R_X86_64_TPOFF64 tlsshared0 0x0 +// RELOC-NEXT: 0x2020C8 R_X86_64_TPOFF64 tlsshared1 0x0 +// RELOC-NEXT: } +// RELOC-NEXT: ] + +// DISASM: _start: + +// Table 11.5: GD -> IE Code Transition (LP64) +// DISASM-NEXT: 201000: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 201009: 48 03 05 b0 10 00 00 addq 4272(%rip), %rax +// DISASM-NEXT: 201010: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 201019: 48 03 05 a8 10 00 00 addq 4264(%rip), %rax + +// Table 11.7: GD -> LE Code Transition (LP64) +// DISASM-NEXT: 201020: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 201029: 48 8d 80 f8 ff ff ff leaq -8(%rax), %rax +// DISASM-NEXT: 201030: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 201039: 48 8d 80 fc ff ff ff leaq -4(%rax), %rax + + +// Table 11.9: LD -> LE Code Transition (LP64) +// DISASM-NEXT: 201040: 66 66 66 66 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax +// DISASM-NEXT: 20104d: 66 66 66 66 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax + +.type tls0,@object +.section .tbss,"awT",@nobits +.globl tls0 +.align 4 +tls0: + .long 0 + .size tls0, 4 + +.type tls1,@object +.globl tls1 +.align 4 +tls1: + .long 0 + .size tls1, 4 + +.section .text +.globl _start +_start: + // Table 11.5: GD -> IE Code Transition (LP64) + .byte 0x66 + leaq tlsshared0@tlsgd(%rip),%rdi + .byte 0x66 + rex64 + call *__tls_get_addr@GOTPCREL(%rip) + + .byte 0x66 + leaq tlsshared1@tlsgd(%rip),%rdi + .byte 0x66 + rex64 + call *__tls_get_addr@GOTPCREL(%rip) + + // Table 11.7: GD -> LE Code Transition (LP64) + .byte 0x66 + leaq tls0@tlsgd(%rip),%rdi + .byte 0x66 + rex64 + call *__tls_get_addr@GOTPCREL(%rip) + + .byte 0x66 + leaq tls1@tlsgd(%rip),%rdi + .byte 0x66 + rex64 + call *__tls_get_addr@GOTPCREL(%rip) + + // Table 11.9: LD -> LE Code Transition (LP64) + leaq tls0@tlsld(%rip),%rdi + call *__tls_get_addr@GOTPCREL(%rip) + + leaq tls1@tlsld(%rip),%rdi + call *__tls_get_addr@GOTPCREL(%rip) diff --git a/lld/test/wasm/data-layout.ll b/lld/test/wasm/data-layout.ll index b01c13ac9b82a..7c215efb0d8f4 100644 --- a/lld/test/wasm/data-layout.ll +++ b/lld/test/wasm/data-layout.ll @@ -85,10 +85,10 @@ target triple = "wasm32-unknown-unknown" ; RELOC: - Type: DATA ; RELOC-NEXT: Relocations: ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 -; RELOC-NEXT: Index: 6 +; RELOC-NEXT: Index: 3 ; RELOC-NEXT: Offset: 0x00000018 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 -; RELOC-NEXT: Index: 3 +; RELOC-NEXT: Index: 4 ; RELOC-NEXT: Offset: 0x0000002E ; RELOC-NEXT: Addend: 4 ; RELOC-NEXT: Segments: @@ -148,7 +148,7 @@ target triple = "wasm32-unknown-unknown" ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Segment: 2 ; RELOC-NEXT: Size: 4 -; RELOC: - Index: 6 +; RELOC-NEXT: - Index: 3 ; RELOC-NEXT: Kind: DATA ; RELOC-NEXT: Name: hello_str ; RELOC-NEXT: Flags: [ ] diff --git a/lld/test/wasm/import-module.ll b/lld/test/wasm/import-module.ll new file mode 100644 index 0000000000000..9a473194ce2c3 --- /dev/null +++ b/lld/test/wasm/import-module.ll @@ -0,0 +1,21 @@ +; RUN: llc -filetype=obj %s -o %t.o +; RUN: wasm-ld --allow-undefined -o %t.wasm %t.o +; RUN: obj2yaml %t.wasm | FileCheck %s + +target triple = "wasm32-unknown-unknown-wasm" + +define void @_start() { + call void @foo(); + ret void +} + +declare void @foo() #0 + +attributes #0 = { "wasm-import-module"="bar" } + +; CHECK: - Type: IMPORT +; CHECK-NEXT: Imports: +; CHECK-NEXT: - Module: bar +; CHECK-NEXT: Field: foo +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: SigIndex: 0 diff --git a/lld/test/wasm/import-names.ll b/lld/test/wasm/import-names.ll new file mode 100644 index 0000000000000..a3953d3356198 --- /dev/null +++ b/lld/test/wasm/import-names.ll @@ -0,0 +1,27 @@ +; RUN: llc -filetype=obj %s -o %t.o +; RUN: wasm-ld --allow-undefined -o %t.wasm %t.o +; RUN: obj2yaml %t.wasm | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +declare void @f0() #0 + +define void @_start() { + call void @f0() + ret void +} + +attributes #0 = { "wasm-import-module"="somewhere" "wasm-import-name"="something" } + +; CHECK: - Type: IMPORT +; CHECK-NEXT: Imports: +; CHECK-NEXT: - Module: somewhere +; CHECK-NEXT: Field: something +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: SigIndex: 0 + +; CHECK: - Type: CUSTOM +; CHECK-NEXT: Name: name +; CHECK-NEXT: FunctionNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: f0 diff --git a/lld/test/wasm/init-fini.ll b/lld/test/wasm/init-fini.ll index 9a7f5357ef015..b17020b177c71 100644 --- a/lld/test/wasm/init-fini.ll +++ b/lld/test/wasm/init-fini.ll @@ -163,64 +163,64 @@ entry: ; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] ; RELOC-NEXT: Function: 7 ; RELOC-NEXT: - Index: 6 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: __dso_handle +; RELOC-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN, UNDEFINED ] +; RELOC-NEXT: - Index: 7 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: externDtor +; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN, UNDEFINED ] +; RELOC-NEXT: Function: 0 +; RELOC-NEXT: - Index: 8 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: externCtor +; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN, UNDEFINED ] +; RELOC-NEXT: Function: 1 +; RELOC-NEXT: - Index: 9 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: myctor +; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; RELOC-NEXT: Function: 14 +; RELOC-NEXT: - Index: 10 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: mydtor +; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; RELOC-NEXT: Function: 15 +; RELOC-NEXT: - Index: 11 +; RELOC-NEXT: Kind: GLOBAL +; RELOC-NEXT: Name: __stack_pointer +; RELOC-NEXT: Flags: [ UNDEFINED ] +; RELOC-NEXT: Global: 0 +; RELOC-NEXT: - Index: 12 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: .Lcall_dtors.101 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] ; RELOC-NEXT: Function: 8 -; RELOC-NEXT: - Index: 7 +; RELOC-NEXT: - Index: 13 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: .Lregister_call_dtors.101 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] ; RELOC-NEXT: Function: 9 -; RELOC-NEXT: - Index: 8 -; RELOC-NEXT: Kind: DATA -; RELOC-NEXT: Name: __dso_handle -; RELOC-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN, UNDEFINED ] -; RELOC-NEXT: - Index: 9 +; RELOC-NEXT: - Index: 14 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: .Lcall_dtors.1001 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] ; RELOC-NEXT: Function: 10 -; RELOC-NEXT: - Index: 10 +; RELOC-NEXT: - Index: 15 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: .Lregister_call_dtors.1001 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] ; RELOC-NEXT: Function: 11 -; RELOC-NEXT: - Index: 11 +; RELOC-NEXT: - Index: 16 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: .Lcall_dtors.4000 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] ; RELOC-NEXT: Function: 12 -; RELOC-NEXT: - Index: 12 -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Name: externDtor -; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN, UNDEFINED ] -; RELOC-NEXT: Function: 0 -; RELOC-NEXT: - Index: 13 +; RELOC-NEXT: - Index: 17 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: .Lregister_call_dtors.4000 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] ; RELOC-NEXT: Function: 13 -; RELOC-NEXT: - Index: 14 -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Name: externCtor -; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN, UNDEFINED ] -; RELOC-NEXT: Function: 1 -; RELOC-NEXT: - Index: 15 -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Name: myctor -; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: Function: 14 -; RELOC-NEXT: - Index: 16 -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Name: mydtor -; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: Function: 15 -; RELOC-NEXT: - Index: 17 -; RELOC-NEXT: Kind: GLOBAL -; RELOC-NEXT: Name: __stack_pointer -; RELOC-NEXT: Flags: [ UNDEFINED ] -; RELOC-NEXT: Global: 0 ; RELOC-NEXT: - Index: 18 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: .Lcall_dtors.101 @@ -251,36 +251,36 @@ entry: ; RELOC-NEXT: Name: .Lregister_call_dtors.2002 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] ; RELOC-NEXT: Function: 21 -; RELOC-NEXT: InitFunctions: +; RELOC-NEXT: InitFunctions: ; RELOC-NEXT: - Priority: 101 ; RELOC-NEXT: Symbol: 0 ; RELOC-NEXT: - Priority: 101 ; RELOC-NEXT: Symbol: 1 ; RELOC-NEXT: - Priority: 101 -; RELOC-NEXT: Symbol: 7 +; RELOC-NEXT: Symbol: 13 ; RELOC-NEXT: - Priority: 101 -; RELOC-NEXT: Symbol: 15 +; RELOC-NEXT: Symbol: 9 ; RELOC-NEXT: - Priority: 101 ; RELOC-NEXT: Symbol: 19 ; RELOC-NEXT: - Priority: 202 -; RELOC-NEXT: Symbol: 15 +; RELOC-NEXT: Symbol: 9 ; RELOC-NEXT: - Priority: 202 ; RELOC-NEXT: Symbol: 21 ; RELOC-NEXT: - Priority: 1001 ; RELOC-NEXT: Symbol: 0 ; RELOC-NEXT: - Priority: 1001 -; RELOC-NEXT: Symbol: 10 -; RELOC-NEXT: - Priority: 2002 ; RELOC-NEXT: Symbol: 15 ; RELOC-NEXT: - Priority: 2002 +; RELOC-NEXT: Symbol: 9 +; RELOC-NEXT: - Priority: 2002 ; RELOC-NEXT: Symbol: 23 ; RELOC-NEXT: - Priority: 4000 -; RELOC-NEXT: Symbol: 14 +; RELOC-NEXT: Symbol: 8 ; RELOC-NEXT: - Priority: 4000 -; RELOC-NEXT: Symbol: 13 +; RELOC-NEXT: Symbol: 17 ; RELOC-NEXT: - Type: CUSTOM ; RELOC-NEXT: Name: name -; RELOC-NEXT: FunctionNames: +; RELOC-NEXT: FunctionNames: ; RELOC-NEXT: - Index: 0 ; RELOC-NEXT: Name: externDtor ; RELOC-NEXT: - Index: 1 diff --git a/lld/test/wasm/locals-duplicate.test b/lld/test/wasm/locals-duplicate.test index 2d6bd0df5314c..74383bf429f69 100644 --- a/lld/test/wasm/locals-duplicate.test +++ b/lld/test/wasm/locals-duplicate.test @@ -270,40 +270,40 @@ ; RELOC-NEXT: - Type: CODE ; RELOC-NEXT: Relocations: ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 4 +; RELOC-NEXT: Index: 18 ; RELOC-NEXT: Offset: 0x00000013 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 6 +; RELOC-NEXT: Index: 3 ; RELOC-NEXT: Offset: 0x0000001C ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 8 +; RELOC-NEXT: Index: 19 ; RELOC-NEXT: Offset: 0x00000025 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 0 +; RELOC-NEXT: Index: 16 ; RELOC-NEXT: Offset: 0x0000002E ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 1 +; RELOC-NEXT: Index: 0 ; RELOC-NEXT: Offset: 0x00000037 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 2 +; RELOC-NEXT: Index: 17 ; RELOC-NEXT: Offset: 0x00000040 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 16 +; RELOC-NEXT: Index: 10 ; RELOC-NEXT: Offset: 0x00000058 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 18 +; RELOC-NEXT: Index: 22 ; RELOC-NEXT: Offset: 0x00000061 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 20 +; RELOC-NEXT: Index: 23 ; RELOC-NEXT: Offset: 0x0000006A ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 12 +; RELOC-NEXT: Index: 8 ; RELOC-NEXT: Offset: 0x00000073 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 13 +; RELOC-NEXT: Index: 20 ; RELOC-NEXT: Offset: 0x0000007C ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 14 +; RELOC-NEXT: Index: 21 ; RELOC-NEXT: Offset: 0x00000085 ; RELOC-NEXT: Functions: ; RELOC-NEXT: - Index: 0 @@ -386,133 +386,133 @@ ; RELOC-NEXT: SymbolTable: ; RELOC-NEXT: - Index: 0 ; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Name: colliding_func1 -; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: Function: 0 -; RELOC-NEXT: - Index: 1 -; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: colliding_func2 ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 1 -; RELOC-NEXT: - Index: 2 -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Name: colliding_func3 -; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: Function: 2 -; RELOC-NEXT: - Index: 3 +; RELOC-NEXT: - Index: 1 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_global1A ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 3 -; RELOC-NEXT: - Index: 4 -; RELOC-NEXT: Kind: DATA -; RELOC-NEXT: Name: colliding_global1 -; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: Segment: 0 -; RELOC-NEXT: Size: 4 -; RELOC-NEXT: - Index: 5 +; RELOC-NEXT: - Index: 2 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_global2A ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 4 -; RELOC-NEXT: - Index: 6 +; RELOC-NEXT: - Index: 3 ; RELOC-NEXT: Kind: DATA ; RELOC-NEXT: Name: colliding_global2 ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Segment: 1 ; RELOC-NEXT: Size: 4 -; RELOC-NEXT: - Index: 7 +; RELOC-NEXT: - Index: 4 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_global3A ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 5 -; RELOC-NEXT: - Index: 8 -; RELOC-NEXT: Kind: DATA -; RELOC-NEXT: Name: colliding_global3 -; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: Segment: 2 -; RELOC-NEXT: Size: 4 -; RELOC-NEXT: - Index: 9 +; RELOC-NEXT: - Index: 5 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_func1A ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 6 -; RELOC-NEXT: - Index: 10 +; RELOC-NEXT: - Index: 6 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_func2A ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 7 -; RELOC-NEXT: - Index: 11 +; RELOC-NEXT: - Index: 7 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_func3A ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 8 -; RELOC-NEXT: - Index: 12 +; RELOC-NEXT: - Index: 8 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: colliding_func1 ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 9 -; RELOC-NEXT: - Index: 13 -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Name: colliding_func2 -; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: Function: 10 -; RELOC-NEXT: - Index: 14 -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Name: colliding_func3 -; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: Function: 11 -; RELOC-NEXT: - Index: 15 +; RELOC-NEXT: - Index: 9 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_global1B ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 12 -; RELOC-NEXT: - Index: 16 +; RELOC-NEXT: - Index: 10 ; RELOC-NEXT: Kind: DATA ; RELOC-NEXT: Name: colliding_global1 ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Segment: 0 ; RELOC-NEXT: Offset: 4 ; RELOC-NEXT: Size: 4 -; RELOC-NEXT: - Index: 17 +; RELOC-NEXT: - Index: 11 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_global2B ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 13 -; RELOC-NEXT: - Index: 18 -; RELOC-NEXT: Kind: DATA -; RELOC-NEXT: Name: colliding_global2 -; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: Segment: 1 -; RELOC-NEXT: Offset: 4 -; RELOC-NEXT: Size: 4 -; RELOC-NEXT: - Index: 19 +; RELOC-NEXT: - Index: 12 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_global3B ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 14 -; RELOC-NEXT: - Index: 20 -; RELOC-NEXT: Kind: DATA -; RELOC-NEXT: Name: colliding_global3 -; RELOC-NEXT: Flags: [ BINDING_LOCAL ] -; RELOC-NEXT: Segment: 2 -; RELOC-NEXT: Offset: 4 -; RELOC-NEXT: Size: 4 -; RELOC-NEXT: - Index: 21 +; RELOC-NEXT: - Index: 13 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_func1B ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 15 -; RELOC-NEXT: - Index: 22 +; RELOC-NEXT: - Index: 14 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_func2B ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 16 -; RELOC-NEXT: - Index: 23 +; RELOC-NEXT: - Index: 15 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_func3B ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 17 +; RELOC-NEXT: - Index: 16 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: colliding_func1 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: Function: 0 +; RELOC-NEXT: - Index: 17 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: colliding_func3 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: Function: 2 +; RELOC-NEXT: - Index: 18 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: colliding_global1 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: Segment: 0 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 19 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: colliding_global3 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: Segment: 2 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 20 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: colliding_func2 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: Function: 10 +; RELOC-NEXT: - Index: 21 +; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: colliding_func3 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: Function: 11 +; RELOC-NEXT: - Index: 22 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: colliding_global2 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: Segment: 1 +; RELOC-NEXT: Offset: 4 +; RELOC-NEXT: Size: 4 +; RELOC-NEXT: - Index: 23 +; RELOC-NEXT: Kind: DATA +; RELOC-NEXT: Name: colliding_global3 +; RELOC-NEXT: Flags: [ BINDING_LOCAL ] +; RELOC-NEXT: Segment: 2 +; RELOC-NEXT: Offset: 4 +; RELOC-NEXT: Size: 4 ; RELOC-NEXT: SegmentInfo: ; RELOC-NEXT: - Index: 0 ; RELOC-NEXT: Name: .bss.colliding_global1 diff --git a/lld/test/wasm/lto/relocatable-undefined.ll b/lld/test/wasm/lto/relocatable-undefined.ll new file mode 100644 index 0000000000000..b9780ee0309b2 --- /dev/null +++ b/lld/test/wasm/lto/relocatable-undefined.ll @@ -0,0 +1,36 @@ +; RUN: llvm-as %s -o %t.o +; RUN: wasm-ld -r -o %t.wasm %t.o +; RUN: obj2yaml %t.wasm | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +@missing_data = external global i32 +declare i32 @missing_func() local_unnamed_addr + +define i32 @foo() { +entry: + %0 = call i32 @missing_func() + %1 = load i32, i32* @missing_data, align 4 + ret i32 %1 +} + + +; CHECK: - Type: CUSTOM +; CHECK-NEXT: Name: linking +; CHECK-NEXT: Version: 2 +; CHECK-NEXT: SymbolTable: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: missing_func +; CHECK-NEXT: Flags: [ UNDEFINED ] +; CHECK-NEXT: Function: 0 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: foo +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 1 +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Kind: DATA +; CHECK-NEXT: Name: missing_data +; CHECK-NEXT: Flags: [ UNDEFINED ] diff --git a/lld/test/wasm/weak-alias.ll b/lld/test/wasm/weak-alias.ll index 0c856e1eafa09..a925c10ccda41 100644 --- a/lld/test/wasm/weak-alias.ll +++ b/lld/test/wasm/weak-alias.ll @@ -187,13 +187,13 @@ entry: ; RELOC-NEXT: - Type: CODE ; RELOC-NEXT: Relocations: ; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; RELOC-NEXT: Index: 4 +; RELOC-NEXT: Index: 1 ; RELOC-NEXT: Offset: 0x00000004 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; RELOC-NEXT: Index: 1 +; RELOC-NEXT: Index: 2 ; RELOC-NEXT: Offset: 0x00000013 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; RELOC-NEXT: Index: 4 +; RELOC-NEXT: Index: 1 ; RELOC-NEXT: Offset: 0x0000001C ; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB ; RELOC-NEXT: Index: 6 @@ -202,10 +202,10 @@ entry: ; RELOC-NEXT: Index: 6 ; RELOC-NEXT: Offset: 0x00000032 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 4 +; RELOC-NEXT: Index: 1 ; RELOC-NEXT: Offset: 0x0000003A ; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; RELOC-NEXT: Index: 4 +; RELOC-NEXT: Index: 1 ; RELOC-NEXT: Offset: 0x00000043 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB ; RELOC-NEXT: Index: 6 @@ -217,10 +217,10 @@ entry: ; RELOC-NEXT: Index: 6 ; RELOC-NEXT: Offset: 0x00000068 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 1 +; RELOC-NEXT: Index: 2 ; RELOC-NEXT: Offset: 0x00000070 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB -; RELOC-NEXT: Index: 1 +; RELOC-NEXT: Index: 2 ; RELOC-NEXT: Offset: 0x00000079 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB ; RELOC-NEXT: Index: 6 @@ -259,24 +259,24 @@ entry: ; RELOC-NEXT: Function: 0 ; RELOC-NEXT: - Index: 1 ; RELOC-NEXT: Kind: FUNCTION +; RELOC-NEXT: Name: alias_fn +; RELOC-NEXT: Flags: [ BINDING_WEAK ] +; RELOC-NEXT: Function: 1 +; RELOC-NEXT: - Index: 2 +; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: direct_fn ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 1 -; RELOC-NEXT: - Index: 2 +; RELOC-NEXT: - Index: 3 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: call_direct ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 2 -; RELOC-NEXT: - Index: 3 +; RELOC-NEXT: - Index: 4 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: call_alias ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 3 -; RELOC-NEXT: - Index: 4 -; RELOC-NEXT: Kind: FUNCTION -; RELOC-NEXT: Name: alias_fn -; RELOC-NEXT: Flags: [ BINDING_WEAK ] -; RELOC-NEXT: Function: 1 ; RELOC-NEXT: - Index: 5 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: call_alias_ptr diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index fab4c0c4ed8bb..ade15a19f66e0 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -434,7 +434,9 @@ static Symbol *handleUndefined(StringRef Name) { static UndefinedGlobal * createUndefinedGlobal(StringRef Name, llvm::wasm::WasmGlobalType *Type) { auto *Sym = - cast(Symtab->addUndefinedGlobal(Name, 0, nullptr, Type)); + cast(Symtab->addUndefinedGlobal(Name, Name, + DefaultModule, 0, + nullptr, Type)); Config->AllowUndefinedSymbols.insert(Sym->getName()); Sym->IsUsedInRegularObj = true; return Sym; diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp index 1145c670253c8..f5884a1beea4b 100644 --- a/lld/wasm/InputChunks.cpp +++ b/lld/wasm/InputChunks.cpp @@ -23,7 +23,7 @@ using namespace llvm::support::endian; using namespace lld; using namespace lld::wasm; -static StringRef ReloctTypeToString(uint8_t RelocType) { +static StringRef reloctTypeToString(uint8_t RelocType) { switch (RelocType) { #define WASM_RELOC(NAME, REL) \ case REL: \ @@ -77,7 +77,7 @@ void InputChunk::verifyRelocTargets() const { warn("expected LEB at relocation site be 5-byte padded"); uint32_t ExpectedValue = File->calcExpectedValue(Rel); if (ExpectedValue != ExistingValue) - warn("unexpected existing value for " + ReloctTypeToString(Rel.Type) + + warn("unexpected existing value for " + reloctTypeToString(Rel.Type) + ": existing=" + Twine(ExistingValue) + " expected=" + Twine(ExpectedValue)); } @@ -103,7 +103,7 @@ void InputChunk::writeTo(uint8_t *Buf) const { for (const WasmRelocation &Rel : Relocations) { uint8_t *Loc = Buf + Rel.Offset + Off; uint32_t Value = File->calcNewValue(Rel); - LLVM_DEBUG(dbgs() << "apply reloc: type=" << ReloctTypeToString(Rel.Type) + LLVM_DEBUG(dbgs() << "apply reloc: type=" << reloctTypeToString(Rel.Type) << " addend=" << Rel.Addend << " index=" << Rel.Index << " value=" << Value << " offset=" << Rel.Offset << "\n"); diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp index e5da23db37739..1e54272163545 100644 --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -377,11 +377,15 @@ Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) { switch (Sym.Info.Kind) { case WASM_SYMBOL_TYPE_FUNCTION: - return Symtab->addUndefinedFunction(Name, Flags, this, Sym.Signature); + return Symtab->addUndefinedFunction(Name, Sym.Info.ImportName, + Sym.Info.ImportModule, Flags, this, + Sym.Signature); case WASM_SYMBOL_TYPE_DATA: return Symtab->addUndefinedData(Name, Flags, this); case WASM_SYMBOL_TYPE_GLOBAL: - return Symtab->addUndefinedGlobal(Name, Flags, this, Sym.GlobalType); + return Symtab->addUndefinedGlobal(Name, Sym.Info.ImportName, + Sym.Info.ImportModule, Flags, this, + Sym.GlobalType); case WASM_SYMBOL_TYPE_SECTION: llvm_unreachable("section symbols cannot be undefined"); } @@ -445,7 +449,8 @@ static Symbol *createBitcodeSymbol(const lto::InputFile::Symbol &ObjSym, if (ObjSym.isUndefined()) { if (ObjSym.isExecutable()) - return Symtab->addUndefinedFunction(Name, Flags, &F, nullptr); + return Symtab->addUndefinedFunction(Name, Name, DefaultModule, Flags, &F, + nullptr); return Symtab->addUndefinedData(Name, Flags, &F); } diff --git a/lld/wasm/LTO.cpp b/lld/wasm/LTO.cpp index 96a947e29d412..e994691cceb2e 100644 --- a/lld/wasm/LTO.cpp +++ b/lld/wasm/LTO.cpp @@ -79,8 +79,9 @@ BitcodeCompiler::~BitcodeCompiler() = default; static void undefine(Symbol *S) { if (auto F = dyn_cast(S)) - replaceSymbol(F, F->getName(), 0, F->getFile(), - F->Signature); + replaceSymbol(F, F->getName(), F->getName(), + DefaultModule, 0, + F->getFile(), F->Signature); else if (isa(S)) replaceSymbol(S, S->getName(), 0, S->getFile()); else diff --git a/lld/wasm/LTO.h b/lld/wasm/LTO.h index cf726de5643ae..d771301f224dc 100644 --- a/lld/wasm/LTO.h +++ b/lld/wasm/LTO.h @@ -23,6 +23,7 @@ #include "lld/Common/LLVM.h" #include "llvm/ADT/SmallString.h" +#include "Writer.h" #include #include diff --git a/lld/wasm/MarkLive.cpp b/lld/wasm/MarkLive.cpp index 3bbd1148f6ad3..723ac4e3c6baa 100644 --- a/lld/wasm/MarkLive.cpp +++ b/lld/wasm/MarkLive.cpp @@ -85,7 +85,7 @@ void lld::wasm::markLive() { // equal to null pointer, only reachable via direct call). if (Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_SLEB || Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_I32) { - FunctionSymbol *FuncSym = cast(Sym); + auto *FuncSym = cast(Sym); if (FuncSym->hasTableIndex() && FuncSym->getTableIndex() == 0) continue; } diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp index 4123d63b74662..6b7b18d4ca77d 100644 --- a/lld/wasm/OutputSections.cpp +++ b/lld/wasm/OutputSections.cpp @@ -111,8 +111,8 @@ void CodeSection::writeTo(uint8_t *Buf) { memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size()); // Write code section bodies - parallelForEach(Functions, - [&](const InputChunk *Chunk) { Chunk->writeTo(Buf); }); + for (const InputChunk *Chunk : Functions) + Chunk->writeTo(Buf); } uint32_t CodeSection::numRelocations() const { @@ -176,7 +176,7 @@ void DataSection::writeTo(uint8_t *Buf) { // Write data section headers memcpy(Buf, DataSectionHeader.data(), DataSectionHeader.size()); - parallelForEach(Segments, [&](const OutputSegment *Segment) { + for (const OutputSegment *Segment : Segments) { // Write data segment header uint8_t *SegStart = Buf + Segment->SectionOffset; memcpy(SegStart, Segment->Header.data(), Segment->Header.size()); @@ -184,7 +184,7 @@ void DataSection::writeTo(uint8_t *Buf) { // Write segment data payload for (const InputChunk *Chunk : Segment->InputSegments) Chunk->writeTo(Buf); - }); + } } uint32_t DataSection::numRelocations() const { @@ -232,8 +232,8 @@ void CustomSection::writeTo(uint8_t *Buf) { Buf += NameData.size(); // Write custom sections payload - parallelForEach(InputSections, - [&](const InputSection *Section) { Section->writeTo(Buf); }); + for (const InputSection *Section : InputSections) + Section->writeTo(Buf); } uint32_t CustomSection::numRelocations() const { diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp index c7983196db36c..65441d293b50b 100644 --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -314,8 +314,9 @@ Symbol *SymbolTable::addDefinedEvent(StringRef Name, uint32_t Flags, return S; } -Symbol *SymbolTable::addUndefinedFunction(StringRef Name, uint32_t Flags, - InputFile *File, +Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef ImportName, + StringRef ImportModule, + uint32_t Flags, InputFile *File, const WasmSignature *Sig) { LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << " [" << (Sig ? toString(*Sig) : "none") << "]\n"); @@ -325,7 +326,8 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef Name, uint32_t Flags, std::tie(S, WasInserted) = insert(Name, File); if (WasInserted) - replaceSymbol(S, Name, Flags, File, Sig); + replaceSymbol(S, Name, ImportName, ImportModule, Flags, + File, Sig); else if (auto *Lazy = dyn_cast(S)) Lazy->fetch(); else @@ -351,7 +353,8 @@ Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags, return S; } -Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, uint32_t Flags, +Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, StringRef ImportName, + StringRef ImportModule, uint32_t Flags, InputFile *File, const WasmGlobalType *Type) { LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n"); @@ -361,7 +364,8 @@ Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, uint32_t Flags, std::tie(S, WasInserted) = insert(Name, File); if (WasInserted) - replaceSymbol(S, Name, Flags, File, Type); + replaceSymbol(S, Name, ImportName, ImportModule, Flags, + File, Type); else if (auto *Lazy = dyn_cast(S)) Lazy->fetch(); else if (S->isDefined()) diff --git a/lld/wasm/SymbolTable.h b/lld/wasm/SymbolTable.h index 5e38e30692abe..64678aee50055 100644 --- a/lld/wasm/SymbolTable.h +++ b/lld/wasm/SymbolTable.h @@ -59,11 +59,13 @@ class SymbolTable { Symbol *addDefinedEvent(StringRef Name, uint32_t Flags, InputFile *File, InputEvent *E); - Symbol *addUndefinedFunction(StringRef Name, uint32_t Flags, InputFile *File, - const WasmSignature *Signature); + Symbol *addUndefinedFunction(StringRef Name, StringRef ImportName, + StringRef ImportModule, uint32_t Flags, + InputFile *File, const WasmSignature *Signature); Symbol *addUndefinedData(StringRef Name, uint32_t Flags, InputFile *File); - Symbol *addUndefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File, - const WasmGlobalType *Type); + Symbol *addUndefinedGlobal(StringRef Name, StringRef ImportName, + StringRef ImportModule, uint32_t Flags, + InputFile *File, const WasmGlobalType *Type); void addLazy(ArchiveFile *F, const llvm::object::Archive::Symbol *Sym); diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h index 11ee66550cdcc..a065338ac1e42 100644 --- a/lld/wasm/Symbols.h +++ b/lld/wasm/Symbols.h @@ -149,13 +149,19 @@ class DefinedFunction : public FunctionSymbol { class UndefinedFunction : public FunctionSymbol { public: - UndefinedFunction(StringRef Name, uint32_t Flags, InputFile *File = nullptr, + UndefinedFunction(StringRef Name, StringRef ImportName, + StringRef ImportModule, uint32_t Flags, + InputFile *File = nullptr, const WasmSignature *Type = nullptr) - : FunctionSymbol(Name, UndefinedFunctionKind, Flags, File, Type) {} + : FunctionSymbol(Name, UndefinedFunctionKind, Flags, File, Type), + ImportName(ImportName), ImportModule(ImportModule) {} static bool classof(const Symbol *S) { return S->kind() == UndefinedFunctionKind; } + + StringRef ImportName; + StringRef ImportModule; }; class SectionSymbol : public Symbol { @@ -261,13 +267,18 @@ class DefinedGlobal : public GlobalSymbol { class UndefinedGlobal : public GlobalSymbol { public: - UndefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File = nullptr, + UndefinedGlobal(StringRef Name, StringRef ImportName, StringRef ImportModule, + uint32_t Flags, InputFile *File = nullptr, const WasmGlobalType *Type = nullptr) - : GlobalSymbol(Name, UndefinedGlobalKind, Flags, File, Type) {} + : GlobalSymbol(Name, UndefinedGlobalKind, Flags, File, Type), + ImportName(ImportName), ImportModule(ImportModule) {} static bool classof(const Symbol *S) { return S->kind() == UndefinedGlobalKind; } + + StringRef ImportName; + StringRef ImportModule; }; // Wasm events are features that suspend the current execution and transfer the diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index 819d4298fef29..902ca61ca19b7 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -39,8 +39,9 @@ using namespace llvm::wasm; using namespace lld; using namespace lld::wasm; -static constexpr int kStackAlignment = 16; -static constexpr const char *kFunctionTableName = "__indirect_function_table"; +static constexpr int StackAlignment = 16; +static constexpr const char *FunctionTableName = "__indirect_function_table"; +const char *lld::wasm::DefaultModule = "env"; namespace { @@ -155,7 +156,7 @@ void Writer::createImportSection() { if (Config->ImportMemory) { WasmImport Import; - Import.Module = "env"; + Import.Module = DefaultModule; Import.Field = "memory"; Import.Kind = WASM_EXTERNAL_MEMORY; Import.Memory.Flags = 0; @@ -172,8 +173,8 @@ void Writer::createImportSection() { if (Config->ImportTable) { uint32_t TableSize = TableBase + IndirectFunctions.size(); WasmImport Import; - Import.Module = "env"; - Import.Field = kFunctionTableName; + Import.Module = DefaultModule; + Import.Field = FunctionTableName; Import.Kind = WASM_EXTERNAL_TABLE; Import.Table.ElemType = WASM_TYPE_FUNCREF; Import.Table.Limits = {0, TableSize, 0}; @@ -182,8 +183,17 @@ void Writer::createImportSection() { for (const Symbol *Sym : ImportedSymbols) { WasmImport Import; - Import.Module = "env"; - Import.Field = Sym->getName(); + if (auto *F = dyn_cast(Sym)) { + Import.Field = F->ImportName; + Import.Module = F->ImportModule; + } else if (auto *G = dyn_cast(Sym)) { + Import.Field = G->ImportName; + Import.Module = G->ImportModule; + } else { + Import.Field = Sym->getName(); + Import.Module = DefaultModule; + } + if (auto *FunctionSym = dyn_cast(Sym)) { Import.Kind = WASM_EXTERNAL_FUNCTION; Import.SigIndex = lookupType(*FunctionSym->Signature); @@ -441,6 +451,13 @@ static uint32_t getWasmFlags(const Symbol *Sym) { Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN; if (Sym->isUndefined()) Flags |= WASM_SYMBOL_UNDEFINED; + if (auto *F = dyn_cast(Sym)) { + if (F->getName() != F->ImportName) + Flags |= WASM_SYMBOL_EXPLICIT_NAME; + } else if (auto *G = dyn_cast(Sym)) { + if (G->getName() != G->ImportName) + Flags |= WASM_SYMBOL_EXPLICIT_NAME; + } return Flags; } @@ -506,15 +523,18 @@ void Writer::createLinkingSection() { if (auto *F = dyn_cast(Sym)) { writeUleb128(Sub.OS, F->getFunctionIndex(), "index"); - if (Sym->isDefined()) + if (Sym->isDefined() || + (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) writeStr(Sub.OS, Sym->getName(), "sym name"); } else if (auto *G = dyn_cast(Sym)) { writeUleb128(Sub.OS, G->getGlobalIndex(), "index"); - if (Sym->isDefined()) + if (Sym->isDefined() || + (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) writeStr(Sub.OS, Sym->getName(), "sym name"); } else if (auto *E = dyn_cast(Sym)) { writeUleb128(Sub.OS, E->getEventIndex(), "index"); - if (Sym->isDefined()) + if (Sym->isDefined() || + (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) writeStr(Sub.OS, Sym->getName(), "sym name"); } else if (isa(Sym)) { writeStr(Sub.OS, Sym->getName(), "sym name"); @@ -663,9 +683,9 @@ void Writer::layoutMemory() { auto PlaceStack = [&]() { if (Config->Relocatable || Config->Shared) return; - MemoryPtr = alignTo(MemoryPtr, kStackAlignment); - if (Config->ZStackSize != alignTo(Config->ZStackSize, kStackAlignment)) - error("stack size must be " + Twine(kStackAlignment) + "-byte aligned"); + MemoryPtr = alignTo(MemoryPtr, StackAlignment); + if (Config->ZStackSize != alignTo(Config->ZStackSize, StackAlignment)) + error("stack size must be " + Twine(StackAlignment) + "-byte aligned"); log("mem: stack size = " + Twine(Config->ZStackSize)); log("mem: stack base = " + Twine(MemoryPtr)); MemoryPtr += Config->ZStackSize; @@ -814,7 +834,7 @@ void Writer::calculateExports() { Exports.push_back(WasmExport{"memory", WASM_EXTERNAL_MEMORY, 0}); if (!Config->Relocatable && Config->ExportTable) - Exports.push_back(WasmExport{kFunctionTableName, WASM_EXTERNAL_TABLE, 0}); + Exports.push_back(WasmExport{FunctionTableName, WASM_EXTERNAL_TABLE, 0}); unsigned FakeGlobalIndex = NumImportedGlobals + InputGlobals.size(); @@ -858,40 +878,42 @@ void Writer::assignSymtab() { StringMap SectionSymbolIndices; unsigned SymbolIndex = SymtabEntries.size(); - for (ObjFile *File : Symtab->ObjectFiles) { - LLVM_DEBUG(dbgs() << "Symtab entries: " << File->getName() << "\n"); - for (Symbol *Sym : File->getSymbols()) { - if (Sym->getFile() != File) - continue; - - if (auto *S = dyn_cast(Sym)) { - StringRef Name = S->getName(); - if (CustomSectionMapping.count(Name) == 0) - continue; - - auto SSI = SectionSymbolIndices.find(Name); - if (SSI != SectionSymbolIndices.end()) { - Sym->setOutputSymbolIndex(SSI->second); - continue; - } - SectionSymbolIndices[Name] = SymbolIndex; - CustomSectionSymbols[Name] = cast(Sym); + auto AddSymbol = [&](Symbol *Sym) { + if (auto *S = dyn_cast(Sym)) { + StringRef Name = S->getName(); + if (CustomSectionMapping.count(Name) == 0) + return; - Sym->markLive(); + auto SSI = SectionSymbolIndices.find(Name); + if (SSI != SectionSymbolIndices.end()) { + Sym->setOutputSymbolIndex(SSI->second); + return; } - // (Since this is relocatable output, GC is not performed so symbols must - // be live.) - assert(Sym->isLive()); - Sym->setOutputSymbolIndex(SymbolIndex++); - SymtabEntries.emplace_back(Sym); + SectionSymbolIndices[Name] = SymbolIndex; + CustomSectionSymbols[Name] = cast(Sym); + + Sym->markLive(); } - } - // For the moment, relocatable output doesn't contain any synthetic functions, - // so no need to look through the Symtab for symbols not referenced by - // Symtab->ObjectFiles. + // (Since this is relocatable output, GC is not performed so symbols must + // be live.) + assert(Sym->isLive()); + Sym->setOutputSymbolIndex(SymbolIndex++); + SymtabEntries.emplace_back(Sym); + }; + + for (Symbol *Sym : Symtab->getSymbols()) + if (!Sym->isLazy()) + AddSymbol(Sym); + + for (ObjFile *File : Symtab->ObjectFiles) { + LLVM_DEBUG(dbgs() << "Local symtab entries: " << File->getName() << "\n"); + for (Symbol *Sym : File->getSymbols()) + if (Sym->isLocal()) + AddSymbol(Sym); + } } uint32_t Writer::lookupType(const WasmSignature &Sig) { diff --git a/lld/wasm/Writer.h b/lld/wasm/Writer.h index a931ba9c29a89..e62f470642285 100644 --- a/lld/wasm/Writer.h +++ b/lld/wasm/Writer.h @@ -15,6 +15,8 @@ namespace wasm { void writeResult(); +extern const char *DefaultModule; + } // namespace wasm } // namespace lld diff --git a/lldb/cmake/modules/AddLLDB.cmake b/lldb/cmake/modules/AddLLDB.cmake index f7cac3dad8375..f82c11d3d317e 100644 --- a/lldb/cmake/modules/AddLLDB.cmake +++ b/lldb/cmake/modules/AddLLDB.cmake @@ -88,7 +88,9 @@ function(add_lldb_library name) # Hack: only some LLDB libraries depend on the clang autogenerated headers, # but it is simple enough to make all of LLDB depend on some of those # headers without negatively impacting much of anything. - add_dependencies(${name} clang-tablegen-targets) + if(NOT LLDB_BUILT_STANDALONE) + add_dependencies(${name} clang-tablegen-targets) + endif() # Add in any extra C++ compilation flags for this library. target_compile_options(${name} PRIVATE ${PARAM_EXTRA_CXXFLAGS}) diff --git a/lldb/cmake/modules/LLDBStandalone.cmake b/lldb/cmake/modules/LLDBStandalone.cmake index e63b2694e6a4c..a9059dd5f9eb4 100644 --- a/lldb/cmake/modules/LLDBStandalone.cmake +++ b/lldb/cmake/modules/LLDBStandalone.cmake @@ -58,7 +58,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) set(LLVM_DIR ${LLVM_OBJ_ROOT}/cmake/modules/CMakeFiles CACHE PATH "Path to LLVM build tree CMake files") set(LLVM_BINARY_DIR ${LLVM_OBJ_ROOT} CACHE PATH "Path to LLVM build tree") set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree") - set(LLVM_EXTERNAL_LIT ${LLVM_TOOLS_BINARY_DIR}/llvm-lit CACHE PATH "Path to llvm-lit") + set(LLVM_DEFAULT_EXTERNAL_LIT ${LLVM_TOOLS_BINARY_DIR}/llvm-lit CACHE PATH "Path to llvm-lit") find_program(LLVM_TABLEGEN_EXE "llvm-tblgen" ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH) diff --git a/lldb/include/lldb/Host/openbsd/HostInfoOpenBSD.h b/lldb/include/lldb/Host/openbsd/HostInfoOpenBSD.h index 5a0388ffdd977..809a6f4461f51 100644 --- a/lldb/include/lldb/Host/openbsd/HostInfoOpenBSD.h +++ b/lldb/include/lldb/Host/openbsd/HostInfoOpenBSD.h @@ -12,12 +12,13 @@ #include "lldb/Host/posix/HostInfoPosix.h" #include "lldb/Utility/FileSpec.h" +#include "llvm/Support/VersionTuple.h" namespace lldb_private { class HostInfoOpenBSD : public HostInfoPosix { public: - static bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update); + static llvm::VersionTuple GetOSVersion(); static bool GetOSBuildString(std::string &s); static bool GetOSKernelDescription(std::string &s); static FileSpec GetProgramFileSpec(); diff --git a/lldb/lit/CMakeLists.txt b/lldb/lit/CMakeLists.txt index 1ac013b2eed30..804e950b3bb03 100644 --- a/lldb/lit/CMakeLists.txt +++ b/lldb/lit/CMakeLists.txt @@ -26,9 +26,6 @@ list(APPEND LLDB_TEST_DEPS llvm-config llvm-mc llvm-objcopy - FileCheck - count - not ) if(TARGET lld) @@ -55,6 +52,14 @@ configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/Suite/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/Suite/lit.site.cfg) +if(NOT LLDB_BUILT_STANDALONE) + list(APPEND LLDB_TEST_DEPS + FileCheck + count + not + ) +endif() + add_lit_testsuite(check-lldb-lit "Running lldb lit test suite" ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${LLDB_TEST_DEPS} diff --git a/lldb/lit/Driver/TestConvenienceVariables.test b/lldb/lit/Driver/TestConvenienceVariables.test index 99536e4c02907..a7b6faa34cb39 100644 --- a/lldb/lit/Driver/TestConvenienceVariables.test +++ b/lldb/lit/Driver/TestConvenienceVariables.test @@ -1,3 +1,4 @@ +REQUIRES: python RUN: %build %p/Inputs/hello.cpp -o %t RUN: %lldb %t -s %p/Inputs/convenience.in -o quit | FileCheck %s @@ -19,4 +20,4 @@ CHECK: 8 CHECK: script lldb.frame.GetLineEntry().GetFileSpec().GetFilename() CHECK: hello.c CHECK: script lldb.frame.GetFunctionName() -CHECK: main \ No newline at end of file +CHECK: main diff --git a/lldb/lit/SymbolFile/NativePDB/globals-fundamental.cpp b/lldb/lit/SymbolFile/NativePDB/globals-fundamental.cpp index 8891eddf66896..b3d3e37fbebbc 100644 --- a/lldb/lit/SymbolFile/NativePDB/globals-fundamental.cpp +++ b/lldb/lit/SymbolFile/NativePDB/globals-fundamental.cpp @@ -1,5 +1,5 @@ // clang-format off -// REQUIRES: lld +// REQUIRES: lld, python // Test that we can display tag types. // RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s diff --git a/lldb/lit/helper/build.py b/lldb/lit/helper/build.py index 26f321d709f8b..fd52b7db4b869 100755 --- a/lldb/lit/helper/build.py +++ b/lldb/lit/helper/build.py @@ -283,19 +283,17 @@ def __init__(self, toolchain_type, args): print('Using alternate compiler "{0}" to match selected target.'.format(self.compiler)) if self.mode == 'link' or self.mode == 'compile-and-link': - self.linker = self._find_linker('link') if toolchain_type == 'msvc' else self._find_linker('lld-link') + self.linker = self._find_linker('link') if toolchain_type == 'msvc' else self._find_linker('lld-link', args.tools_dir) if not self.linker: raise ValueError('Unable to find an appropriate linker.') self.compile_env, self.link_env = self._get_visual_studio_environment() - def _find_linker(self, name): - if sys.platform == 'win32': - name = name + '.exe' + def _find_linker(self, name, search_paths=[]): compiler_dir = os.path.dirname(self.compiler) - linker_path = os.path.join(compiler_dir, name) - if not os.path.exists(linker_path): - raise ValueError('Could not find \'{}\''.format(linker_path)) + linker_path = find_executable(name, [compiler_dir] + search_paths) + if linker_path is None: + raise ValueError('Could not find \'{}\''.format(name)) return linker_path def _get_vc_install_dir(self): diff --git a/lldb/lit/helper/toolchain.py b/lldb/lit/helper/toolchain.py index 938f343badcc2..11aa0bcf4e7c7 100644 --- a/lldb/lit/helper/toolchain.py +++ b/lldb/lit/helper/toolchain.py @@ -51,7 +51,8 @@ def use_lldb_substitutions(config): llvm_config.add_tool_substitutions(primary_tools, [config.lldb_tools_dir]) - if lldbmi.was_resolved: + # lldb-mi always fails without Python support + if lldbmi.was_resolved and not config.lldb_disable_python: config.available_features.add('lldb-mi') def _use_msvc_substitutions(config): diff --git a/lldb/lit/lit.cfg.py b/lldb/lit/lit.cfg.py index e1db7621e3280..ff4e60e5b4bd5 100644 --- a/lldb/lit/lit.cfg.py +++ b/lldb/lit/lit.cfg.py @@ -73,3 +73,6 @@ def calculate_arch_features(arch_string): if os.path.isdir(cachedir): print("Deleting module cache at %s."%cachedir) shutil.rmtree(cachedir) + +if not config.lldb_disable_python: + config.available_features.add('python') diff --git a/lldb/lit/lit.site.cfg.py.in b/lldb/lit/lit.site.cfg.py.in index fbf88efcc2f58..738b25d09310e 100644 --- a/lldb/lit/lit.site.cfg.py.in +++ b/lldb/lit/lit.site.cfg.py.in @@ -17,6 +17,7 @@ config.python_executable = "@PYTHON_EXECUTABLE@" config.have_zlib = @LLVM_ENABLE_ZLIB@ config.host_triple = "@LLVM_HOST_TRIPLE@" config.lldb_bitness = 64 if @LLDB_IS_64_BITS@ else 32 +config.lldb_disable_python = @LLDB_DISABLE_PYTHON@ # Support substitution of the tools and libs dirs with user parameters. This is # used when we can't determine the tool dir at configuration time. diff --git a/lldb/lit/tools/lldb-mi/lit.local.cfg b/lldb/lit/tools/lldb-mi/lit.local.cfg new file mode 100644 index 0000000000000..ff28e265b3f13 --- /dev/null +++ b/lldb/lit/tools/lldb-mi/lit.local.cfg @@ -0,0 +1,2 @@ +if not "lldb-mi" in config.available_features: + config.unsupported = True diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp index 8e18458b90c20..98a39ea95315a 100644 --- a/lldb/source/Core/Value.cpp +++ b/lldb/source/Core/Value.cpp @@ -210,31 +210,35 @@ bool Value::ValueOf(ExecutionContext *exe_ctx) { } uint64_t Value::GetValueByteSize(Status *error_ptr, ExecutionContext *exe_ctx) { + uint64_t byte_size = 0; + switch (m_context_type) { case eContextTypeRegisterInfo: // RegisterInfo * - if (GetRegisterInfo()) { - if (error_ptr) - error_ptr->Clear(); - return GetRegisterInfo()->byte_size; - } + if (GetRegisterInfo()) + byte_size = GetRegisterInfo()->byte_size; break; case eContextTypeInvalid: case eContextTypeLLDBType: // Type * case eContextTypeVariable: // Variable * { - auto *scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; - if (llvm::Optional size = GetCompilerType().GetByteSize(scope)) { - if (error_ptr) - error_ptr->Clear(); - return *size; - } - break; + const CompilerType &ast_type = GetCompilerType(); + if (ast_type.IsValid()) + if (llvm::Optional size = ast_type.GetByteSize( + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr)) + byte_size = *size; + } break; } + + if (error_ptr) { + if (byte_size == 0) { + if (error_ptr->Success()) + error_ptr->SetErrorString("Unable to determine byte size."); + } else { + error_ptr->Clear(); + } } - if (error_ptr && error_ptr->Success()) - error_ptr->SetErrorString("Unable to determine byte size."); - return 0; + return byte_size; } const CompilerType &Value::GetCompilerType() { diff --git a/lldb/source/Host/common/MainLoop.cpp b/lldb/source/Host/common/MainLoop.cpp index 39c353e6717ec..337ddd51dd6b9 100644 --- a/lldb/source/Host/common/MainLoop.cpp +++ b/lldb/source/Host/common/MainLoop.cpp @@ -108,8 +108,14 @@ Status MainLoop::RunImpl::Poll() { num_events = kevent(loop.m_kqueue, in_events.data(), in_events.size(), out_events, llvm::array_lengthof(out_events), nullptr); - if (num_events < 0) - return Status("kevent() failed with error %d\n", num_events); + if (num_events < 0) { + if (errno == EINTR) { + // in case of EINTR, let the main loop run one iteration + // we need to zero num_events to avoid assertions failing + num_events = 0; + } else + return Status(errno, eErrorTypePOSIX); + } return Status(); } diff --git a/lldb/source/Host/openbsd/Host.cpp b/lldb/source/Host/openbsd/Host.cpp index cba1f4ee6b7cb..8db0498d14b56 100644 --- a/lldb/source/Host/openbsd/Host.cpp +++ b/lldb/source/Host/openbsd/Host.cpp @@ -68,8 +68,7 @@ GetOpenBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, cstr = data.GetCStr(&offset); if (cstr) { - process_info.GetExecutableFile().SetFile(cstr, false, - FileSpec::Style::native); + process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native); if (!(match_info_ptr == NULL || NameMatches( diff --git a/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp b/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp index 548958899322c..cf7acb79da00e 100644 --- a/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp +++ b/lldb/source/Host/openbsd/HostInfoOpenBSD.cpp @@ -17,16 +17,17 @@ using namespace lldb_private; -bool HostInfoOpenBSD::GetOSVersion(uint32_t &major, uint32_t &minor, - uint32_t &update) { +llvm::VersionTuple HostInfoOpenBSD::GetOSVersion() { struct utsname un; ::memset(&un, 0, sizeof(utsname)); if (uname(&un) < 0) - return false; + return llvm::VersionTuple(); - int status = sscanf(un.release, "%u.%u", &major, &minor); - return status == 2; + unsigned major, minor; + if (2 == sscanf(un.release, "%u.%u", &major, &minor)) + return llvm::VersionTuple(major, minor); + return llvm::VersionTuple(); } bool HostInfoOpenBSD::GetOSBuildString(std::string &s) { diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp index 50bf29b094df0..c7313e6f98773 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp @@ -19,9 +19,26 @@ #include "Plugins/Process/Utility/RegisterContextLinux_i386.h" #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" - +#include #include +// Newer toolchains define __get_cpuid_count in cpuid.h, but some +// older-but-still-supported ones (e.g. gcc 5.4.0) don't, so we +// define it locally here, following the definition in clang/lib/Headers. +static inline int get_cpuid_count(unsigned int __leaf, + unsigned int __subleaf, + unsigned int *__eax, unsigned int *__ebx, + unsigned int *__ecx, unsigned int *__edx) +{ + unsigned int __max_leaf = __get_cpuid_max(__leaf & 0x80000000, 0); + + if (__max_leaf == 0 || __max_leaf < __leaf) + return 0; + + __cpuid_count(__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx); + return 1; +} + using namespace lldb_private; using namespace lldb_private::process_linux; @@ -268,12 +285,29 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) { } } +// Return the size of the XSTATE area supported on this cpu. It is necessary to +// allocate the full size of the area even if we do not use/recognise all of it +// because ptrace(PTRACE_SETREGSET, NT_X86_XSTATE) will refuse to write to it if +// we do not pass it a buffer of sufficient size. The size is always at least +// sizeof(FPR) so that the allocated buffer can be safely cast to FPR*. +static std::size_t GetXSTATESize() { + unsigned int eax, ebx, ecx, edx; + // First check whether the XSTATE are is supported at all. + if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx) || !(ecx & bit_XSAVE)) + return sizeof(FPR); + + // Then fetch the maximum size of the area. + if (!get_cpuid_count(0x0d, 0, &eax, &ebx, &ecx, &edx)) + return sizeof(FPR); + return std::max(ecx, sizeof(FPR)); +} + NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64( const ArchSpec &target_arch, NativeThreadProtocol &native_thread) : NativeRegisterContextLinux(native_thread, CreateRegisterInfoInterface(target_arch)), - m_xstate_type(XStateType::Invalid), m_fpr(), m_iovec(), m_ymm_set(), - m_mpx_set(), m_reg_info(), m_gpr_x86_64() { + m_xstate_type(XStateType::Invalid), m_ymm_set(), m_mpx_set(), + m_reg_info(), m_gpr_x86_64() { // Set up data about ranges of valid registers. switch (target_arch.GetMachine()) { case llvm::Triple::x86: @@ -329,14 +363,13 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64( break; } - // Initialize m_iovec to point to the buffer and buffer size using the - // conventions of Berkeley style UIO structures, as required by PTRACE - // extensions. - m_iovec.iov_base = &m_fpr; - m_iovec.iov_len = sizeof(m_fpr); + std::size_t xstate_size = GetXSTATESize(); + m_xstate.reset(static_cast(std::malloc(xstate_size))); + m_iovec.iov_base = m_xstate.get(); + m_iovec.iov_len = xstate_size; // Clear out the FPR state. - ::memset(&m_fpr, 0, sizeof(m_fpr)); + ::memset(m_xstate.get(), 0, xstate_size); // Store byte offset of fctrl (i.e. first register of FPR) const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl"); @@ -439,14 +472,17 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, if (byte_order != lldb::eByteOrderInvalid) { if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) - reg_value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_st].bytes, - reg_info->byte_size, byte_order); + reg_value.SetBytes( + m_xstate->fxsave.stmm[reg - m_reg_info.first_st].bytes, + reg_info->byte_size, byte_order); if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) - reg_value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_mm].bytes, - reg_info->byte_size, byte_order); + reg_value.SetBytes( + m_xstate->fxsave.stmm[reg - m_reg_info.first_mm].bytes, + reg_info->byte_size, byte_order); if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) - reg_value.SetBytes(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, - reg_info->byte_size, byte_order); + reg_value.SetBytes( + m_xstate->fxsave.xmm[reg - m_reg_info.first_xmm].bytes, + reg_info->byte_size, byte_order); if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) { // Concatenate ymm using the register halves in xmm.bytes and // ymmh.bytes @@ -488,7 +524,7 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, return error; } - // Get pointer to m_fpr.fxsave variable and set the data from it. + // Get pointer to m_xstate->fxsave variable and set the data from it. // Byte offsets of all registers are calculated wrt 'UserArea' structure. // However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)} @@ -499,9 +535,9 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, // Since, FPR structure is also one of the member of UserArea structure. // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - // byte_offset(fctrl wrt UserArea) - assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr)); - uint8_t *src = - (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea; + assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(FPR)); + uint8_t *src = (uint8_t *)m_xstate.get() + reg_info->byte_offset - + m_fctrl_offset_in_userarea; switch (reg_info->byte_size) { case 1: reg_value.SetUInt8(*(uint8_t *)src); @@ -527,7 +563,7 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, void NativeRegisterContextLinux_x86_64::UpdateXSTATEforWrite( uint32_t reg_index) { - XSAVE_HDR::XFeature &xstate_bv = m_fpr.xsave.header.xstate_bv; + XSAVE_HDR::XFeature &xstate_bv = m_xstate->xsave.header.xstate_bv; if (IsFPR(reg_index)) { // IsFPR considers both %st and %xmm registers as floating point, but these // map to two features. Set both flags, just in case. @@ -559,15 +595,15 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister( if (IsFPR(reg_index) || IsAVX(reg_index) || IsMPX(reg_index)) { if (reg_info->encoding == lldb::eEncodingVector) { if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st) - ::memcpy(m_fpr.fxsave.stmm[reg_index - m_reg_info.first_st].bytes, + ::memcpy(m_xstate->fxsave.stmm[reg_index - m_reg_info.first_st].bytes, reg_value.GetBytes(), reg_value.GetByteSize()); if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm) - ::memcpy(m_fpr.fxsave.stmm[reg_index - m_reg_info.first_mm].bytes, + ::memcpy(m_xstate->fxsave.stmm[reg_index - m_reg_info.first_mm].bytes, reg_value.GetBytes(), reg_value.GetByteSize()); if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm) - ::memcpy(m_fpr.fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes, + ::memcpy(m_xstate->fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes, reg_value.GetBytes(), reg_value.GetByteSize()); if (reg_index >= m_reg_info.first_ymm && @@ -596,7 +632,7 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister( return Status("CopyMPXtoXSTATE() failed"); } } else { - // Get pointer to m_fpr.fxsave variable and set the data to it. + // Get pointer to m_xstate->fxsave variable and set the data to it. // Byte offsets of all registers are calculated wrt 'UserArea' structure. // However, WriteFPR() takes m_fpr (of type FPR structure) and writes @@ -608,8 +644,8 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister( // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - // byte_offset(fctrl wrt UserArea) assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < - sizeof(m_fpr)); - uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset - + sizeof(FPR)); + uint8_t *dst = (uint8_t *)m_xstate.get() + reg_info->byte_offset - m_fctrl_offset_in_userarea; switch (reg_info->byte_size) { case 1: @@ -667,7 +703,7 @@ Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues( ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize()); dst += GetRegisterInfoInterface().GetGPRSize(); if (m_xstate_type == XStateType::FXSAVE) - ::memcpy(dst, &m_fpr.fxsave, sizeof(m_fpr.fxsave)); + ::memcpy(dst, &m_xstate->fxsave, sizeof(m_xstate->fxsave)); else if (m_xstate_type == XStateType::XSAVE) { lldb::ByteOrder byte_order = GetByteOrder(); @@ -700,7 +736,7 @@ Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues( } } // Copy the extended register state including the assembled ymm registers. - ::memcpy(dst, &m_fpr, sizeof(m_fpr)); + ::memcpy(dst, m_xstate.get(), sizeof(FPR)); } else { assert(false && "how do we save the floating point registers?"); error.SetErrorString("unsure how to save the floating point registers"); @@ -758,9 +794,9 @@ Status NativeRegisterContextLinux_x86_64::WriteAllRegisterValues( src += GetRegisterInfoInterface().GetGPRSize(); if (m_xstate_type == XStateType::FXSAVE) - ::memcpy(&m_fpr.fxsave, src, sizeof(m_fpr.fxsave)); + ::memcpy(&m_xstate->fxsave, src, sizeof(m_xstate->fxsave)); else if (m_xstate_type == XStateType::XSAVE) - ::memcpy(&m_fpr.xsave, src, sizeof(m_fpr.xsave)); + ::memcpy(&m_xstate->xsave, src, sizeof(m_xstate->xsave)); error = WriteFPR(); if (error.Fail()) @@ -814,12 +850,12 @@ bool NativeRegisterContextLinux_x86_64::IsCPUFeatureAvailable( return true; case RegSet::avx: // Check if CPU has AVX and if there is kernel support, by // reading in the XCR0 area of XSAVE. - if ((m_fpr.xsave.i387.xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX) + if ((m_xstate->xsave.i387.xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX) return true; break; case RegSet::mpx: // Check if CPU has MPX and if there is kernel support, by // reading in the XCR0 area of XSAVE. - if ((m_fpr.xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX) + if ((m_xstate->xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX) return true; break; } @@ -856,10 +892,10 @@ Status NativeRegisterContextLinux_x86_64::WriteFPR() { switch (m_xstate_type) { case XStateType::FXSAVE: return WriteRegisterSet( - &m_iovec, sizeof(m_fpr.fxsave), + &m_iovec, sizeof(m_xstate->fxsave), fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture())); case XStateType::XSAVE: - return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xsave), NT_X86_XSTATE); + return WriteRegisterSet(&m_iovec, sizeof(m_xstate->xsave), NT_X86_XSTATE); default: return Status("Unrecognized FPR type."); } @@ -879,11 +915,11 @@ bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM( if (byte_order == lldb::eByteOrderLittle) { ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, - m_fpr.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, + m_xstate->fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - m_fpr.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, + m_xstate->xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } @@ -891,10 +927,10 @@ bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM( if (byte_order == lldb::eByteOrderBig) { ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - m_fpr.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, + m_xstate->fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, - m_fpr.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, + m_xstate->xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } @@ -907,19 +943,19 @@ bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE( return false; if (byte_order == lldb::eByteOrderLittle) { - ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + ::memcpy(m_xstate->fxsave.xmm[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); - ::memcpy(m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + ::memcpy(m_xstate->xsave.ymmh[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), sizeof(YMMHReg)); return true; } if (byte_order == lldb::eByteOrderBig) { - ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + ::memcpy(m_xstate->fxsave.xmm[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), sizeof(XMMReg)); - ::memcpy(m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + ::memcpy(m_xstate->xsave.ymmh[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } @@ -929,7 +965,7 @@ bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE( void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() { switch (m_xstate_type) { case XStateType::FXSAVE: - return &m_fpr.fxsave; + return &m_xstate->fxsave; case XStateType::XSAVE: return &m_iovec; default: @@ -940,7 +976,7 @@ void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() { size_t NativeRegisterContextLinux_x86_64::GetFPRSize() { switch (m_xstate_type) { case XStateType::FXSAVE: - return sizeof(m_fpr.fxsave); + return sizeof(m_xstate->fxsave); case XStateType::XSAVE: return sizeof(m_iovec); default: @@ -953,14 +989,14 @@ Status NativeRegisterContextLinux_x86_64::ReadFPR() { // Probe XSAVE and if it is not supported fall back to FXSAVE. if (m_xstate_type != XStateType::FXSAVE) { - error = ReadRegisterSet(&m_iovec, sizeof(m_fpr.xsave), NT_X86_XSTATE); + error = ReadRegisterSet(&m_iovec, sizeof(m_xstate->xsave), NT_X86_XSTATE); if (!error.Fail()) { m_xstate_type = XStateType::XSAVE; return error; } } error = ReadRegisterSet( - &m_iovec, sizeof(m_fpr.xsave), + &m_iovec, sizeof(m_xstate->xsave), fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture())); if (!error.Fail()) { m_xstate_type = XStateType::FXSAVE; @@ -982,11 +1018,11 @@ bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoMPX(uint32_t reg) { if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) { ::memcpy(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, - m_fpr.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, + m_xstate->xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof(MPXReg)); } else { ::memcpy(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, - m_fpr.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, + m_xstate->xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr)); } return true; @@ -997,10 +1033,10 @@ bool NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) { return false; if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) { - ::memcpy(m_fpr.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, + ::memcpy(m_xstate->xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof(MPXReg)); } else { - ::memcpy(m_fpr.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, + ::memcpy(m_xstate->xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr)); } return true; diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h index 9dcf82f50a458..2970326306e53 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h @@ -109,7 +109,8 @@ class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux { // Private member variables. mutable XStateType m_xstate_type; - FPR m_fpr; // Extended States Area, named FPR for historical reasons. + std::unique_ptr + m_xstate; // Extended States Area, named FPR for historical reasons. struct iovec m_iovec; YMM m_ymm_set; MPX m_mpx_set; diff --git a/lldb/source/Plugins/Process/NetBSD/CMakeLists.txt b/lldb/source/Plugins/Process/NetBSD/CMakeLists.txt index e131e6d70468b..586725bb7a566 100644 --- a/lldb/source/Plugins/Process/NetBSD/CMakeLists.txt +++ b/lldb/source/Plugins/Process/NetBSD/CMakeLists.txt @@ -11,6 +11,7 @@ add_lldb_library(lldbPluginProcessNetBSD PLUGIN lldbUtility lldbPluginProcessPOSIX lldbPluginProcessUtility + util LINK_COMPONENTS Support ) diff --git a/lldb/unittests/Host/MainLoopTest.cpp b/lldb/unittests/Host/MainLoopTest.cpp index 8f2c55c2416df..6b7a5cf1f55de 100644 --- a/lldb/unittests/Host/MainLoopTest.cpp +++ b/lldb/unittests/Host/MainLoopTest.cpp @@ -137,4 +137,28 @@ TEST_F(MainLoopTest, Signal) { ASSERT_TRUE(loop.Run().Success()); ASSERT_EQ(1u, callback_count); } + +// Test that a signal which is not monitored by the MainLoop does not +// cause a premature exit. +TEST_F(MainLoopTest, UnmonitoredSignal) { + MainLoop loop; + Status error; + struct sigaction sa; + sa.sa_sigaction = [](int, siginfo_t *, void *) { }; + sa.sa_flags = SA_SIGINFO; // important: no SA_RESTART + sigemptyset(&sa.sa_mask); + ASSERT_EQ(0, sigaction(SIGUSR2, &sa, nullptr)); + + auto handle = loop.RegisterSignal(SIGUSR1, make_callback(), error); + ASSERT_TRUE(error.Success()); + std::thread killer([]() { + sleep(1); + kill(getpid(), SIGUSR2); + sleep(1); + kill(getpid(), SIGUSR1); + }); + ASSERT_TRUE(loop.Run().Success()); + killer.join(); + ASSERT_EQ(1u, callback_count); +} #endif diff --git a/llvm/.gitignore b/llvm/.gitignore index 0aa0a8a80a966..be58944c9b3a1 100644 --- a/llvm/.gitignore +++ b/llvm/.gitignore @@ -72,6 +72,8 @@ docs/_build # VS2017 and VSCode config files. .vscode .vs +# clangd index +.clangd #==============================================================================# # Files created in tree by the Go bindings. diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index b144be50f8431..81c2bab39ec96 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -18,10 +18,10 @@ if(NOT DEFINED LLVM_VERSION_MINOR) set(LLVM_VERSION_MINOR 0) endif() if(NOT DEFINED LLVM_VERSION_PATCH) - set(LLVM_VERSION_PATCH 0) + set(LLVM_VERSION_PATCH 1) endif() if(NOT DEFINED LLVM_VERSION_SUFFIX) - set(LLVM_VERSION_SUFFIX svn) + set(LLVM_VERSION_SUFFIX "") endif() if (NOT PACKAGE_VERSION) @@ -383,9 +383,12 @@ option(LLVM_ENABLE_EXPENSIVE_CHECKS "Enable expensive checks" OFF) set(LLVM_ABI_BREAKING_CHECKS "WITH_ASSERTS" CACHE STRING "Enable abi-breaking checks. Can be WITH_ASSERTS, FORCE_ON or FORCE_OFF.") -option(LLVM_FORCE_USE_OLD_HOST_TOOLCHAIN +option(LLVM_FORCE_USE_OLD_TOOLCHAIN "Set to ON to force using an old, unsupported host toolchain." OFF) +option(LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN + "Set to ON to only warn when using a toolchain which is about to be deprecated, instead of emitting an error." OFF) + option(LLVM_USE_INTEL_JITEVENTS "Use Intel JIT API to inform Intel(R) VTune(TM) Amplifier XE 2011 about JIT code" OFF) diff --git a/llvm/bindings/go/llvm/ir.go b/llvm/bindings/go/llvm/ir.go index 1872a2ffe5109..3e85137a751a0 100644 --- a/llvm/bindings/go/llvm/ir.go +++ b/llvm/bindings/go/llvm/ir.go @@ -1263,7 +1263,7 @@ func (v Value) Indices() []uint32 { num := C.LLVMGetNumIndices(v.C) indicesPtr := C.LLVMGetIndices(v.C) // https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices - rawIndices := (*[1 << 30]C.uint)(unsafe.Pointer(indicesPtr))[:num:num] + rawIndices := (*[1 << 20]C.uint)(unsafe.Pointer(indicesPtr))[:num:num] indices := make([]uint32, num) for i := range indices { indices[i] = uint32(rawIndices[i]) diff --git a/llvm/bindings/go/llvm/ir_test.go b/llvm/bindings/go/llvm/ir_test.go index 10f4968ba89f2..4d559c3367158 100644 --- a/llvm/bindings/go/llvm/ir_test.go +++ b/llvm/bindings/go/llvm/ir_test.go @@ -31,7 +31,7 @@ func testAttribute(t *testing.T, name string) { fn.AddFunctionAttr(attr) newattr := fn.GetEnumFunctionAttribute(kind) if attr != newattr { - t.Errorf("got attribute mask %d, want %d", newattr, attr) + t.Errorf("got attribute %p, want %p", newattr.C, attr.C) } text := mod.String() @@ -42,7 +42,7 @@ func testAttribute(t *testing.T, name string) { fn.RemoveEnumFunctionAttribute(kind) newattr = fn.GetEnumFunctionAttribute(kind) if !newattr.IsNil() { - t.Errorf("got attribute mask %d, want 0", newattr) + t.Errorf("got attribute %p, want 0", newattr.C) } } diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake index 4dbc0ddaf4f01..1a417447278b8 100644 --- a/llvm/cmake/modules/AddLLVM.cmake +++ b/llvm/cmake/modules/AddLLVM.cmake @@ -855,6 +855,7 @@ if(NOT LLVM_TOOLCHAIN_TOOLS) llvm-lib llvm-objdump llvm-rc + llvm-profdata ) endif() @@ -1280,7 +1281,6 @@ function(get_llvm_lit_path base_dir file_name) cmake_parse_arguments(ARG "ALLOW_EXTERNAL" "" "" ${ARGN}) if (ARG_ALLOW_EXTERNAL) - set(LLVM_DEFAULT_EXTERNAL_LIT "${LLVM_EXTERNAL_LIT}") set (LLVM_EXTERNAL_LIT "" CACHE STRING "Command used to spawn lit") if ("${LLVM_EXTERNAL_LIT}" STREQUAL "") set(LLVM_EXTERNAL_LIT "${LLVM_DEFAULT_EXTERNAL_LIT}") diff --git a/llvm/cmake/modules/CheckCompilerVersion.cmake b/llvm/cmake/modules/CheckCompilerVersion.cmake index adf500ad53a72..b1cb552742289 100644 --- a/llvm/cmake/modules/CheckCompilerVersion.cmake +++ b/llvm/cmake/modules/CheckCompilerVersion.cmake @@ -1,52 +1,94 @@ -# Check if the host compiler is new enough. LLVM requires at least GCC 4.8, -# MSVC 2015 (Update 3), or Clang 3.1. +# Check if the host compiler is new enough. +# These versions are updated based on the following policy: +# llvm.org/docs/DeveloperPolicy.html#toolchain include(CheckCXXSourceCompiles) -if(NOT DEFINED LLVM_COMPILER_CHECKED) - set(LLVM_COMPILER_CHECKED ON) +set(GCC_MIN 4.8) +set(GCC_SOFT_ERROR 5.1) +set(CLANG_MIN 3.1) +set(CLANG_SOFT_ERROR 3.5) +set(APPLECLANG_MIN 3.1) +set(APPLECLANG_SOFT_ERROR 6.0) +set(MSVC_MIN 19.00.24213.1) +set(MSVC_SOFT_ERROR 19.1) - if(NOT LLVM_FORCE_USE_OLD_TOOLCHAIN) - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8) - message(FATAL_ERROR "Host GCC version must be at least 4.8!") - endif() - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.1) - message(FATAL_ERROR "Host Clang version must be at least 3.1!") - endif() +# Map the above GCC versions to dates: https://gcc.gnu.org/develop.html#timeline +set(GCC_MIN_DATE 20130322) +set(GCC_SOFT_ERROR_DATE 20150422) - if (CMAKE_CXX_SIMULATE_ID MATCHES "MSVC") - if (CMAKE_CXX_SIMULATE_VERSION VERSION_LESS 19.0) - message(FATAL_ERROR "Host Clang must have at least -fms-compatibility-version=19.0") - endif() - set(CLANG_CL 1) - elseif(NOT LLVM_ENABLE_LIBCXX) - # Otherwise, test that we aren't using too old of a version of libstdc++ - # with the Clang compiler. This is tricky as there is no real way to - # check the version of libstdc++ directly. Instead we test for a known - # bug in libstdc++4.6 that is fixed in libstdc++4.7. - set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) - set(OLD_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++0x") - check_cxx_source_compiles(" -#include -std::atomic x(0.0f); -int main() { return (float)x; }" - LLVM_NO_OLD_LIBSTDCXX) - if(NOT LLVM_NO_OLD_LIBSTDCXX) - message(FATAL_ERROR "Host Clang must be able to find libstdc++4.8 or newer!") - endif() - set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) - set(CMAKE_REQUIRED_LIBRARIES ${OLD_CMAKE_REQUIRED_LIBRARIES}) - endif() - elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0) - message(FATAL_ERROR "Host Visual Studio must be at least 2015") - elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.00.24213.1) - message(WARNING "Host Visual Studio should at least be 2015 Update 3 (MSVC 19.00.24213.1)" - " due to miscompiles from earlier versions") + +if(DEFINED LLVM_COMPILER_CHECKED) + return() +endif() +set(LLVM_COMPILER_CHECKED ON) + +if(LLVM_FORCE_USE_OLD_TOOLCHAIN) + return() +endif() + +function(check_compiler_version NAME NICE_NAME MINIMUM_VERSION SOFT_ERROR_VERSION) + if(NOT CMAKE_CXX_COMPILER_ID STREQUAL NAME) + return() + endif() + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS MINIMUM_VERSION) + message(FATAL_ERROR "Host ${NICE_NAME} version must be at least ${MINIMUM_VERSION}, your version is ${CMAKE_CXX_COMPILER_VERSION}.") + elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS SOFT_ERROR_VERSION) + if(LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN) + message(WARNING "Host ${NICE_NAME} version should be at least ${SOFT_ERROR_VERSION} because LLVM will soon use new C++ features which your toolchain version doesn't support. Your version is ${CMAKE_CXX_COMPILER_VERSION}. Ignoring because you've set LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN, but very soon your toolchain won't be supported.") + else() + message(FATAL_ERROR "Host ${NICE_NAME} version should be at least ${SOFT_ERROR_VERSION} because LLVM will soon use new C++ features which your toolchain version doesn't support. Your version is ${CMAKE_CXX_COMPILER_VERSION}. You can temporarily opt out using LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN, but very soon your toolchain won't be supported.") + endif() + endif() +endfunction(check_compiler_version) + +check_compiler_version("GNU" "GCC" ${GCC_MIN} ${GCC_SOFT_ERROR}) +check_compiler_version("Clang" "Clang" ${CLANG_MIN} ${CLANG_SOFT_ERROR}) +check_compiler_version("AppleClang" "Apple Clang" ${APPLECLANG_MIN} ${APPLECLANG_SOFT_ERROR}) +check_compiler_version("MSVC" "Visual Studio" ${MSVC_MIN} ${MSVC_SOFT_ERROR}) + +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + if (CMAKE_CXX_SIMULATE_ID MATCHES "MSVC") + if (CMAKE_CXX_SIMULATE_VERSION VERSION_LESS MSVC_MIN) + message(FATAL_ERROR "Host Clang must have at least -fms-compatibility-version=${MSVC_MIN}, your version is ${CMAKE_CXX_COMPILER_VERSION}.") + endif() + set(CLANG_CL 1) + elseif(NOT LLVM_ENABLE_LIBCXX) + # Test that we aren't using too old of a version of libstdc++. + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(OLD_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++0x") + check_cxx_source_compiles(" +#include +#if defined(__GLIBCXX__) +#if __GLIBCXX__ < ${GCC_MIN_DATE} +#error Unsupported libstdc++ version +#endif +#endif +int main() { return 0; } +" + LLVM_LIBSTDCXX_MIN) + if(NOT LLVM_LIBSTDCXX_MIN) + message(FATAL_ERROR "libstdc++ version must be at least ${GCC_MIN}.") + endif() + check_cxx_source_compiles(" +#include +#if defined(__GLIBCXX__) +#if __GLIBCXX__ < ${GCC_SOFT_ERROR_DATE} +#error Unsupported libstdc++ version +#endif +#endif +int main() { return 0; } +" + LLVM_LIBSTDCXX_SOFT_ERROR) + if(NOT LLVM_LIBSTDCXX_SOFT_ERROR) + if(LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN) + message(WARNING "libstdc++ version should be at least ${GCC_SOFT_ERROR} because LLVM will soon use new C++ features which your toolchain version doesn't support. Ignoring because you've set LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN, but very soon your toolchain won't be supported.") + else() + message(FATAL_ERROR "libstdc++ version should be at least ${GCC_SOFT_ERROR} because LLVM will soon use new C++ features which your toolchain version doesn't support. You can temporarily opt out using LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN, but very soon your toolchain won't be supported.") endif() endif() + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_LIBRARIES ${OLD_CMAKE_REQUIRED_LIBRARIES}) endif() endif() diff --git a/llvm/cmake/modules/CrossCompile.cmake b/llvm/cmake/modules/CrossCompile.cmake index b239816c82539..bc3b210f01859 100644 --- a/llvm/cmake/modules/CrossCompile.cmake +++ b/llvm/cmake/modules/CrossCompile.cmake @@ -52,6 +52,7 @@ function(llvm_create_cross_target_internal target_name toolchain buildtype) -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="${experimental_targets_to_build_arg}" -DLLVM_DEFAULT_TARGET_TRIPLE="${TARGET_TRIPLE}" -DLLVM_TARGET_ARCH="${LLVM_TARGET_ARCH}" + -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN="${LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN}" ${build_type_flags} ${linker_flag} ${external_clang_dir} WORKING_DIRECTORY ${LLVM_${target_name}_BUILD} DEPENDS CREATE_LLVM_${target_name} diff --git a/llvm/cmake/modules/LLVMProcessSources.cmake b/llvm/cmake/modules/LLVMProcessSources.cmake index 7cbd2863500cf..d0be0e8b3ba3d 100644 --- a/llvm/cmake/modules/LLVMProcessSources.cmake +++ b/llvm/cmake/modules/LLVMProcessSources.cmake @@ -30,7 +30,15 @@ endmacro(add_td_sources) function(add_header_files_for_glob hdrs_out glob) file(GLOB hds ${glob}) - set(${hdrs_out} ${hds} PARENT_SCOPE) + set(filtered) + foreach(file ${hds}) + # Explicit existence check is necessary to filter dangling symlinks + # out. See https://bugs.gentoo.org/674662. + if(EXISTS ${file}) + list(APPEND filtered ${file}) + endif() + endforeach() + set(${hdrs_out} ${filtered} PARENT_SCOPE) endfunction(add_header_files_for_glob) function(find_all_header_files hdrs_out additional_headerdirs) diff --git a/llvm/docs/CMake.rst b/llvm/docs/CMake.rst index a5a574e570777..eb219c58560b6 100644 --- a/llvm/docs/CMake.rst +++ b/llvm/docs/CMake.rst @@ -573,6 +573,15 @@ LLVM-specific variables options, which are passed to the CCACHE_MAXSIZE and CCACHE_DIR environment variables, respectively. +**LLVM_FORCE_USE_OLD_TOOLCHAIN**:BOOL + If enabled, the compiler and standard library versions won't be checked. LLVM + may not compile at all, or might fail at runtime due to known bugs in these + toolchains. + +**LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN**:BOOL + If enabled, the compiler version check will only warn when using a toolchain + which is about to be deprecated, instead of emitting an error. + CMake Caches ============ diff --git a/llvm/docs/DeveloperPolicy.rst b/llvm/docs/DeveloperPolicy.rst index 09912940cde2d..4ed67cbf1ef1d 100644 --- a/llvm/docs/DeveloperPolicy.rst +++ b/llvm/docs/DeveloperPolicy.rst @@ -22,7 +22,7 @@ This policy is also designed to accomplish the following objectives: #. Make life as simple and easy for contributors as possible. -#. Keep the tip of tree as stable as possible. +#. Keep the top of tree as stable as possible. #. Establish awareness of the project's :ref:`copyright, license, and patent policies ` with contributors to the project. @@ -638,6 +638,47 @@ In essences, these rules are necessary for targets to gain and retain their status, but also markers to define bit-rot, and will be used to clean up the tree from unmaintained targets. +.. _toolchain: + +Updating Toolchain Requirements +------------------------------- + +We intend to require newer toolchains as time goes by. This means LLVM's +codebase can use newer versions of C++ as they get standardized. Requiring newer +toolchains to build LLVM can be painful for those building LLVM; therefore, it +will only be done through the following process: + + * Generally, try to support LLVM and GCC versions from the last 3 years at a + minimum. This time-based guideline is not strict: we may support much older + compilers, or decide to support fewer versions. + + * An RFC is sent to the `llvm-dev mailing list `_ + + - Detail upsides of the version increase (e.g. which newer C++ language or + library features LLVM should use; avoid miscompiles in particular compiler + versions, etc). + - Detail downsides on important platforms (e.g. Ubuntu LTS status). + + * Once the RFC reaches consensus, update the CMake toolchain version checks as + well as the :doc:`getting started` guide. We want to + soft-error when developers compile LLVM. We say "soft-error" because the + error can be turned into a warning using a CMake flag. This is an important + step: LLVM still doesn't have code which requires the new toolchains, but it + soon will. If you compile LLVM but don't read the mailing list, we should + tell you! + + * Ensure that at least one LLVM release has had this soft-error. Not all + developers compile LLVM top-of-tree. These release-bound developers should + also be told about upcoming changes. + + * Turn the soft-error into a hard-error after said LLVM release has branched. + + * Update the :doc:`coding standards` to allow the new + features we've explicitly approved in the RFC. + + * Start using the new features in LLVM's codebase. + + .. _copyright-license-patents: Copyright, License, and Patents diff --git a/llvm/docs/GettingStarted.rst b/llvm/docs/GettingStarted.rst index b714cc6601a04..c22e821e3b7a0 100644 --- a/llvm/docs/GettingStarted.rst +++ b/llvm/docs/GettingStarted.rst @@ -170,7 +170,7 @@ uses the package and provides other details. Package Version Notes =========================================================== ============ ========================================== `GNU Make `_ 3.79, 3.79.1 Makefile/build processor -`GCC `_ >=4.8.0 C/C++ compiler\ :sup:`1` +`GCC `_ >=5.1.0 C/C++ compiler\ :sup:`1` `python `_ >=2.7 Automated test suite\ :sup:`2` `zlib `_ >=1.2.3.4 Compression library\ :sup:`3` =========================================================== ============ ========================================== @@ -220,15 +220,25 @@ Host C++ Toolchain, both Compiler and Standard Library ------------------------------------------------------ LLVM is very demanding of the host C++ compiler, and as such tends to expose -bugs in the compiler. We are also planning to follow improvements and -developments in the C++ language and library reasonably closely. As such, we -require a modern host C++ toolchain, both compiler and standard library, in -order to build LLVM. +bugs in the compiler. We also attempt to follow improvements and developments in +the C++ language and library reasonably closely. As such, we require a modern +host C++ toolchain, both compiler and standard library, in order to build LLVM. -For the most popular host toolchains we check for specific minimum versions in -our build systems: +LLVM is written using the subset of C++ documented in :doc:`coding +standards`. To enforce this language version, we check the most +popular host toolchains for specific minimum versions in our build systems: + +* Clang 3.5 +* Apple Clang 6.0 +* GCC 5.1 +* Visual Studio 2017 + +The below versions currently soft-error as we transition to the new compiler +versions listed above. The LLVM codebase is currently known to compile correctly +with the following compilers, though this will change in the near future: * Clang 3.1 +* Apple Clang 3.1 * GCC 4.8 * Visual Studio 2015 (Update 3) @@ -282,33 +292,36 @@ The first step is to get a recent GCC toolchain installed. The most common distribution on which users have struggled with the version requirements is Ubuntu Precise, 12.04 LTS. For this distribution, one easy option is to install the `toolchain testing PPA`_ and use it to install a modern GCC. There is -a really nice discussions of this on the `ask ubuntu stack exchange`_. However, -not all users can use PPAs and there are many other distributions, so it may be -necessary (or just useful, if you're here you *are* doing compiler development -after all) to build and install GCC from source. It is also quite easy to do -these days. +a really nice discussions of this on the `ask ubuntu stack exchange`_ and a +`github gist`_ with updated commands. However, not all users can use PPAs and +there are many other distributions, so it may be necessary (or just useful, if +you're here you *are* doing compiler development after all) to build and install +GCC from source. It is also quite easy to do these days. .. _toolchain testing PPA: https://launchpad.net/~ubuntu-toolchain-r/+archive/test .. _ask ubuntu stack exchange: - http://askubuntu.com/questions/271388/how-to-install-gcc-4-8-in-ubuntu-12-04-from-the-terminal + https://askubuntu.com/questions/466651/how-do-i-use-the-latest-gcc-on-ubuntu/581497#58149 +.. _github gist: + https://gist.github.com/application2000/73fd6f4bf1be6600a2cf9f56315a2d91 -Easy steps for installing GCC 4.8.2: +Easy steps for installing GCC 5.1.0: .. code-block:: console - % wget https://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2 - % wget https://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2.sig + % gcc_version=5.1.0 + % wget https://ftp.gnu.org/gnu/gcc/gcc-${gcc_version}/gcc-${gcc_version}.tar.bz2 + % wget https://ftp.gnu.org/gnu/gcc/gcc-${gcc_version}/gcc-${gcc_version}.tar.bz2.sig % wget https://ftp.gnu.org/gnu/gnu-keyring.gpg - % signature_invalid=`gpg --verify --no-default-keyring --keyring ./gnu-keyring.gpg gcc-4.8.2.tar.bz2.sig` + % signature_invalid=`gpg --verify --no-default-keyring --keyring ./gnu-keyring.gpg gcc-${gcc_version}.tar.bz2.sig` % if [ $signature_invalid ]; then echo "Invalid signature" ; exit 1 ; fi - % tar -xvjf gcc-4.8.2.tar.bz2 - % cd gcc-4.8.2 + % tar -xvjf gcc-${gcc_version}.tar.bz2 + % cd gcc-${gcc_version} % ./contrib/download_prerequisites % cd .. - % mkdir gcc-4.8.2-build - % cd gcc-4.8.2-build - % $PWD/../gcc-4.8.2/configure --prefix=$HOME/toolchains --enable-languages=c,c++ + % mkdir gcc-${gcc_version}-build + % cd gcc-${gcc_version}-build + % $PWD/../gcc-${gcc_version}/configure --prefix=$HOME/toolchains --enable-languages=c,c++ % make -j$(nproc) % make install @@ -316,7 +329,7 @@ For more details, check out the excellent `GCC wiki entry`_, where I got most of this information from. .. _GCC wiki entry: - http://gcc.gnu.org/wiki/InstallingGCC + https://gcc.gnu.org/wiki/InstallingGCC Once you have a GCC toolchain, configure your build of LLVM to use the new toolchain for your host compiler and C++ standard library. Because the new @@ -336,7 +349,7 @@ If you fail to set rpath, most LLVM binaries will fail on startup with a message from the loader similar to ``libstdc++.so.6: version `GLIBCXX_3.4.20' not found``. This means you need to tweak the -rpath linker flag. -When you build Clang, you will need to give *it* access to modern C++11 +When you build Clang, you will need to give *it* access to modern C++ standard library in order to use it as your new host in part of a bootstrap. There are two easy ways to do this, either build (and install) libc++ along with Clang and then use it with the ``-stdlib=libc++`` compile and link flag, diff --git a/llvm/docs/LibFuzzer.rst b/llvm/docs/LibFuzzer.rst index 0737fbbcd9305..37b0833599a94 100644 --- a/llvm/docs/LibFuzzer.rst +++ b/llvm/docs/LibFuzzer.rst @@ -645,10 +645,20 @@ coverage set of the process (since the fuzzer is in-process). In other words, by using more external dependencies we will slow down the fuzzer while the main reason for it to exist is extreme speed. -Q. What about Windows then? The fuzzer contains code that does not build on Windows. +Q. Does libFuzzer Support Windows? ------------------------------------------------------------------------------------ -Volunteers are welcome. +Yes, libFuzzer now supports Windows. Initial support was added in r341082. +You can download a build of Clang for Windows +that has libFuzzer from +`LLVM Snapshot Builds `_. + +Using libFuzzer on Windows without ASAN is unsupported. Building fuzzers with the +``/MD`` (dynamic runtime library) compile option is unsupported. Support for these +may be added in the future. Linking fuzzers with the ``/INCREMENTAL`` link option +(or the ``/DEBUG`` option which implies it) is also unsupported. + +Send any questions or comments to the mailing list: libfuzzer(#)googlegroups.com Q. When libFuzzer is not a good solution for a problem? --------------------------------------------------------- diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index db9cf51949520..16121585d24fb 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -5,12 +5,6 @@ LLVM 8.0.0 Release Notes .. contents:: :local: -.. warning:: - These are in-progress notes for the upcoming LLVM 8 release. - Release notes for previous releases can be found on - `the Download Page `_. - - Introduction ============ @@ -18,7 +12,7 @@ This document contains the release notes for the LLVM Compiler Infrastructure, release 8.0.0. Here we describe the status of LLVM, including major improvements from the previous release, improvements in various subprojects of LLVM, and some of the current users of the code. All LLVM releases may be downloaded -from the `LLVM releases web site `_. +from the `LLVM releases web site `_. For more information about LLVM, including information about the latest release, please check out the `main LLVM web site `_. If you @@ -26,58 +20,214 @@ have questions or comments, the `LLVM Developer's Mailing List `_ is a good place to send them. -Note that if you are reading this file from a Subversion checkout or the main -LLVM web page, this document applies to the *next* release, not the current -one. To see the release notes for a specific release, please see the `releases -page `_. +Minimum Required Compiler Version +================================= +As `discussed on the mailing list +`_, +building LLVM will soon require more recent toolchains as follows: + +============= ==== +Clang 3.5 +Apple Clang 6.0 +GCC 5.1 +Visual Studio 2017 +============= ==== + +A new CMake check when configuring LLVM provides a soft-error if your +toolchain will become unsupported soon. You can opt out of the soft-error by +setting the ``LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN`` CMake variable to +``ON``. + + +Known Issues +============ + +These are issues that couldn't be fixed before the release. See the bug reports +for the latest status. + +* `PR40547 `_ Clang gets miscompiled by trunk GCC. + +* `PR40761 `_ "asan-dynamic" doesn't work on FreeBSD. + Non-comprehensive list of changes in this release ================================================= -.. NOTE - For small 1-3 sentence descriptions, just add an entry at the end of - this list. If your description won't fit comfortably in one bullet - point (e.g. maybe you would like to give an example of the - functionality, or simply have a lot to talk about), see the `NOTE` below - for adding a new subsection. * The **llvm-cov** tool can now export lcov trace files using the `-format=lcov` option of the `export` command. -* The add_llvm_loadable_module CMake macro has been removed. The - add_llvm_library macro with the MODULE argument now provides the same +* The ``add_llvm_loadable_module`` CMake macro has been removed. The + ``add_llvm_library`` macro with the ``MODULE`` argument now provides the same functionality. See `Writing an LLVM Pass `_. -.. NOTE - If you would like to document a larger change, then you can add a - subsection about it right here. You can copy the following boilerplate - and un-indent it (the indentation causes it to be inside this comment). +* For MinGW, references to data variables that might need to be imported + from a dll are accessed via a stub, to allow the linker to convert it to + a dllimport if needed. + +* Added support for labels as offsets in ``.reloc`` directive. - Special New Feature - ------------------- +* Support for precise identification of X86 instructions with memory operands, + by using debug information. This supports profile-driven cache prefetching. + It is enabled with the ``-x86-discriminate-memops`` LLVM Flag. - Makes programs 10x faster by doing Special New Thing. +* Support for profile-driven software cache prefetching on X86. This is part of + a larger system, consisting of: an offline cache prefetches recommender, + AutoFDO tooling, and LLVM. In this system, a binary compiled with + ``-x86-discriminate-memops`` is run under the observation of the recommender. + The recommender identifies certain memory access instructions by their binary + file address, and recommends a prefetch of a specific type (NTA, T0, etc) be + performed at a specified fixed offset from such an instruction's memory + operand. Next, this information needs to be converted to the AutoFDO syntax + and the resulting profile may be passed back to the compiler with the LLVM + flag ``-prefetch-hints-file``, together with the exact same set of + compilation parameters used for the original binary. More information is + available in the `RFC + `_. + +* Windows support for libFuzzer (x86_64). Changes to the LLVM IR ---------------------- +* Function attribute ``speculative_load_hardening`` has been introduced to + allow indicating that `Speculative Load Hardening + `_ must be enabled for the function body. -Changes to the ARM Backend --------------------------- - During this release ... +Changes to the JIT APIs +----------------------- + +The ORC (On Request Compilation) JIT APIs have been updated to support +concurrent compilation. The existing (non-concurrent) ORC layer classes and +related APIs are deprecated, have been renamed with a "Legacy" prefix (e.g. +LegacyIRCompileLayer). The deprecated clasess will be removed in LLVM 9. + +An example JIT stack using the concurrent ORC APIs, called LLJIT, has been +added (see include/llvm/ExecutionEngine/Orc/LLJIT.h). The lli tool has been +updated to use LLJIT. + +MCJIT and ExecutionEngine continue to be supported, though ORC should be +preferred for new projects. + +Changes to the C++ APIs +----------------------- + +Three of the IR library methods related to debugging information for +functions and methods have changed their prototypes: + + DIBuilder::createMethod + DIBuilder::createFunction + DIBuilder::createTempFunctionFwdDecl + +In all cases, several individual parameters were removed, and replaced +by a single 'SPFlags' (subprogram flags) parameter. The individual +parameters are: 'isLocalToUnit'; 'isDefinition'; 'isOptimized'; and +for 'createMethod', 'Virtuality'. The new 'SPFlags' parameter has a +default value equivalent to passing 'false' for the three 'bool' +parameters, and zero (non-virtual) to the 'Virtuality' parameter. For +any old-style API call that passed 'true' or a non-zero virtuality to +these methods, you will need to substitute the correct 'SPFlags' value. +The helper method 'DISubprogram::toSPFlags()' might be useful in making +this conversion. + +Changes to the AArch64 Target +----------------------------- + +* Support for Speculative Load Hardening has been added. + +* Initial support for the Tiny code model, where code and its statically + defined symbols must live within 1MB of each other. + +* Added support for the ``.arch_extension`` assembler directive, just like + on ARM. + + +Changes to the Hexagon Target +----------------------------- + +* Added support for Hexagon/HVX V66 ISA. Changes to the MIPS Target -------------------------- - During this release ... +* Improved support of GlobalISel instruction selection framework. + +* Implemented emission of ``R_MIPS_JALR`` and ``R_MICROMIPS_JALR`` + relocations. These relocations provide hints to a linker for optimization + of jumps to protected symbols. + +* ORC JIT has been supported for MIPS and MIPS64 architectures. + +* Assembler now suggests alternative MIPS instruction mnemonics when + an invalid one is specified. + +* Improved support for MIPS N32 ABI. + +* Added new instructions (``pll.ps``, ``plu.ps``, ``cvt.s.pu``, + ``cvt.s.pl``, ``cvt.ps``, ``sigrie``). + +* Numerous bug fixes and code cleanups. Changes to the PowerPC Target ----------------------------- - During this release ... +* Switched to non-PIC default + +* Deprecated Darwin support + +* Enabled Out-of-Order scheduling for P9 + +* Better overload rules for compatible vector type parameter + +* Support constraint 'wi', modifier 'x' and VSX registers in inline asm + +* More ``__float128`` support + +* Added new builtins like vector int128 ``pack``/``unpack`` and + ``stxvw4x.be``/``stxvd2x.be`` + +* Provided significant improvements to the automatic vectorizer + +* Code-gen improvements (especially for Power9) + +* Fixed some long-standing bugs in the back end + +* Added experimental prologue/epilogue improvements + +* Enabled builtins tests in compiler-rt + +* Add ``___fixunstfti``/``floattitf`` in compiler-rt to support conversion + between IBM double-double and unsigned int128 + +* Disable randomized address space when running the sanitizers on Linux ppc64le + +* Completed support in LLD for ELFv2 + +* Enabled llvm-exegesis latency mode for PPC + + +Changes to the SystemZ Target +----------------------------- + +* A number of bugs related to C/C++ language vector extension support were + fixed: the ``-mzvector`` option now actually enables the ``__vector`` and + ``__bool`` keywords, the ``vec_step`` intrinsic now works, and the + ``vec_insert_and_zero`` and ``vec_orc`` intrinsics now generate correct code. + +* The ``__float128`` keyword, which had been accidentally enabled in some + earlier releases, is now no longer supported. On SystemZ, the ``long double`` + data type itself already uses the IEEE 128-bit floating-point format. + +* When the compiler inlines ``strcmp`` or ``memcmp``, the generated code no + longer returns ``INT_MIN`` as the negative result value under any + circumstances. + +* Various code-gen improvements, in particular related to improved + auto-vectorization, inlining, and instruction scheduling. + Changes to the X86 Target ------------------------- @@ -85,15 +235,18 @@ Changes to the X86 Target * Machine model for AMD bdver2 (Piledriver) CPU was added. It is used to support instruction scheduling and other instruction cost heuristics. -Changes to the AMDGPU Target ------------------------------ +* New AVX512F gather and scatter intrinsics were added that take a mask + instead of a scalar integer. This removes the need for a bitcast in IR. The + new intrinsics are named like the old intrinsics with ``llvm.avx512.`` + replaced with ``llvm.avx512.mask.``. The old intrinsics will be removed in a + future release. - During this release ... +* Added ``cascadelake`` as a CPU name for -march. This is ``skylake-avx512`` + with the addition of the ``avx512vnni`` instruction set. -Changes to the AVR Target ------------------------------ +* ADCX instruction will no longer be emitted. This instruction is rarely better + than the legacy ADC instruction and just increased code size. - During this release ... Changes to the WebAssembly Target --------------------------------- @@ -108,22 +261,65 @@ return values, once the underlying WebAssembly platform itself supports it. Additionally, multithreading support is not yet included in the stable ABI. -Changes to the OCaml bindings ------------------------------ +Changes to the Nios2 Target +--------------------------- +* The Nios2 target was removed from this release. -Changes to the C API --------------------- +Changes to LLDB +=============== +* Printed source code is now syntax highlighted in the terminal (only for C + languages). + +* The expression command now supports tab completing expressions. -Changes to the DAG infrastructure ---------------------------------- External Open Source Projects Using LLVM 8 ========================================== -* A project... +LDC - the LLVM-based D compiler +------------------------------- + +`D `_ is a language with C-like syntax and static typing. It +pragmatically combines efficiency, control, and modeling power, with safety and +programmer productivity. D supports powerful concepts like Compile-Time Function +Execution (CTFE) and Template Meta-Programming, provides an innovative approach +to concurrency and offers many classical paradigms. + +`LDC `_ uses the frontend from the reference compiler +combined with LLVM as backend to produce efficient native code. LDC targets +x86/x86_64 systems like Linux, OS X, FreeBSD and Windows and also Linux on ARM +and PowerPC (32/64 bit). Ports to other architectures like AArch64 and MIPS64 +are underway. + +Open Dylan Compiler +------------------- + +`Dylan `_ is a multi-paradigm functional +and object-oriented programming language. It is dynamic while +providing a programming model designed to support efficient machine +code generation, including fine-grained control over dynamic and +static behavior. Dylan also features a powerful macro facility for +expressive metaprogramming. + +The Open Dylan compiler can use LLVM as one of its code-generating +back-ends, including full support for debug info generation. (Open +Dylan generates LLVM bitcode directly using a native Dylan IR and +bitcode library.) Development of a Dylan debugger and interactive REPL +making use of the LLDB libraries is in progress. + +Zig Programming Language +------------------------ + +`Zig `_ is a system programming language intended to be +an alternative to C. It provides high level features such as generics, compile +time function execution, and partial evaluation, while exposing low level LLVM +IR features such as aliases and intrinsics. Zig uses Clang to provide automatic +import of .h symbols, including inline functions and simple macros. Zig uses +LLD combined with lazily building compiler-rt to provide out-of-the-box +cross-compiling for all supported targets. Additional Information diff --git a/llvm/docs/index.rst b/llvm/docs/index.rst index 4527fe5105346..49bd327f47dec 100644 --- a/llvm/docs/index.rst +++ b/llvm/docs/index.rst @@ -1,11 +1,6 @@ Overview ======== -.. warning:: - - If you are using a released version of LLVM, see `the download page - `_ to find your documentation. - The LLVM compiler infrastructure supports a wide range of projects, from industrial strength compilers to specialized JIT applications to small research projects. diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h index d9f0f94b298d4..b02ddb6b7e299 100644 --- a/llvm/include/llvm/BinaryFormat/Wasm.h +++ b/llvm/include/llvm/BinaryFormat/Wasm.h @@ -165,7 +165,8 @@ struct WasmSymbolInfo { StringRef Name; uint8_t Kind; uint32_t Flags; - StringRef Module; // For undefined symbols the module name of the import + StringRef ImportModule; // For undefined symbols the module of the import + StringRef ImportName; // For undefined symbols the name of the import union { // For function or global symbols, the index in function or global index // space. @@ -284,6 +285,7 @@ const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2; const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0; const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4; const unsigned WASM_SYMBOL_UNDEFINED = 0x10; +const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x40; #define WASM_RELOC(name, value) name = value, diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h index 25edf5bcce516..6dbe1650adabf 100644 --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -329,6 +329,7 @@ class MachineFunction { bool CallsUnwindInit = false; bool HasEHScopes = false; bool HasEHFunclets = false; + bool HasLocalEscape = false; /// List of C++ TypeInfo used. std::vector TypeInfos; @@ -811,6 +812,9 @@ class MachineFunction { bool hasEHFunclets() const { return HasEHFunclets; } void setHasEHFunclets(bool V) { HasEHFunclets = V; } + bool hasLocalEscape() const { return HasLocalEscape; } + void setHasLocalEscape(bool V) { HasLocalEscape = V; } + /// Find or create an LandingPadInfo for the specified MachineBasicBlock. LandingPadInfo &getOrCreateLandingPadInfo(MachineBasicBlock *LandingPad); diff --git a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td index 7913ce828fbc0..6585cb71769ab 100644 --- a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td +++ b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td @@ -392,6 +392,24 @@ class AMDGPULDSF32Intrin : [IntrArgMemOnly, NoCapture<0>] >; +class AMDGPUDSOrderedIntrinsic : Intrinsic< + [llvm_i32_ty], + // M0 = {hi16:address, lo16:waveID}. Allow passing M0 as a pointer, so that + // the bit packing can be optimized at the IR level. + [LLVMQualPointerType, // IntToPtr(M0) + llvm_i32_ty, // value to add or swap + llvm_i32_ty, // ordering + llvm_i32_ty, // scope + llvm_i1_ty, // isVolatile + llvm_i32_ty, // ordered count index (OA index), also added to the address + llvm_i1_ty, // wave release, usually set to 1 + llvm_i1_ty], // wave done, set to 1 for the last ordered instruction + [NoCapture<0>] +>; + +def int_amdgcn_ds_ordered_add : AMDGPUDSOrderedIntrinsic; +def int_amdgcn_ds_ordered_swap : AMDGPUDSOrderedIntrinsic; + def int_amdgcn_ds_fadd : AMDGPULDSF32Intrin<"__builtin_amdgcn_ds_faddf">; def int_amdgcn_ds_fmin : AMDGPULDSF32Intrin<"__builtin_amdgcn_ds_fminf">; def int_amdgcn_ds_fmax : AMDGPULDSF32Intrin<"__builtin_amdgcn_ds_fmaxf">; diff --git a/llvm/include/llvm/IR/IntrinsicsX86.td b/llvm/include/llvm/IR/IntrinsicsX86.td index 8d8cc8e97678f..4f4bcbc67bfb8 100644 --- a/llvm/include/llvm/IR/IntrinsicsX86.td +++ b/llvm/include/llvm/IR/IntrinsicsX86.td @@ -1677,71 +1677,73 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Gather ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + // NOTE: These can't be ArgMemOnly because you can put the address completely + // in the index register. def int_x86_avx2_gather_d_pd : GCCBuiltin<"__builtin_ia32_gatherd_pd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_d_pd_256 : GCCBuiltin<"__builtin_ia32_gatherd_pd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_q_pd : GCCBuiltin<"__builtin_ia32_gatherq_pd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_q_pd_256 : GCCBuiltin<"__builtin_ia32_gatherq_pd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_d_ps : GCCBuiltin<"__builtin_ia32_gatherd_ps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_d_ps_256 : GCCBuiltin<"__builtin_ia32_gatherd_ps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_q_ps : GCCBuiltin<"__builtin_ia32_gatherq_ps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_q_ps_256 : GCCBuiltin<"__builtin_ia32_gatherq_ps256">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_d_q : GCCBuiltin<"__builtin_ia32_gatherd_q">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_d_q_256 : GCCBuiltin<"__builtin_ia32_gatherd_q256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_q_q : GCCBuiltin<"__builtin_ia32_gatherq_q">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_q_q_256 : GCCBuiltin<"__builtin_ia32_gatherq_q256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_d_d : GCCBuiltin<"__builtin_ia32_gatherd_d">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_d_d_256 : GCCBuiltin<"__builtin_ia32_gatherd_d256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_q_d : GCCBuiltin<"__builtin_ia32_gatherq_d">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx2_gather_q_d_256 : GCCBuiltin<"__builtin_ia32_gatherq_d256">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; } // Misc. @@ -3564,530 +3566,542 @@ let TargetPrefix = "x86" in { // Gather and Scatter ops let TargetPrefix = "x86" in { // NOTE: These are deprecated in favor of the versions that take a vXi1 mask. + // NOTE: These can't be ArgMemOnly because you can put the address completely + // in the index register. def int_x86_avx512_gather_dpd_512 : GCCBuiltin<"__builtin_ia32_gathersiv8df">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather_dps_512 : GCCBuiltin<"__builtin_ia32_gathersiv16sf">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather_qpd_512 : GCCBuiltin<"__builtin_ia32_gatherdiv8df">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather_qps_512 : GCCBuiltin<"__builtin_ia32_gatherdiv16sf">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather_dpq_512 : GCCBuiltin<"__builtin_ia32_gathersiv8di">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather_dpi_512 : GCCBuiltin<"__builtin_ia32_gathersiv16si">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather_qpq_512 : GCCBuiltin<"__builtin_ia32_gatherdiv8di">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather_qpi_512 : GCCBuiltin<"__builtin_ia32_gatherdiv16si">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3div2_df : GCCBuiltin<"__builtin_ia32_gather3div2df">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3div2_di : GCCBuiltin<"__builtin_ia32_gather3div2di">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3div4_df : GCCBuiltin<"__builtin_ia32_gather3div4df">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3div4_di : GCCBuiltin<"__builtin_ia32_gather3div4di">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3div4_sf : GCCBuiltin<"__builtin_ia32_gather3div4sf">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3div4_si : GCCBuiltin<"__builtin_ia32_gather3div4si">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3div8_sf : GCCBuiltin<"__builtin_ia32_gather3div8sf">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3div8_si : GCCBuiltin<"__builtin_ia32_gather3div8si">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3siv2_df : GCCBuiltin<"__builtin_ia32_gather3siv2df">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3siv2_di : GCCBuiltin<"__builtin_ia32_gather3siv2di">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3siv4_df : GCCBuiltin<"__builtin_ia32_gather3siv4df">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3siv4_di : GCCBuiltin<"__builtin_ia32_gather3siv4di">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3siv4_sf : GCCBuiltin<"__builtin_ia32_gather3siv4sf">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3siv4_si : GCCBuiltin<"__builtin_ia32_gather3siv4si">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3siv8_sf : GCCBuiltin<"__builtin_ia32_gather3siv8sf">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_gather3siv8_si : GCCBuiltin<"__builtin_ia32_gather3siv8si">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; // scatter // NOTE: These are deprecated in favor of the versions that take a vXi1 mask. + // NOTE: These can't be ArgMemOnly because you can put the address completely + // in the index register. def int_x86_avx512_scatter_dpd_512 : GCCBuiltin<"__builtin_ia32_scattersiv8df">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatter_dps_512 : GCCBuiltin<"__builtin_ia32_scattersiv16sf">, Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty, llvm_v16i32_ty, llvm_v16f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatter_qpd_512 : GCCBuiltin<"__builtin_ia32_scatterdiv8df">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_v8f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatter_qps_512 : GCCBuiltin<"__builtin_ia32_scatterdiv16sf">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_v8f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatter_dpq_512 : GCCBuiltin<"__builtin_ia32_scattersiv8di">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatter_dpi_512 : GCCBuiltin<"__builtin_ia32_scattersiv16si">, Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatter_qpq_512 : GCCBuiltin<"__builtin_ia32_scatterdiv8di">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty,llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatter_qpi_512 : GCCBuiltin<"__builtin_ia32_scatterdiv16si">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_v8i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatterdiv2_df : GCCBuiltin<"__builtin_ia32_scatterdiv2df">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatterdiv2_di : GCCBuiltin<"__builtin_ia32_scatterdiv2di">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatterdiv4_df : GCCBuiltin<"__builtin_ia32_scatterdiv4df">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatterdiv4_di : GCCBuiltin<"__builtin_ia32_scatterdiv4di">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatterdiv4_sf : GCCBuiltin<"__builtin_ia32_scatterdiv4sf">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatterdiv4_si : GCCBuiltin<"__builtin_ia32_scatterdiv4si">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatterdiv8_sf : GCCBuiltin<"__builtin_ia32_scatterdiv8sf">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scatterdiv8_si : GCCBuiltin<"__builtin_ia32_scatterdiv8si">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scattersiv2_df : GCCBuiltin<"__builtin_ia32_scattersiv2df">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v2f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scattersiv2_di : GCCBuiltin<"__builtin_ia32_scattersiv2di">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scattersiv4_df : GCCBuiltin<"__builtin_ia32_scattersiv4df">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scattersiv4_di : GCCBuiltin<"__builtin_ia32_scattersiv4di">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scattersiv4_sf : GCCBuiltin<"__builtin_ia32_scattersiv4sf">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scattersiv4_si : GCCBuiltin<"__builtin_ia32_scattersiv4si">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scattersiv8_sf : GCCBuiltin<"__builtin_ia32_scattersiv8sf">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_scattersiv8_si : GCCBuiltin<"__builtin_ia32_scattersiv8si">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; // gather prefetch + // NOTE: These can't be ArgMemOnly because you can put the address completely + // in the index register. def int_x86_avx512_gatherpf_dpd_512 : GCCBuiltin<"__builtin_ia32_gatherpfdpd">, Intrinsic<[], [llvm_i8_ty, llvm_v8i32_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], []>; def int_x86_avx512_gatherpf_dps_512 : GCCBuiltin<"__builtin_ia32_gatherpfdps">, Intrinsic<[], [llvm_i16_ty, llvm_v16i32_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], []>; def int_x86_avx512_gatherpf_qpd_512 : GCCBuiltin<"__builtin_ia32_gatherpfqpd">, Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], []>; def int_x86_avx512_gatherpf_qps_512 : GCCBuiltin<"__builtin_ia32_gatherpfqps">, Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], []>; // scatter prefetch + // NOTE: These can't be ArgMemOnly because you can put the address completely + // in the index register. def int_x86_avx512_scatterpf_dpd_512 : GCCBuiltin<"__builtin_ia32_scatterpfdpd">, Intrinsic<[], [llvm_i8_ty, llvm_v8i32_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], []>; def int_x86_avx512_scatterpf_dps_512 : GCCBuiltin<"__builtin_ia32_scatterpfdps">, Intrinsic<[], [llvm_i16_ty, llvm_v16i32_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], []>; def int_x86_avx512_scatterpf_qpd_512 : GCCBuiltin<"__builtin_ia32_scatterpfqpd">, Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], []>; def int_x86_avx512_scatterpf_qps_512 : GCCBuiltin<"__builtin_ia32_scatterpfqps">, Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], []>; } // AVX512 gather/scatter intrinsics that use vXi1 masks. let TargetPrefix = "x86" in { + // NOTE: These can't be ArgMemOnly because you can put the address completely + // in the index register. def int_x86_avx512_mask_gather_dpd_512 : Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather_dps_512 : Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_ptr_ty, llvm_v16i32_ty, llvm_v16i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather_qpd_512 : Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather_qps_512 : Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather_dpq_512 : Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather_dpi_512 : Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_ptr_ty, llvm_v16i32_ty, llvm_v16i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather_qpq_512 : Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather_qpi_512 : Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3div2_df : Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3div2_di : Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3div4_df : Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3div4_di : Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3div4_sf : Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3div4_si : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3div8_sf : Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3div8_si : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3siv2_df : Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3siv2_di : Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3siv4_df : Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3siv4_di : Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3siv4_sf : Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3siv4_si : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3siv8_sf : Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_gather3siv8_si : Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem]>; def int_x86_avx512_mask_scatter_dpd_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i32_ty, llvm_v8f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scatter_dps_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v16i1_ty, llvm_v16i32_ty, llvm_v16f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scatter_qpd_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i64_ty, llvm_v8f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scatter_qps_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i64_ty, llvm_v8f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; + // NOTE: These can't be ArgMemOnly because you can put the address completely + // in the index register. def int_x86_avx512_mask_scatter_dpq_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i32_ty, llvm_v8i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scatter_dpi_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v16i1_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scatter_qpq_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty,llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scatter_qpi_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i64_ty, llvm_v8i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scatterdiv2_df : Intrinsic<[], [llvm_ptr_ty, llvm_v2i1_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scatterdiv2_di : Intrinsic<[], [llvm_ptr_ty, llvm_v2i1_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scatterdiv4_df : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scatterdiv4_di : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scatterdiv4_sf : Intrinsic<[], [llvm_ptr_ty, llvm_v2i1_ty, llvm_v2i64_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scatterdiv4_si : Intrinsic<[], [llvm_ptr_ty, llvm_v2i1_ty, llvm_v2i64_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scatterdiv8_sf : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i64_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scatterdiv8_si : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i64_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scattersiv2_df : Intrinsic<[], [llvm_ptr_ty, llvm_v2i1_ty, llvm_v4i32_ty, llvm_v2f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scattersiv2_di : Intrinsic<[], [llvm_ptr_ty, llvm_v2i1_ty, llvm_v4i32_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scattersiv4_df : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i32_ty, llvm_v4f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scattersiv4_di : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i32_ty, llvm_v4i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scattersiv4_sf : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scattersiv4_si : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scattersiv8_sf : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; def int_x86_avx512_mask_scattersiv8_si : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + []>; } // AVX-512 conflict detection instruction diff --git a/llvm/include/llvm/MC/MCSymbolWasm.h b/llvm/include/llvm/MC/MCSymbolWasm.h index 8e66dc881d0fb..34639b6ebb640 100644 --- a/llvm/include/llvm/MC/MCSymbolWasm.h +++ b/llvm/include/llvm/MC/MCSymbolWasm.h @@ -19,7 +19,8 @@ class MCSymbolWasm : public MCSymbol { bool IsWeak = false; bool IsHidden = false; bool IsComdat = false; - std::string ModuleName; + Optional ImportModule; + Optional ImportName; wasm::WasmSignature *Signature = nullptr; Optional GlobalType; Optional EventType; @@ -32,7 +33,7 @@ class MCSymbolWasm : public MCSymbol { // Use a module name of "env" for now, for compatibility with existing tools. // This is temporary, and may change, as the ABI is not yet stable. MCSymbolWasm(const StringMapEntry *Name, bool isTemporary) - : MCSymbol(SymbolKindWasm, Name, isTemporary), ModuleName("env") {} + : MCSymbol(SymbolKindWasm, Name, isTemporary) {} static bool classof(const MCSymbol *S) { return S->isWasm(); } const MCExpr *getSize() const { return SymbolSize; } @@ -55,8 +56,21 @@ class MCSymbolWasm : public MCSymbol { bool isComdat() const { return IsComdat; } void setComdat(bool isComdat) { IsComdat = isComdat; } - const StringRef getModuleName() const { return ModuleName; } - void setModuleName(StringRef Name) { ModuleName = Name; } + const StringRef getImportModule() const { + if (ImportModule.hasValue()) { + return ImportModule.getValue(); + } + return "env"; + } + void setImportModule(StringRef Name) { ImportModule = Name; } + + const StringRef getImportName() const { + if (ImportName.hasValue()) { + return ImportName.getValue(); + } + return getName(); + } + void setImportName(StringRef Name) { ImportName = Name; } const wasm::WasmSignature *getSignature() const { return Signature; } void setSignature(wasm::WasmSignature *Sig) { Signature = Sig; } diff --git a/llvm/include/llvm/Support/JSON.h b/llvm/include/llvm/Support/JSON.h index 7a04fd52bc50e..2b95a174e018c 100644 --- a/llvm/include/llvm/Support/JSON.h +++ b/llvm/include/llvm/Support/JSON.h @@ -481,6 +481,7 @@ class Value { mutable llvm::AlignedCharArrayUnion Union; + friend bool operator==(const Value &, const Value &); }; bool operator==(const Value &, const Value &); diff --git a/llvm/include/llvm/Transforms/Utils/FunctionImportUtils.h b/llvm/include/llvm/Transforms/Utils/FunctionImportUtils.h index e24398b90012b..fe13559768189 100644 --- a/llvm/include/llvm/Transforms/Utils/FunctionImportUtils.h +++ b/llvm/include/llvm/Transforms/Utils/FunctionImportUtils.h @@ -44,6 +44,11 @@ class FunctionImportGlobalProcessing { /// to promote any non-renamable values. SmallPtrSet Used; + /// Keep track of any COMDATs that require renaming (because COMDAT + /// leader was promoted and renamed). Maps from original COMDAT to one + /// with new name. + DenseMap RenamedComdats; + /// Check if we should promote the given local value to global scope. bool shouldPromoteLocalToGlobal(const GlobalValue *SGV); diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index 4643f75da42d1..ae86ee3d36500 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -161,25 +161,66 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, } if (T.isOSWindows() && !T.isOSCygMing()) { - // Win32 does not support long double + // XXX: The earliest documentation available at the moment is for VS2015/VC19: + // https://docs.microsoft.com/en-us/cpp/c-runtime-library/floating-point-support?view=vs-2015 + // XXX: In order to use an MSVCRT older than VC19, + // the specific library version must be explicit in the target triple, + // e.g., x86_64-pc-windows-msvc18. + bool hasPartialC99 = true; + if (T.isKnownWindowsMSVCEnvironment()) { + unsigned Major, Minor, Micro; + T.getEnvironmentVersion(Major, Minor, Micro); + hasPartialC99 = (Major == 0 || Major >= 19); + } + + // Latest targets support C89 math functions, in part. + bool isARM = (T.getArch() == Triple::aarch64 || + T.getArch() == Triple::arm); + bool hasPartialFloat = (isARM || + T.getArch() == Triple::x86_64); + + // Win32 does not support float C89 math functions, in general. + if (!hasPartialFloat) { + TLI.setUnavailable(LibFunc_acosf); + TLI.setUnavailable(LibFunc_asinf); + TLI.setUnavailable(LibFunc_atan2f); + TLI.setUnavailable(LibFunc_atanf); + TLI.setUnavailable(LibFunc_ceilf); + TLI.setUnavailable(LibFunc_cosf); + TLI.setUnavailable(LibFunc_coshf); + TLI.setUnavailable(LibFunc_expf); + TLI.setUnavailable(LibFunc_floorf); + TLI.setUnavailable(LibFunc_fmodf); + TLI.setUnavailable(LibFunc_log10f); + TLI.setUnavailable(LibFunc_logf); + TLI.setUnavailable(LibFunc_modff); + TLI.setUnavailable(LibFunc_powf); + TLI.setUnavailable(LibFunc_sinf); + TLI.setUnavailable(LibFunc_sinhf); + TLI.setUnavailable(LibFunc_sqrtf); + TLI.setUnavailable(LibFunc_tanf); + TLI.setUnavailable(LibFunc_tanhf); + } + if (!isARM) + TLI.setUnavailable(LibFunc_fabsf); + TLI.setUnavailable(LibFunc_frexpf); + TLI.setUnavailable(LibFunc_ldexpf); + + // Win32 does not support long double C89 math functions. TLI.setUnavailable(LibFunc_acosl); TLI.setUnavailable(LibFunc_asinl); - TLI.setUnavailable(LibFunc_atanl); TLI.setUnavailable(LibFunc_atan2l); + TLI.setUnavailable(LibFunc_atanl); TLI.setUnavailable(LibFunc_ceill); - TLI.setUnavailable(LibFunc_copysignl); TLI.setUnavailable(LibFunc_cosl); TLI.setUnavailable(LibFunc_coshl); TLI.setUnavailable(LibFunc_expl); - TLI.setUnavailable(LibFunc_fabsf); // Win32 and Win64 both lack fabsf TLI.setUnavailable(LibFunc_fabsl); TLI.setUnavailable(LibFunc_floorl); - TLI.setUnavailable(LibFunc_fmaxl); - TLI.setUnavailable(LibFunc_fminl); TLI.setUnavailable(LibFunc_fmodl); TLI.setUnavailable(LibFunc_frexpl); - TLI.setUnavailable(LibFunc_ldexpf); TLI.setUnavailable(LibFunc_ldexpl); + TLI.setUnavailable(LibFunc_log10l); TLI.setUnavailable(LibFunc_logl); TLI.setUnavailable(LibFunc_modfl); TLI.setUnavailable(LibFunc_powl); @@ -189,81 +230,66 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, TLI.setUnavailable(LibFunc_tanl); TLI.setUnavailable(LibFunc_tanhl); - // Win32 only has C89 math - TLI.setUnavailable(LibFunc_acosh); - TLI.setUnavailable(LibFunc_acoshf); + // Win32 does not fully support C99 math functions. + if (!hasPartialC99) { + TLI.setUnavailable(LibFunc_acosh); + TLI.setUnavailable(LibFunc_acoshf); + TLI.setUnavailable(LibFunc_asinh); + TLI.setUnavailable(LibFunc_asinhf); + TLI.setUnavailable(LibFunc_atanh); + TLI.setUnavailable(LibFunc_atanhf); + TLI.setAvailableWithName(LibFunc_cabs, "_cabs"); + TLI.setUnavailable(LibFunc_cabsf); + TLI.setUnavailable(LibFunc_cbrt); + TLI.setUnavailable(LibFunc_cbrtf); + TLI.setAvailableWithName(LibFunc_copysign, "_copysign"); + TLI.setAvailableWithName(LibFunc_copysignf, "_copysignf"); + TLI.setUnavailable(LibFunc_exp2); + TLI.setUnavailable(LibFunc_exp2f); + TLI.setUnavailable(LibFunc_expm1); + TLI.setUnavailable(LibFunc_expm1f); + TLI.setUnavailable(LibFunc_fmax); + TLI.setUnavailable(LibFunc_fmaxf); + TLI.setUnavailable(LibFunc_fmin); + TLI.setUnavailable(LibFunc_fminf); + TLI.setUnavailable(LibFunc_log1p); + TLI.setUnavailable(LibFunc_log1pf); + TLI.setUnavailable(LibFunc_log2); + TLI.setUnavailable(LibFunc_log2f); + TLI.setAvailableWithName(LibFunc_logb, "_logb"); + if (hasPartialFloat) + TLI.setAvailableWithName(LibFunc_logbf, "_logbf"); + else + TLI.setUnavailable(LibFunc_logbf); + TLI.setUnavailable(LibFunc_rint); + TLI.setUnavailable(LibFunc_rintf); + TLI.setUnavailable(LibFunc_round); + TLI.setUnavailable(LibFunc_roundf); + TLI.setUnavailable(LibFunc_trunc); + TLI.setUnavailable(LibFunc_truncf); + } + + // Win32 does not support long double C99 math functions. TLI.setUnavailable(LibFunc_acoshl); - TLI.setUnavailable(LibFunc_asinh); - TLI.setUnavailable(LibFunc_asinhf); TLI.setUnavailable(LibFunc_asinhl); - TLI.setUnavailable(LibFunc_atanh); - TLI.setUnavailable(LibFunc_atanhf); TLI.setUnavailable(LibFunc_atanhl); - TLI.setUnavailable(LibFunc_cabs); - TLI.setUnavailable(LibFunc_cabsf); TLI.setUnavailable(LibFunc_cabsl); - TLI.setUnavailable(LibFunc_cbrt); - TLI.setUnavailable(LibFunc_cbrtf); TLI.setUnavailable(LibFunc_cbrtl); - TLI.setUnavailable(LibFunc_exp2); - TLI.setUnavailable(LibFunc_exp2f); + TLI.setUnavailable(LibFunc_copysignl); TLI.setUnavailable(LibFunc_exp2l); - TLI.setUnavailable(LibFunc_expm1); - TLI.setUnavailable(LibFunc_expm1f); TLI.setUnavailable(LibFunc_expm1l); - TLI.setUnavailable(LibFunc_log2); - TLI.setUnavailable(LibFunc_log2f); - TLI.setUnavailable(LibFunc_log2l); - TLI.setUnavailable(LibFunc_log1p); - TLI.setUnavailable(LibFunc_log1pf); + TLI.setUnavailable(LibFunc_fmaxl); + TLI.setUnavailable(LibFunc_fminl); TLI.setUnavailable(LibFunc_log1pl); - TLI.setUnavailable(LibFunc_logb); - TLI.setUnavailable(LibFunc_logbf); + TLI.setUnavailable(LibFunc_log2l); TLI.setUnavailable(LibFunc_logbl); - TLI.setUnavailable(LibFunc_nearbyint); - TLI.setUnavailable(LibFunc_nearbyintf); TLI.setUnavailable(LibFunc_nearbyintl); - TLI.setUnavailable(LibFunc_rint); - TLI.setUnavailable(LibFunc_rintf); TLI.setUnavailable(LibFunc_rintl); - TLI.setUnavailable(LibFunc_round); - TLI.setUnavailable(LibFunc_roundf); TLI.setUnavailable(LibFunc_roundl); - TLI.setUnavailable(LibFunc_trunc); - TLI.setUnavailable(LibFunc_truncf); TLI.setUnavailable(LibFunc_truncl); - // Win32 provides some C99 math with mangled names - TLI.setAvailableWithName(LibFunc_copysign, "_copysign"); - - if (T.getArch() == Triple::x86) { - // Win32 on x86 implements single-precision math functions as macros - TLI.setUnavailable(LibFunc_acosf); - TLI.setUnavailable(LibFunc_asinf); - TLI.setUnavailable(LibFunc_atanf); - TLI.setUnavailable(LibFunc_atan2f); - TLI.setUnavailable(LibFunc_ceilf); - TLI.setUnavailable(LibFunc_copysignf); - TLI.setUnavailable(LibFunc_cosf); - TLI.setUnavailable(LibFunc_coshf); - TLI.setUnavailable(LibFunc_expf); - TLI.setUnavailable(LibFunc_floorf); - TLI.setUnavailable(LibFunc_fminf); - TLI.setUnavailable(LibFunc_fmaxf); - TLI.setUnavailable(LibFunc_fmodf); - TLI.setUnavailable(LibFunc_logf); - TLI.setUnavailable(LibFunc_log10f); - TLI.setUnavailable(LibFunc_modff); - TLI.setUnavailable(LibFunc_powf); - TLI.setUnavailable(LibFunc_sinf); - TLI.setUnavailable(LibFunc_sinhf); - TLI.setUnavailable(LibFunc_sqrtf); - TLI.setUnavailable(LibFunc_tanf); - TLI.setUnavailable(LibFunc_tanhf); - } - - // Win32 does *not* provide these functions, but they are - // generally available on POSIX-compliant systems: + // Win32 does not support these functions, but + // they are generally available on POSIX-compliant systems. TLI.setUnavailable(LibFunc_access); TLI.setUnavailable(LibFunc_bcmp); TLI.setUnavailable(LibFunc_bcopy); @@ -318,12 +344,6 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, TLI.setUnavailable(LibFunc_utime); TLI.setUnavailable(LibFunc_utimes); TLI.setUnavailable(LibFunc_write); - - // Win32 does *not* provide provide these functions, but they are - // specified by C99: - TLI.setUnavailable(LibFunc_atoll); - TLI.setUnavailable(LibFunc_frexpf); - TLI.setUnavailable(LibFunc_llabs); } switch (T.getOS()) { diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 8cabad4ad3123..154f81f2622d4 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1836,7 +1836,10 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty, unsigned Index = 0; SmallVector ArgTypeIndices; - TypeIndex ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]); + TypeIndex ReturnTypeIndex = TypeIndex::Void(); + if (ReturnAndArgs.size() > Index) { + ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]); + } // If the first argument is a pointer type and this isn't a static method, // treat it as the special 'this' parameter, which is encoded separately from diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 1de2ffb6cfa11..18c5fe27b1a8f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1956,8 +1956,10 @@ void DebugLocEntry::finalize(const AsmPrinter &AP, void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) { // Emit the size. Asm->OutStreamer->AddComment("Loc expr size"); - Asm->emitInt16(DebugLocs.getBytes(Entry).size()); - + if (getDwarfVersion() >= 5) + Asm->EmitULEB128(DebugLocs.getBytes(Entry).size()); + else + Asm->emitInt16(DebugLocs.getBytes(Entry).size()); // Emit the entry. APByteStreamer Streamer(*Asm); emitDebugLocEntry(Streamer, Entry); diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp index cf8e8c69bc2a6..92df09b7d6a23 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp @@ -545,15 +545,17 @@ void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) { OS.AddComment(Comment); }; - // Emit a label assignment with the SEH frame offset so we can use it for - // llvm.eh.recoverfp. - StringRef FLinkageName = - GlobalValue::dropLLVMManglingEscape(MF->getFunction().getName()); - MCSymbol *ParentFrameOffset = - Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName); - const MCExpr *MCOffset = - MCConstantExpr::create(FuncInfo.SEHSetFrameOffset, Ctx); - Asm->OutStreamer->EmitAssignment(ParentFrameOffset, MCOffset); + if (!isAArch64) { + // Emit a label assignment with the SEH frame offset so we can use it for + // llvm.eh.recoverfp. + StringRef FLinkageName = + GlobalValue::dropLLVMManglingEscape(MF->getFunction().getName()); + MCSymbol *ParentFrameOffset = + Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName); + const MCExpr *MCOffset = + MCConstantExpr::create(FuncInfo.SEHSetFrameOffset, Ctx); + Asm->OutStreamer->EmitAssignment(ParentFrameOffset, MCOffset); + } // Use the assembler to compute the number of table entries through label // difference and division. @@ -937,6 +939,9 @@ void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo, if (FI != INT_MAX) { const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering(); unsigned UnusedReg; + // FIXME: getFrameIndexReference needs to match the behavior of + // AArch64RegisterInfo::hasBasePointer in which one of the scenarios where + // SP is used is if frame size >= 256. Offset = TFI->getFrameIndexReference(*Asm->MF, FI, UnusedReg); } diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index 764a84c7e1327..dc1ad953e71d4 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -225,12 +225,13 @@ void MachineInstr::addOperand(MachineFunction &MF, const MachineOperand &Op) { } #ifndef NDEBUG - bool isMetaDataOp = Op.getType() == MachineOperand::MO_Metadata; + bool isDebugOp = Op.getType() == MachineOperand::MO_Metadata || + Op.getType() == MachineOperand::MO_MCSymbol; // OpNo now points as the desired insertion point. Unless this is a variadic // instruction, only implicit regs are allowed beyond MCID->getNumOperands(). // RegMask operands go between the explicit and implicit operands. assert((isImpReg || Op.isRegMask() || MCID->isVariadic() || - OpNo < MCID->getNumOperands() || isMetaDataOp) && + OpNo < MCID->getNumOperands() || isDebugOp) && "Trying to add an operand to a machine instr that is already done!"); #endif diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index ff5505c977213..6af01423ca106 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -16214,23 +16214,29 @@ static SDValue reduceBuildVecToShuffleWithZero(SDNode *BV, SelectionDAG &DAG) { // The build vector contains some number of undef elements and exactly // one other element. That other element must be a zero-extended scalar // extracted from a vector at a constant index to turn this into a shuffle. + // Also, require that the build vector does not implicitly truncate/extend + // its elements. // TODO: This could be enhanced to allow ANY_EXTEND as well as ZERO_EXTEND. + EVT VT = BV->getValueType(0); SDValue Zext = BV->getOperand(ZextElt); if (Zext.getOpcode() != ISD::ZERO_EXTEND || !Zext.hasOneUse() || Zext.getOperand(0).getOpcode() != ISD::EXTRACT_VECTOR_ELT || - !isa(Zext.getOperand(0).getOperand(1))) + !isa(Zext.getOperand(0).getOperand(1)) || + Zext.getValueSizeInBits() != VT.getScalarSizeInBits()) return SDValue(); - // The zero-extend must be a multiple of the source size. + // The zero-extend must be a multiple of the source size, and we must be + // building a vector of the same size as the source of the extract element. SDValue Extract = Zext.getOperand(0); unsigned DestSize = Zext.getValueSizeInBits(); unsigned SrcSize = Extract.getValueSizeInBits(); - if (DestSize % SrcSize != 0) + if (DestSize % SrcSize != 0 || + Extract.getOperand(0).getValueSizeInBits() != VT.getSizeInBits()) return SDValue(); // Create a shuffle mask that will combine the extracted element with zeros // and undefs. - int ZextRatio = DestSize / SrcSize; + int ZextRatio = DestSize / SrcSize; int NumMaskElts = NumBVOps * ZextRatio; SmallVector ShufMask(NumMaskElts, -1); for (int i = 0; i != NumMaskElts; ++i) { @@ -16260,7 +16266,7 @@ static SDValue reduceBuildVecToShuffleWithZero(SDNode *BV, SelectionDAG &DAG) { SDValue ZeroVec = DAG.getConstant(0, DL, VecVT); SDValue Shuf = DAG.getVectorShuffle(VecVT, DL, Extract.getOperand(0), ZeroVec, ShufMask); - return DAG.getBitcast(BV->getValueType(0), Shuf); + return DAG.getBitcast(VT, Shuf); } // Check to see if this is a BUILD_VECTOR of a bunch of EXTRACT_VECTOR_ELT diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 871ab9b29881b..bfeb3d1bc2b91 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6182,6 +6182,8 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { .addFrameIndex(FI); } + MF.setHasLocalEscape(true); + return nullptr; } diff --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp index 661dc18f7a85e..d3059280a60fc 100644 --- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp +++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp @@ -14,6 +14,7 @@ #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -398,6 +399,7 @@ TargetRegisterInfo::getRegAllocationHints(unsigned VirtReg, const std::pair> &Hints_MRI = MRI.getRegAllocationHints(VirtReg); + SmallSet HintedRegs; // First hint may be a target hint. bool Skip = (Hints_MRI.first != 0); for (auto Reg : Hints_MRI.second) { @@ -411,6 +413,10 @@ TargetRegisterInfo::getRegAllocationHints(unsigned VirtReg, if (VRM && isVirtualRegister(Phys)) Phys = VRM->getPhys(Phys); + // Don't add the same reg twice (Hints_MRI may contain multiple virtual + // registers allocated to the same physreg). + if (!HintedRegs.insert(Phys).second) + continue; // Check that Phys is a valid hint in VirtReg's register class. if (!isPhysicalRegister(Phys)) continue; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index ba55ffc28174f..8a88a2fa3a09a 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -301,7 +301,7 @@ void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { OS << format(" Data alignment factor: %d\n", (int32_t)DataAlignmentFactor); OS << format(" Return address column: %d\n", (int32_t)ReturnAddressRegister); if (Personality) - OS << format(" Personality Address: %08x\n", *Personality); + OS << format(" Personality Address: %016" PRIx64 "\n", *Personality); if (!AugmentationData.empty()) { OS << " Augmentation data: "; for (uint8_t Byte : AugmentationData) @@ -320,7 +320,7 @@ void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { (uint32_t)InitialLocation, (uint32_t)InitialLocation + (uint32_t)AddressRange); if (LSDAAddress) - OS << format(" LSDA Address: %08x\n", *LSDAAddress); + OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress); CFIs.dump(OS, MRI, IsEH); OS << "\n"; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp index f8b5ff6ec8fb6..94df6946f3ae2 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -184,7 +184,8 @@ DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, unsigned *Offset, } if (Kind != dwarf::DW_LLE_base_address) { - unsigned Bytes = Data.getU16(Offset); + unsigned Bytes = + Version >= 5 ? Data.getULEB128(Offset) : Data.getU16(Offset); // A single location description describing the location of the object... StringRef str = Data.getData().substr(*Offset, Bytes); *Offset += Bytes; diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp index b2eb8b09982e8..27064154221f4 100644 --- a/llvm/lib/IR/AutoUpgrade.cpp +++ b/llvm/lib/IR/AutoUpgrade.cpp @@ -469,6 +469,11 @@ static bool UpgradeX86IntrinsicFunction(Function *F, StringRef Name, } } + if (Name == "seh.recoverfp") { + NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_recoverfp); + return true; + } + return false; } @@ -544,10 +549,6 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::thread_pointer); return true; } - if (Name == "x86.seh.recoverfp") { - NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_recoverfp); - return true; - } break; } diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 89f3b30cddd6f..1b505776ca19b 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -1271,18 +1271,25 @@ void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, // This is the first place we are able to copy this information. Alias->setExternal(Symbol.isExternal()); Alias->setBinding(Symbol.getBinding()); + Alias->setOther(Symbol.getOther()); if (!Symbol.isUndefined() && !Rest.startswith("@@@")) continue; - // FIXME: produce a better error message. + // FIXME: Get source locations for these errors or diagnose them earlier. if (Symbol.isUndefined() && Rest.startswith("@@") && - !Rest.startswith("@@@")) - report_fatal_error("A @@ version cannot be undefined"); + !Rest.startswith("@@@")) { + Asm.getContext().reportError(SMLoc(), "versioned symbol " + AliasName + + " must be defined"); + continue; + } - if (Renames.count(&Symbol) && Renames[&Symbol] != Alias) - report_fatal_error(llvm::Twine("Multiple symbol versions defined for ") + - Symbol.getName()); + if (Renames.count(&Symbol) && Renames[&Symbol] != Alias) { + Asm.getContext().reportError( + SMLoc(), llvm::Twine("multiple symbol versions defined for ") + + Symbol.getName()); + continue; + } Renames.insert(std::make_pair(&Symbol, Alias)); } diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index 3c022199145fb..0e4174a7a4c94 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -559,6 +559,11 @@ static void AttemptToFoldSymbolOffsetDifference( if (Asm->isThumbFunc(&SA)) Addend |= 1; + // If symbol is labeled as micromips, we set low-bit to ensure + // correct offset in .gcc_except_table + if (Asm->getBackend().isMicroMips(&SA)) + Addend |= 1; + // Clear the symbol expr pointers to indicate we have folded these // operands. A = B = nullptr; diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index cf42a6f7075b9..a0506715be372 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -3364,10 +3364,11 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { } if (FileNumber == -1) { - if (!getContext().getAsmInfo()->hasSingleParameterDotFile()) - return Error(DirectiveLoc, - "target does not support '.file' without a number"); - getStreamer().EmitFileDirective(Filename); + // Ignore the directive if there is no number and the target doesn't support + // numberless .file directives. This allows some portability of assembler + // between different object file formats. + if (getContext().getAsmInfo()->hasSingleParameterDotFile()) + getStreamer().EmitFileDirective(Filename); } else { // In case there is a -g option as well as debug info from directive .file, // we turn off the -g option, directly use the existing debug info instead. diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp index 0724b109e1a1d..3ef1514455af3 100644 --- a/llvm/lib/MC/MCWin64EH.cpp +++ b/llvm/lib/MC/MCWin64EH.cpp @@ -453,6 +453,38 @@ static void ARM64EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin, } } +// Returns the epilog symbol of an epilog with the exact same unwind code +// sequence, if it exists. Otherwise, returns nulltpr. +// EpilogInstrs - Unwind codes for the current epilog. +// Epilogs - Epilogs that potentialy match the current epilog. +static MCSymbol* +FindMatchingEpilog(const std::vector& EpilogInstrs, + const std::vector& Epilogs, + const WinEH::FrameInfo *info) { + for (auto *EpilogStart : Epilogs) { + auto InstrsIter = info->EpilogMap.find(EpilogStart); + assert(InstrsIter != info->EpilogMap.end() && + "Epilog not found in EpilogMap"); + const auto &Instrs = InstrsIter->second; + + if (Instrs.size() != EpilogInstrs.size()) + continue; + + bool Match = true; + for (unsigned i = 0; i < Instrs.size(); ++i) + if (Instrs[i].Operation != EpilogInstrs[i].Operation || + Instrs[i].Offset != EpilogInstrs[i].Offset || + Instrs[i].Register != EpilogInstrs[i].Register) { + Match = false; + break; + } + + if (Match) + return EpilogStart; + } + return nullptr; +} + // Populate the .xdata section. The format of .xdata on ARM64 is documented at // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) { @@ -477,12 +509,28 @@ static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) { // Process epilogs. MapVector EpilogInfo; + // Epilogs processed so far. + std::vector AddedEpilogs; + for (auto &I : info->EpilogMap) { MCSymbol *EpilogStart = I.first; auto &EpilogInstrs = I.second; uint32_t CodeBytes = ARM64CountOfUnwindCodes(EpilogInstrs); - EpilogInfo[EpilogStart] = TotalCodeBytes; - TotalCodeBytes += CodeBytes; + + MCSymbol* MatchingEpilog = + FindMatchingEpilog(EpilogInstrs, AddedEpilogs, info); + if (MatchingEpilog) { + assert(EpilogInfo.find(MatchingEpilog) != EpilogInfo.end() && + "Duplicate epilog not found"); + EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog); + // Clear the unwind codes in the EpilogMap, so that they don't get output + // in the logic below. + EpilogInstrs.clear(); + } else { + EpilogInfo[EpilogStart] = TotalCodeBytes; + TotalCodeBytes += CodeBytes; + AddedEpilogs.push_back(EpilogStart); + } } // Code Words, Epilog count, E, X, Vers, Function Length diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index 0cca3757be907..b07fe05cad5b9 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -368,7 +368,13 @@ void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section, // Now that the section is complete and we know how big it is, patch up the // section size field at the start of the section. void WasmObjectWriter::endSection(SectionBookkeeping &Section) { - uint64_t Size = W.OS.tell() - Section.PayloadOffset; + uint64_t Size = W.OS.tell(); + // /dev/null doesn't support seek/tell and can report offset of 0. + // Simply skip this patching in that case. + if (!Size) + return; + + Size -= Section.PayloadOffset; if (uint32_t(Size) != Size) report_fatal_error("section size does not fit in a uint32_t"); @@ -982,7 +988,8 @@ void WasmObjectWriter::writeLinkingMetaDataSection( case wasm::WASM_SYMBOL_TYPE_GLOBAL: case wasm::WASM_SYMBOL_TYPE_EVENT: encodeULEB128(Sym.ElementIndex, W.OS); - if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) + if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 || + (Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) writeString(Sym.Name); break; case wasm::WASM_SYMBOL_TYPE_DATA: @@ -1162,8 +1169,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, MCSymbolWasm *MemorySym = cast(Ctx.getOrCreateSymbol("__linear_memory")); wasm::WasmImport MemImport; - MemImport.Module = MemorySym->getModuleName(); - MemImport.Field = MemorySym->getName(); + MemImport.Module = MemorySym->getImportModule(); + MemImport.Field = MemorySym->getImportName(); MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY; Imports.push_back(MemImport); @@ -1173,8 +1180,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, MCSymbolWasm *TableSym = cast(Ctx.getOrCreateSymbol("__indirect_function_table")); wasm::WasmImport TableImport; - TableImport.Module = TableSym->getModuleName(); - TableImport.Field = TableSym->getName(); + TableImport.Module = TableSym->getImportModule(); + TableImport.Field = TableSym->getImportName(); TableImport.Kind = wasm::WASM_EXTERNAL_TABLE; TableImport.Table.ElemType = wasm::WASM_TYPE_FUNCREF; Imports.push_back(TableImport); @@ -1200,8 +1207,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, if (!WS.isDefined() && !WS.isComdat()) { if (WS.isFunction()) { wasm::WasmImport Import; - Import.Module = WS.getModuleName(); - Import.Field = WS.getName(); + Import.Module = WS.getImportModule(); + Import.Field = WS.getImportName(); Import.Kind = wasm::WASM_EXTERNAL_FUNCTION; Import.SigIndex = getFunctionType(WS); Imports.push_back(Import); @@ -1211,8 +1218,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, report_fatal_error("undefined global symbol cannot be weak"); wasm::WasmImport Import; - Import.Module = WS.getModuleName(); - Import.Field = WS.getName(); + Import.Module = WS.getImportModule(); + Import.Field = WS.getImportName(); Import.Kind = wasm::WASM_EXTERNAL_GLOBAL; Import.Global = WS.getGlobalType(); Imports.push_back(Import); @@ -1222,8 +1229,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, report_fatal_error("undefined event symbol cannot be weak"); wasm::WasmImport Import; - Import.Module = WS.getModuleName(); - Import.Field = WS.getName(); + Import.Module = WS.getImportModule(); + Import.Field = WS.getImportName(); Import.Kind = wasm::WASM_EXTERNAL_EVENT; Import.Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION; Import.Event.SigIndex = getEventType(WS); @@ -1448,6 +1455,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL; if (WS.isUndefined()) Flags |= wasm::WASM_SYMBOL_UNDEFINED; + if (WS.getName() != WS.getImportName()) + Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME; wasm::WasmSymbolInfo Info; Info.Name = WS.getName(); diff --git a/llvm/lib/Object/COFFImportFile.cpp b/llvm/lib/Object/COFFImportFile.cpp index dc11cc4bcffe6..e7c7efe436764 100644 --- a/llvm/lib/Object/COFFImportFile.cpp +++ b/llvm/lib/Object/COFFImportFile.cpp @@ -496,7 +496,7 @@ NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym, // COFF Header coff_file_header Header{ - u16(0), + u16(Machine), u16(NumberOfSections), u32(0), u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section))), diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp index d84cb48c9fbd5..66a53becbb056 100644 --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -505,9 +505,13 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { Function.SymbolName = Info.Name; } else { wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex]; + if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) + Info.Name = readString(Ctx); + else + Info.Name = Import.Field; Signature = &Signatures[Import.SigIndex]; - Info.Name = Import.Field; - Info.Module = Import.Module; + Info.ImportName = Import.Field; + Info.ImportModule = Import.Module; } break; @@ -530,8 +534,13 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { Global.SymbolName = Info.Name; } else { wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex]; - Info.Name = Import.Field; + if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) + Info.Name = readString(Ctx); + else + Info.Name = Import.Field; GlobalType = &Import.Global; + Info.ImportName = Import.Field; + Info.ImportModule = Import.Module; } break; @@ -585,9 +594,14 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { } else { wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex]; + if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) + Info.Name = readString(Ctx); + else + Info.Name = Import.Field; EventType = &Import.Event; Signature = &Signatures[EventType->SigIndex]; - Info.Name = Import.Field; + Info.ImportName = Import.Field; + Info.ImportModule = Import.Module; } break; } diff --git a/llvm/lib/Support/JSON.cpp b/llvm/lib/Support/JSON.cpp index d468013fb94a5..07a556814915d 100644 --- a/llvm/lib/Support/JSON.cpp +++ b/llvm/lib/Support/JSON.cpp @@ -182,6 +182,12 @@ bool operator==(const Value &L, const Value &R) { case Value::Boolean: return *L.getAsBoolean() == *R.getAsBoolean(); case Value::Number: + // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 + // The same integer must convert to the same double, per the standard. + // However we see 64-vs-80-bit precision comparisons with gcc-7 -O3 -m32. + // So we avoid floating point promotion for exact comparisons. + if (L.Type == Value::T_Integer || R.Type == Value::T_Integer) + return L.getAsInteger() == R.getAsInteger(); return *L.getAsNumber() == *R.getAsNumber(); case Value::String: return *L.getAsString() == *R.getAsString(); diff --git a/llvm/lib/Support/Unix/Threading.inc b/llvm/lib/Support/Unix/Threading.inc index 2d49ce1ad747a..92bec36d6a2da 100644 --- a/llvm/lib/Support/Unix/Threading.inc +++ b/llvm/lib/Support/Unix/Threading.inc @@ -202,6 +202,12 @@ void llvm::get_thread_name(SmallVectorImpl &Name) { char buf[len]; ::pthread_getname_np(::pthread_self(), buf, len); + Name.append(buf, buf + strlen(buf)); +#elif defined(__OpenBSD__) + constexpr uint32_t len = get_max_thread_name_length_impl(); + char buf[len]; + ::pthread_get_name_np(::pthread_self(), buf, len); + Name.append(buf, buf + strlen(buf)); #elif defined(__linux__) #if HAVE_PTHREAD_GETNAME_NP diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index 0442076992e24..2e1d1f1130a9d 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -471,9 +471,18 @@ void AArch64AsmPrinter::EmitJumpTableInfo() { const std::vector &JT = MJTI->getJumpTables(); if (JT.empty()) return; + const Function &F = MF->getFunction(); const TargetLoweringObjectFile &TLOF = getObjFileLowering(); - MCSection *ReadOnlySec = TLOF.getSectionForJumpTable(MF->getFunction(), TM); - OutStreamer->SwitchSection(ReadOnlySec); + bool JTInDiffSection = + !STI->isTargetCOFF() || + !TLOF.shouldPutJumpTableInFunctionSection( + MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32, + F); + if (JTInDiffSection) { + // Drop it in the readonly section. + MCSection *ReadOnlySec = TLOF.getSectionForJumpTable(F, TM); + OutStreamer->SwitchSection(ReadOnlySec); + } auto AFI = MF->getInfo(); for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) { @@ -694,6 +703,34 @@ void AArch64AsmPrinter::EmitInstruction(const MachineInstr *MI) { switch (MI->getOpcode()) { default: break; + case AArch64::MOVMCSym: { + unsigned DestReg = MI->getOperand(0).getReg(); + const MachineOperand &MO_Sym = MI->getOperand(1); + MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym); + MCOperand Hi_MCSym, Lo_MCSym; + + Hi_MOSym.setTargetFlags(AArch64II::MO_G1 | AArch64II::MO_S); + Lo_MOSym.setTargetFlags(AArch64II::MO_G0 | AArch64II::MO_NC); + + MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym); + MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym); + + MCInst MovZ; + MovZ.setOpcode(AArch64::MOVZXi); + MovZ.addOperand(MCOperand::createReg(DestReg)); + MovZ.addOperand(Hi_MCSym); + MovZ.addOperand(MCOperand::createImm(16)); + EmitToStreamer(*OutStreamer, MovZ); + + MCInst MovK; + MovK.setOpcode(AArch64::MOVKXi); + MovK.addOperand(MCOperand::createReg(DestReg)); + MovK.addOperand(MCOperand::createReg(DestReg)); + MovK.addOperand(Lo_MCSym); + MovK.addOperand(MCOperand::createImm(0)); + EmitToStreamer(*OutStreamer, MovK); + return; + } case AArch64::MOVIv2d_ns: // If the target has , lower this // instruction to movi.16b instead. diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index 538a8d7e8fbcf..57f630a18c8ad 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -228,6 +228,10 @@ bool AArch64FrameLowering::hasFP(const MachineFunction &MF) const { MFI.getMaxCallFrameSize() > DefaultSafeSPDisplacement) return true; + // Win64 SEH requires frame pointer if funclets are present. + if (MF.hasLocalEscape()) + return true; + return false; } @@ -2104,9 +2108,6 @@ void AArch64FrameLowering::processFunctionBeforeFrameFinalized( while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup)) ++MBBI; - if (MBBI->isTerminator()) - return; - // Create an UnwindHelp object. int UnwindHelpFI = MFI.CreateStackObject(/*size*/8, /*alignment*/16, false); @@ -2114,8 +2115,10 @@ void AArch64FrameLowering::processFunctionBeforeFrameFinalized( // We need to store -2 into the UnwindHelp object at the start of the // function. DebugLoc DL; - RS->enterBasicBlock(MBB); - unsigned DstReg = RS->scavengeRegister(&AArch64::GPR64RegClass, MBBI, 0); + RS->enterBasicBlockEnd(MBB); + RS->backward(std::prev(MBBI)); + unsigned DstReg = RS->FindUnusedReg(&AArch64::GPR64commonRegClass); + assert(DstReg && "There must be a free register after frame setup"); BuildMI(MBB, MBBI, DL, TII.get(AArch64::MOVi64imm), DstReg).addImm(-2); BuildMI(MBB, MBBI, DL, TII.get(AArch64::STURXi)) .addReg(DstReg, getKillRegState(true)) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index e01ca14d7f63d..762f4413d72b9 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -2743,6 +2743,34 @@ SDValue AArch64TargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, case Intrinsic::aarch64_neon_umin: return DAG.getNode(ISD::UMIN, dl, Op.getValueType(), Op.getOperand(1), Op.getOperand(2)); + + case Intrinsic::localaddress: { + // Returns one of the stack, base, or frame pointer registers, depending on + // which is used to reference local variables. + MachineFunction &MF = DAG.getMachineFunction(); + const AArch64RegisterInfo *RegInfo = Subtarget->getRegisterInfo(); + unsigned Reg; + if (RegInfo->hasBasePointer(MF)) + Reg = RegInfo->getBaseRegister(); + else // This function handles the SP or FP case. + Reg = RegInfo->getFrameRegister(MF); + return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, + Op.getSimpleValueType()); + } + + case Intrinsic::eh_recoverfp: { + // FIXME: This needs to be implemented to correctly handle highly aligned + // stack objects. For now we simply return the incoming FP. Refer D53541 + // for more details. + SDValue FnOp = Op.getOperand(1); + SDValue IncomingFPOp = Op.getOperand(2); + GlobalAddressSDNode *GSD = dyn_cast(FnOp); + auto *Fn = dyn_cast_or_null(GSD ? GSD->getGlobal() : nullptr); + if (!Fn) + report_fatal_error( + "llvm.eh.recoverfp must take a function as the first argument"); + return IncomingFPOp; + } } } diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index ada0678885729..50316ebe218b7 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -2292,6 +2292,31 @@ void AArch64InstrInfo::copyPhysRegTuple(MachineBasicBlock &MBB, } } +void AArch64InstrInfo::copyGPRRegTuple(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + DebugLoc DL, unsigned DestReg, + unsigned SrcReg, bool KillSrc, + unsigned Opcode, unsigned ZeroReg, + llvm::ArrayRef Indices) const { + const TargetRegisterInfo *TRI = &getRegisterInfo(); + unsigned NumRegs = Indices.size(); + +#ifndef NDEBUG + uint16_t DestEncoding = TRI->getEncodingValue(DestReg); + uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg); + assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 && + "GPR reg sequences should not be able to overlap"); +#endif + + for (unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) { + const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode)); + AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI); + MIB.addReg(ZeroReg); + AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI); + MIB.addImm(0); + } +} + void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, unsigned DestReg, @@ -2431,6 +2456,22 @@ void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB, return; } + if (AArch64::XSeqPairsClassRegClass.contains(DestReg) && + AArch64::XSeqPairsClassRegClass.contains(SrcReg)) { + static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64}; + copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRXrs, + AArch64::XZR, Indices); + return; + } + + if (AArch64::WSeqPairsClassRegClass.contains(DestReg) && + AArch64::WSeqPairsClassRegClass.contains(SrcReg)) { + static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32}; + copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRWrs, + AArch64::WZR, Indices); + return; + } + if (AArch64::FPR128RegClass.contains(DestReg) && AArch64::FPR128RegClass.contains(SrcReg)) { if (Subtarget.hasNEON()) { diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h index 9954669d56750..e48c26d4a84a0 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h @@ -122,6 +122,10 @@ class AArch64InstrInfo final : public AArch64GenInstrInfo { const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc, unsigned Opcode, llvm::ArrayRef Indices) const; + void copyGPRRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + DebugLoc DL, unsigned DestReg, unsigned SrcReg, + bool KillSrc, unsigned Opcode, unsigned ZeroReg, + llvm::ArrayRef Indices) const; void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override; diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index c24b8b36441bb..86a4119c45f58 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -133,6 +133,10 @@ def UseNegativeImmediates : Predicate<"false">, AssemblerPredicate<"!FeatureNoNegativeImmediates", "NegativeImmediates">; +def AArch64LocalRecover : SDNode<"ISD::LOCAL_RECOVER", + SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, + SDTCisInt<1>]>>; + //===----------------------------------------------------------------------===// // AArch64-specific DAG Nodes. @@ -6801,5 +6805,8 @@ def : Pat<(AArch64tcret tglobaladdr:$dst, (i32 timm:$FPDiff)), def : Pat<(AArch64tcret texternalsym:$dst, (i32 timm:$FPDiff)), (TCRETURNdi texternalsym:$dst, imm:$FPDiff)>; +def MOVMCSym : Pseudo<(outs GPR64:$dst), (ins i64imm:$sym), []>, Sched<[]>; +def : Pat<(i64 (AArch64LocalRecover mcsym:$sym)), (MOVMCSym mcsym:$sym)>; + include "AArch64InstrAtomics.td" include "AArch64SVEInstrInfo.td" diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp index 96ae45ae3d0dc..3daac23592de7 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -466,6 +466,13 @@ void AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, // Modify MI as necessary to handle as much of 'Offset' as possible Offset = TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg); + + if (MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE) { + MachineOperand &FI = MI.getOperand(FIOperandNum); + FI.ChangeToImmediate(Offset); + return; + } + if (rewriteAArch64FrameIndex(MI, FIOperandNum, FrameReg, Offset, TII)) return; diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td index d3710cea0687e..8e6aa69eae854 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td @@ -649,10 +649,12 @@ def FPR128Op : RegisterOperand { // ARMv8.1a atomic CASP register operands -def WSeqPairs : RegisterTuples<[sube32, subo32], - [(rotl GPR32, 0), (rotl GPR32, 1)]>; -def XSeqPairs : RegisterTuples<[sube64, subo64], - [(rotl GPR64, 0), (rotl GPR64, 1)]>; +def WSeqPairs : RegisterTuples<[sube32, subo32], + [(decimate (rotl GPR32, 0), 2), + (decimate (rotl GPR32, 1), 2)]>; +def XSeqPairs : RegisterTuples<[sube64, subo64], + [(decimate (rotl GPR64, 0), 2), + (decimate (rotl GPR64, 1), 2)]>; def WSeqPairsClass : RegisterClass<"AArch64", [untyped], 32, (add WSeqPairs)>{ diff --git a/llvm/lib/Target/AArch64/AArch64SchedExynosM4.td b/llvm/lib/Target/AArch64/AArch64SchedExynosM4.td index 4d892465b3f27..61652b1d8e3dc 100644 --- a/llvm/lib/Target/AArch64/AArch64SchedExynosM4.td +++ b/llvm/lib/Target/AArch64/AArch64SchedExynosM4.td @@ -239,7 +239,6 @@ def M4WriteNEONK : SchedWriteRes<[M4UnitNSHF, M4UnitS0]> { let Latency = 5; let NumMicroOps = 2; } def M4WriteNEONL : SchedWriteRes<[M4UnitNMUL]> { let Latency = 3; } -def M4WriteNEONM : SchedWriteRes<[M4UnitNMUL]> { let Latency = 3; } def M4WriteNEONN : SchedWriteRes<[M4UnitNMSC, M4UnitNMSC]> { let Latency = 5; let NumMicroOps = 2; } @@ -480,8 +479,6 @@ def M4WriteCOPY : SchedWriteVariant<[SchedVar, SchedVar]>; def M4WriteMOVI : SchedWriteVariant<[SchedVar, SchedVar]>; -def M4WriteMULL : SchedWriteVariant<[SchedVar, - SchedVar]>; // Fast forwarding. def M4ReadAESM1 : SchedReadAdvance<+1, [M4WriteNCRY1]>; @@ -489,7 +486,8 @@ def M4ReadFMACM1 : SchedReadAdvance<+1, [M4WriteFMAC4, M4WriteFMAC4H, M4WriteFMAC5]>; def M4ReadNMULM1 : SchedReadAdvance<+1, [M4WriteNMUL3]>; -def M4ReadMULLP2 : SchedReadAdvance<-2, [M4WriteNEONM]>; +def M4ReadNMULP2 : SchedReadAdvance<-2, [M4WriteNMUL3]>; + //===----------------------------------------------------------------------===// // Coarse scheduling model. @@ -662,10 +660,8 @@ def : InstRW<[M4WriteNEONK], (instregex "^FMOVDXHighr")>; def : InstRW<[M4WriteFCVT3H], (instregex "^F(RECP|RSQRT)Ev1f16")>; def : InstRW<[M4WriteFCVT3], (instregex "^F(RECP|RSQRT)Ev1i(32|64)")>; def : InstRW<[M4WriteNMSC1], (instregex "^FRECPXv1")>; -def : InstRW<[M4WriteFMAC4H, - M4ReadFMACM1], (instregex "^F(RECP|RSQRT)S16")>; -def : InstRW<[M4WriteFMAC4, - M4ReadFMACM1], (instregex "^F(RECP|RSQRT)S(32|64)")>; +def : InstRW<[M4WriteFMAC4H], (instregex "^F(RECP|RSQRT)S16")>; +def : InstRW<[M4WriteFMAC4], (instregex "^F(RECP|RSQRT)S(32|64)")>; // FP load instructions. def : InstRW<[WriteVLD], (instregex "^LDR[SDQ]l")>; @@ -736,14 +732,20 @@ def : InstRW<[M4WriteNALU1], (instregex "^(AND|BIC|EOR|NOT|ORN|ORR)v")>; def : InstRW<[M4WriteNMSC1], (instregex "^[SU](MIN|MAX)v")>; def : InstRW<[M4WriteNMSC2], (instregex "^[SU](MIN|MAX)Pv")>; def : InstRW<[M4WriteNHAD3], (instregex "^[SU](MIN|MAX)Vv")>; -def : InstRW<[M4WriteNMUL3], (instregex "^(SQR?D)?MULH?v")>; def : InstRW<[M4WriteNMUL3, M4ReadNMULM1], (instregex "^ML[AS]v")>; -def : InstRW<[M4WriteNMUL3], (instregex "^SQRDML[AS]H")>; -def : InstRW<[M4WriteMULL, - M4ReadMULLP2], (instregex "^(S|U|SQD)ML[AS]Lv")>; -def : InstRW<[M4WriteMULL, - M4ReadMULLP2], (instregex "^(S|U|SQD)MULLv")>; +def : InstRW<[M4WriteNMUL3, + M4ReadNMULM1], (instregex "^(SQR?D)?MULH?v")>; +def : InstRW<[M4WriteNMUL3, + M4ReadNMULM1], (instregex "^SQRDML[AS]H")>; +def : InstRW<[M4WriteNMUL3, + M4ReadNMULM1], (instregex "^(S|U|SQD)ML[AS]L(v1(i32|i64)|v2i32|v4i16|v8i8)")>; +def : InstRW<[M4WriteNMUL3, + M4ReadNMULP2], (instregex "^(S|U|SQD)ML[AS]L(v4i32|v8i16|v16i8)")>; +def : InstRW<[M4WriteNMUL3, + M4ReadNMULM1], (instregex "^(S|U|SQD)MULL(v1(i32|i64)|v2i32|v4i16|v8i8)")>; +def : InstRW<[M4WriteNMUL3, + M4ReadNMULP2], (instregex "^(S|U|SQD)MULL(v4i32|v8i16|v16i8)")>; def : InstRW<[M4WriteNMUL3], (instregex "^[SU]DOT(lane)?v")>; def : InstRW<[M4WriteNHAD3], (instregex "^[SU]ADALPv")>; def : InstRW<[M4WriteNSHT4A], (instregex "^[SU]R?SRA[dv]")>; @@ -808,10 +810,8 @@ def : InstRW<[M4WriteNALU1], (instregex "^FMOVv.f(32|64)")>; def : InstRW<[M4WriteFCVT3H], (instregex "^F(RECP|RSQRT)Ev[248]f16")>; def : InstRW<[M4WriteFCVT3], (instregex "^F(RECP|RSQRT)Ev[248]f(32|64)")>; def : InstRW<[M4WriteFCVT3], (instregex "^U(RECP|RSQRT)Ev[24]i32")>; -def : InstRW<[M4WriteFMAC4H, - M4ReadFMACM1], (instregex "^F(RECP|RSQRT)Sv.f16")>; -def : InstRW<[M4WriteFMAC4, - M4ReadFMACM1], (instregex "^F(RECP|RSQRT)Sv.f(32|64)")>; +def : InstRW<[M4WriteFMAC4H], (instregex "^F(RECP|RSQRT)Sv.f16")>; +def : InstRW<[M4WriteFMAC4], (instregex "^F(RECP|RSQRT)Sv.f(32|64)")>; def : InstRW<[M4WriteNSHF1], (instregex "^REV(16|32|64)v")>; def : InstRW<[M4WriteNSHFA], (instregex "^TB[LX]v(8|16)i8One")>; def : InstRW<[M4WriteNSHFB], (instregex "^TB[LX]v(8|16)i8Two")>; diff --git a/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td b/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td index 48c54230e9d85..316036d894064 100644 --- a/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td +++ b/llvm/lib/Target/AArch64/AArch64SchedPredExynos.td @@ -103,17 +103,6 @@ def ExynosScaledIdxPred : MCSchedPredicate; // Identify FP instructions. def ExynosFPPred : MCSchedPredicate>; -// Identify whether an instruction whose result is a long vector -// operates on the upper half of the input registers. -def ExynosLongVectorUpperFn : TIIPredicate< - "isExynosLongVectorUpper", - MCOpcodeSwitchStatement< - [MCOpcodeSwitchCase< - IsLongVectorUpperOp.ValidOpcodes, - MCReturnStatement>], - MCReturnStatement>>; -def ExynosLongVectorUpperPred : MCSchedPredicate; - // Identify 128-bit NEON instructions. def ExynosQFormPred : MCSchedPredicate; diff --git a/llvm/lib/Target/AArch64/AArch64SchedPredicates.td b/llvm/lib/Target/AArch64/AArch64SchedPredicates.td index dbaf11fc95dd2..b23572b41b9cc 100644 --- a/llvm/lib/Target/AArch64/AArch64SchedPredicates.td +++ b/llvm/lib/Target/AArch64/AArch64SchedPredicates.td @@ -268,59 +268,6 @@ def IsStoreRegOffsetOp : CheckOpcode<[STRBBroW, STRBBroX, def IsLoadStoreRegOffsetOp : CheckOpcode; -// Identify whether an instruction whose result is a long vector -// operates on the upper half of the input registers. -def IsLongVectorUpperOp : CheckOpcode<[FCVTLv8i16, FCVTLv4i32, - FCVTNv8i16, FCVTNv4i32, - FCVTXNv4f32, - PMULLv16i8, PMULLv2i64, - RADDHNv8i16_v16i8, RADDHNv4i32_v8i16, RADDHNv2i64_v4i32, - RSHRNv16i8_shift, RSHRNv8i16_shift, RSHRNv4i32_shift, - RSUBHNv8i16_v16i8, RSUBHNv4i32_v8i16, RSUBHNv2i64_v4i32, - SABALv16i8_v8i16, SABALv8i16_v4i32, SABALv4i32_v2i64, - SABDLv16i8_v8i16, SABDLv8i16_v4i32, SABDLv4i32_v2i64, - SADDLv16i8_v8i16, SADDLv8i16_v4i32, SADDLv4i32_v2i64, - SADDWv16i8_v8i16, SADDWv8i16_v4i32, SADDWv4i32_v2i64, - SHLLv16i8, SHLLv8i16, SHLLv4i32, - SHRNv16i8_shift, SHRNv8i16_shift, SHRNv4i32_shift, - SMLALv16i8_v8i16, SMLALv8i16_v4i32, SMLALv4i32_v2i64, - SMLALv8i16_indexed, SMLALv4i32_indexed, - SMLSLv16i8_v8i16, SMLSLv8i16_v4i32, SMLSLv4i32_v2i64, - SMLSLv8i16_indexed, SMLSLv4i32_indexed, - SMULLv16i8_v8i16, SMULLv8i16_v4i32, SMULLv4i32_v2i64, - SMULLv8i16_indexed, SMULLv4i32_indexed, - SQDMLALv8i16_v4i32, SQDMLALv4i32_v2i64, - SQDMLALv8i16_indexed, SQDMLALv4i32_indexed, - SQDMLSLv8i16_v4i32, SQDMLSLv4i32_v2i64, - SQDMLSLv8i16_indexed, SQDMLSLv4i32_indexed, - SQDMULLv8i16_v4i32, SQDMULLv4i32_v2i64, - SQDMULLv8i16_indexed, SQDMULLv4i32_indexed, - SQRSHRNv16i8_shift, SQRSHRNv8i16_shift, SQRSHRNv4i32_shift, - SQRSHRUNv16i8_shift, SQRSHRUNv8i16_shift, SQRSHRUNv4i32_shift, - SQSHRNv16i8_shift, SQSHRNv8i16_shift, SQSHRNv4i32_shift, - SQSHRUNv16i8_shift, SQSHRUNv8i16_shift, SQSHRUNv4i32_shift, - SQXTNv16i8, SQXTNv8i16, SQXTNv4i32, - SQXTUNv16i8, SQXTUNv8i16, SQXTUNv4i32, - SSHLLv16i8_shift, SSHLLv8i16_shift, SSHLLv4i32_shift, - SSUBLv16i8_v8i16, SSUBLv8i16_v4i32, SSUBLv4i32_v2i64, - SSUBWv16i8_v8i16, SSUBWv8i16_v4i32, SSUBWv4i32_v2i64, - UABALv16i8_v8i16, UABALv8i16_v4i32, UABALv4i32_v2i64, - UABDLv16i8_v8i16, UABDLv8i16_v4i32, UABDLv4i32_v2i64, - UADDLv16i8_v8i16, UADDLv8i16_v4i32, UADDLv4i32_v2i64, - UADDWv16i8_v8i16, UADDWv8i16_v4i32, UADDWv4i32_v2i64, - UMLALv16i8_v8i16, UMLALv8i16_v4i32, UMLALv4i32_v2i64, - UMLALv8i16_indexed, UMLALv4i32_indexed, - UMLSLv16i8_v8i16, UMLSLv8i16_v4i32, UMLSLv4i32_v2i64, - UMLSLv8i16_indexed, UMLSLv4i32_indexed, - UMULLv16i8_v8i16, UMULLv8i16_v4i32, UMULLv4i32_v2i64, - UMULLv8i16_indexed, UMULLv4i32_indexed, - UQSHRNv16i8_shift, UQSHRNv8i16_shift, UQSHRNv4i32_shift, - UQXTNv16i8, UQXTNv8i16, UQXTNv4i32, - USHLLv16i8_shift, USHLLv8i16_shift, USHLLv4i32_shift, - USUBLv16i8_v8i16, USUBLv8i16_v4i32, USUBLv4i32_v2i64, - USUBWv16i8_v8i16, USUBWv8i16_v4i32, USUBWv4i32_v2i64, - XTNv16i8, XTNv8i16, XTNv4i32]>; - // Target predicates. // Identify an instruction that effectively transfers a register to another. diff --git a/llvm/lib/Target/AArch64/AArch64SpeculationHardening.cpp b/llvm/lib/Target/AArch64/AArch64SpeculationHardening.cpp index e9699b0367d3d..50300305abe33 100644 --- a/llvm/lib/Target/AArch64/AArch64SpeculationHardening.cpp +++ b/llvm/lib/Target/AArch64/AArch64SpeculationHardening.cpp @@ -103,6 +103,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Pass.h" #include "llvm/Support/CodeGen.h" @@ -146,25 +147,31 @@ class AArch64SpeculationHardening : public MachineFunctionPass { BitVector RegsAlreadyMasked; bool functionUsesHardeningRegister(MachineFunction &MF) const; - bool instrumentControlFlow(MachineBasicBlock &MBB); + bool instrumentControlFlow(MachineBasicBlock &MBB, + bool &UsesFullSpeculationBarrier); bool endsWithCondControlFlow(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, AArch64CC::CondCode &CondCode) const; void insertTrackingCode(MachineBasicBlock &SplitEdgeBB, AArch64CC::CondCode &CondCode, DebugLoc DL) const; - void insertSPToRegTaintPropagation(MachineBasicBlock *MBB, + void insertSPToRegTaintPropagation(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const; - void insertRegToSPTaintPropagation(MachineBasicBlock *MBB, + void insertRegToSPTaintPropagation(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned TmpReg) const; + void insertFullSpeculationBarrier(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + DebugLoc DL) const; bool slhLoads(MachineBasicBlock &MBB); bool makeGPRSpeculationSafe(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MachineInstr &MI, unsigned Reg); - bool lowerSpeculationSafeValuePseudos(MachineBasicBlock &MBB); + bool lowerSpeculationSafeValuePseudos(MachineBasicBlock &MBB, + bool UsesFullSpeculationBarrier); bool expandSpeculationSafeValue(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI); + MachineBasicBlock::iterator MBBI, + bool UsesFullSpeculationBarrier); bool insertCSDB(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc DL); }; @@ -207,15 +214,19 @@ bool AArch64SpeculationHardening::endsWithCondControlFlow( return true; } +void AArch64SpeculationHardening::insertFullSpeculationBarrier( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + DebugLoc DL) const { + // A full control flow speculation barrier consists of (DSB SYS + ISB) + BuildMI(MBB, MBBI, DL, TII->get(AArch64::DSB)).addImm(0xf); + BuildMI(MBB, MBBI, DL, TII->get(AArch64::ISB)).addImm(0xf); +} + void AArch64SpeculationHardening::insertTrackingCode( MachineBasicBlock &SplitEdgeBB, AArch64CC::CondCode &CondCode, DebugLoc DL) const { if (UseControlFlowSpeculationBarrier) { - // insert full control flow speculation barrier (DSB SYS + ISB) - BuildMI(SplitEdgeBB, SplitEdgeBB.begin(), DL, TII->get(AArch64::ISB)) - .addImm(0xf); - BuildMI(SplitEdgeBB, SplitEdgeBB.begin(), DL, TII->get(AArch64::DSB)) - .addImm(0xf); + insertFullSpeculationBarrier(SplitEdgeBB, SplitEdgeBB.begin(), DL); } else { BuildMI(SplitEdgeBB, SplitEdgeBB.begin(), DL, TII->get(AArch64::CSELXr)) .addDef(MisspeculatingTaintReg) @@ -227,7 +238,7 @@ void AArch64SpeculationHardening::insertTrackingCode( } bool AArch64SpeculationHardening::instrumentControlFlow( - MachineBasicBlock &MBB) { + MachineBasicBlock &MBB, bool &UsesFullSpeculationBarrier) { LLVM_DEBUG(dbgs() << "Instrument control flow tracking on MBB: " << MBB); bool Modified = false; @@ -263,55 +274,105 @@ bool AArch64SpeculationHardening::instrumentControlFlow( } // Perform correct code generation around function calls and before returns. - { - SmallVector ReturnInstructions; - SmallVector CallInstructions; + // The below variables record the return/terminator instructions and the call + // instructions respectively; including which register is available as a + // temporary register just before the recorded instructions. + SmallVector, 4> ReturnInstructions; + SmallVector, 4> CallInstructions; + // if a temporary register is not available for at least one of the + // instructions for which we need to transfer taint to the stack pointer, we + // need to insert a full speculation barrier. + // TmpRegisterNotAvailableEverywhere tracks that condition. + bool TmpRegisterNotAvailableEverywhere = false; + + RegScavenger RS; + RS.enterBasicBlock(MBB); + + for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); I++) { + MachineInstr &MI = *I; + if (!MI.isReturn() && !MI.isCall()) + continue; - for (MachineInstr &MI : MBB) { - if (MI.isReturn()) - ReturnInstructions.push_back(&MI); - else if (MI.isCall()) - CallInstructions.push_back(&MI); - } + // The RegScavenger represents registers available *after* the MI + // instruction pointed to by RS.getCurrentPosition(). + // We need to have a register that is available *before* the MI is executed. + if (I != MBB.begin()) + RS.forward(std::prev(I)); + // FIXME: The below just finds *a* unused register. Maybe code could be + // optimized more if this looks for the register that isn't used for the + // longest time around this place, to enable more scheduling freedom. Not + // sure if that would actually result in a big performance difference + // though. Maybe RegisterScavenger::findSurvivorBackwards has some logic + // already to do this - but it's unclear if that could easily be used here. + unsigned TmpReg = RS.FindUnusedReg(&AArch64::GPR64commonRegClass); + LLVM_DEBUG(dbgs() << "RS finds " + << ((TmpReg == 0) ? "no register " : "register "); + if (TmpReg != 0) dbgs() << printReg(TmpReg, TRI) << " "; + dbgs() << "to be available at MI " << MI); + if (TmpReg == 0) + TmpRegisterNotAvailableEverywhere = true; + if (MI.isReturn()) + ReturnInstructions.push_back({&MI, TmpReg}); + else if (MI.isCall()) + CallInstructions.push_back({&MI, TmpReg}); + } - Modified |= - (ReturnInstructions.size() > 0) || (CallInstructions.size() > 0); + if (TmpRegisterNotAvailableEverywhere) { + // When a temporary register is not available everywhere in this basic + // basic block where a propagate-taint-to-sp operation is needed, just + // emit a full speculation barrier at the start of this basic block, which + // renders the taint/speculation tracking in this basic block unnecessary. + insertFullSpeculationBarrier(MBB, MBB.begin(), + (MBB.begin())->getDebugLoc()); + UsesFullSpeculationBarrier = true; + Modified = true; + } else { + for (auto MI_Reg : ReturnInstructions) { + assert(MI_Reg.second != 0); + LLVM_DEBUG( + dbgs() + << " About to insert Reg to SP taint propagation with temp register " + << printReg(MI_Reg.second, TRI) + << " on instruction: " << *MI_Reg.first); + insertRegToSPTaintPropagation(MBB, MI_Reg.first, MI_Reg.second); + Modified = true; + } - for (MachineInstr *Return : ReturnInstructions) - insertRegToSPTaintPropagation(Return->getParent(), Return, AArch64::X17); - for (MachineInstr *Call : CallInstructions) { + for (auto MI_Reg : CallInstructions) { + assert(MI_Reg.second != 0); + LLVM_DEBUG(dbgs() << " About to insert Reg to SP and back taint " + "propagation with temp register " + << printReg(MI_Reg.second, TRI) + << " around instruction: " << *MI_Reg.first); // Just after the call: - MachineBasicBlock::iterator i = Call; - i++; - insertSPToRegTaintPropagation(Call->getParent(), i); + insertSPToRegTaintPropagation( + MBB, std::next((MachineBasicBlock::iterator)MI_Reg.first)); // Just before the call: - insertRegToSPTaintPropagation(Call->getParent(), Call, AArch64::X17); + insertRegToSPTaintPropagation(MBB, MI_Reg.first, MI_Reg.second); + Modified = true; } } - return Modified; } void AArch64SpeculationHardening::insertSPToRegTaintPropagation( - MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI) const { + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const { // If full control flow speculation barriers are used, emit a control flow // barrier to block potential miss-speculation in flight coming in to this // function. if (UseControlFlowSpeculationBarrier) { - // insert full control flow speculation barrier (DSB SYS + ISB) - BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::DSB)).addImm(0xf); - BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::ISB)).addImm(0xf); + insertFullSpeculationBarrier(MBB, MBBI, DebugLoc()); return; } // CMP SP, #0 === SUBS xzr, SP, #0 - BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::SUBSXri)) + BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::SUBSXri)) .addDef(AArch64::XZR) .addUse(AArch64::SP) .addImm(0) .addImm(0); // no shift // CSETM x16, NE === CSINV x16, xzr, xzr, EQ - BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::CSINVXr)) + BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::CSINVXr)) .addDef(MisspeculatingTaintReg) .addUse(AArch64::XZR) .addUse(AArch64::XZR) @@ -319,7 +380,7 @@ void AArch64SpeculationHardening::insertSPToRegTaintPropagation( } void AArch64SpeculationHardening::insertRegToSPTaintPropagation( - MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI, + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned TmpReg) const { // If full control flow speculation barriers are used, there will not be // miss-speculation when returning from this function, and therefore, also @@ -328,19 +389,19 @@ void AArch64SpeculationHardening::insertRegToSPTaintPropagation( return; // mov Xtmp, SP === ADD Xtmp, SP, #0 - BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::ADDXri)) + BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::ADDXri)) .addDef(TmpReg) .addUse(AArch64::SP) .addImm(0) .addImm(0); // no shift // and Xtmp, Xtmp, TaintReg === AND Xtmp, Xtmp, TaintReg, #0 - BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::ANDXrs)) + BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::ANDXrs)) .addDef(TmpReg, RegState::Renamable) .addUse(TmpReg, RegState::Kill | RegState::Renamable) .addUse(MisspeculatingTaintReg, RegState::Kill) .addImm(0); // mov SP, Xtmp === ADD SP, Xtmp, #0 - BuildMI(*MBB, MBBI, DebugLoc(), TII->get(AArch64::ADDXri)) + BuildMI(MBB, MBBI, DebugLoc(), TII->get(AArch64::ADDXri)) .addDef(AArch64::SP) .addUse(TmpReg, RegState::Kill) .addImm(0) @@ -484,7 +545,8 @@ bool AArch64SpeculationHardening::slhLoads(MachineBasicBlock &MBB) { /// \brief If MBBI references a pseudo instruction that should be expanded /// here, do the expansion and return true. Otherwise return false. bool AArch64SpeculationHardening::expandSpeculationSafeValue( - MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) { + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + bool UsesFullSpeculationBarrier) { MachineInstr &MI = *MBBI; unsigned Opcode = MI.getOpcode(); bool Is64Bit = true; @@ -499,7 +561,7 @@ bool AArch64SpeculationHardening::expandSpeculationSafeValue( // Just remove the SpeculationSafe pseudo's if control flow // miss-speculation isn't happening because we're already inserting barriers // to guarantee that. - if (!UseControlFlowSpeculationBarrier) { + if (!UseControlFlowSpeculationBarrier && !UsesFullSpeculationBarrier) { unsigned DstReg = MI.getOperand(0).getReg(); unsigned SrcReg = MI.getOperand(1).getReg(); // Mark this register and all its aliasing registers as needing to be @@ -537,7 +599,7 @@ bool AArch64SpeculationHardening::insertCSDB(MachineBasicBlock &MBB, } bool AArch64SpeculationHardening::lowerSpeculationSafeValuePseudos( - MachineBasicBlock &MBB) { + MachineBasicBlock &MBB, bool UsesFullSpeculationBarrier) { bool Modified = false; RegsNeedingCSDBBeforeUse.reset(); @@ -572,15 +634,16 @@ bool AArch64SpeculationHardening::lowerSpeculationSafeValuePseudos( break; } - if (NeedToEmitBarrier) + if (NeedToEmitBarrier && !UsesFullSpeculationBarrier) Modified |= insertCSDB(MBB, MBBI, DL); - Modified |= expandSpeculationSafeValue(MBB, MBBI); + Modified |= + expandSpeculationSafeValue(MBB, MBBI, UsesFullSpeculationBarrier); MBBI = NMBBI; } - if (RegsNeedingCSDBBeforeUse.any()) + if (RegsNeedingCSDBBeforeUse.any() && !UsesFullSpeculationBarrier) Modified |= insertCSDB(MBB, MBBI, DL); return Modified; @@ -609,7 +672,7 @@ bool AArch64SpeculationHardening::runOnMachineFunction(MachineFunction &MF) { Modified |= slhLoads(MBB); } - // 2.a Add instrumentation code to function entry and exits. + // 2. Add instrumentation code to function entry and exits. LLVM_DEBUG( dbgs() << "***** AArch64SpeculationHardening - track control flow *****\n"); @@ -620,17 +683,15 @@ bool AArch64SpeculationHardening::runOnMachineFunction(MachineFunction &MF) { EntryBlocks.push_back(LPI.LandingPadBlock); for (auto Entry : EntryBlocks) insertSPToRegTaintPropagation( - Entry, Entry->SkipPHIsLabelsAndDebug(Entry->begin())); - - // 2.b Add instrumentation code to every basic block. - for (auto &MBB : MF) - Modified |= instrumentControlFlow(MBB); + *Entry, Entry->SkipPHIsLabelsAndDebug(Entry->begin())); - LLVM_DEBUG(dbgs() << "***** AArch64SpeculationHardening - Lowering " - "SpeculationSafeValue Pseudos *****\n"); - // Step 3: Lower SpeculationSafeValue pseudo instructions. - for (auto &MBB : MF) - Modified |= lowerSpeculationSafeValuePseudos(MBB); + // 3. Add instrumentation code to every basic block. + for (auto &MBB : MF) { + bool UsesFullSpeculationBarrier = false; + Modified |= instrumentControlFlow(MBB, UsesFullSpeculationBarrier); + Modified |= + lowerSpeculationSafeValuePseudos(MBB, UsesFullSpeculationBarrier); + } return Modified; } diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp index 4e016525f7e4e..219c33ef73c51 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp @@ -209,8 +209,8 @@ static std::string computeDataLayout(const Triple &TT, static Reloc::Model getEffectiveRelocModel(const Triple &TT, Optional RM) { - // AArch64 Darwin is always PIC. - if (TT.isOSDarwin()) + // AArch64 Darwin and Windows are always PIC. + if (TT.isOSDarwin() || TT.isOSWindows()) return Reloc::PIC_; // On ELF platforms the default static relocation model has a smart enough // linker to cope with referencing external symbols defined in a shared diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp index 4102f1eb5cc12..64afabd450c1f 100644 --- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -1779,8 +1779,8 @@ static DecodeStatus DecodeGPRSeqPairsClassRegisterClass(MCInst &Inst, if (RegNo & 0x1) return Fail; - unsigned Register = AArch64MCRegisterClasses[RegClassID].getRegister(RegNo); - Inst.addOperand(MCOperand::createReg(Register)); + unsigned Reg = AArch64MCRegisterClasses[RegClassID].getRegister(RegNo / 2); + Inst.addOperand(MCOperand::createReg(Reg)); return Success; } diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.h b/llvm/lib/Target/AMDGPU/AMDGPU.h index bb7801c172f60..55668867cc8e2 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPU.h +++ b/llvm/lib/Target/AMDGPU/AMDGPU.h @@ -254,7 +254,7 @@ namespace AMDGPUAS { FLAT_ADDRESS = 0, ///< Address space for flat memory. GLOBAL_ADDRESS = 1, ///< Address space for global memory (RAT0, VTX0). - REGION_ADDRESS = 2, ///< Address space for region memory. + REGION_ADDRESS = 2, ///< Address space for region memory. (GDS) CONSTANT_ADDRESS = 4, ///< Address space for constant memory (VTX2) LOCAL_ADDRESS = 3, ///< Address space for local memory. diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp index 6951c915b1772..8d36511a28303 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp @@ -4192,6 +4192,7 @@ const char* AMDGPUTargetLowering::getTargetNodeName(unsigned Opcode) const { NODE_NAME_CASE(TBUFFER_STORE_FORMAT_D16) NODE_NAME_CASE(TBUFFER_LOAD_FORMAT) NODE_NAME_CASE(TBUFFER_LOAD_FORMAT_D16) + NODE_NAME_CASE(DS_ORDERED_COUNT) NODE_NAME_CASE(ATOMIC_CMP_SWAP) NODE_NAME_CASE(ATOMIC_INC) NODE_NAME_CASE(ATOMIC_DEC) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h index 0d22cb2e3e20b..d4a751d00a503 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h @@ -474,6 +474,7 @@ enum NodeType : unsigned { TBUFFER_STORE_FORMAT_D16, TBUFFER_LOAD_FORMAT, TBUFFER_LOAD_FORMAT_D16, + DS_ORDERED_COUNT, ATOMIC_CMP_SWAP, ATOMIC_INC, ATOMIC_DEC, diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td b/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td index 9dbd7751b4d88..4d0962f65fdc1 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td +++ b/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td @@ -72,6 +72,8 @@ def : SourceOfDivergence; def : SourceOfDivergence; def : SourceOfDivergence; def : SourceOfDivergence; +def : SourceOfDivergence; +def : SourceOfDivergence; foreach intr = AMDGPUImageDimAtomicIntrinsics in def : SourceOfDivergence; diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp index 11e4ba4b5010d..62e7e44ddb80c 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp @@ -308,6 +308,8 @@ bool GCNTTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst, switch (Inst->getIntrinsicID()) { case Intrinsic::amdgcn_atomic_inc: case Intrinsic::amdgcn_atomic_dec: + case Intrinsic::amdgcn_ds_ordered_add: + case Intrinsic::amdgcn_ds_ordered_swap: case Intrinsic::amdgcn_ds_fadd: case Intrinsic::amdgcn_ds_fmin: case Intrinsic::amdgcn_ds_fmax: { diff --git a/llvm/lib/Target/AMDGPU/DSInstructions.td b/llvm/lib/Target/AMDGPU/DSInstructions.td index 31d2ebef481d2..9c7097e9a5206 100644 --- a/llvm/lib/Target/AMDGPU/DSInstructions.td +++ b/llvm/lib/Target/AMDGPU/DSInstructions.td @@ -817,6 +817,11 @@ defm : DSAtomicRetPat_mc; defm : DSAtomicCmpXChg_mc; +def : Pat < + (SIds_ordered_count i32:$value, i16:$offset), + (DS_ORDERED_COUNT $value, (as_i16imm $offset)) +>; + //===----------------------------------------------------------------------===// // Real instructions //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp b/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp index c6396de89c4f6..69ddbfb539583 100644 --- a/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp +++ b/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp @@ -88,14 +88,28 @@ static bool isSMovRel(unsigned Opcode) { } } -static bool isSendMsgTraceDataOrGDS(const MachineInstr &MI) { +static bool isSendMsgTraceDataOrGDS(const SIInstrInfo &TII, + const MachineInstr &MI) { + if (TII.isAlwaysGDS(MI.getOpcode())) + return true; + switch (MI.getOpcode()) { case AMDGPU::S_SENDMSG: case AMDGPU::S_SENDMSGHALT: case AMDGPU::S_TTRACEDATA: return true; + // These DS opcodes don't support GDS. + case AMDGPU::DS_NOP: + case AMDGPU::DS_PERMUTE_B32: + case AMDGPU::DS_BPERMUTE_B32: + return false; default: - // TODO: GDS + if (TII.isDS(MI.getOpcode())) { + int GDS = AMDGPU::getNamedOperandIdx(MI.getOpcode(), + AMDGPU::OpName::gds); + if (MI.getOperand(GDS).getImm()) + return true; + } return false; } } @@ -145,7 +159,7 @@ GCNHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { checkReadM0Hazards(MI) > 0) return NoopHazard; - if (ST.hasReadM0SendMsgHazard() && isSendMsgTraceDataOrGDS(*MI) && + if (ST.hasReadM0SendMsgHazard() && isSendMsgTraceDataOrGDS(TII, *MI) && checkReadM0Hazards(MI) > 0) return NoopHazard; @@ -199,7 +213,7 @@ unsigned GCNHazardRecognizer::PreEmitNoops(MachineInstr *MI) { isSMovRel(MI->getOpcode()))) return std::max(WaitStates, checkReadM0Hazards(MI)); - if (ST.hasReadM0SendMsgHazard() && isSendMsgTraceDataOrGDS(*MI)) + if (ST.hasReadM0SendMsgHazard() && isSendMsgTraceDataOrGDS(TII, *MI)) return std::max(WaitStates, checkReadM0Hazards(MI)); return WaitStates; diff --git a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp index f4e8669583699..d679abd107d21 100644 --- a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp +++ b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp @@ -201,49 +201,55 @@ static bool updateOperand(FoldCandidate &Fold, Mod.setImm(Mod.getImm() & ~SISrcMods::OP_SEL_1); } } + } - if (Fold.needsShrink()) { - MachineBasicBlock *MBB = MI->getParent(); - auto Liveness = MBB->computeRegisterLiveness(&TRI, AMDGPU::VCC, MI); - if (Liveness != MachineBasicBlock::LQR_Dead) - return false; - - MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); - int Op32 = Fold.getShrinkOpcode(); - MachineOperand &Dst0 = MI->getOperand(0); - MachineOperand &Dst1 = MI->getOperand(1); - assert(Dst0.isDef() && Dst1.isDef()); - - bool HaveNonDbgCarryUse = !MRI.use_nodbg_empty(Dst1.getReg()); + if ((Fold.isImm() || Fold.isFI()) && Fold.needsShrink()) { + MachineBasicBlock *MBB = MI->getParent(); + auto Liveness = MBB->computeRegisterLiveness(&TRI, AMDGPU::VCC, MI); + if (Liveness != MachineBasicBlock::LQR_Dead) + return false; - const TargetRegisterClass *Dst0RC = MRI.getRegClass(Dst0.getReg()); - unsigned NewReg0 = MRI.createVirtualRegister(Dst0RC); - const TargetRegisterClass *Dst1RC = MRI.getRegClass(Dst1.getReg()); - unsigned NewReg1 = MRI.createVirtualRegister(Dst1RC); + MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); + int Op32 = Fold.getShrinkOpcode(); + MachineOperand &Dst0 = MI->getOperand(0); + MachineOperand &Dst1 = MI->getOperand(1); + assert(Dst0.isDef() && Dst1.isDef()); - MachineInstr *Inst32 = TII.buildShrunkInst(*MI, Op32); + bool HaveNonDbgCarryUse = !MRI.use_nodbg_empty(Dst1.getReg()); - if (HaveNonDbgCarryUse) { - BuildMI(*MBB, MI, MI->getDebugLoc(), TII.get(AMDGPU::COPY), Dst1.getReg()) - .addReg(AMDGPU::VCC, RegState::Kill); - } + const TargetRegisterClass *Dst0RC = MRI.getRegClass(Dst0.getReg()); + unsigned NewReg0 = MRI.createVirtualRegister(Dst0RC); - // Keep the old instruction around to avoid breaking iterators, but - // replace the outputs with dummy registers. - Dst0.setReg(NewReg0); - Dst1.setReg(NewReg1); + MachineInstr *Inst32 = TII.buildShrunkInst(*MI, Op32); - if (Fold.isCommuted()) - TII.commuteInstruction(*Inst32, false); - return true; + if (HaveNonDbgCarryUse) { + BuildMI(*MBB, MI, MI->getDebugLoc(), TII.get(AMDGPU::COPY), Dst1.getReg()) + .addReg(AMDGPU::VCC, RegState::Kill); } - Old.ChangeToImmediate(Fold.ImmToFold); + // Keep the old instruction around to avoid breaking iterators, but + // replace it with a dummy instruction to remove uses. + // + // FIXME: We should not invert how this pass looks at operands to avoid + // this. Should track set of foldable movs instead of looking for uses + // when looking at a use. + Dst0.setReg(NewReg0); + for (unsigned I = MI->getNumOperands() - 1; I > 0; --I) + MI->RemoveOperand(I); + MI->setDesc(TII.get(AMDGPU::IMPLICIT_DEF)); + + if (Fold.isCommuted()) + TII.commuteInstruction(*Inst32, false); return true; } assert(!Fold.needsShrink() && "not handled"); + if (Fold.isImm()) { + Old.ChangeToImmediate(Fold.ImmToFold); + return true; + } + if (Fold.isFI()) { Old.ChangeToFrameIndex(Fold.FrameIndexToFold); return true; @@ -344,7 +350,7 @@ static bool tryAddToFoldList(SmallVectorImpl &FoldList, if ((Opc == AMDGPU::V_ADD_I32_e64 || Opc == AMDGPU::V_SUB_I32_e64 || Opc == AMDGPU::V_SUBREV_I32_e64) && // FIXME - OpToFold->isImm()) { + (OpToFold->isImm() || OpToFold->isFI())) { MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo(); // Verify the other operand is a VGPR, otherwise we would violate the @@ -357,7 +363,10 @@ static bool tryAddToFoldList(SmallVectorImpl &FoldList, assert(MI->getOperand(1).isDef()); - int Op32 = AMDGPU::getVOPe32(Opc); + // Make sure to get the 32-bit version of the commuted opcode. + unsigned MaybeCommutedOpc = MI->getOpcode(); + int Op32 = AMDGPU::getVOPe32(MaybeCommutedOpc); + FoldList.push_back(FoldCandidate(MI, CommuteOpNo, OpToFold, true, Op32)); return true; diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index 0ba921647097d..12113fcc1fcb8 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -910,6 +910,8 @@ bool SITargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, switch (IntrID) { case Intrinsic::amdgcn_atomic_inc: case Intrinsic::amdgcn_atomic_dec: + case Intrinsic::amdgcn_ds_ordered_add: + case Intrinsic::amdgcn_ds_ordered_swap: case Intrinsic::amdgcn_ds_fadd: case Intrinsic::amdgcn_ds_fmin: case Intrinsic::amdgcn_ds_fmax: { @@ -937,6 +939,8 @@ bool SITargetLowering::getAddrModeArguments(IntrinsicInst *II, switch (II->getIntrinsicID()) { case Intrinsic::amdgcn_atomic_inc: case Intrinsic::amdgcn_atomic_dec: + case Intrinsic::amdgcn_ds_ordered_add: + case Intrinsic::amdgcn_ds_ordered_swap: case Intrinsic::amdgcn_ds_fadd: case Intrinsic::amdgcn_ds_fmin: case Intrinsic::amdgcn_ds_fmax: { @@ -5438,6 +5442,63 @@ SDValue SITargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op, SDLoc DL(Op); switch (IntrID) { + case Intrinsic::amdgcn_ds_ordered_add: + case Intrinsic::amdgcn_ds_ordered_swap: { + MemSDNode *M = cast(Op); + SDValue Chain = M->getOperand(0); + SDValue M0 = M->getOperand(2); + SDValue Value = M->getOperand(3); + unsigned OrderedCountIndex = M->getConstantOperandVal(7); + unsigned WaveRelease = M->getConstantOperandVal(8); + unsigned WaveDone = M->getConstantOperandVal(9); + unsigned ShaderType; + unsigned Instruction; + + switch (IntrID) { + case Intrinsic::amdgcn_ds_ordered_add: + Instruction = 0; + break; + case Intrinsic::amdgcn_ds_ordered_swap: + Instruction = 1; + break; + } + + if (WaveDone && !WaveRelease) + report_fatal_error("ds_ordered_count: wave_done requires wave_release"); + + switch (DAG.getMachineFunction().getFunction().getCallingConv()) { + case CallingConv::AMDGPU_CS: + case CallingConv::AMDGPU_KERNEL: + ShaderType = 0; + break; + case CallingConv::AMDGPU_PS: + ShaderType = 1; + break; + case CallingConv::AMDGPU_VS: + ShaderType = 2; + break; + case CallingConv::AMDGPU_GS: + ShaderType = 3; + break; + default: + report_fatal_error("ds_ordered_count unsupported for this calling conv"); + } + + unsigned Offset0 = OrderedCountIndex << 2; + unsigned Offset1 = WaveRelease | (WaveDone << 1) | (ShaderType << 2) | + (Instruction << 4); + unsigned Offset = Offset0 | (Offset1 << 8); + + SDValue Ops[] = { + Chain, + Value, + DAG.getTargetConstant(Offset, DL, MVT::i16), + copyToM0(DAG, Chain, DL, M0).getValue(1), // Glue + }; + return DAG.getMemIntrinsicNode(AMDGPUISD::DS_ORDERED_COUNT, DL, + M->getVTList(), Ops, M->getMemoryVT(), + M->getMemOperand()); + } case Intrinsic::amdgcn_atomic_inc: case Intrinsic::amdgcn_atomic_dec: case Intrinsic::amdgcn_ds_fadd: diff --git a/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp b/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp index afc0b44676109..3c13bccd94fa8 100644 --- a/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp +++ b/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp @@ -536,10 +536,13 @@ void WaitcntBrackets::updateByEvent(const SIInstrInfo *TII, CurrScore); } if (Inst.mayStore()) { - setExpScore( - &Inst, TII, TRI, MRI, - AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::data0), - CurrScore); + if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), + AMDGPU::OpName::data0) != -1) { + setExpScore( + &Inst, TII, TRI, MRI, + AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::data0), + CurrScore); + } if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::data1) != -1) { setExpScore(&Inst, TII, TRI, MRI, @@ -1093,7 +1096,8 @@ void SIInsertWaitcnts::updateEventWaitcntAfter(MachineInstr &Inst, // bracket and the destination operand scores. // TODO: Use the (TSFlags & SIInstrFlags::LGKM_CNT) property everywhere. if (TII->isDS(Inst) && TII->usesLGKM_CNT(Inst)) { - if (TII->hasModifiersSet(Inst, AMDGPU::OpName::gds)) { + if (TII->isAlwaysGDS(Inst.getOpcode()) || + TII->hasModifiersSet(Inst, AMDGPU::OpName::gds)) { ScoreBrackets->updateByEvent(TII, TRI, MRI, GDS_ACCESS, Inst); ScoreBrackets->updateByEvent(TII, TRI, MRI, GDS_GPR_LOCK, Inst); } else { diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp index 2370d5fa7b27b..7f7f1807987ab 100644 --- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp +++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp @@ -2390,6 +2390,16 @@ bool SIInstrInfo::isSchedulingBoundary(const MachineInstr &MI, changesVGPRIndexingMode(MI); } +bool SIInstrInfo::isAlwaysGDS(uint16_t Opcode) const { + return Opcode == AMDGPU::DS_ORDERED_COUNT || + Opcode == AMDGPU::DS_GWS_INIT || + Opcode == AMDGPU::DS_GWS_SEMA_V || + Opcode == AMDGPU::DS_GWS_SEMA_BR || + Opcode == AMDGPU::DS_GWS_SEMA_P || + Opcode == AMDGPU::DS_GWS_SEMA_RELEASE_ALL || + Opcode == AMDGPU::DS_GWS_BARRIER; +} + bool SIInstrInfo::hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const { unsigned Opcode = MI.getOpcode(); @@ -2403,7 +2413,8 @@ bool SIInstrInfo::hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const // EXEC = 0, but checking for that case here seems not worth it // given the typical code patterns. if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT || - Opcode == AMDGPU::EXP || Opcode == AMDGPU::EXP_DONE) + Opcode == AMDGPU::EXP || Opcode == AMDGPU::EXP_DONE || + Opcode == AMDGPU::DS_ORDERED_COUNT) return true; if (MI.isInlineAsm()) diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.h b/llvm/lib/Target/AMDGPU/SIInstrInfo.h index 5b1a05f3785ec..8847fd6babb36 100644 --- a/llvm/lib/Target/AMDGPU/SIInstrInfo.h +++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.h @@ -450,6 +450,8 @@ class SIInstrInfo final : public AMDGPUGenInstrInfo { return get(Opcode).TSFlags & SIInstrFlags::DS; } + bool isAlwaysGDS(uint16_t Opcode) const; + static bool isMIMG(const MachineInstr &MI) { return MI.getDesc().TSFlags & SIInstrFlags::MIMG; } diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.td b/llvm/lib/Target/AMDGPU/SIInstrInfo.td index 13afa4d4974bf..180a7b0601d74 100644 --- a/llvm/lib/Target/AMDGPU/SIInstrInfo.td +++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.td @@ -45,6 +45,11 @@ def SIsbuffer_load : SDNode<"AMDGPUISD::SBUFFER_LOAD", [SDNPMayLoad, SDNPMemOperand] >; +def SIds_ordered_count : SDNode<"AMDGPUISD::DS_ORDERED_COUNT", + SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisVT<1, i32>, SDTCisVT<2, i16>]>, + [SDNPMayLoad, SDNPMayStore, SDNPMemOperand, SDNPHasChain, SDNPInGlue] +>; + def SIatomic_inc : SDNode<"AMDGPUISD::ATOMIC_INC", SDTAtomic2, [SDNPMayLoad, SDNPMayStore, SDNPMemOperand, SDNPHasChain] >; diff --git a/llvm/lib/Target/AMDGPU/VOP2Instructions.td b/llvm/lib/Target/AMDGPU/VOP2Instructions.td index e3fd7b5f9fadd..8cf524a5128d8 100644 --- a/llvm/lib/Target/AMDGPU/VOP2Instructions.td +++ b/llvm/lib/Target/AMDGPU/VOP2Instructions.td @@ -515,18 +515,12 @@ let AddedComplexity = 1 in { } let SubtargetPredicate = HasAddNoCarryInsts in { - def : DivergentBinOp; - def : DivergentBinOp; - def : DivergentBinOp; + def : DivergentBinOp; + def : DivergentBinOp; } - -def : DivergentBinOp; - def : DivergentBinOp; -def : DivergentBinOp; - -def : DivergentBinOp; +def : DivergentBinOp; def : DivergentBinOp; def : DivergentBinOp; diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 21de0f6a7630e..7e90edbbdabb9 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -1984,32 +1984,10 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Build a sequence of copy-to-reg nodes chained together with token chain // and flag operands which copy the outgoing args into the appropriate regs. SDValue InFlag; - // Tail call byval lowering might overwrite argument registers so in case of - // tail call optimization the copies to registers are lowered later. - if (!isTailCall) - for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { - Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, - RegsToPass[i].second, InFlag); - InFlag = Chain.getValue(1); - } - - // For tail calls lower the arguments to the 'real' stack slot. - if (isTailCall) { - // Force all the incoming stack arguments to be loaded from the stack - // before any new outgoing arguments are stored to the stack, because the - // outgoing stack slots may alias the incoming argument stack slots, and - // the alias isn't otherwise explicit. This is slightly more conservative - // than necessary, because it means that each store effectively depends - // on every argument instead of just those arguments it would clobber. - - // Do not flag preceding copytoreg stuff together with the following stuff. - InFlag = SDValue(); - for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { - Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, - RegsToPass[i].second, InFlag); - InFlag = Chain.getValue(1); - } - InFlag = SDValue(); + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); } // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp index 57fc978b54bb6..5db7577823226 100644 --- a/llvm/lib/Target/AVR/AVRISelLowering.cpp +++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp @@ -26,19 +26,21 @@ #include "AVR.h" #include "AVRMachineFunctionInfo.h" +#include "AVRSubtarget.h" #include "AVRTargetMachine.h" #include "MCTargetDesc/AVRMCTargetDesc.h" namespace llvm { -AVRTargetLowering::AVRTargetLowering(AVRTargetMachine &tm) - : TargetLowering(tm) { +AVRTargetLowering::AVRTargetLowering(const AVRTargetMachine &TM, + const AVRSubtarget &STI) + : TargetLowering(TM), Subtarget(STI) { // Set up the register classes. addRegisterClass(MVT::i8, &AVR::GPR8RegClass); addRegisterClass(MVT::i16, &AVR::DREGSRegClass); // Compute derived properties from the register classes. - computeRegisterProperties(tm.getSubtargetImpl()->getRegisterInfo()); + computeRegisterProperties(Subtarget.getRegisterInfo()); setBooleanContents(ZeroOrOneBooleanContent); setBooleanVectorContents(ZeroOrOneBooleanContent); @@ -163,6 +165,13 @@ AVRTargetLowering::AVRTargetLowering(AVRTargetMachine &tm) setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand); setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand); + // Expand multiplications to libcalls when there is + // no hardware MUL. + if (!Subtarget.supportsMultiplication()) { + setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand); + } + for (MVT VT : MVT::integer_valuetypes()) { setOperationAction(ISD::MULHS, VT, Expand); setOperationAction(ISD::MULHU, VT, Expand); @@ -1271,7 +1280,7 @@ SDValue AVRTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Add a register mask operand representing the call-preserved registers. const AVRTargetMachine &TM = (const AVRTargetMachine &)getTargetMachine(); - const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->getRegisterInfo(); + const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); const uint32_t *Mask = TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv); assert(Mask && "Missing call preserved mask for calling convention"); @@ -1434,7 +1443,7 @@ MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &MI, MachineFunction *F = BB->getParent(); MachineRegisterInfo &RI = F->getRegInfo(); const AVRTargetMachine &TM = (const AVRTargetMachine &)getTargetMachine(); - const TargetInstrInfo &TII = *TM.getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); DebugLoc dl = MI.getDebugLoc(); switch (MI.getOpcode()) { @@ -1575,7 +1584,7 @@ static bool isCopyMulResult(MachineBasicBlock::iterator const &I) { MachineBasicBlock *AVRTargetLowering::insertMul(MachineInstr &MI, MachineBasicBlock *BB) const { const AVRTargetMachine &TM = (const AVRTargetMachine &)getTargetMachine(); - const TargetInstrInfo &TII = *TM.getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); MachineBasicBlock::iterator I(MI); ++I; // in any case insert *after* the mul instruction if (isCopyMulResult(I)) @@ -1838,9 +1847,6 @@ std::pair AVRTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const { - auto STI = static_cast(this->getTargetMachine()) - .getSubtargetImpl(); - // We only support i8 and i16. // //:FIXME: remove this assert for now since it gets sometimes executed @@ -1884,8 +1890,8 @@ AVRTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, } } - return TargetLowering::getRegForInlineAsmConstraint(STI->getRegisterInfo(), - Constraint, VT); + return TargetLowering::getRegForInlineAsmConstraint( + Subtarget.getRegisterInfo(), Constraint, VT); } void AVRTargetLowering::LowerAsmOperandForConstraint(SDValue Op, diff --git a/llvm/lib/Target/AVR/AVRISelLowering.h b/llvm/lib/Target/AVR/AVRISelLowering.h index c90c65c81f700..7d77dd8fb0188 100644 --- a/llvm/lib/Target/AVR/AVRISelLowering.h +++ b/llvm/lib/Target/AVR/AVRISelLowering.h @@ -64,12 +64,14 @@ enum NodeType { } // end of namespace AVRISD +class AVRSubtarget; class AVRTargetMachine; /// Performs target lowering for the AVR. class AVRTargetLowering : public TargetLowering { public: - explicit AVRTargetLowering(AVRTargetMachine &TM); + explicit AVRTargetLowering(const AVRTargetMachine &TM, + const AVRSubtarget &STI); public: MVT getScalarShiftAmountTy(const DataLayout &, EVT LHSTy) const override { @@ -164,6 +166,10 @@ class AVRTargetLowering : public TargetLowering { const SDLoc &dl, SelectionDAG &DAG, SmallVectorImpl &InVals) const; +protected: + + const AVRSubtarget &Subtarget; + private: MachineBasicBlock *insertShift(MachineInstr &MI, MachineBasicBlock *BB) const; MachineBasicBlock *insertMul(MachineInstr &MI, MachineBasicBlock *BB) const; diff --git a/llvm/lib/Target/AVR/AVRSubtarget.cpp b/llvm/lib/Target/AVR/AVRSubtarget.cpp index 556d69ec52341..c7c566270f432 100644 --- a/llvm/lib/Target/AVR/AVRSubtarget.cpp +++ b/llvm/lib/Target/AVR/AVRSubtarget.cpp @@ -29,9 +29,9 @@ namespace llvm { AVRSubtarget::AVRSubtarget(const Triple &TT, const std::string &CPU, - const std::string &FS, AVRTargetMachine &TM) + const std::string &FS, const AVRTargetMachine &TM) : AVRGenSubtargetInfo(TT, CPU, FS), InstrInfo(), FrameLowering(), - TLInfo(TM), TSInfo(), + TLInfo(TM, initializeSubtargetDependencies(CPU, FS, TM)), TSInfo(), // Subtarget features m_hasSRAM(false), m_hasJMPCALL(false), m_hasIJMPCALL(false), @@ -44,4 +44,12 @@ AVRSubtarget::AVRSubtarget(const Triple &TT, const std::string &CPU, ParseSubtargetFeatures(CPU, FS); } +AVRSubtarget & +AVRSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, + const TargetMachine &TM) { + // Parse features string. + ParseSubtargetFeatures(CPU, FS); + return *this; +} + } // end of namespace llvm diff --git a/llvm/lib/Target/AVR/AVRSubtarget.h b/llvm/lib/Target/AVR/AVRSubtarget.h index fa26738da1900..ba036d5e40616 100644 --- a/llvm/lib/Target/AVR/AVRSubtarget.h +++ b/llvm/lib/Target/AVR/AVRSubtarget.h @@ -37,7 +37,7 @@ class AVRSubtarget : public AVRGenSubtargetInfo { //! \param FS The feature string. //! \param TM The target machine. AVRSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS, - AVRTargetMachine &TM); + const AVRTargetMachine &TM); const AVRInstrInfo *getInstrInfo() const override { return &InstrInfo; } const TargetFrameLowering *getFrameLowering() const override { return &FrameLowering; } @@ -49,6 +49,9 @@ class AVRSubtarget : public AVRGenSubtargetInfo { /// \note Definition of function is auto generated by `tblgen`. void ParseSubtargetFeatures(StringRef CPU, StringRef FS); + AVRSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS, + const TargetMachine &TM); + // Subtarget feature getters. // See AVR.td for details. bool hasSRAM() const { return m_hasSRAM; } diff --git a/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp b/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp index f39c21fc8aa2b..5e9b108c2de3a 100644 --- a/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp +++ b/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp @@ -17,6 +17,7 @@ #include "MSP430InstrInfo.h" #include "MSP430MCInstLower.h" #include "MSP430TargetMachine.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -28,6 +29,7 @@ #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/TargetRegistry.h" @@ -44,6 +46,8 @@ namespace { StringRef getPassName() const override { return "MSP430 Assembly Printer"; } + bool runOnMachineFunction(MachineFunction &MF) override; + void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, const char* Modifier = nullptr); void printSrcMemOperand(const MachineInstr *MI, int OpNum, @@ -55,6 +59,8 @@ namespace { unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, raw_ostream &O) override; void EmitInstruction(const MachineInstr *MI) override; + + void EmitInterruptVectorSection(MachineFunction &ISR); }; } // end of anonymous namespace @@ -153,6 +159,32 @@ void MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) { EmitToStreamer(*OutStreamer, TmpInst); } +void MSP430AsmPrinter::EmitInterruptVectorSection(MachineFunction &ISR) { + MCSection *Cur = OutStreamer->getCurrentSectionOnly(); + const auto *F = &ISR.getFunction(); + assert(F->hasFnAttribute("interrupt") && + "Functions with MSP430_INTR CC should have 'interrupt' attribute"); + StringRef IVIdx = F->getFnAttribute("interrupt").getValueAsString(); + MCSection *IV = OutStreamer->getContext().getELFSection( + "__interrupt_vector_" + IVIdx, + ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_EXECINSTR); + OutStreamer->SwitchSection(IV); + + const MCSymbol *FunctionSymbol = getSymbol(F); + OutStreamer->EmitSymbolValue(FunctionSymbol, TM.getProgramPointerSize()); + OutStreamer->SwitchSection(Cur); +} + +bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) { + // Emit separate section for an interrupt vector if ISR + if (MF.getFunction().getCallingConv() == CallingConv::MSP430_INTR) + EmitInterruptVectorSection(MF); + + SetupMachineFunction(MF); + EmitFunctionBody(); + return false; +} + // Force static initialization. extern "C" void LLVMInitializeMSP430AsmPrinter() { RegisterAsmPrinter X(getTheMSP430Target()); diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index d2fed6861477b..f10d100bfe11c 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -65,10 +65,7 @@ class MCInstrInfo; } // end namespace llvm -static cl::opt -EmitJalrReloc("mips-jalr-reloc", cl::Hidden, - cl::desc("MIPS: Emit R_{MICRO}MIPS_JALR relocation with jalr"), - cl::init(true)); +extern cl::opt EmitJalrReloc; namespace { diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp index 18d7dd99be34a..2f2dd4e03c40a 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp @@ -15,6 +15,13 @@ using namespace llvm; +// Note: this option is defined here to be visible from libLLVMMipsAsmParser +// and libLLVMMipsCodeGen +cl::opt +EmitJalrReloc("mips-jalr-reloc", cl::Hidden, + cl::desc("MIPS: Emit R_{MICRO}MIPS_JALR relocation with jalr"), + cl::init(true)); + namespace { static const MCPhysReg O32IntRegs[4] = {Mips::A0, Mips::A1, Mips::A2, Mips::A3}; diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index a90db2384c466..ab8a6753eadcf 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -89,7 +89,10 @@ namespace MipsII { MO_GOT_HI16, MO_GOT_LO16, MO_CALL_HI16, - MO_CALL_LO16 + MO_CALL_LO16, + + /// Helper operand used to generate R_MIPS_JALR + MO_JALR }; enum { diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index f43a4d980f92a..e3dcbaccfd080 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -614,8 +614,9 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl &Fixups, llvm_unreachable("Unhandled fixup kind!"); break; case MipsMCExpr::MEK_DTPREL: - llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only"); - break; + // MEK_DTPREL is used for marking TLS DIEExpr only + // and contains a regular sub-expression. + return getExprOpValue(MipsExpr->getSubExpr(), Fixups, STI); case MipsMCExpr::MEK_CALL_HI16: FixupKind = Mips::fixup_Mips_CALL_HI16; break; diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp index 99857e083c6ca..2d7312725205f 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp @@ -44,8 +44,10 @@ void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { llvm_unreachable("MEK_None and MEK_Special are invalid"); break; case MEK_DTPREL: - llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only"); - break; + // MEK_DTPREL is used for marking TLS DIEExpr only + // and contains a regular sub-expression. + getSubExpr()->print(OS, MAI, true); + return; case MEK_CALL_HI16: OS << "%call_hi"; break; @@ -161,7 +163,9 @@ MipsMCExpr::evaluateAsRelocatableImpl(MCValue &Res, case MEK_Special: llvm_unreachable("MEK_None and MEK_Special are invalid"); case MEK_DTPREL: - llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only"); + // MEK_DTPREL is used for marking TLS DIEExpr only + // and contains a regular sub-expression. + return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup); case MEK_DTPREL_HI: case MEK_DTPREL_LO: case MEK_GOT: @@ -249,9 +253,6 @@ void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { case MEK_Special: llvm_unreachable("MEK_None and MEK_Special are invalid"); break; - case MEK_DTPREL: - llvm_unreachable("MEK_DTPREL is used for TLS DIEExpr only"); - break; case MEK_CALL_HI16: case MEK_CALL_LO16: case MEK_GOT: @@ -274,6 +275,7 @@ void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { if (const MipsMCExpr *E = dyn_cast(getSubExpr())) E->fixELFSymbolsInTLSFixups(Asm); break; + case MEK_DTPREL: case MEK_DTPREL_HI: case MEK_DTPREL_LO: case MEK_TLSLDM: diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 58f9717e1cc61..a46f84bd1c9cb 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -700,8 +700,11 @@ void MipsTargetAsmStreamer::emitDirectiveCpreturn(unsigned SaveLocation, } void MipsTargetAsmStreamer::emitDirectiveModuleFP() { - OS << "\t.module\tfp="; - OS << ABIFlagsSection.getFpABIString(ABIFlagsSection.getFpABI()) << "\n"; + MipsABIFlagsSection::FpABIKind FpABI = ABIFlagsSection.getFpABI(); + if (FpABI == MipsABIFlagsSection::FpABIKind::SOFT) + OS << "\t.module\tsoftfloat\n"; + else + OS << "\t.module\tfp=" << ABIFlagsSection.getFpABIString(FpABI) << "\n"; } void MipsTargetAsmStreamer::emitDirectiveSetFp( diff --git a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td index 814918d25e70d..994a8882f9425 100644 --- a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -460,6 +460,7 @@ class JALRC16_MMR6_DESC_BASE let isCall = 1; let hasDelaySlot = 0; let Defs = [RA]; + let hasPostISelHook = 1; } class JALRC16_MMR6_DESC : JALRC16_MMR6_DESC_BASE<"jalr", GPR32Opnd>; @@ -1039,7 +1040,7 @@ class TRUNC_L_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"trunc.l.d", FGR64Opnd, class TRUNC_W_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"trunc.w.s", FGR32Opnd, FGR32Opnd, II_TRUNC>; class TRUNC_W_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"trunc.w.d", FGR32Opnd, - AFGR64Opnd, II_TRUNC>; + FGR64Opnd, II_TRUNC>; class SQRT_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"sqrt.s", FGR32Opnd, FGR32Opnd, II_SQRT_S, fsqrt>; class SQRT_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"sqrt.d", AFGR64Opnd, AFGR64Opnd, @@ -1749,6 +1750,8 @@ def : MipsPat<(f32 fpimm0), (MTC1_MMR6 ZERO)>, ISA_MICROMIPS32R6; def : MipsPat<(f32 fpimm0neg), (FNEG_S_MMR6 (MTC1_MMR6 ZERO))>, ISA_MICROMIPS32R6; def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), (TRUNC_W_D_MMR6 FGR64Opnd:$src)>, ISA_MICROMIPS32R6; +def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src), + (TRUNC_W_S_MMR6 FGR32Opnd:$src)>, ISA_MICROMIPS32R6; def : MipsPat<(and GPRMM16:$src, immZExtAndi16:$imm), (ANDI16_MMR6 GPRMM16:$src, immZExtAndi16:$imm)>, diff --git a/llvm/lib/Target/Mips/MicroMipsInstrFPU.td b/llvm/lib/Target/Mips/MicroMipsInstrFPU.td index 1731afc1961f8..9e76165e7ad71 100644 --- a/llvm/lib/Target/Mips/MicroMipsInstrFPU.td +++ b/llvm/lib/Target/Mips/MicroMipsInstrFPU.td @@ -425,6 +425,11 @@ def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), def : MipsPat<(MipsTruncIntFP AFGR64Opnd:$src), (TRUNC_W_MM AFGR64Opnd:$src)>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; +def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), + (CVT_W_D64_MM FGR64Opnd:$src)>, ISA_MICROMIPS32_NOT_MIPS32R6, + FGR_64; +def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src), + (TRUNC_W_S_MM FGR32Opnd:$src)>, ISA_MICROMIPS32_NOT_MIPS32R6; // Selects defm : MovzPats0, diff --git a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td index af380a0ec71e0..ccc4f04bb92d8 100644 --- a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td @@ -426,6 +426,7 @@ class JumpLinkRegMM16 : let isCall = 1; let hasDelaySlot = 1; let Defs = [RA]; + let hasPostISelHook = 1; } // 16-bit Jump Reg diff --git a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td index 2bd0cf2d59a64..fb239f572ef22 100644 --- a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td @@ -1105,7 +1105,7 @@ def : MipsPat<(select i32:$cond, immz, i32:$f), // Pseudo instructions let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1, - hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT] in { + hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT], hasPostISelHook = 1 in { class TailCallRegR6 : PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>, PseudoInstExpansion<(JumpInst RT:$rt, RO:$rs)>; diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index 362431fd42a6c..c35f5beb68804 100644 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -68,6 +68,8 @@ using namespace llvm; #define DEBUG_TYPE "mips-asm-printer" +extern cl::opt EmitJalrReloc; + MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() const { return static_cast(*OutStreamer->getTargetStreamer()); } @@ -148,6 +150,40 @@ void MipsAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer, EmitToStreamer(OutStreamer, TmpInst0); } +// If there is an MO_JALR operand, insert: +// +// .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol +// tmplabel: +// +// This is an optimization hint for the linker which may then replace +// an indirect call with a direct branch. +static void emitDirectiveRelocJalr(const MachineInstr &MI, + MCContext &OutContext, + TargetMachine &TM, + MCStreamer &OutStreamer, + const MipsSubtarget &Subtarget) { + for (unsigned int I = MI.getDesc().getNumOperands(), E = MI.getNumOperands(); + I < E; ++I) { + MachineOperand MO = MI.getOperand(I); + if (MO.isMCSymbol() && (MO.getTargetFlags() & MipsII::MO_JALR)) { + MCSymbol *Callee = MO.getMCSymbol(); + if (Callee && !Callee->getName().empty()) { + MCSymbol *OffsetLabel = OutContext.createTempSymbol(); + const MCExpr *OffsetExpr = + MCSymbolRefExpr::create(OffsetLabel, OutContext); + const MCExpr *CaleeExpr = + MCSymbolRefExpr::create(Callee, OutContext); + OutStreamer.EmitRelocDirective + (*OffsetExpr, + Subtarget.inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR", + CaleeExpr, SMLoc(), *TM.getMCSubtargetInfo()); + OutStreamer.EmitLabel(OffsetLabel); + return; + } + } + } +} + void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { MipsTargetStreamer &TS = getTargetStreamer(); unsigned Opc = MI->getOpcode(); @@ -207,6 +243,11 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { return; } + if (EmitJalrReloc && + (MI->isReturn() || MI->isCall() || MI->isIndirectBranch())) { + emitDirectiveRelocJalr(*MI, OutContext, TM, *OutStreamer, *Subtarget); + } + MachineBasicBlock::const_instr_iterator I = MI->getIterator(); MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end(); @@ -772,7 +813,8 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // We should always emit a '.module fp=...' but binutils 2.24 does not accept // it. We therefore emit it when it contradicts the ABI defaults (-mfpxx or // -mfp64) and omit it otherwise. - if (ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) + if ((ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) || + STI.useSoftFloat()) TS.emitDirectiveModuleFP(); // We should always emit a '.module [no]oddspreg' but binutils 2.24 does not diff --git a/llvm/lib/Target/Mips/MipsDSPInstrInfo.td b/llvm/lib/Target/Mips/MipsDSPInstrInfo.td index b9824220b5580..a4078026e4f9f 100644 --- a/llvm/lib/Target/Mips/MipsDSPInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsDSPInstrInfo.td @@ -1314,7 +1314,9 @@ def PseudoCMPU_LE_QB : PseudoCMP; def PseudoPICK_PH : PseudoPICK; def PseudoPICK_QB : PseudoPICK; -def PseudoMTLOHI_DSP : PseudoMTLOHI; +let AdditionalPredicates = [HasDSP] in { + def PseudoMTLOHI_DSP : PseudoMTLOHI; +} // Patterns. class DSPPat : diff --git a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp index e3823e0dfdb8a..61e77fbeea6d3 100644 --- a/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -726,6 +726,7 @@ bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin, // but we don't have enough information to make that decision. if (InMicroMipsMode && TII->getInstSizeInBytes(*CurrI) == 2 && (Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch || + Opcode == Mips::PseudoIndirectBranch_MM || Opcode == Mips::PseudoReturn || Opcode == Mips::TAILCALL)) continue; // Instructions LWP/SWP and MOVEP should not be in a delay slot as that diff --git a/llvm/lib/Target/Mips/MipsFastISel.cpp b/llvm/lib/Target/Mips/MipsFastISel.cpp index 22ade31a72cdb..168750b2cba93 100644 --- a/llvm/lib/Target/Mips/MipsFastISel.cpp +++ b/llvm/lib/Target/Mips/MipsFastISel.cpp @@ -56,6 +56,7 @@ #include "llvm/IR/Type.h" #include "llvm/IR/User.h" #include "llvm/IR/Value.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSymbol.h" @@ -75,6 +76,8 @@ using namespace llvm; +extern cl::opt EmitJalrReloc; + namespace { class MipsFastISel final : public FastISel { @@ -951,21 +954,34 @@ bool MipsFastISel::selectBranch(const Instruction *I) { // MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)]; MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)]; - // For now, just try the simplest case where it's fed by a compare. + + // Fold the common case of a conditional branch with a comparison + // in the same block. + unsigned ZExtCondReg = 0; if (const CmpInst *CI = dyn_cast(BI->getCondition())) { - MVT CIMVT = - TLI.getValueType(DL, CI->getOperand(0)->getType(), true).getSimpleVT(); - if (CIMVT == MVT::i1) + if (CI->hasOneUse() && CI->getParent() == I->getParent()) { + ZExtCondReg = createResultReg(&Mips::GPR32RegClass); + if (!emitCmp(ZExtCondReg, CI)) + return false; + } + } + + // For the general case, we need to mask with 1. + if (ZExtCondReg == 0) { + unsigned CondReg = getRegForValue(BI->getCondition()); + if (CondReg == 0) return false; - unsigned CondReg = getRegForValue(CI); - BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ)) - .addReg(CondReg) - .addMBB(TBB); - finishCondBranch(BI->getParent(), TBB, FBB); - return true; + ZExtCondReg = emitIntExt(MVT::i1, CondReg, MVT::i32, true); + if (ZExtCondReg == 0) + return false; } - return false; + + BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ)) + .addReg(ZExtCondReg) + .addMBB(TBB); + finishCondBranch(BI->getParent(), TBB, FBB); + return true; } bool MipsFastISel::selectCmp(const Instruction *I) { @@ -1551,6 +1567,16 @@ bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) { CLI.Call = MIB; + if (EmitJalrReloc && !Subtarget->inMips16Mode()) { + // Attach callee address to the instruction, let asm printer emit + // .reloc R_MIPS_JALR. + if (Symbol) + MIB.addSym(Symbol, MipsII::MO_JALR); + else + MIB.addSym(FuncInfo.MF->getContext().getOrCreateSymbol( + Addr.getGlobalValue()->getName()), MipsII::MO_JALR); + } + // Finish off the call including any return values. return finishCall(CLI, RetVT, NumBytes); } diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index 8c2a364cdfa95..0f9c075ba0ccf 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -57,6 +57,7 @@ #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CodeGen.h" @@ -91,6 +92,8 @@ NoZeroDivCheck("mno-check-zero-division", cl::Hidden, cl::desc("MIPS: Don't trap on integer division by zero."), cl::init(false)); +extern cl::opt EmitJalrReloc; + static const MCPhysReg Mips64DPRegs[8] = { Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64, Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64 @@ -2879,6 +2882,54 @@ getOpndList(SmallVectorImpl &Ops, Ops.push_back(InFlag); } +void MipsTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, + SDNode *Node) const { + switch (MI.getOpcode()) { + default: + return; + case Mips::JALR: + case Mips::JALRPseudo: + case Mips::JALR64: + case Mips::JALR64Pseudo: + case Mips::JALR16_MM: + case Mips::JALRC16_MMR6: + case Mips::TAILCALLREG: + case Mips::TAILCALLREG64: + case Mips::TAILCALLR6REG: + case Mips::TAILCALL64R6REG: + case Mips::TAILCALLREG_MM: + case Mips::TAILCALLREG_MMR6: { + if (!EmitJalrReloc || + Subtarget.inMips16Mode() || + !isPositionIndependent() || + Node->getNumOperands() < 1 || + Node->getOperand(0).getNumOperands() < 2) { + return; + } + // We are after the callee address, set by LowerCall(). + // If added to MI, asm printer will emit .reloc R_MIPS_JALR for the + // symbol. + const SDValue TargetAddr = Node->getOperand(0).getOperand(1); + StringRef Sym; + if (const GlobalAddressSDNode *G = + dyn_cast_or_null(TargetAddr)) { + Sym = G->getGlobal()->getName(); + } + else if (const ExternalSymbolSDNode *ES = + dyn_cast_or_null(TargetAddr)) { + Sym = ES->getSymbol(); + } + + if (Sym.empty()) + return; + + MachineFunction *MF = MI.getParent()->getParent(); + MCSymbol *S = MF->getContext().getOrCreateSymbol(Sym); + MI.addOperand(MachineOperand::CreateMCSymbol(S, MipsII::MO_JALR)); + } + } +} + /// LowerCall - functions arguments are copied from virtual regs to /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. SDValue @@ -2930,7 +2981,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // the maximum out going argument area (including the reserved area), and // preallocates the stack space on entrance to the caller. // - // FIXME: We should do the same for efficency and space. + // FIXME: We should do the same for efficiency and space. // Note: The check on the calling convention below must match // MipsABIInfo::GetCalleeAllocdArgSizeInBytes(). diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h index e043f133a09fd..c88633be02b77 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/llvm/lib/Target/Mips/MipsISelLowering.h @@ -341,6 +341,9 @@ class TargetRegisterClass; EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override; + void AdjustInstrPostInstrSelection(MachineInstr &MI, + SDNode *Node) const override; + void HandleByVal(CCState *, unsigned &, unsigned) const override; unsigned getRegisterByName(const char* RegName, EVT VT, diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.cpp b/llvm/lib/Target/Mips/MipsInstrInfo.cpp index bfb4c775205de..e38bef4663a7d 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.cpp +++ b/llvm/lib/Target/Mips/MipsInstrInfo.cpp @@ -653,6 +653,16 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc, MIB.addImm(0); + // If I has an MCSymbol operand (used by asm printer, to emit R_MIPS_JALR), + // add it to the new instruction. + for (unsigned J = I->getDesc().getNumOperands(), E = I->getNumOperands(); + J < E; ++J) { + const MachineOperand &MO = I->getOperand(J); + if (MO.isMCSymbol() && (MO.getTargetFlags() & MipsII::MO_JALR)) + MIB.addSym(MO.getMCSymbol(), MipsII::MO_JALR); + } + + } else { for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { if (BranchWithZeroOperand && (unsigned)ZeroOperandPosition == J) @@ -825,7 +835,8 @@ MipsInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { {MO_GOT_HI16, "mips-got-hi16"}, {MO_GOT_LO16, "mips-got-lo16"}, {MO_CALL_HI16, "mips-call-hi16"}, - {MO_CALL_LO16, "mips-call-lo16"} + {MO_CALL_LO16, "mips-call-lo16"}, + {MO_JALR, "mips-jalr"} }; return makeArrayRef(Flags); } diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index d9398b7d6024a..46721e6cb9e5f 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -1623,11 +1623,15 @@ let isCall=1, hasDelaySlot=1, isCTI=1, Defs = [RA] in { class JumpLinkRegPseudo: PseudoSE<(outs), (ins RO:$rs), [(MipsJmpLink RO:$rs)], II_JALR>, - PseudoInstExpansion<(JALRInst RetReg, ResRO:$rs)>; + PseudoInstExpansion<(JALRInst RetReg, ResRO:$rs)> { + let hasPostISelHook = 1; + } class JumpLinkReg: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [], II_JALR, FrmR, opstr>; + [], II_JALR, FrmR, opstr> { + let hasPostISelHook = 1; + } class BGEZAL_FT : @@ -1646,7 +1650,9 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1, class TailCallReg : PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>, - PseudoInstExpansion<(JumpInst RO:$rs)>; + PseudoInstExpansion<(JumpInst RO:$rs)> { + let hasPostISelHook = 1; + } } class BAL_BR_Pseudo : diff --git a/llvm/lib/Target/Mips/MipsMCInstLower.cpp b/llvm/lib/Target/Mips/MipsMCInstLower.cpp index 46b37ceae3918..4a7c0ce2be19b 100644 --- a/llvm/lib/Target/Mips/MipsMCInstLower.cpp +++ b/llvm/lib/Target/Mips/MipsMCInstLower.cpp @@ -117,6 +117,8 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, case MipsII::MO_CALL_LO16: TargetKind = MipsMCExpr::MEK_CALL_LO16; break; + case MipsII::MO_JALR: + return MCOperand(); } switch (MOTy) { diff --git a/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp b/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp index c7ab90ed2a3ba..2b26caaa9f49c 100644 --- a/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -447,6 +447,9 @@ bool MipsSEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { case Mips::PseudoMTLOHI_DSP: expandPseudoMTLoHi(MBB, MI, Mips::MTLO_DSP, Mips::MTHI_DSP, true); break; + case Mips::PseudoMTLOHI_MM: + expandPseudoMTLoHi(MBB, MI, Mips::MTLO_MM, Mips::MTHI_MM, false); + break; case Mips::PseudoCVT_S_W: expandCvtFPInt(MBB, MI, Mips::CVT_S_W, Mips::MTC1, false); break; diff --git a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp index 26869f2508231..cce239cac970e 100644 --- a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp +++ b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp @@ -61,6 +61,14 @@ extern "C" void LLVMInitializePowerPCDisassembler() { createPPCLEDisassembler); } +static DecodeStatus DecodePCRel24BranchTarget(MCInst &Inst, unsigned Imm, + uint64_t Addr, + const void *Decoder) { + int32_t Offset = SignExtend32<24>(Imm); + Inst.addOperand(MCOperand::createImm(Offset)); + return MCDisassembler::Success; +} + // FIXME: These can be generated by TableGen from the existing register // encoding values! diff --git a/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp b/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp index fc29e4effbb12..6824168b890dd 100644 --- a/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp +++ b/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp @@ -382,8 +382,11 @@ void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo, // Branches can take an immediate operand. This is used by the branch // selection pass to print .+8, an eight byte displacement from the PC. - O << ".+"; - printAbsBranchOperand(MI, OpNo, O); + O << "."; + int32_t Imm = SignExtend32<32>((unsigned)MI->getOperand(OpNo).getImm() << 2); + if (Imm >= 0) + O << "+"; + O << Imm; } void PPCInstPrinter::printAbsBranchOperand(const MCInst *MI, unsigned OpNo, diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp index a1e4e07b25af4..78609ef3d4e09 100644 --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -15,6 +15,7 @@ #include "InstPrinter/PPCInstPrinter.h" #include "MCTargetDesc/PPCMCAsmInfo.h" #include "PPCTargetStreamer.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/ELF.h" @@ -182,16 +183,33 @@ class PPCTargetELFStreamer : public PPCTargetStreamer { void emitAssignment(MCSymbol *S, const MCExpr *Value) override { auto *Symbol = cast(S); + // When encoding an assignment to set symbol A to symbol B, also copy // the st_other bits encoding the local entry point offset. - if (Value->getKind() != MCExpr::SymbolRef) - return; - const auto &RhsSym = cast( - static_cast(Value)->getSymbol()); - unsigned Other = Symbol->getOther(); + if (copyLocalEntry(Symbol, Value)) + UpdateOther.insert(Symbol); + else + UpdateOther.erase(Symbol); + } + + void finish() override { + for (auto *Sym : UpdateOther) + copyLocalEntry(Sym, Sym->getVariableValue()); + } + +private: + SmallPtrSet UpdateOther; + + bool copyLocalEntry(MCSymbolELF *D, const MCExpr *S) { + auto *Ref = dyn_cast(S); + if (!Ref) + return false; + const auto &RhsSym = cast(Ref->getSymbol()); + unsigned Other = D->getOther(); Other &= ~ELF::STO_PPC64_LOCAL_MASK; Other |= RhsSym.getOther() & ELF::STO_PPC64_LOCAL_MASK; - Symbol->setOther(Other); + D->setOther(Other); + return true; } }; diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 31acd0ff870fd..70e9049a2ab32 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -4359,8 +4359,8 @@ void PPCDAGToDAGISel::Select(SDNode *N) { const Module *M = MF->getFunction().getParent(); if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) != MVT::i32 || - !PPCSubTarget->isSecurePlt() || !PPCSubTarget->isTargetELF() || - M->getPICLevel() == PICLevel::SmallPIC) + (!TM.isPositionIndependent() || !PPCSubTarget->isSecurePlt()) || + !PPCSubTarget->isTargetELF() || M->getPICLevel() == PICLevel::SmallPIC) break; SDValue Op = N->getOperand(1); diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index dd3f1ac790894..77aa4fe3d4158 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -737,7 +737,9 @@ def abscondbrtarget : Operand { def calltarget : Operand { let PrintMethod = "printBranchOperand"; let EncoderMethod = "getDirectBrEncoding"; + let DecoderMethod = "DecodePCRel24BranchTarget"; let ParserMatchClass = PPCDirectBrAsmOperand; + let OperandType = "OPERAND_PCREL"; } def abscalltarget : Operand { let PrintMethod = "printAbsBranchOperand"; diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp index c0cbfd779cb90..1fdf74549dec1 100644 --- a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp @@ -138,6 +138,9 @@ void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { if (isDarwin()) HasLazyResolverStubs = true; + if (TargetTriple.isOSNetBSD() || TargetTriple.isOSOpenBSD()) + SecurePlt = true; + if (HasSPE && IsPPC64) report_fatal_error( "SPE is only supported for 32-bit targets.\n", false); if (HasSPE && (HasAltivec || HasQPX || HasVSX || HasFPU)) diff --git a/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp b/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp index 33caa66154ff2..ad6ea3760feee 100644 --- a/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -189,7 +189,7 @@ SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, MachineInstr *StMI = BuildMI(*MI.getParent(), II, dl, TII.get(SP::STDFri)) .addReg(FrameReg).addImm(0).addReg(SrcEvenReg); - replaceFI(MF, II, *StMI, dl, 0, Offset, FrameReg); + replaceFI(MF, *StMI, *StMI, dl, 0, Offset, FrameReg); MI.setDesc(TII.get(SP::STDFri)); MI.getOperand(2).setReg(SrcOddReg); Offset += 8; @@ -201,7 +201,7 @@ SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, MachineInstr *StMI = BuildMI(*MI.getParent(), II, dl, TII.get(SP::LDDFri), DestEvenReg) .addReg(FrameReg).addImm(0); - replaceFI(MF, II, *StMI, dl, 1, Offset, FrameReg); + replaceFI(MF, *StMI, *StMI, dl, 1, Offset, FrameReg); MI.setDesc(TII.get(SP::LDDFri)); MI.getOperand(0).setReg(DestOddReg); diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index 2a825c1316f3b..607e55bf71c87 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -5618,55 +5618,96 @@ SDValue SystemZTargetLowering::combineBSWAP( static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) { // We have a SELECT_CCMASK or BR_CCMASK comparing the condition code // set by the CCReg instruction using the CCValid / CCMask masks, - // If the CCReg instruction is itself a (ICMP (SELECT_CCMASK)) testing - // the condition code set by some other instruction, see whether we - // can directly use that condition code. - bool Invert = false; + // If the CCReg instruction is itself a ICMP testing the condition + // code set by some other instruction, see whether we can directly + // use that condition code. - // Verify that we have an appropriate mask for a EQ or NE comparison. + // Verify that we have an ICMP against some constant. if (CCValid != SystemZ::CCMASK_ICMP) return false; - if (CCMask == SystemZ::CCMASK_CMP_NE) - Invert = !Invert; - else if (CCMask != SystemZ::CCMASK_CMP_EQ) - return false; - - // Verify that we have an ICMP that is the user of a SELECT_CCMASK. - SDNode *ICmp = CCReg.getNode(); + auto *ICmp = CCReg.getNode(); if (ICmp->getOpcode() != SystemZISD::ICMP) return false; - SDNode *Select = ICmp->getOperand(0).getNode(); - if (Select->getOpcode() != SystemZISD::SELECT_CCMASK) + auto *CompareLHS = ICmp->getOperand(0).getNode(); + auto *CompareRHS = dyn_cast(ICmp->getOperand(1)); + if (!CompareRHS) return false; - // Verify that the ICMP compares against one of select values. - auto *CompareVal = dyn_cast(ICmp->getOperand(1)); - if (!CompareVal) - return false; - auto *TrueVal = dyn_cast(Select->getOperand(0)); - if (!TrueVal) - return false; - auto *FalseVal = dyn_cast(Select->getOperand(1)); - if (!FalseVal) - return false; - if (CompareVal->getZExtValue() == FalseVal->getZExtValue()) - Invert = !Invert; - else if (CompareVal->getZExtValue() != TrueVal->getZExtValue()) - return false; + // Optimize the case where CompareLHS is a SELECT_CCMASK. + if (CompareLHS->getOpcode() == SystemZISD::SELECT_CCMASK) { + // Verify that we have an appropriate mask for a EQ or NE comparison. + bool Invert = false; + if (CCMask == SystemZ::CCMASK_CMP_NE) + Invert = !Invert; + else if (CCMask != SystemZ::CCMASK_CMP_EQ) + return false; - // Compute the effective CC mask for the new branch or select. - auto *NewCCValid = dyn_cast(Select->getOperand(2)); - auto *NewCCMask = dyn_cast(Select->getOperand(3)); - if (!NewCCValid || !NewCCMask) - return false; - CCValid = NewCCValid->getZExtValue(); - CCMask = NewCCMask->getZExtValue(); - if (Invert) - CCMask ^= CCValid; + // Verify that the ICMP compares against one of select values. + auto *TrueVal = dyn_cast(CompareLHS->getOperand(0)); + if (!TrueVal) + return false; + auto *FalseVal = dyn_cast(CompareLHS->getOperand(1)); + if (!FalseVal) + return false; + if (CompareRHS->getZExtValue() == FalseVal->getZExtValue()) + Invert = !Invert; + else if (CompareRHS->getZExtValue() != TrueVal->getZExtValue()) + return false; - // Return the updated CCReg link. - CCReg = Select->getOperand(4); - return true; + // Compute the effective CC mask for the new branch or select. + auto *NewCCValid = dyn_cast(CompareLHS->getOperand(2)); + auto *NewCCMask = dyn_cast(CompareLHS->getOperand(3)); + if (!NewCCValid || !NewCCMask) + return false; + CCValid = NewCCValid->getZExtValue(); + CCMask = NewCCMask->getZExtValue(); + if (Invert) + CCMask ^= CCValid; + + // Return the updated CCReg link. + CCReg = CompareLHS->getOperand(4); + return true; + } + + // Optimize the case where CompareRHS is (SRA (SHL (IPM))). + if (CompareLHS->getOpcode() == ISD::SRA) { + auto *SRACount = dyn_cast(CompareLHS->getOperand(1)); + if (!SRACount || SRACount->getZExtValue() != 30) + return false; + auto *SHL = CompareLHS->getOperand(0).getNode(); + if (SHL->getOpcode() != ISD::SHL) + return false; + auto *SHLCount = dyn_cast(SHL->getOperand(1)); + if (!SHLCount || SHLCount->getZExtValue() != 30 - SystemZ::IPM_CC) + return false; + auto *IPM = SHL->getOperand(0).getNode(); + if (IPM->getOpcode() != SystemZISD::IPM) + return false; + + // Avoid introducing CC spills (because SRA would clobber CC). + if (!CompareLHS->hasOneUse()) + return false; + // Verify that the ICMP compares against zero. + if (CompareRHS->getZExtValue() != 0) + return false; + + // Compute the effective CC mask for the new branch or select. + switch (CCMask) { + case SystemZ::CCMASK_CMP_EQ: break; + case SystemZ::CCMASK_CMP_NE: break; + case SystemZ::CCMASK_CMP_LT: CCMask = SystemZ::CCMASK_CMP_GT; break; + case SystemZ::CCMASK_CMP_GT: CCMask = SystemZ::CCMASK_CMP_LT; break; + case SystemZ::CCMASK_CMP_LE: CCMask = SystemZ::CCMASK_CMP_GE; break; + case SystemZ::CCMASK_CMP_GE: CCMask = SystemZ::CCMASK_CMP_LE; break; + default: return false; + } + + // Return the updated CCReg link. + CCReg = IPM->getOperand(0); + return true; + } + + return false; } SDValue SystemZTargetLowering::combineBR_CCMASK( diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp index b03b4edaa4abc..8aab5c2c49998 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -557,80 +557,6 @@ bool SystemZInstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg, return false; } -// If Reg is a virtual register, return its definition, otherwise return null. -static MachineInstr *getDef(unsigned Reg, - const MachineRegisterInfo *MRI) { - if (TargetRegisterInfo::isPhysicalRegister(Reg)) - return nullptr; - return MRI->getUniqueVRegDef(Reg); -} - -// Return true if MI is a shift of type Opcode by Imm bits. -static bool isShift(MachineInstr *MI, unsigned Opcode, int64_t Imm) { - return (MI->getOpcode() == Opcode && - !MI->getOperand(2).getReg() && - MI->getOperand(3).getImm() == Imm); -} - -// If the destination of MI has no uses, delete it as dead. -static void eraseIfDead(MachineInstr *MI, const MachineRegisterInfo *MRI) { - if (MRI->use_nodbg_empty(MI->getOperand(0).getReg())) - MI->eraseFromParent(); -} - -// Compare compares SrcReg against zero. Check whether SrcReg contains -// the result of an IPM sequence whose input CC survives until Compare, -// and whether Compare is therefore redundant. Delete it and return -// true if so. -static bool removeIPMBasedCompare(MachineInstr &Compare, unsigned SrcReg, - const MachineRegisterInfo *MRI, - const TargetRegisterInfo *TRI) { - MachineInstr *LGFR = nullptr; - MachineInstr *RLL = getDef(SrcReg, MRI); - if (RLL && RLL->getOpcode() == SystemZ::LGFR) { - LGFR = RLL; - RLL = getDef(LGFR->getOperand(1).getReg(), MRI); - } - if (!RLL || !isShift(RLL, SystemZ::RLL, 31)) - return false; - - MachineInstr *SRL = getDef(RLL->getOperand(1).getReg(), MRI); - if (!SRL || !isShift(SRL, SystemZ::SRL, SystemZ::IPM_CC)) - return false; - - MachineInstr *IPM = getDef(SRL->getOperand(1).getReg(), MRI); - if (!IPM || IPM->getOpcode() != SystemZ::IPM) - return false; - - // Check that there are no assignments to CC between the IPM and Compare, - if (IPM->getParent() != Compare.getParent()) - return false; - MachineBasicBlock::iterator MBBI = IPM, MBBE = Compare.getIterator(); - for (++MBBI; MBBI != MBBE; ++MBBI) { - MachineInstr &MI = *MBBI; - if (MI.modifiesRegister(SystemZ::CC, TRI)) - return false; - } - - Compare.eraseFromParent(); - if (LGFR) - eraseIfDead(LGFR, MRI); - eraseIfDead(RLL, MRI); - eraseIfDead(SRL, MRI); - eraseIfDead(IPM, MRI); - - return true; -} - -bool SystemZInstrInfo::optimizeCompareInstr( - MachineInstr &Compare, unsigned SrcReg, unsigned SrcReg2, int Mask, - int Value, const MachineRegisterInfo *MRI) const { - assert(!SrcReg2 && "Only optimizing constant comparisons so far"); - bool IsLogical = (Compare.getDesc().TSFlags & SystemZII::IsLogical) != 0; - return Value == 0 && !IsLogical && - removeIPMBasedCompare(Compare, SrcReg, MRI, &RI); -} - bool SystemZInstrInfo::canInsertSelect(const MachineBasicBlock &MBB, ArrayRef Pred, unsigned TrueReg, unsigned FalseReg, diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h index 216139eb7c796..0392430ed872c 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h @@ -208,9 +208,6 @@ class SystemZInstrInfo : public SystemZGenInstrInfo { int *BytesAdded = nullptr) const override; bool analyzeCompare(const MachineInstr &MI, unsigned &SrcReg, unsigned &SrcReg2, int &Mask, int &Value) const override; - bool optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg, - unsigned SrcReg2, int Mask, int Value, - const MachineRegisterInfo *MRI) const override; bool canInsertSelect(const MachineBasicBlock&, ArrayRef Cond, unsigned, unsigned, int&, int&, int&) const override; void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, diff --git a/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp b/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp index e0d7bca9a94b9..4592e82eea718 100644 --- a/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp @@ -164,17 +164,17 @@ static SDValue emitCLC(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, } // Convert the current CC value into an integer that is 0 if CC == 0, -// less than zero if CC == 1 and greater than zero if CC >= 2. +// greater than zero if CC == 1 and less than zero if CC >= 2. // The sequence starts with IPM, which puts CC into bits 29 and 28 // of an integer and clears bits 30 and 31. static SDValue addIPMSequence(const SDLoc &DL, SDValue CCReg, SelectionDAG &DAG) { SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, CCReg); - SDValue SRL = DAG.getNode(ISD::SRL, DL, MVT::i32, IPM, - DAG.getConstant(SystemZ::IPM_CC, DL, MVT::i32)); - SDValue ROTL = DAG.getNode(ISD::ROTL, DL, MVT::i32, SRL, - DAG.getConstant(31, DL, MVT::i32)); - return ROTL; + SDValue SHL = DAG.getNode(ISD::SHL, DL, MVT::i32, IPM, + DAG.getConstant(30 - SystemZ::IPM_CC, DL, MVT::i32)); + SDValue SRA = DAG.getNode(ISD::SRA, DL, MVT::i32, SHL, + DAG.getConstant(30, DL, MVT::i32)); + return SRA; } std::pair SystemZSelectionDAGInfo::EmitTargetCodeForMemcmp( @@ -184,7 +184,8 @@ std::pair SystemZSelectionDAGInfo::EmitTargetCodeForMemcmp( if (auto *CSize = dyn_cast(Size)) { uint64_t Bytes = CSize->getZExtValue(); assert(Bytes > 0 && "Caller should have handled 0-size case"); - SDValue CCReg = emitCLC(DAG, DL, Chain, Src1, Src2, Bytes); + // Swap operands to invert CC == 1 vs. CC == 2 cases. + SDValue CCReg = emitCLC(DAG, DL, Chain, Src2, Src1, Bytes); Chain = CCReg.getValue(1); return std::make_pair(addIPMSequence(DL, CCReg, DAG), Chain); } @@ -232,7 +233,8 @@ std::pair SystemZSelectionDAGInfo::EmitTargetCodeForStrcmp( SDValue Src2, MachinePointerInfo Op1PtrInfo, MachinePointerInfo Op2PtrInfo) const { SDVTList VTs = DAG.getVTList(Src1.getValueType(), MVT::i32, MVT::Other); - SDValue Unused = DAG.getNode(SystemZISD::STRCMP, DL, VTs, Chain, Src1, Src2, + // Swap operands to invert CC == 1 vs. CC == 2 cases. + SDValue Unused = DAG.getNode(SystemZISD::STRCMP, DL, VTs, Chain, Src2, Src1, DAG.getConstant(0, DL, MVT::i32)); SDValue CCReg = Unused.getValue(1); Chain = Unused.getValue(2); diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp index 50143fb0ece36..7caeebb1a9aad 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -113,8 +113,15 @@ void WebAssemblyTargetAsmStreamer::emitEventType(const MCSymbolWasm *Sym) { } void WebAssemblyTargetAsmStreamer::emitImportModule(const MCSymbolWasm *Sym, - StringRef ModuleName) { - OS << "\t.import_module\t" << Sym->getName() << ", " << ModuleName << '\n'; + StringRef ImportModule) { + OS << "\t.import_module\t" << Sym->getName() << ", " + << ImportModule << '\n'; +} + +void WebAssemblyTargetAsmStreamer::emitImportName(const MCSymbolWasm *Sym, + StringRef ImportName) { + OS << "\t.import_name\t" << Sym->getName() << ", " + << ImportName << '\n'; } void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) { diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h index 3073938118b45..2ee9956c8e384 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h @@ -45,7 +45,10 @@ class WebAssemblyTargetStreamer : public MCTargetStreamer { virtual void emitEventType(const MCSymbolWasm *Sym) = 0; /// .import_module virtual void emitImportModule(const MCSymbolWasm *Sym, - StringRef ModuleName) = 0; + StringRef ImportModule) = 0; + /// .import_name + virtual void emitImportName(const MCSymbolWasm *Sym, + StringRef ImportName) = 0; protected: void emitValueType(wasm::ValType Type); @@ -67,7 +70,8 @@ class WebAssemblyTargetAsmStreamer final : public WebAssemblyTargetStreamer { void emitIndIdx(const MCExpr *Value) override; void emitGlobalType(const MCSymbolWasm *Sym) override; void emitEventType(const MCSymbolWasm *Sym) override; - void emitImportModule(const MCSymbolWasm *Sym, StringRef ModuleName) override; + void emitImportModule(const MCSymbolWasm *Sym, StringRef ImportModule) override; + void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName) override; }; /// This part is for Wasm object output @@ -82,7 +86,9 @@ class WebAssemblyTargetWasmStreamer final : public WebAssemblyTargetStreamer { void emitGlobalType(const MCSymbolWasm *Sym) override {} void emitEventType(const MCSymbolWasm *Sym) override {} void emitImportModule(const MCSymbolWasm *Sym, - StringRef ModuleName) override {} + StringRef ImportModule) override {} + void emitImportName(const MCSymbolWasm *Sym, + StringRef ImportName) override {} }; /// This part is for null output @@ -98,6 +104,7 @@ class WebAssemblyTargetNullStreamer final : public WebAssemblyTargetStreamer { void emitGlobalType(const MCSymbolWasm *) override {} void emitEventType(const MCSymbolWasm *) override {} void emitImportModule(const MCSymbolWasm *, StringRef) override {} + void emitImportName(const MCSymbolWasm *, StringRef) override {} }; } // end namespace llvm diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index c4f03dfa7f9e4..b492d11469507 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -111,9 +111,16 @@ void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) { F.hasFnAttribute("wasm-import-module")) { StringRef Name = F.getFnAttribute("wasm-import-module").getValueAsString(); - Sym->setModuleName(Name); + Sym->setImportModule(Name); getTargetStreamer()->emitImportModule(Sym, Name); } + if (TM.getTargetTriple().isOSBinFormatWasm() && + F.hasFnAttribute("wasm-import-name")) { + StringRef Name = + F.getFnAttribute("wasm-import-name").getValueAsString(); + Sym->setImportName(Name); + getTargetStreamer()->emitImportName(Sym, Name); + } } } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp index 1a416520f97d0..13f37f611ed05 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp @@ -36,11 +36,6 @@ using namespace llvm; #define DEBUG_TYPE "wasm-fix-function-bitcasts" -static cl::opt - TemporaryWorkarounds("wasm-temporary-workarounds", - cl::desc("Apply certain temporary workarounds"), - cl::init(true), cl::Hidden); - namespace { class FixFunctionBitcasts final : public ModulePass { StringRef getPassName() const override { @@ -227,6 +222,17 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) { return Wrapper; } +// Test whether a main function with type FuncTy should be rewritten to have +// type MainTy. +bool shouldFixMainFunction(FunctionType *FuncTy, FunctionType *MainTy) { + // Only fix the main function if it's the standard zero-arg form. That way, + // the standard cases will work as expected, and users will see signature + // mismatches from the linker for non-standard cases. + return FuncTy->getReturnType() == MainTy->getReturnType() && + FuncTy->getNumParams() == 0 && + !FuncTy->isVarArg(); +} + bool FixFunctionBitcasts::runOnModule(Module &M) { LLVM_DEBUG(dbgs() << "********** Fix Function Bitcasts **********\n"); @@ -243,14 +249,14 @@ bool FixFunctionBitcasts::runOnModule(Module &M) { // "int main(int argc, char *argv[])", create an artificial call with it // bitcasted to that type so that we generate a wrapper for it, so that // the C runtime can call it. - if (!TemporaryWorkarounds && !F.isDeclaration() && F.getName() == "main") { + if (F.getName() == "main") { Main = &F; LLVMContext &C = M.getContext(); Type *MainArgTys[] = {Type::getInt32Ty(C), PointerType::get(Type::getInt8PtrTy(C), 0)}; FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(C), MainArgTys, /*isVarArg=*/false); - if (F.getFunctionType() != MainTy) { + if (shouldFixMainFunction(F.getFunctionType(), MainTy)) { LLVM_DEBUG(dbgs() << "Found `main` function with incorrect type: " << *F.getFunctionType() << "\n"); Value *Args[] = {UndefValue::get(MainArgTys[0]), @@ -298,12 +304,18 @@ bool FixFunctionBitcasts::runOnModule(Module &M) { Main->setName("__original_main"); Function *MainWrapper = cast(CallMain->getCalledValue()->stripPointerCasts()); - MainWrapper->setName("main"); - MainWrapper->setLinkage(Main->getLinkage()); - MainWrapper->setVisibility(Main->getVisibility()); - Main->setLinkage(Function::PrivateLinkage); - Main->setVisibility(Function::DefaultVisibility); delete CallMain; + if (Main->isDeclaration()) { + // The wrapper is not needed in this case as we don't need to export + // it to anyone else. + MainWrapper->eraseFromParent(); + } else { + // Otherwise give the wrapper the same linkage as the original main + // function, so that it can be called from the same places. + MainWrapper->setName("main"); + MainWrapper->setLinkage(Main->getLinkage()); + MainWrapper->setVisibility(Main->getVisibility()); + } } return true; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 003848e342279..f7f29d85cbb27 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -669,13 +669,16 @@ WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI, if (IsVarArg) { // Outgoing non-fixed arguments are placed in a buffer. First // compute their offsets and the total amount of buffer space needed. - for (SDValue Arg : - make_range(OutVals.begin() + NumFixedArgs, OutVals.end())) { + for (unsigned I = NumFixedArgs; I < Outs.size(); ++I) { + const ISD::OutputArg &Out = Outs[I]; + SDValue &Arg = OutVals[I]; EVT VT = Arg.getValueType(); assert(VT != MVT::iPTR && "Legalized args should be concrete"); Type *Ty = VT.getTypeForEVT(*DAG.getContext()); + unsigned Align = std::max(Out.Flags.getOrigAlign(), + Layout.getABITypeAlignment(Ty)); unsigned Offset = CCInfo.AllocateStack(Layout.getTypeAllocSize(Ty), - Layout.getABITypeAlignment(Ty)); + Align); CCInfo.addLoc(CCValAssign::getMem(ArgLocs.size(), VT.getSimpleVT(), Offset, VT.getSimpleVT(), CCValAssign::Full)); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td index d5b63d6436973..bd41f46214a35 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td @@ -122,10 +122,3 @@ def : Pat<(select (i32 (seteq I32:$cond, 0)), I32:$lhs, I32:$rhs), (SELECT_I32 I32:$rhs, I32:$lhs, I32:$cond)>; def : Pat<(select (i32 (seteq I32:$cond, 0)), I64:$lhs, I64:$rhs), (SELECT_I64 I64:$rhs, I64:$lhs, I32:$cond)>; - -// The legalizer inserts an unnecessary `and 1` to make input conform -// to getBooleanContents, which we can lower away. -def : Pat<(select (i32 (and I32:$cond, 1)), I32:$lhs, I32:$rhs), - (SELECT_I32 I32:$lhs, I32:$rhs, I32:$cond)>; -def : Pat<(select (i32 (and I32:$cond, 1)), I64:$lhs, I64:$rhs), - (SELECT_I64 I64:$lhs, I64:$rhs, I32:$cond)>; diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index 899b50d0f78f3..81391b96d1267 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -1115,8 +1115,7 @@ bool X86AsmParser::ParseRegister(unsigned &RegNo, } // Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens. - if (RegNo == 0 && (Tok.getString() == "st" || Tok.getString() == "ST")) { - RegNo = X86::ST0; + if (RegNo == X86::ST0) { Parser.Lex(); // Eat 'st' // Check to see if we have '(4)' after %st. diff --git a/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp b/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp index 0e861d5ddbc9d..3a074818c762b 100644 --- a/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp +++ b/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp @@ -200,3 +200,14 @@ void X86ATTInstPrinter::printU8Imm(const MCInst *MI, unsigned Op, O << markup("getOperand(Op).getImm() & 0xff) << markup(">"); } + +void X86ATTInstPrinter::printSTiRegOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &OS) { + const MCOperand &Op = MI->getOperand(OpNo); + unsigned Reg = Op.getReg(); + // Override the default printing to print st(0) instead st. + if (Reg == X86::ST0) + OS << markup(""); + else + printRegName(OS, Reg); +} diff --git a/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h b/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h index 57422bc9a0b2a..584dc9c286e60 100644 --- a/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h +++ b/llvm/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h @@ -44,6 +44,7 @@ class X86ATTInstPrinter final : public X86InstPrinterCommon { void printSrcIdx(const MCInst *MI, unsigned Op, raw_ostream &O); void printDstIdx(const MCInst *MI, unsigned Op, raw_ostream &O); void printU8Imm(const MCInst *MI, unsigned Op, raw_ostream &OS); + void printSTiRegOperand(const MCInst *MI, unsigned OpNo, raw_ostream &OS); void printanymem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { printMemReference(MI, OpNo, O); diff --git a/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp b/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp index 044b715641520..b31f8ab80838d 100644 --- a/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp +++ b/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp @@ -160,3 +160,14 @@ void X86IntelInstPrinter::printU8Imm(const MCInst *MI, unsigned Op, O << formatImm(MI->getOperand(Op).getImm() & 0xff); } + +void X86IntelInstPrinter::printSTiRegOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &OS) { + const MCOperand &Op = MI->getOperand(OpNo); + unsigned Reg = Op.getReg(); + // Override the default printing to print st(0) instead st. + if (Reg == X86::ST0) + OS << "st(0)"; + else + printRegName(OS, Reg); +} diff --git a/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h b/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h index 3b34a8052becb..fe52bd482a262 100644 --- a/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h +++ b/llvm/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h @@ -39,6 +39,7 @@ class X86IntelInstPrinter final : public X86InstPrinterCommon { void printSrcIdx(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printDstIdx(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printU8Imm(const MCInst *MI, unsigned Op, raw_ostream &O); + void printSTiRegOperand(const MCInst *MI, unsigned OpNo, raw_ostream &OS); void printanymem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { printMemReference(MI, OpNo, O); diff --git a/llvm/lib/Target/X86/X86DiscriminateMemOps.cpp b/llvm/lib/Target/X86/X86DiscriminateMemOps.cpp index 3654bf04f4e98..6bee20b617dde 100644 --- a/llvm/lib/Target/X86/X86DiscriminateMemOps.cpp +++ b/llvm/lib/Target/X86/X86DiscriminateMemOps.cpp @@ -27,6 +27,14 @@ using namespace llvm; #define DEBUG_TYPE "x86-discriminate-memops" +static cl::opt EnableDiscriminateMemops( + DEBUG_TYPE, cl::init(false), + cl::desc("Generate unique debug info for each instruction with a memory " + "operand. Should be enabled for profile-drived cache prefetching, " + "both in the build of the binary being profiled, as well as in " + "the build of the binary consuming the profile."), + cl::Hidden); + namespace { using Location = std::pair; @@ -67,6 +75,9 @@ char X86DiscriminateMemOps::ID = 0; X86DiscriminateMemOps::X86DiscriminateMemOps() : MachineFunctionPass(ID) {} bool X86DiscriminateMemOps::runOnMachineFunction(MachineFunction &MF) { + if (!EnableDiscriminateMemops) + return false; + DISubprogram *FDI = MF.getFunction().getSubprogram(); if (!FDI || !FDI->getUnit()->getDebugInfoForProfiling()) return false; diff --git a/llvm/lib/Target/X86/X86FastISel.cpp b/llvm/lib/Target/X86/X86FastISel.cpp index 9dd3f2652543a..12cd613c34cbe 100644 --- a/llvm/lib/Target/X86/X86FastISel.cpp +++ b/llvm/lib/Target/X86/X86FastISel.cpp @@ -399,7 +399,7 @@ bool X86FastISel::X86FastEmitLoad(EVT VT, X86AddressMode &AM, case MVT::v2i64: case MVT::v8i16: case MVT::v16i8: - if (IsNonTemporal && Alignment >= 16) + if (IsNonTemporal && Alignment >= 16 && HasSSE41) Opc = HasVLX ? X86::VMOVNTDQAZ128rm : HasAVX ? X86::VMOVNTDQArm : X86::MOVNTDQArm; else if (Alignment >= 16) diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index 5ac153244df92..fe75dbd8eff4e 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -1138,15 +1138,23 @@ bool X86DAGToDAGISel::matchWrapper(SDValue N, X86ISelAddressMode &AM) { if (AM.hasSymbolicDisplacement()) return true; + bool IsRIPRelTLS = false; bool IsRIPRel = N.getOpcode() == X86ISD::WrapperRIP; + if (IsRIPRel) { + SDValue Val = N.getOperand(0); + if (Val.getOpcode() == ISD::TargetGlobalTLSAddress) + IsRIPRelTLS = true; + } - // We can't use an addressing mode in the 64-bit large code model. In the - // medium code model, we use can use an mode when RIP wrappers are present. - // That signifies access to globals that are known to be "near", such as the - // GOT itself. + // We can't use an addressing mode in the 64-bit large code model. + // Global TLS addressing is an exception. In the medium code model, + // we use can use a mode when RIP wrappers are present. + // That signifies access to globals that are known to be "near", + // such as the GOT itself. CodeModel::Model M = TM.getCodeModel(); if (Subtarget->is64Bit() && - (M == CodeModel::Large || (M == CodeModel::Medium && !IsRIPRel))) + ((M == CodeModel::Large && !IsRIPRelTLS) || + (M == CodeModel::Medium && !IsRIPRel))) return true; // Base and index reg must be 0 in order to use %rip as base. diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index b6a692ee187d8..2dfee3a4701e6 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -13884,7 +13884,6 @@ static SDValue lowerVectorShuffleAsLanePermuteAndPermute( int NumEltsPerLane = NumElts / NumLanes; SmallVector SrcLaneMask(NumLanes, SM_SentinelUndef); - SmallVector LaneMask(NumElts, SM_SentinelUndef); SmallVector PermMask(NumElts, SM_SentinelUndef); for (int i = 0; i != NumElts; ++i) { @@ -13899,10 +13898,20 @@ static SDValue lowerVectorShuffleAsLanePermuteAndPermute( return SDValue(); SrcLaneMask[DstLane] = SrcLane; - LaneMask[i] = (SrcLane * NumEltsPerLane) + (i % NumEltsPerLane); PermMask[i] = (DstLane * NumEltsPerLane) + (M % NumEltsPerLane); } + // Make sure we set all elements of the lane mask, to avoid undef propagation. + SmallVector LaneMask(NumElts, SM_SentinelUndef); + for (int DstLane = 0; DstLane != NumLanes; ++DstLane) { + int SrcLane = SrcLaneMask[DstLane]; + if (0 <= SrcLane) + for (int j = 0; j != NumEltsPerLane; ++j) { + LaneMask[(DstLane * NumEltsPerLane) + j] = + (SrcLane * NumEltsPerLane) + j; + } + } + // If we're only shuffling a single lowest lane and the rest are identity // then don't bother. // TODO - isShuffleMaskInputInPlace could be extended to something like this. @@ -27202,6 +27211,8 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::VSHLI: return "X86ISD::VSHLI"; case X86ISD::VSRLI: return "X86ISD::VSRLI"; case X86ISD::VSRAI: return "X86ISD::VSRAI"; + case X86ISD::VSHLV: return "X86ISD::VSHLV"; + case X86ISD::VSRLV: return "X86ISD::VSRLV"; case X86ISD::VSRAV: return "X86ISD::VSRAV"; case X86ISD::VROTLI: return "X86ISD::VROTLI"; case X86ISD::VROTRI: return "X86ISD::VROTRI"; @@ -38123,8 +38134,11 @@ static SDValue combineTruncatedArithmetic(SDNode *N, SelectionDAG &DAG, return true; // See if this is a single use constant which can be constant folded. - SDValue BC = peekThroughOneUseBitcasts(Op); - return ISD::isBuildVectorOfConstantSDNodes(BC.getNode()); + // NOTE: We don't peek throught bitcasts here because there is currently + // no support for constant folding truncate+bitcast+vector_of_constants. So + // we'll just send up with a truncate on both operands which will + // get turned back into (truncate (binop)) causing an infinite loop. + return ISD::isBuildVectorOfConstantSDNodes(Op.getNode()); }; auto TruncateArithmetic = [&](SDValue N0, SDValue N1) { @@ -42505,6 +42519,14 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, if (StringRef("{flags}").equals_lower(Constraint)) return std::make_pair(X86::EFLAGS, &X86::CCRRegClass); + // dirflag -> DF + if (StringRef("{dirflag}").equals_lower(Constraint)) + return std::make_pair(X86::DF, &X86::DFCCRRegClass); + + // fpsr -> FPSW + if (StringRef("{fpsr}").equals_lower(Constraint)) + return std::make_pair(X86::FPSW, &X86::FPCCRRegClass); + // 'A' means [ER]AX + [ER]DX. if (Constraint == "A") { if (Subtarget.is64Bit()) diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h index 910acd80e8b8c..66d5d43946a26 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.h +++ b/llvm/lib/Target/X86/X86ISelLowering.h @@ -315,10 +315,8 @@ namespace llvm { // Vector shift elements VSHL, VSRL, VSRA, - // Vector variable shift right arithmetic. - // Unlike ISD::SRA, in case shift count greater then element size - // use sign bit to fill destination data element. - VSRAV, + // Vector variable shift + VSHLV, VSRLV, VSRAV, // Vector shift elements by immediate VSHLI, VSRLI, VSRAI, diff --git a/llvm/lib/Target/X86/X86InsertPrefetch.cpp b/llvm/lib/Target/X86/X86InsertPrefetch.cpp index 30b46a09ef0f9..8bd57aa2278ba 100644 --- a/llvm/lib/Target/X86/X86InsertPrefetch.cpp +++ b/llvm/lib/Target/X86/X86InsertPrefetch.cpp @@ -34,7 +34,8 @@ using namespace sampleprof; static cl::opt PrefetchHintsFile("prefetch-hints-file", - cl::desc("Path to the prefetch hints profile."), + cl::desc("Path to the prefetch hints profile. See also " + "-x86-discriminate-memops"), cl::Hidden); namespace { diff --git a/llvm/lib/Target/X86/X86InstrAVX512.td b/llvm/lib/Target/X86/X86InstrAVX512.td index 7423cb85acd25..85676f102be0a 100644 --- a/llvm/lib/Target/X86/X86InstrAVX512.td +++ b/llvm/lib/Target/X86/X86InstrAVX512.td @@ -6445,52 +6445,53 @@ defm : avx512_var_shift_lowering; // Special handing for handling VPSRAV intrinsics. -multiclass avx512_var_shift_int_lowering p> { +multiclass avx512_var_shift_int_lowering p> { let Predicates = p in { - def : Pat<(_.VT (X86vsrav _.RC:$src1, _.RC:$src2)), + def : Pat<(_.VT (OpNode _.RC:$src1, _.RC:$src2)), (!cast(InstrStr#_.ZSuffix#rr) _.RC:$src1, _.RC:$src2)>; - def : Pat<(_.VT (X86vsrav _.RC:$src1, (_.LdFrag addr:$src2))), + def : Pat<(_.VT (OpNode _.RC:$src1, (_.LdFrag addr:$src2))), (!cast(InstrStr#_.ZSuffix##rm) _.RC:$src1, addr:$src2)>; def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, _.RC:$src2), _.RC:$src0)), + (OpNode _.RC:$src1, _.RC:$src2), _.RC:$src0)), (!cast(InstrStr#_.ZSuffix#rrk) _.RC:$src0, _.KRC:$mask, _.RC:$src1, _.RC:$src2)>; def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, (_.LdFrag addr:$src2)), + (OpNode _.RC:$src1, (_.LdFrag addr:$src2)), _.RC:$src0)), (!cast(InstrStr#_.ZSuffix##rmk) _.RC:$src0, _.KRC:$mask, _.RC:$src1, addr:$src2)>; def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, _.RC:$src2), _.ImmAllZerosV)), + (OpNode _.RC:$src1, _.RC:$src2), _.ImmAllZerosV)), (!cast(InstrStr#_.ZSuffix#rrkz) _.KRC:$mask, _.RC:$src1, _.RC:$src2)>; def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, (_.LdFrag addr:$src2)), + (OpNode _.RC:$src1, (_.LdFrag addr:$src2)), _.ImmAllZerosV)), (!cast(InstrStr#_.ZSuffix##rmkz) _.KRC:$mask, _.RC:$src1, addr:$src2)>; } } -multiclass avx512_var_shift_int_lowering_mb p> : - avx512_var_shift_int_lowering { +multiclass avx512_var_shift_int_lowering_mb p> : + avx512_var_shift_int_lowering { let Predicates = p in { - def : Pat<(_.VT (X86vsrav _.RC:$src1, + def : Pat<(_.VT (OpNode _.RC:$src1, (X86VBroadcast (_.ScalarLdFrag addr:$src2)))), (!cast(InstrStr#_.ZSuffix##rmb) _.RC:$src1, addr:$src2)>; def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, + (OpNode _.RC:$src1, (X86VBroadcast (_.ScalarLdFrag addr:$src2))), _.RC:$src0)), (!cast(InstrStr#_.ZSuffix##rmbk) _.RC:$src0, _.KRC:$mask, _.RC:$src1, addr:$src2)>; def : Pat<(_.VT (vselect _.KRCWM:$mask, - (X86vsrav _.RC:$src1, + (OpNode _.RC:$src1, (X86VBroadcast (_.ScalarLdFrag addr:$src2))), _.ImmAllZerosV)), (!cast(InstrStr#_.ZSuffix##rmbkz) _.KRC:$mask, @@ -6498,15 +6499,47 @@ multiclass avx512_var_shift_int_lowering_mb; -defm : avx512_var_shift_int_lowering<"VPSRAVW", v16i16x_info, [HasVLX, HasBWI]>; -defm : avx512_var_shift_int_lowering<"VPSRAVW", v32i16_info, [HasBWI]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVD", v4i32x_info, [HasVLX]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVD", v8i32x_info, [HasVLX]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVD", v16i32_info, [HasAVX512]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVQ", v2i64x_info, [HasVLX]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVQ", v4i64x_info, [HasVLX]>; -defm : avx512_var_shift_int_lowering_mb<"VPSRAVQ", v8i64_info, [HasAVX512]>; +multiclass avx512_var_shift_int_lowering_vl { + defm : avx512_var_shift_int_lowering; + defm : avx512_var_shift_int_lowering; + defm : avx512_var_shift_int_lowering; +} + +multiclass avx512_var_shift_int_lowering_mb_vl { + defm : avx512_var_shift_int_lowering_mb; + defm : avx512_var_shift_int_lowering_mb; + defm : avx512_var_shift_int_lowering_mb; +} + +defm : avx512_var_shift_int_lowering_vl<"VPSRAVW", X86vsrav, avx512vl_i16_info, + HasBWI>; +defm : avx512_var_shift_int_lowering_mb_vl<"VPSRAVD", X86vsrav, + avx512vl_i32_info, HasAVX512>; +defm : avx512_var_shift_int_lowering_mb_vl<"VPSRAVQ", X86vsrav, + avx512vl_i64_info, HasAVX512>; + +defm : avx512_var_shift_int_lowering_vl<"VPSRLVW", X86vsrlv, avx512vl_i16_info, + HasBWI>; +defm : avx512_var_shift_int_lowering_mb_vl<"VPSRLVD", X86vsrlv, + avx512vl_i32_info, HasAVX512>; +defm : avx512_var_shift_int_lowering_mb_vl<"VPSRLVQ", X86vsrlv, + avx512vl_i64_info, HasAVX512>; + +defm : avx512_var_shift_int_lowering_vl<"VPSLLVW", X86vshlv, avx512vl_i16_info, + HasBWI>; +defm : avx512_var_shift_int_lowering_mb_vl<"VPSLLVD", X86vshlv, + avx512vl_i32_info, HasAVX512>; +defm : avx512_var_shift_int_lowering_mb_vl<"VPSLLVQ", X86vshlv, + avx512vl_i64_info, HasAVX512>; + // Use 512bit VPROL/VPROLI version to implement v2i64/v4i64 + v4i32/v8i32 in case NoVLX. let Predicates = [HasAVX512, NoVLX] in { diff --git a/llvm/lib/Target/X86/X86InstrFPStack.td b/llvm/lib/Target/X86/X86InstrFPStack.td index 5912a31996131..8e12efff77eab 100644 --- a/llvm/lib/Target/X86/X86InstrFPStack.td +++ b/llvm/lib/Target/X86/X86InstrFPStack.td @@ -230,7 +230,7 @@ def _FI32m : FPI<0xDA, fp, (outs), (ins i32mem:$src), } // mayLoad = 1, hasSideEffects = 1 } -let Defs = [FPSW] in { +let Defs = [FPSW], Uses = [FPCW] in { // FPBinary_rr just defines pseudo-instructions, no need to set a scheduling // resources. let hasNoSchedulingInfo = 1 in { @@ -258,42 +258,42 @@ defm DIVR: FPBinary; } // Defs = [FPSW] class FPST0rInst - : FPI<0xD8, fp, (outs), (ins RST:$op), asm>; + : FPI<0xD8, fp, (outs), (ins RSTi:$op), asm>; class FPrST0Inst - : FPI<0xDC, fp, (outs), (ins RST:$op), asm>; + : FPI<0xDC, fp, (outs), (ins RSTi:$op), asm>; class FPrST0PInst - : FPI<0xDE, fp, (outs), (ins RST:$op), asm>; + : FPI<0xDE, fp, (outs), (ins RSTi:$op), asm>; // NOTE: GAS and apparently all other AT&T style assemblers have a broken notion // of some of the 'reverse' forms of the fsub and fdiv instructions. As such, // we have to put some 'r's in and take them out of weird places. -let SchedRW = [WriteFAdd] in { -def ADD_FST0r : FPST0rInst ; -def ADD_FrST0 : FPrST0Inst ; -def ADD_FPrST0 : FPrST0PInst; -def SUBR_FST0r : FPST0rInst ; -def SUB_FrST0 : FPrST0Inst ; -def SUB_FPrST0 : FPrST0PInst; -def SUB_FST0r : FPST0rInst ; -def SUBR_FrST0 : FPrST0Inst ; -def SUBR_FPrST0 : FPrST0PInst; +let SchedRW = [WriteFAdd], Defs = [FPSW], Uses = [FPCW] in { +def ADD_FST0r : FPST0rInst ; +def ADD_FrST0 : FPrST0Inst ; +def ADD_FPrST0 : FPrST0PInst; +def SUBR_FST0r : FPST0rInst ; +def SUB_FrST0 : FPrST0Inst ; +def SUB_FPrST0 : FPrST0PInst; +def SUB_FST0r : FPST0rInst ; +def SUBR_FrST0 : FPrST0Inst ; +def SUBR_FPrST0 : FPrST0PInst; } // SchedRW -let SchedRW = [WriteFCom] in { +let SchedRW = [WriteFCom], Defs = [FPSW], Uses = [FPCW] in { def COM_FST0r : FPST0rInst ; def COMP_FST0r : FPST0rInst ; } // SchedRW -let SchedRW = [WriteFMul] in { -def MUL_FST0r : FPST0rInst ; -def MUL_FrST0 : FPrST0Inst ; -def MUL_FPrST0 : FPrST0PInst; +let SchedRW = [WriteFMul], Defs = [FPSW], Uses = [FPCW] in { +def MUL_FST0r : FPST0rInst ; +def MUL_FrST0 : FPrST0Inst ; +def MUL_FPrST0 : FPrST0PInst; } // SchedRW -let SchedRW = [WriteFDiv] in { -def DIVR_FST0r : FPST0rInst ; -def DIV_FrST0 : FPrST0Inst ; -def DIV_FPrST0 : FPrST0PInst; -def DIV_FST0r : FPST0rInst ; -def DIVR_FrST0 : FPrST0Inst ; -def DIVR_FPrST0 : FPrST0PInst; +let SchedRW = [WriteFDiv], Defs = [FPSW], Uses = [FPCW] in { +def DIVR_FST0r : FPST0rInst ; +def DIV_FrST0 : FPrST0Inst ; +def DIV_FPrST0 : FPrST0PInst; +def DIV_FST0r : FPST0rInst ; +def DIVR_FrST0 : FPrST0Inst ; +def DIVR_FPrST0 : FPrST0PInst; } // SchedRW // Unary operations. @@ -307,7 +307,7 @@ def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src), OneArgFPRW, def _F : FPI<0xD9, fp, (outs), (ins), asmstring>; } -let Defs = [FPSW] in { +let Defs = [FPSW], Uses = [FPCW] in { let SchedRW = [WriteFSign] in { defm CHS : FPUnary; @@ -335,7 +335,7 @@ def TST_F : FPI<0xD9, MRM_E4, (outs), (ins), "ftst">; // Versions of FP instructions that take a single memory operand. Added for the // disassembler; remove as they are included with patterns elsewhere. -let SchedRW = [WriteFComLd] in { +let SchedRW = [WriteFComLd], Defs = [FPSW], Uses = [FPCW] in { def FCOM32m : FPI<0xD8, MRM2m, (outs), (ins f32mem:$src), "fcom{s}\t$src">; def FCOMP32m : FPI<0xD8, MRM3m, (outs), (ins f32mem:$src), "fcomp{s}\t$src">; @@ -398,22 +398,22 @@ defm CMOVNP : FPCMov; let Predicates = [HasCMov] in { // These are not factored because there's no clean way to pass DA/DB. -def CMOVB_F : FPI<0xDA, MRM0r, (outs), (ins RST:$op), - "fcmovb\t{$op, %st(0)|st(0), $op}">; -def CMOVBE_F : FPI<0xDA, MRM2r, (outs), (ins RST:$op), - "fcmovbe\t{$op, %st(0)|st(0), $op}">; -def CMOVE_F : FPI<0xDA, MRM1r, (outs), (ins RST:$op), - "fcmove\t{$op, %st(0)|st(0), $op}">; -def CMOVP_F : FPI<0xDA, MRM3r, (outs), (ins RST:$op), - "fcmovu\t{$op, %st(0)|st(0), $op}">; -def CMOVNB_F : FPI<0xDB, MRM0r, (outs), (ins RST:$op), - "fcmovnb\t{$op, %st(0)|st(0), $op}">; -def CMOVNBE_F: FPI<0xDB, MRM2r, (outs), (ins RST:$op), - "fcmovnbe\t{$op, %st(0)|st(0), $op}">; -def CMOVNE_F : FPI<0xDB, MRM1r, (outs), (ins RST:$op), - "fcmovne\t{$op, %st(0)|st(0), $op}">; -def CMOVNP_F : FPI<0xDB, MRM3r, (outs), (ins RST:$op), - "fcmovnu\t{$op, %st(0)|st(0), $op}">; +def CMOVB_F : FPI<0xDA, MRM0r, (outs), (ins RSTi:$op), + "fcmovb\t{$op, %st|st, $op}">; +def CMOVBE_F : FPI<0xDA, MRM2r, (outs), (ins RSTi:$op), + "fcmovbe\t{$op, %st|st, $op}">; +def CMOVE_F : FPI<0xDA, MRM1r, (outs), (ins RSTi:$op), + "fcmove\t{$op, %st|st, $op}">; +def CMOVP_F : FPI<0xDA, MRM3r, (outs), (ins RSTi:$op), + "fcmovu\t{$op, %st|st, $op}">; +def CMOVNB_F : FPI<0xDB, MRM0r, (outs), (ins RSTi:$op), + "fcmovnb\t{$op, %st|st, $op}">; +def CMOVNBE_F: FPI<0xDB, MRM2r, (outs), (ins RSTi:$op), + "fcmovnbe\t{$op, %st|st, $op}">; +def CMOVNE_F : FPI<0xDB, MRM1r, (outs), (ins RSTi:$op), + "fcmovne\t{$op, %st|st, $op}">; +def CMOVNP_F : FPI<0xDB, MRM3r, (outs), (ins RSTi:$op), + "fcmovnu\t{$op, %st|st, $op}">; } // Predicates = [HasCMov] } // SchedRW @@ -454,7 +454,7 @@ def ILD_Fp64m80: FpI_<(outs RFP80:$dst), (ins i64mem:$src), ZeroArgFP, [(set RFP80:$dst, (X86fild addr:$src, i64))]>; } // SchedRW -let SchedRW = [WriteStore] in { +let SchedRW = [WriteStore], Uses = [FPCW] in { def ST_Fp32m : FpIf32<(outs), (ins f32mem:$op, RFP32:$src), OneArgFP, [(store RFP32:$src, addr:$op)]>; def ST_Fp64m32 : FpIf64<(outs), (ins f32mem:$op, RFP64:$src), OneArgFP, @@ -489,7 +489,7 @@ def IST_Fp16m80 : FpI_<(outs), (ins i16mem:$op, RFP80:$src), OneArgFP, []>; def IST_Fp32m80 : FpI_<(outs), (ins i32mem:$op, RFP80:$src), OneArgFP, []>; def IST_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, []>; } // mayStore -} // SchedRW +} // SchedRW, Uses = [FPCW] let mayLoad = 1, SchedRW = [WriteLoad] in { def LD_F32m : FPI<0xD9, MRM0m, (outs), (ins f32mem:$src), "fld{s}\t$src">; @@ -499,7 +499,7 @@ def ILD_F16m : FPI<0xDF, MRM0m, (outs), (ins i16mem:$src), "fild{s}\t$src">; def ILD_F32m : FPI<0xDB, MRM0m, (outs), (ins i32mem:$src), "fild{l}\t$src">; def ILD_F64m : FPI<0xDF, MRM5m, (outs), (ins i64mem:$src), "fild{ll}\t$src">; } -let mayStore = 1, SchedRW = [WriteStore] in { +let mayStore = 1, SchedRW = [WriteStore], Uses = [FPCW] in { def ST_F32m : FPI<0xD9, MRM2m, (outs), (ins f32mem:$dst), "fst{s}\t$dst">; def ST_F64m : FPI<0xDD, MRM2m, (outs), (ins f64mem:$dst), "fst{l}\t$dst">; def ST_FP32m : FPI<0xD9, MRM3m, (outs), (ins f32mem:$dst), "fstp{s}\t$dst">; @@ -513,7 +513,7 @@ def IST_FP64m : FPI<0xDF, MRM7m, (outs), (ins i64mem:$dst), "fistp{ll}\t$dst">; } // FISTTP requires SSE3 even though it's a FPStack op. -let Predicates = [HasSSE3], SchedRW = [WriteStore] in { +let Predicates = [HasSSE3], SchedRW = [WriteStore], Uses = [FPCW] in { def ISTT_Fp16m32 : FpI_<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, [(X86fp_to_i16mem RFP32:$src, addr:$op)]>; def ISTT_Fp32m32 : FpI_<(outs), (ins i32mem:$op, RFP32:$src), OneArgFP, @@ -534,7 +534,7 @@ def ISTT_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, [(X86fp_to_i64mem RFP80:$src, addr:$op)]>; } // Predicates = [HasSSE3] -let mayStore = 1, SchedRW = [WriteStore] in { +let mayStore = 1, SchedRW = [WriteStore], Uses = [FPCW] in { def ISTT_FP16m : FPI<0xDF, MRM1m, (outs), (ins i16mem:$dst), "fisttp{s}\t$dst">; def ISTT_FP32m : FPI<0xDB, MRM1m, (outs), (ins i32mem:$dst), "fisttp{l}\t$dst">; def ISTT_FP64m : FPI<0xDD, MRM1m, (outs), (ins i64mem:$dst), "fisttp{ll}\t$dst">; @@ -542,10 +542,10 @@ def ISTT_FP64m : FPI<0xDD, MRM1m, (outs), (ins i64mem:$dst), "fisttp{ll}\t$dst"> // FP Stack manipulation instructions. let SchedRW = [WriteMove] in { -def LD_Frr : FPI<0xD9, MRM0r, (outs), (ins RST:$op), "fld\t$op">; -def ST_Frr : FPI<0xDD, MRM2r, (outs), (ins RST:$op), "fst\t$op">; -def ST_FPrr : FPI<0xDD, MRM3r, (outs), (ins RST:$op), "fstp\t$op">; -def XCH_F : FPI<0xD9, MRM1r, (outs), (ins RST:$op), "fxch\t$op">; +def LD_Frr : FPI<0xD9, MRM0r, (outs), (ins RSTi:$op), "fld\t$op">; +def ST_Frr : FPI<0xDD, MRM2r, (outs), (ins RSTi:$op), "fst\t$op">; +def ST_FPrr : FPI<0xDD, MRM3r, (outs), (ins RSTi:$op), "fstp\t$op">; +def XCH_F : FPI<0xD9, MRM1r, (outs), (ins RSTi:$op), "fxch\t$op">; } // Floating point constant loads. @@ -570,7 +570,7 @@ def LD_F0 : FPI<0xD9, MRM_EE, (outs), (ins), "fldz">; let SchedRW = [WriteFLD1] in def LD_F1 : FPI<0xD9, MRM_E8, (outs), (ins), "fld1">; -let SchedRW = [WriteFLDC], Defs = [FPSW] in { +let SchedRW = [WriteFLDC] in { def FLDL2T : I<0xD9, MRM_E9, (outs), (ins), "fldl2t", []>; def FLDL2E : I<0xD9, MRM_EA, (outs), (ins), "fldl2e", []>; def FLDPI : I<0xD9, MRM_EB, (outs), (ins), "fldpi", []>; @@ -579,7 +579,7 @@ def FLDLN2 : I<0xD9, MRM_ED, (outs), (ins), "fldln2", []>; } // SchedRW // Floating point compares. -let SchedRW = [WriteFCom] in { +let SchedRW = [WriteFCom], Uses = [FPCW] in { def UCOM_Fpr32 : FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, [(set FPSW, (trunc (X86cmp RFP32:$lhs, RFP32:$rhs)))]>; def UCOM_Fpr64 : FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, @@ -591,37 +591,37 @@ def UCOM_Fpr80 : FpI_ <(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, let SchedRW = [WriteFCom] in { // CC = ST(0) cmp ST(i) -let Defs = [EFLAGS, FPSW] in { -let Predicates = [FPStackf32, HasCMov] in -def UCOM_FpIr32: FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, - [(set EFLAGS, (X86cmp RFP32:$lhs, RFP32:$rhs))]>; -let Predicates = [FPStackf64, HasCMov] in -def UCOM_FpIr64: FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, - [(set EFLAGS, (X86cmp RFP64:$lhs, RFP64:$rhs))]>; -let Predicates = [HasCMov] in +let Defs = [EFLAGS, FPSW], Uses = [FPCW] in { +def UCOM_FpIr32: FpI_<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, + [(set EFLAGS, (X86cmp RFP32:$lhs, RFP32:$rhs))]>, + Requires<[FPStackf32, HasCMov]>; +def UCOM_FpIr64: FpI_<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, + [(set EFLAGS, (X86cmp RFP64:$lhs, RFP64:$rhs))]>, + Requires<[FPStackf64, HasCMov]>; def UCOM_FpIr80: FpI_<(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, - [(set EFLAGS, (X86cmp RFP80:$lhs, RFP80:$rhs))]>; + [(set EFLAGS, (X86cmp RFP80:$lhs, RFP80:$rhs))]>, + Requires<[HasCMov]>; } -let Defs = [FPSW], Uses = [ST0] in { +let Defs = [FPSW], Uses = [ST0, FPCW] in { def UCOM_Fr : FPI<0xDD, MRM4r, // FPSW = cmp ST(0) with ST(i) - (outs), (ins RST:$reg), "fucom\t$reg">; + (outs), (ins RSTi:$reg), "fucom\t$reg">; def UCOM_FPr : FPI<0xDD, MRM5r, // FPSW = cmp ST(0) with ST(i), pop - (outs), (ins RST:$reg), "fucomp\t$reg">; + (outs), (ins RSTi:$reg), "fucomp\t$reg">; def UCOM_FPPr : FPI<0xDA, MRM_E9, // cmp ST(0) with ST(1), pop, pop (outs), (ins), "fucompp">; } -let Defs = [EFLAGS, FPSW], Uses = [ST0] in { +let Defs = [EFLAGS, FPSW], Uses = [ST0, FPCW] in { def UCOM_FIr : FPI<0xDB, MRM5r, // CC = cmp ST(0) with ST(i) - (outs), (ins RST:$reg), "fucomi\t$reg">; + (outs), (ins RSTi:$reg), "fucomi\t{$reg, %st|st, $reg}">; def UCOM_FIPr : FPI<0xDF, MRM5r, // CC = cmp ST(0) with ST(i), pop - (outs), (ins RST:$reg), "fucompi\t$reg">; -} + (outs), (ins RSTi:$reg), "fucompi\t{$reg, %st|st, $reg}">; -let Defs = [EFLAGS, FPSW] in { -def COM_FIr : FPI<0xDB, MRM6r, (outs), (ins RST:$reg), "fcomi\t$reg">; -def COM_FIPr : FPI<0xDF, MRM6r, (outs), (ins RST:$reg), "fcompi\t$reg">; +def COM_FIr : FPI<0xDB, MRM6r, (outs), (ins RSTi:$reg), + "fcomi\t{$reg, %st|st, $reg}">; +def COM_FIPr : FPI<0xDF, MRM6r, (outs), (ins RSTi:$reg), + "fcompi\t{$reg, %st|st, $reg}">; } } // SchedRW @@ -631,12 +631,12 @@ let Defs = [AX], Uses = [FPSW] in def FNSTSW16r : I<0xDF, MRM_E0, // AX = fp flags (outs), (ins), "fnstsw\t{%ax|ax}", [(set AX, (X86fp_stsw FPSW))]>; -let Defs = [FPSW] in +let Defs = [FPSW], Uses = [FPCW] in def FNSTCW16m : I<0xD9, MRM7m, // [mem16] = X87 control world (outs), (ins i16mem:$dst), "fnstcw\t$dst", [(X86fp_cwd_get16 addr:$dst)]>; } // SchedRW -let Defs = [FPSW], mayLoad = 1 in +let Defs = [FPSW,FPCW], mayLoad = 1 in def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16] (outs), (ins i16mem:$dst), "fldcw\t$dst", []>, Sched<[WriteLoad]>; @@ -645,8 +645,8 @@ def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16] let SchedRW = [WriteMicrocoded] in { let Defs = [FPSW] in { def FNINIT : I<0xDB, MRM_E3, (outs), (ins), "fninit", []>; -def FFREE : FPI<0xDD, MRM0r, (outs), (ins RST:$reg), "ffree\t$reg">; -def FFREEP : FPI<0xDF, MRM0r, (outs), (ins RST:$reg), "ffreep\t$reg">; +def FFREE : FPI<0xDD, MRM0r, (outs), (ins RSTi:$reg), "ffree\t$reg">; +def FFREEP : FPI<0xDF, MRM0r, (outs), (ins RSTi:$reg), "ffreep\t$reg">; // Clear exceptions def FNCLEX : I<0xDB, MRM_E2, (outs), (ins), "fnclex", []>; diff --git a/llvm/lib/Target/X86/X86InstrFragmentsSIMD.td b/llvm/lib/Target/X86/X86InstrFragmentsSIMD.td index 11a27ba90586b..3d508e2c34f39 100644 --- a/llvm/lib/Target/X86/X86InstrFragmentsSIMD.td +++ b/llvm/lib/Target/X86/X86InstrFragmentsSIMD.td @@ -198,6 +198,8 @@ def X86vsra : SDNode<"X86ISD::VSRA", X86vshiftuniform>; def X86vshiftvariable : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>, SDTCisSameAs<0,2>, SDTCisInt<0>]>; +def X86vshlv : SDNode<"X86ISD::VSHLV", X86vshiftvariable>; +def X86vsrlv : SDNode<"X86ISD::VSRLV", X86vshiftvariable>; def X86vsrav : SDNode<"X86ISD::VSRAV", X86vshiftvariable>; def X86vshli : SDNode<"X86ISD::VSHLI", X86vshiftimm>; diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index e53f83baa3c62..4ec4d566ca998 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -3231,39 +3231,39 @@ def : InstAlias<"fucompi", (UCOM_FIPr ST1), 0>; // instructions like "fadd %st(0), %st(0)" as "fadd %st(0)" for consistency with // gas. multiclass FpUnaryAlias { - def : InstAlias; - def : InstAlias; + def : InstAlias; } -defm : FpUnaryAlias<"fadd", ADD_FST0r>; +defm : FpUnaryAlias<"fadd", ADD_FST0r, 0>; defm : FpUnaryAlias<"faddp", ADD_FPrST0, 0>; -defm : FpUnaryAlias<"fsub", SUB_FST0r>; -defm : FpUnaryAlias<"fsub{|r}p", SUBR_FPrST0>; -defm : FpUnaryAlias<"fsubr", SUBR_FST0r>; -defm : FpUnaryAlias<"fsub{r|}p", SUB_FPrST0>; -defm : FpUnaryAlias<"fmul", MUL_FST0r>; -defm : FpUnaryAlias<"fmulp", MUL_FPrST0>; -defm : FpUnaryAlias<"fdiv", DIV_FST0r>; -defm : FpUnaryAlias<"fdiv{|r}p", DIVR_FPrST0>; -defm : FpUnaryAlias<"fdivr", DIVR_FST0r>; -defm : FpUnaryAlias<"fdiv{r|}p", DIV_FPrST0>; +defm : FpUnaryAlias<"fsub", SUB_FST0r, 0>; +defm : FpUnaryAlias<"fsub{|r}p", SUBR_FPrST0, 0>; +defm : FpUnaryAlias<"fsubr", SUBR_FST0r, 0>; +defm : FpUnaryAlias<"fsub{r|}p", SUB_FPrST0, 0>; +defm : FpUnaryAlias<"fmul", MUL_FST0r, 0>; +defm : FpUnaryAlias<"fmulp", MUL_FPrST0, 0>; +defm : FpUnaryAlias<"fdiv", DIV_FST0r, 0>; +defm : FpUnaryAlias<"fdiv{|r}p", DIVR_FPrST0, 0>; +defm : FpUnaryAlias<"fdivr", DIVR_FST0r, 0>; +defm : FpUnaryAlias<"fdiv{r|}p", DIV_FPrST0, 0>; defm : FpUnaryAlias<"fcomi", COM_FIr, 0>; defm : FpUnaryAlias<"fucomi", UCOM_FIr, 0>; -defm : FpUnaryAlias<"fcompi", COM_FIPr>; -defm : FpUnaryAlias<"fucompi", UCOM_FIPr>; +defm : FpUnaryAlias<"fcompi", COM_FIPr, 0>; +defm : FpUnaryAlias<"fucompi", UCOM_FIPr, 0>; -// Handle "f{mulp,addp} st(0), $op" the same as "f{mulp,addp} $op", since they +// Handle "f{mulp,addp} $op, %st(0)" the same as "f{mulp,addp} $op", since they // commute. We also allow fdiv[r]p/fsubrp even though they don't commute, // solely because gas supports it. -def : InstAlias<"faddp\t{%st(0), $op|$op, st(0)}", (ADD_FPrST0 RST:$op), 0>; -def : InstAlias<"fmulp\t{%st(0), $op|$op, st(0)}", (MUL_FPrST0 RST:$op)>; -def : InstAlias<"fsub{|r}p\t{%st(0), $op|$op, st(0)}", (SUBR_FPrST0 RST:$op)>; -def : InstAlias<"fsub{r|}p\t{%st(0), $op|$op, st(0)}", (SUB_FPrST0 RST:$op)>; -def : InstAlias<"fdiv{|r}p\t{%st(0), $op|$op, st(0)}", (DIVR_FPrST0 RST:$op)>; -def : InstAlias<"fdiv{r|}p\t{%st(0), $op|$op, st(0)}", (DIV_FPrST0 RST:$op)>; +def : InstAlias<"faddp\t{$op, %st|st, $op}", (ADD_FPrST0 RSTi:$op), 0>; +def : InstAlias<"fmulp\t{$op, %st|st, $op}", (MUL_FPrST0 RSTi:$op), 0>; +def : InstAlias<"fsub{|r}p\t{$op, %st|st, $op}", (SUBR_FPrST0 RSTi:$op), 0>; +def : InstAlias<"fsub{r|}p\t{$op, %st|st, $op}", (SUB_FPrST0 RSTi:$op), 0>; +def : InstAlias<"fdiv{|r}p\t{$op, %st|st, $op}", (DIVR_FPrST0 RSTi:$op), 0>; +def : InstAlias<"fdiv{r|}p\t{$op, %st|st, $op}", (DIV_FPrST0 RSTi:$op), 0>; def : InstAlias<"fnstsw" , (FNSTSW16r), 0>; diff --git a/llvm/lib/Target/X86/X86InstrSSE.td b/llvm/lib/Target/X86/X86InstrSSE.td index e2bcd18ce6607..ddfc369b1180e 100644 --- a/llvm/lib/Target/X86/X86InstrSSE.td +++ b/llvm/lib/Target/X86/X86InstrSSE.td @@ -8318,7 +8318,7 @@ def : Pat<(v32i8 (X86SubVBroadcast (v16i8 VR128:$src))), // Variable Bit Shifts // multiclass avx2_var_shift opc, string OpcodeStr, SDNode OpNode, - ValueType vt128, ValueType vt256> { + SDNode IntrinNode, ValueType vt128, ValueType vt256> { def rr : AVX28I opc, string OpcodeStr, SDNode OpNode, (vt256 (load addr:$src2)))))]>, VEX_4V, VEX_L, Sched<[SchedWriteVarVecShift.YMM.Folded, SchedWriteVarVecShift.YMM.ReadAfterFold]>; + + def : Pat<(vt128 (IntrinNode VR128:$src1, VR128:$src2)), + (!cast(NAME#"rr") VR128:$src1, VR128:$src2)>; + def : Pat<(vt128 (IntrinNode VR128:$src1, (load addr:$src2))), + (!cast(NAME#"rm") VR128:$src1, addr:$src2)>; + def : Pat<(vt256 (IntrinNode VR256:$src1, VR256:$src2)), + (!cast(NAME#"Yrr") VR256:$src1, VR256:$src2)>; + def : Pat<(vt256 (IntrinNode VR256:$src1, (load addr:$src2))), + (!cast(NAME#"Yrm") VR256:$src1, addr:$src2)>; } let Predicates = [HasAVX2, NoVLX] in { - defm VPSLLVD : avx2_var_shift<0x47, "vpsllvd", shl, v4i32, v8i32>; - defm VPSLLVQ : avx2_var_shift<0x47, "vpsllvq", shl, v2i64, v4i64>, VEX_W; - defm VPSRLVD : avx2_var_shift<0x45, "vpsrlvd", srl, v4i32, v8i32>; - defm VPSRLVQ : avx2_var_shift<0x45, "vpsrlvq", srl, v2i64, v4i64>, VEX_W; - defm VPSRAVD : avx2_var_shift<0x46, "vpsravd", sra, v4i32, v8i32>; - - def : Pat<(v4i32 (X86vsrav VR128:$src1, VR128:$src2)), - (VPSRAVDrr VR128:$src1, VR128:$src2)>; - def : Pat<(v4i32 (X86vsrav VR128:$src1, (load addr:$src2))), - (VPSRAVDrm VR128:$src1, addr:$src2)>; - def : Pat<(v8i32 (X86vsrav VR256:$src1, VR256:$src2)), - (VPSRAVDYrr VR256:$src1, VR256:$src2)>; - def : Pat<(v8i32 (X86vsrav VR256:$src1, (load addr:$src2))), - (VPSRAVDYrm VR256:$src1, addr:$src2)>; + defm VPSLLVD : avx2_var_shift<0x47, "vpsllvd", shl, X86vshlv, v4i32, v8i32>; + defm VPSLLVQ : avx2_var_shift<0x47, "vpsllvq", shl, X86vshlv, v2i64, v4i64>, VEX_W; + defm VPSRLVD : avx2_var_shift<0x45, "vpsrlvd", srl, X86vsrlv, v4i32, v8i32>; + defm VPSRLVQ : avx2_var_shift<0x45, "vpsrlvq", srl, X86vsrlv, v2i64, v4i64>, VEX_W; + defm VPSRAVD : avx2_var_shift<0x46, "vpsravd", sra, X86vsrav, v4i32, v8i32>; } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/X86/X86IntrinsicsInfo.h b/llvm/lib/Target/X86/X86IntrinsicsInfo.h index 151e1b9136c4a..acb3d48463de6 100644 --- a/llvm/lib/Target/X86/X86IntrinsicsInfo.h +++ b/llvm/lib/Target/X86/X86IntrinsicsInfo.h @@ -389,10 +389,10 @@ static const IntrinsicData IntrinsicsWithoutChain[] = { X86_INTRINSIC_DATA(avx2_pslli_d, VSHIFT, X86ISD::VSHLI, 0), X86_INTRINSIC_DATA(avx2_pslli_q, VSHIFT, X86ISD::VSHLI, 0), X86_INTRINSIC_DATA(avx2_pslli_w, VSHIFT, X86ISD::VSHLI, 0), - X86_INTRINSIC_DATA(avx2_psllv_d, INTR_TYPE_2OP, ISD::SHL, 0), - X86_INTRINSIC_DATA(avx2_psllv_d_256, INTR_TYPE_2OP, ISD::SHL, 0), - X86_INTRINSIC_DATA(avx2_psllv_q, INTR_TYPE_2OP, ISD::SHL, 0), - X86_INTRINSIC_DATA(avx2_psllv_q_256, INTR_TYPE_2OP, ISD::SHL, 0), + X86_INTRINSIC_DATA(avx2_psllv_d, INTR_TYPE_2OP, X86ISD::VSHLV, 0), + X86_INTRINSIC_DATA(avx2_psllv_d_256, INTR_TYPE_2OP, X86ISD::VSHLV, 0), + X86_INTRINSIC_DATA(avx2_psllv_q, INTR_TYPE_2OP, X86ISD::VSHLV, 0), + X86_INTRINSIC_DATA(avx2_psllv_q_256, INTR_TYPE_2OP, X86ISD::VSHLV, 0), X86_INTRINSIC_DATA(avx2_psra_d, INTR_TYPE_2OP, X86ISD::VSRA, 0), X86_INTRINSIC_DATA(avx2_psra_w, INTR_TYPE_2OP, X86ISD::VSRA, 0), X86_INTRINSIC_DATA(avx2_psrai_d, VSHIFT, X86ISD::VSRAI, 0), @@ -405,10 +405,10 @@ static const IntrinsicData IntrinsicsWithoutChain[] = { X86_INTRINSIC_DATA(avx2_psrli_d, VSHIFT, X86ISD::VSRLI, 0), X86_INTRINSIC_DATA(avx2_psrli_q, VSHIFT, X86ISD::VSRLI, 0), X86_INTRINSIC_DATA(avx2_psrli_w, VSHIFT, X86ISD::VSRLI, 0), - X86_INTRINSIC_DATA(avx2_psrlv_d, INTR_TYPE_2OP, ISD::SRL, 0), - X86_INTRINSIC_DATA(avx2_psrlv_d_256, INTR_TYPE_2OP, ISD::SRL, 0), - X86_INTRINSIC_DATA(avx2_psrlv_q, INTR_TYPE_2OP, ISD::SRL, 0), - X86_INTRINSIC_DATA(avx2_psrlv_q_256, INTR_TYPE_2OP, ISD::SRL, 0), + X86_INTRINSIC_DATA(avx2_psrlv_d, INTR_TYPE_2OP, X86ISD::VSRLV, 0), + X86_INTRINSIC_DATA(avx2_psrlv_d_256, INTR_TYPE_2OP, X86ISD::VSRLV, 0), + X86_INTRINSIC_DATA(avx2_psrlv_q, INTR_TYPE_2OP, X86ISD::VSRLV, 0), + X86_INTRINSIC_DATA(avx2_psrlv_q_256, INTR_TYPE_2OP, X86ISD::VSRLV, 0), X86_INTRINSIC_DATA(avx512_add_pd_512, INTR_TYPE_2OP, ISD::FADD, X86ISD::FADD_RND), X86_INTRINSIC_DATA(avx512_add_ps_512, INTR_TYPE_2OP, ISD::FADD, X86ISD::FADD_RND), X86_INTRINSIC_DATA(avx512_cmp_pd_128, CMP_MASK_CC, X86ISD::CMPM, 0), @@ -943,11 +943,11 @@ static const IntrinsicData IntrinsicsWithoutChain[] = { X86_INTRINSIC_DATA(avx512_pslli_d_512, VSHIFT, X86ISD::VSHLI, 0), X86_INTRINSIC_DATA(avx512_pslli_q_512, VSHIFT, X86ISD::VSHLI, 0), X86_INTRINSIC_DATA(avx512_pslli_w_512, VSHIFT, X86ISD::VSHLI, 0), - X86_INTRINSIC_DATA(avx512_psllv_d_512, INTR_TYPE_2OP, ISD::SHL, 0), - X86_INTRINSIC_DATA(avx512_psllv_q_512, INTR_TYPE_2OP, ISD::SHL, 0), - X86_INTRINSIC_DATA(avx512_psllv_w_128, INTR_TYPE_2OP, ISD::SHL, 0), - X86_INTRINSIC_DATA(avx512_psllv_w_256, INTR_TYPE_2OP, ISD::SHL, 0), - X86_INTRINSIC_DATA(avx512_psllv_w_512, INTR_TYPE_2OP, ISD::SHL, 0), + X86_INTRINSIC_DATA(avx512_psllv_d_512, INTR_TYPE_2OP, X86ISD::VSHLV, 0), + X86_INTRINSIC_DATA(avx512_psllv_q_512, INTR_TYPE_2OP, X86ISD::VSHLV, 0), + X86_INTRINSIC_DATA(avx512_psllv_w_128, INTR_TYPE_2OP, X86ISD::VSHLV, 0), + X86_INTRINSIC_DATA(avx512_psllv_w_256, INTR_TYPE_2OP, X86ISD::VSHLV, 0), + X86_INTRINSIC_DATA(avx512_psllv_w_512, INTR_TYPE_2OP, X86ISD::VSHLV, 0), X86_INTRINSIC_DATA(avx512_psra_d_512, INTR_TYPE_2OP, X86ISD::VSRA, 0), X86_INTRINSIC_DATA(avx512_psra_q_128, INTR_TYPE_2OP, X86ISD::VSRA, 0), X86_INTRINSIC_DATA(avx512_psra_q_256, INTR_TYPE_2OP, X86ISD::VSRA, 0), @@ -971,11 +971,11 @@ static const IntrinsicData IntrinsicsWithoutChain[] = { X86_INTRINSIC_DATA(avx512_psrli_d_512, VSHIFT, X86ISD::VSRLI, 0), X86_INTRINSIC_DATA(avx512_psrli_q_512, VSHIFT, X86ISD::VSRLI, 0), X86_INTRINSIC_DATA(avx512_psrli_w_512, VSHIFT, X86ISD::VSRLI, 0), - X86_INTRINSIC_DATA(avx512_psrlv_d_512, INTR_TYPE_2OP, ISD::SRL, 0), - X86_INTRINSIC_DATA(avx512_psrlv_q_512, INTR_TYPE_2OP, ISD::SRL, 0), - X86_INTRINSIC_DATA(avx512_psrlv_w_128, INTR_TYPE_2OP, ISD::SRL, 0), - X86_INTRINSIC_DATA(avx512_psrlv_w_256, INTR_TYPE_2OP, ISD::SRL, 0), - X86_INTRINSIC_DATA(avx512_psrlv_w_512, INTR_TYPE_2OP, ISD::SRL, 0), + X86_INTRINSIC_DATA(avx512_psrlv_d_512, INTR_TYPE_2OP, X86ISD::VSRLV, 0), + X86_INTRINSIC_DATA(avx512_psrlv_q_512, INTR_TYPE_2OP, X86ISD::VSRLV, 0), + X86_INTRINSIC_DATA(avx512_psrlv_w_128, INTR_TYPE_2OP, X86ISD::VSRLV, 0), + X86_INTRINSIC_DATA(avx512_psrlv_w_256, INTR_TYPE_2OP, X86ISD::VSRLV, 0), + X86_INTRINSIC_DATA(avx512_psrlv_w_512, INTR_TYPE_2OP, X86ISD::VSRLV, 0), X86_INTRINSIC_DATA(avx512_pternlog_d_128, INTR_TYPE_4OP, X86ISD::VPTERNLOG, 0), X86_INTRINSIC_DATA(avx512_pternlog_d_256, INTR_TYPE_4OP, X86ISD::VPTERNLOG, 0), X86_INTRINSIC_DATA(avx512_pternlog_d_512, INTR_TYPE_4OP, X86ISD::VPTERNLOG, 0), diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp index 55842a4a20914..bc39cee34c4ad 100644 --- a/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -497,6 +497,9 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { BitVector Reserved(getNumRegs()); const X86FrameLowering *TFI = getFrameLowering(MF); + // Set the floating point control register as reserved. + Reserved.set(X86::FPCW); + // Set the stack-pointer register and its aliases as reserved. for (MCSubRegIterator I(X86::RSP, this, /*IncludeSelf=*/true); I.isValid(); ++I) diff --git a/llvm/lib/Target/X86/X86RegisterInfo.td b/llvm/lib/Target/X86/X86RegisterInfo.td index aa20273f89abe..6a0538138528b 100644 --- a/llvm/lib/Target/X86/X86RegisterInfo.td +++ b/llvm/lib/Target/X86/X86RegisterInfo.td @@ -278,7 +278,7 @@ def K7 : X86Reg<"k7", 7>, DwarfRegNum<[125, 100, 100]>; // pseudo registers, but we still mark them as aliasing FP registers. That // way both kinds can be live without exceeding the stack depth. ST registers // are only live around inline assembly. -def ST0 : X86Reg<"st(0)", 0>, DwarfRegNum<[33, 12, 11]>; +def ST0 : X86Reg<"st", 0>, DwarfRegNum<[33, 12, 11]>; def ST1 : X86Reg<"st(1)", 1>, DwarfRegNum<[34, 13, 12]>; def ST2 : X86Reg<"st(2)", 2>, DwarfRegNum<[35, 14, 13]>; def ST3 : X86Reg<"st(3)", 3>, DwarfRegNum<[36, 15, 14]>; @@ -288,7 +288,10 @@ def ST6 : X86Reg<"st(6)", 6>, DwarfRegNum<[39, 18, 17]>; def ST7 : X86Reg<"st(7)", 7>, DwarfRegNum<[40, 19, 18]>; // Floating-point status word -def FPSW : X86Reg<"fpsw", 0>; +def FPSW : X86Reg<"fpsr", 0>; + +// Floating-point control word +def FPCW : X86Reg<"fpcr", 0>; // Status flags register. // @@ -539,6 +542,9 @@ def RST : RegisterClass<"X86", [f80, f64, f32], 32, (sequence "ST%u", 0, 7)> { let isAllocatable = 0; } +// Helper to allow %st to print as %st(0) when its encoded in the instruction. +def RSTi : RegisterOperand; + // Generic vector registers: VR64 and VR128. // Ensure that float types are declared first - only float is legal on SSE1. def VR64: RegisterClass<"X86", [x86mmx], 64, (sequence "MM%u", 0, 7)>; diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp index afcb49dc22632..217a12ddf896e 100644 --- a/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -38,6 +38,7 @@ #include "llvm/IR/Attributes.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Pass.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/CommandLine.h" @@ -512,6 +513,9 @@ void X86PassConfig::addPreEmitPass2() { // correct CFA calculation rule where needed by inserting appropriate CFI // instructions. const Triple &TT = TM->getTargetTriple(); - if (!TT.isOSDarwin() && !TT.isOSWindows()) + const MCAsmInfo *MAI = TM->getMCAsmInfo(); + if (!TT.isOSDarwin() && + (!TT.isOSWindows() || + MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI)) addPass(createCFIInstrInserter()); } diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index be7d43bbcf2c3..fef051aa1b7c3 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1376,7 +1376,8 @@ Instruction *InstCombiner::foldVectorBinop(BinaryOperator &Inst) { if (match(LHS, m_ShuffleVector(m_Value(L0), m_Value(L1), m_Constant(Mask))) && match(RHS, m_ShuffleVector(m_Value(R0), m_Value(R1), m_Specific(Mask))) && LHS->hasOneUse() && RHS->hasOneUse() && - cast(LHS)->isConcat()) { + cast(LHS)->isConcat() && + cast(RHS)->isConcat()) { // This transform does not have the speculative execution constraint as // below because the shuffle is a concatenation. The new binops are // operating on exactly the same elements as the existing binop. @@ -3065,9 +3066,11 @@ static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) { I->isTerminator()) return false; - // Do not sink alloca instructions out of the entry block. - if (isa(I) && I->getParent() == - &DestBlock->getParent()->getEntryBlock()) + // Do not sink static or dynamic alloca instructions. Static allocas must + // remain in the entry block, and dynamic allocas must not be sunk in between + // a stacksave / stackrestore pair, which would incorrectly shorten its + // lifetime. + if (isa(I)) return false; // Do not sink into catchswitch blocks. diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index e6573af2077dc..b2230afa13d8a 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -321,6 +321,7 @@ static cl::opt ClOriginBase("msan-origin-base", cl::desc("Define custom MSan OriginBase"), cl::Hidden, cl::init(0)); +static const char *const kMsanModuleCtorName = "msan.module_ctor"; static const char *const kMsanInitName = "__msan_init"; namespace { @@ -586,6 +587,8 @@ class MemorySanitizer { /// An empty volatile inline asm that prevents callback merge. InlineAsm *EmptyAsm; + + Function *MsanCtorFunction; }; /// A legacy function pass for msan instrumentation. @@ -839,6 +842,8 @@ Value *MemorySanitizer::getKmsanShadowOriginAccessFn(bool isStore, int size) { } /// Module-level initialization. +/// +/// inserts a call to __msan_init to the module's constructor list. void MemorySanitizer::initializeModule(Module &M) { auto &DL = M.getDataLayout(); @@ -913,7 +918,22 @@ void MemorySanitizer::initializeModule(Module &M) { OriginStoreWeights = MDBuilder(*C).createBranchWeights(1, 1000); if (!CompileKernel) { - getOrCreateInitFunction(M, kMsanInitName); + std::tie(MsanCtorFunction, std::ignore) = + getOrCreateSanitizerCtorAndInitFunctions( + M, kMsanModuleCtorName, kMsanInitName, + /*InitArgTypes=*/{}, + /*InitArgs=*/{}, + // This callback is invoked when the functions are created the first + // time. Hook them into the global ctors list in that case: + [&](Function *Ctor, Function *) { + if (!ClWithComdat) { + appendToGlobalCtors(M, Ctor, 0); + return; + } + Comdat *MsanCtorComdat = M.getOrInsertComdat(kMsanModuleCtorName); + Ctor->setComdat(MsanCtorComdat); + appendToGlobalCtors(M, Ctor, 0, Ctor); + }); if (TrackOrigins) M.getOrInsertGlobal("__msan_track_origins", IRB.getInt32Ty(), [&] { @@ -4458,6 +4478,8 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan, } bool MemorySanitizer::sanitizeFunction(Function &F, TargetLibraryInfo &TLI) { + if (!CompileKernel && (&F == MsanCtorFunction)) + return false; MemorySanitizerVisitor Visitor(F, *this, TLI); // Clear out readonly/readnone attributes. diff --git a/llvm/lib/Transforms/Scalar/MergeICmps.cpp b/llvm/lib/Transforms/Scalar/MergeICmps.cpp index 69fd8b163a070..a24fee54949d3 100644 --- a/llvm/lib/Transforms/Scalar/MergeICmps.cpp +++ b/llvm/lib/Transforms/Scalar/MergeICmps.cpp @@ -11,21 +11,37 @@ // later typically inlined as a chain of efficient hardware comparisons). This // typically benefits c++ member or nonmember operator==(). // -// The basic idea is to replace a larger chain of integer comparisons loaded -// from contiguous memory locations into a smaller chain of such integer +// The basic idea is to replace a longer chain of integer comparisons loaded +// from contiguous memory locations into a shorter chain of larger integer // comparisons. Benefits are double: // - There are less jumps, and therefore less opportunities for mispredictions // and I-cache misses. // - Code size is smaller, both because jumps are removed and because the // encoding of a 2*n byte compare is smaller than that of two n-byte // compares. - +// +// Example: +// +// struct S { +// int a; +// char b; +// char c; +// uint16_t d; +// bool operator==(const S& o) const { +// return a == o.a && b == o.b && c == o.c && d == o.d; +// } +// }; +// +// Is optimized as : +// +// bool S::operator==(const S& o) const { +// return memcmp(this, &o, 8) == 0; +// } +// +// Which will later be expanded (ExpandMemCmp) as a single 8-bytes icmp. +// //===----------------------------------------------------------------------===// -#include -#include -#include -#include #include "llvm/Analysis/Loads.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" @@ -34,6 +50,10 @@ #include "llvm/Pass.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BuildLibCalls.h" +#include +#include +#include +#include using namespace llvm; @@ -50,76 +70,95 @@ static bool isSimpleLoadOrStore(const Instruction *I) { return false; } -// A BCE atom. +// A BCE atom "Binary Compare Expression Atom" represents an integer load +// that is a constant offset from a base value, e.g. `a` or `o.c` in the example +// at the top. struct BCEAtom { - BCEAtom() : GEP(nullptr), LoadI(nullptr), Offset() {} - - const Value *Base() const { return GEP ? GEP->getPointerOperand() : nullptr; } - + BCEAtom() = default; + BCEAtom(GetElementPtrInst *GEP, LoadInst *LoadI, int BaseId, APInt Offset) + : GEP(GEP), LoadI(LoadI), BaseId(BaseId), Offset(Offset) {} + + // We want to order BCEAtoms by (Base, Offset). However we cannot use + // the pointer values for Base because these are non-deterministic. + // To make sure that the sort order is stable, we first assign to each atom + // base value an index based on its order of appearance in the chain of + // comparisons. We call this index `BaseOrdering`. For example, for: + // b[3] == c[2] && a[1] == d[1] && b[4] == c[3] + // | block 1 | | block 2 | | block 3 | + // b gets assigned index 0 and a index 1, because b appears as LHS in block 1, + // which is before block 2. + // We then sort by (BaseOrdering[LHS.Base()], LHS.Offset), which is stable. bool operator<(const BCEAtom &O) const { - assert(Base() && "invalid atom"); - assert(O.Base() && "invalid atom"); - // Just ordering by (Base(), Offset) is sufficient. However because this - // means that the ordering will depend on the addresses of the base - // values, which are not reproducible from run to run. To guarantee - // stability, we use the names of the values if they exist; we sort by: - // (Base.getName(), Base(), Offset). - const int NameCmp = Base()->getName().compare(O.Base()->getName()); - if (NameCmp == 0) { - if (Base() == O.Base()) { - return Offset.slt(O.Offset); - } - return Base() < O.Base(); - } - return NameCmp < 0; + return BaseId != O.BaseId ? BaseId < O.BaseId : Offset.slt(O.Offset); } - GetElementPtrInst *GEP; - LoadInst *LoadI; + GetElementPtrInst *GEP = nullptr; + LoadInst *LoadI = nullptr; + unsigned BaseId = 0; APInt Offset; }; +// A class that assigns increasing ids to values in the order in which they are +// seen. See comment in `BCEAtom::operator<()``. +class BaseIdentifier { +public: + // Returns the id for value `Base`, after assigning one if `Base` has not been + // seen before. + int getBaseId(const Value *Base) { + assert(Base && "invalid base"); + const auto Insertion = BaseToIndex.try_emplace(Base, Order); + if (Insertion.second) + ++Order; + return Insertion.first->second; + } + +private: + unsigned Order = 1; + DenseMap BaseToIndex; +}; + // If this value is a load from a constant offset w.r.t. a base address, and // there are no other users of the load or address, returns the base address and // the offset. -BCEAtom visitICmpLoadOperand(Value *const Val) { - BCEAtom Result; - if (auto *const LoadI = dyn_cast(Val)) { - LLVM_DEBUG(dbgs() << "load\n"); - if (LoadI->isUsedOutsideOfBlock(LoadI->getParent())) { - LLVM_DEBUG(dbgs() << "used outside of block\n"); - return {}; - } - // Do not optimize atomic loads to non-atomic memcmp - if (!LoadI->isSimple()) { - LLVM_DEBUG(dbgs() << "volatile or atomic\n"); - return {}; - } - Value *const Addr = LoadI->getOperand(0); - if (auto *const GEP = dyn_cast(Addr)) { - LLVM_DEBUG(dbgs() << "GEP\n"); - if (GEP->isUsedOutsideOfBlock(LoadI->getParent())) { - LLVM_DEBUG(dbgs() << "used outside of block\n"); - return {}; - } - const auto &DL = GEP->getModule()->getDataLayout(); - if (!isDereferenceablePointer(GEP, DL)) { - LLVM_DEBUG(dbgs() << "not dereferenceable\n"); - // We need to make sure that we can do comparison in any order, so we - // require memory to be unconditionnally dereferencable. - return {}; - } - Result.Offset = APInt(DL.getPointerTypeSizeInBits(GEP->getType()), 0); - if (GEP->accumulateConstantOffset(DL, Result.Offset)) { - Result.GEP = GEP; - Result.LoadI = LoadI; - } - } +BCEAtom visitICmpLoadOperand(Value *const Val, BaseIdentifier &BaseId) { + auto *const LoadI = dyn_cast(Val); + if (!LoadI) + return {}; + LLVM_DEBUG(dbgs() << "load\n"); + if (LoadI->isUsedOutsideOfBlock(LoadI->getParent())) { + LLVM_DEBUG(dbgs() << "used outside of block\n"); + return {}; + } + // Do not optimize atomic loads to non-atomic memcmp + if (!LoadI->isSimple()) { + LLVM_DEBUG(dbgs() << "volatile or atomic\n"); + return {}; } - return Result; + Value *const Addr = LoadI->getOperand(0); + auto *const GEP = dyn_cast(Addr); + if (!GEP) + return {}; + LLVM_DEBUG(dbgs() << "GEP\n"); + if (GEP->isUsedOutsideOfBlock(LoadI->getParent())) { + LLVM_DEBUG(dbgs() << "used outside of block\n"); + return {}; + } + const auto &DL = GEP->getModule()->getDataLayout(); + if (!isDereferenceablePointer(GEP, DL)) { + LLVM_DEBUG(dbgs() << "not dereferenceable\n"); + // We need to make sure that we can do comparison in any order, so we + // require memory to be unconditionnally dereferencable. + return {}; + } + APInt Offset = APInt(DL.getPointerTypeSizeInBits(GEP->getType()), 0); + if (!GEP->accumulateConstantOffset(DL, Offset)) + return {}; + return BCEAtom(GEP, LoadI, BaseId.getBaseId(GEP->getPointerOperand()), + Offset); } -// A basic block with a comparison between two BCE atoms. +// A basic block with a comparison between two BCE atoms, e.g. `a == o.a` in the +// example at the top. // The block might do extra work besides the atom comparison, in which case // doesOtherWork() returns true. Under some conditions, the block can be // split into the atom comparison part and the "other work" part @@ -137,9 +176,7 @@ class BCECmpBlock { if (Rhs_ < Lhs_) std::swap(Rhs_, Lhs_); } - bool IsValid() const { - return Lhs_.Base() != nullptr && Rhs_.Base() != nullptr; - } + bool IsValid() const { return Lhs_.BaseId != 0 && Rhs_.BaseId != 0; } // Assert the block is consistent: If valid, it should also have // non-null members besides Lhs_ and Rhs_. @@ -265,7 +302,8 @@ bool BCECmpBlock::doesOtherWork() const { // Visit the given comparison. If this is a comparison between two valid // BCE atoms, returns the comparison. BCECmpBlock visitICmp(const ICmpInst *const CmpI, - const ICmpInst::Predicate ExpectedPredicate) { + const ICmpInst::Predicate ExpectedPredicate, + BaseIdentifier &BaseId) { // The comparison can only be used once: // - For intermediate blocks, as a branch condition. // - For the final block, as an incoming value for the Phi. @@ -275,25 +313,27 @@ BCECmpBlock visitICmp(const ICmpInst *const CmpI, LLVM_DEBUG(dbgs() << "cmp has several uses\n"); return {}; } - if (CmpI->getPredicate() == ExpectedPredicate) { - LLVM_DEBUG(dbgs() << "cmp " - << (ExpectedPredicate == ICmpInst::ICMP_EQ ? "eq" : "ne") - << "\n"); - auto Lhs = visitICmpLoadOperand(CmpI->getOperand(0)); - if (!Lhs.Base()) return {}; - auto Rhs = visitICmpLoadOperand(CmpI->getOperand(1)); - if (!Rhs.Base()) return {}; - const auto &DL = CmpI->getModule()->getDataLayout(); - return BCECmpBlock(std::move(Lhs), std::move(Rhs), - DL.getTypeSizeInBits(CmpI->getOperand(0)->getType())); - } - return {}; + if (CmpI->getPredicate() != ExpectedPredicate) + return {}; + LLVM_DEBUG(dbgs() << "cmp " + << (ExpectedPredicate == ICmpInst::ICMP_EQ ? "eq" : "ne") + << "\n"); + auto Lhs = visitICmpLoadOperand(CmpI->getOperand(0), BaseId); + if (!Lhs.BaseId) + return {}; + auto Rhs = visitICmpLoadOperand(CmpI->getOperand(1), BaseId); + if (!Rhs.BaseId) + return {}; + const auto &DL = CmpI->getModule()->getDataLayout(); + return BCECmpBlock(std::move(Lhs), std::move(Rhs), + DL.getTypeSizeInBits(CmpI->getOperand(0)->getType())); } // Visit the given comparison block. If this is a comparison between two valid // BCE atoms, returns the comparison. BCECmpBlock visitCmpBlock(Value *const Val, BasicBlock *const Block, - const BasicBlock *const PhiBlock) { + const BasicBlock *const PhiBlock, + BaseIdentifier &BaseId) { if (Block->empty()) return {}; auto *const BranchI = dyn_cast(Block->getTerminator()); if (!BranchI) return {}; @@ -306,7 +346,7 @@ BCECmpBlock visitCmpBlock(Value *const Val, BasicBlock *const Block, auto *const CmpI = dyn_cast(Val); if (!CmpI) return {}; LLVM_DEBUG(dbgs() << "icmp\n"); - auto Result = visitICmp(CmpI, ICmpInst::ICMP_EQ); + auto Result = visitICmp(CmpI, ICmpInst::ICMP_EQ, BaseId); Result.CmpI = CmpI; Result.BranchI = BranchI; return Result; @@ -323,7 +363,8 @@ BCECmpBlock visitCmpBlock(Value *const Val, BasicBlock *const Block, assert(BranchI->getNumSuccessors() == 2 && "expecting a cond branch"); BasicBlock *const FalseBlock = BranchI->getSuccessor(1); auto Result = visitICmp( - CmpI, FalseBlock == PhiBlock ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE); + CmpI, FalseBlock == PhiBlock ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE, + BaseId); Result.CmpI = CmpI; Result.BranchI = BranchI; return Result; @@ -335,9 +376,9 @@ static inline void enqueueBlock(std::vector &Comparisons, BCECmpBlock &Comparison) { LLVM_DEBUG(dbgs() << "Block '" << Comparison.BB->getName() << "': Found cmp of " << Comparison.SizeBits() - << " bits between " << Comparison.Lhs().Base() << " + " + << " bits between " << Comparison.Lhs().BaseId << " + " << Comparison.Lhs().Offset << " and " - << Comparison.Rhs().Base() << " + " + << Comparison.Rhs().BaseId << " + " << Comparison.Rhs().Offset << "\n"); LLVM_DEBUG(dbgs() << "\n"); Comparisons.push_back(Comparison); @@ -360,8 +401,8 @@ class BCECmpChain { private: static bool IsContiguous(const BCECmpBlock &First, const BCECmpBlock &Second) { - return First.Lhs().Base() == Second.Lhs().Base() && - First.Rhs().Base() == Second.Rhs().Base() && + return First.Lhs().BaseId == Second.Lhs().BaseId && + First.Rhs().BaseId == Second.Rhs().BaseId && First.Lhs().Offset + First.SizeBits() / 8 == Second.Lhs().Offset && First.Rhs().Offset + First.SizeBits() / 8 == Second.Rhs().Offset; } @@ -385,11 +426,12 @@ BCECmpChain::BCECmpChain(const std::vector &Blocks, PHINode &Phi, assert(!Blocks.empty() && "a chain should have at least one block"); // Now look inside blocks to check for BCE comparisons. std::vector Comparisons; + BaseIdentifier BaseId; for (size_t BlockIdx = 0; BlockIdx < Blocks.size(); ++BlockIdx) { BasicBlock *const Block = Blocks[BlockIdx]; assert(Block && "invalid block"); BCECmpBlock Comparison = visitCmpBlock(Phi.getIncomingValueForBlock(Block), - Block, Phi.getParent()); + Block, Phi.getParent(), BaseId); Comparison.BB = Block; if (!Comparison.IsValid()) { LLVM_DEBUG(dbgs() << "chain with invalid BCECmpBlock, no merge.\n"); @@ -466,9 +508,10 @@ BCECmpChain::BCECmpChain(const std::vector &Blocks, PHINode &Phi, #endif // MERGEICMPS_DOT_ON // Reorder blocks by LHS. We can do that without changing the // semantics because we are only accessing dereferencable memory. - llvm::sort(Comparisons_, [](const BCECmpBlock &a, const BCECmpBlock &b) { - return a.Lhs() < b.Lhs(); - }); + llvm::sort(Comparisons_, + [](const BCECmpBlock &LhsBlock, const BCECmpBlock &RhsBlock) { + return LhsBlock.Lhs() < RhsBlock.Lhs(); + }); #ifdef MERGEICMPS_DOT_ON errs() << "AFTER REORDERING:\n\n"; dump(); diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp index eab77cf4cda9b..68ca6c47c8f1a 100644 --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -3031,7 +3031,10 @@ class llvm::sroa::AllocaSliceRewriter ConstantInt *Size = ConstantInt::get(cast(II.getArgOperand(0)->getType()), NewEndOffset - NewBeginOffset); - Value *Ptr = getNewAllocaSlicePtr(IRB, OldPtr->getType()); + // Lifetime intrinsics always expect an i8* so directly get such a pointer + // for the new alloca slice. + Type *PointerTy = IRB.getInt8PtrTy(OldPtr->getType()->getPointerAddressSpace()); + Value *Ptr = getNewAllocaSlicePtr(IRB, PointerTy); Value *New; if (II.getIntrinsicID() == Intrinsic::lifetime_start) New = IRB.CreateLifetimeStart(Ptr, Size); diff --git a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp index a9772e31da509..81d63ee80394e 100644 --- a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp +++ b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp @@ -249,6 +249,8 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) { bool DoPromote = false; if (GV.hasLocalLinkage() && ((DoPromote = shouldPromoteLocalToGlobal(&GV)) || isPerformingImport())) { + // Save the original name string before we rename GV below. + auto Name = GV.getName().str(); // Once we change the name or linkage it is difficult to determine // again whether we should promote since shouldPromoteLocalToGlobal needs // to locate the summary (based on GUID from name and linkage). Therefore, @@ -257,6 +259,12 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) { GV.setLinkage(getLinkage(&GV, DoPromote)); if (!GV.hasLocalLinkage()) GV.setVisibility(GlobalValue::HiddenVisibility); + + // If we are renaming a COMDAT leader, ensure that we record the COMDAT + // for later renaming as well. This is required for COFF. + if (const auto *C = GV.getComdat()) + if (C->getName() == Name) + RenamedComdats.try_emplace(C, M.getOrInsertComdat(GV.getName())); } else GV.setLinkage(getLinkage(&GV, /* DoPromote */ false)); @@ -281,6 +289,16 @@ void FunctionImportGlobalProcessing::processGlobalsForThinLTO() { processGlobalForThinLTO(SF); for (GlobalAlias &GA : M.aliases()) processGlobalForThinLTO(GA); + + // Replace any COMDATS that required renaming (because the COMDAT leader was + // promoted and renamed). + if (!RenamedComdats.empty()) + for (auto &GO : M.global_objects()) + if (auto *C = GO.getComdat()) { + auto Replacement = RenamedComdats.find(C); + if (Replacement != RenamedComdats.end()) + GO.setComdat(Replacement->second); + } } bool FunctionImportGlobalProcessing::run() { diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp index a93d1aeb62ef9..112e80d27e345 100644 --- a/llvm/lib/Transforms/Utils/LoopUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp @@ -217,7 +217,10 @@ static Optional getOptionalBoolLoopAttribute(const Loop *TheLoop, // When the value is absent it is interpreted as 'attribute set'. return true; case 2: - return mdconst::extract_or_null(MD->getOperand(1).get()); + if (ConstantInt *IntMD = + mdconst::extract_or_null(MD->getOperand(1).get())) + return IntMD->getZExtValue(); + return true; } llvm_unreachable("unexpected number of options"); } @@ -376,17 +379,17 @@ TransformationMode llvm::hasVectorizeTransformation(Loop *L) { Optional InterleaveCount = getOptionalIntLoopAttribute(L, "llvm.loop.interleave.count"); - if (Enable == true) { - // 'Forcing' vector width and interleave count to one effectively disables - // this tranformation. - if (VectorizeWidth == 1 && InterleaveCount == 1) - return TM_SuppressedByUser; - return TM_ForcedByUser; - } + // 'Forcing' vector width and interleave count to one effectively disables + // this tranformation. + if (Enable == true && VectorizeWidth == 1 && InterleaveCount == 1) + return TM_SuppressedByUser; if (getBooleanLoopAttribute(L, "llvm.loop.isvectorized")) return TM_Disable; + if (Enable == true) + return TM_ForcedByUser; + if (VectorizeWidth == 1 && InterleaveCount == 1) return TM_Disable; diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 2e856a7e6802e..a07fffe9b98b9 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -1468,8 +1468,9 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, // If any of the scalars is marked as a value that needs to stay scalar, then // we need to gather the scalars. + // The reduction nodes (stored in UserIgnoreList) also should stay scalar. for (unsigned i = 0, e = VL.size(); i != e; ++i) { - if (MustGather.count(VL[i])) { + if (MustGather.count(VL[i]) || is_contained(UserIgnoreList, VL[i])) { LLVM_DEBUG(dbgs() << "SLP: Gathering due to gathered scalar.\n"); newTreeEntry(VL, false, UserTreeIdx); return; diff --git a/llvm/test/CodeGen/AArch64/build-vector-extract.ll b/llvm/test/CodeGen/AArch64/build-vector-extract.ll new file mode 100644 index 0000000000000..a785533e8db9b --- /dev/null +++ b/llvm/test/CodeGen/AArch64/build-vector-extract.ll @@ -0,0 +1,441 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=aarch64-- | FileCheck %s + +define <2 x i64> @extract0_i32_zext_insert0_i64_undef(<4 x i32> %x) { +; CHECK-LABEL: extract0_i32_zext_insert0_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: movi v1.2d, #0000000000000000 +; CHECK-NEXT: zip1 v0.4s, v0.4s, v1.4s +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 0 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract0_i32_zext_insert0_i64_zero(<4 x i32> %x) { +; CHECK-LABEL: extract0_i32_zext_insert0_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: fmov w8, s0 +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[0], x8 +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 0 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract1_i32_zext_insert0_i64_undef(<4 x i32> %x) { +; CHECK-LABEL: extract1_i32_zext_insert0_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: zip1 v0.4s, v0.4s, v0.4s +; CHECK-NEXT: movi v1.2d, #0000000000000000 +; CHECK-NEXT: ext v0.16b, v0.16b, v1.16b, #12 +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 1 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract1_i32_zext_insert0_i64_zero(<4 x i32> %x) { +; CHECK-LABEL: extract1_i32_zext_insert0_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, v0.s[1] +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[0], x8 +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 1 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract2_i32_zext_insert0_i64_undef(<4 x i32> %x) { +; CHECK-LABEL: extract2_i32_zext_insert0_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: uzp1 v0.4s, v0.4s, v0.4s +; CHECK-NEXT: movi v1.2d, #0000000000000000 +; CHECK-NEXT: ext v0.16b, v0.16b, v1.16b, #12 +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 2 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract2_i32_zext_insert0_i64_zero(<4 x i32> %x) { +; CHECK-LABEL: extract2_i32_zext_insert0_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, v0.s[2] +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[0], x8 +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 2 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract3_i32_zext_insert0_i64_undef(<4 x i32> %x) { +; CHECK-LABEL: extract3_i32_zext_insert0_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: movi v1.2d, #0000000000000000 +; CHECK-NEXT: ext v0.16b, v0.16b, v1.16b, #12 +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 3 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract3_i32_zext_insert0_i64_zero(<4 x i32> %x) { +; CHECK-LABEL: extract3_i32_zext_insert0_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, v0.s[3] +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[0], x8 +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 3 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract0_i32_zext_insert1_i64_undef(<4 x i32> %x) { +; CHECK-LABEL: extract0_i32_zext_insert1_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: movi v1.2d, #0000000000000000 +; CHECK-NEXT: zip1 v1.4s, v0.4s, v1.4s +; CHECK-NEXT: ext v0.16b, v0.16b, v1.16b, #8 +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 0 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract0_i32_zext_insert1_i64_zero(<4 x i32> %x) { +; CHECK-LABEL: extract0_i32_zext_insert1_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: fmov w8, s0 +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[1], x8 +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 0 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract1_i32_zext_insert1_i64_undef(<4 x i32> %x) { +; CHECK-LABEL: extract1_i32_zext_insert1_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: ext v0.16b, v0.16b, v0.16b, #8 +; CHECK-NEXT: movi v1.2d, #0000000000000000 +; CHECK-NEXT: ext v0.16b, v0.16b, v1.16b, #4 +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 1 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract1_i32_zext_insert1_i64_zero(<4 x i32> %x) { +; CHECK-LABEL: extract1_i32_zext_insert1_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, v0.s[1] +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[1], x8 +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 1 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract2_i32_zext_insert1_i64_undef(<4 x i32> %x) { +; CHECK-LABEL: extract2_i32_zext_insert1_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: mov v0.s[3], wzr +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 2 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract2_i32_zext_insert1_i64_zero(<4 x i32> %x) { +; CHECK-LABEL: extract2_i32_zext_insert1_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, v0.s[2] +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[1], x8 +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 2 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract3_i32_zext_insert1_i64_undef(<4 x i32> %x) { +; CHECK-LABEL: extract3_i32_zext_insert1_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: movi v1.2d, #0000000000000000 +; CHECK-NEXT: ext v0.16b, v0.16b, v1.16b, #4 +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 3 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract3_i32_zext_insert1_i64_zero(<4 x i32> %x) { +; CHECK-LABEL: extract3_i32_zext_insert1_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, v0.s[3] +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[1], x8 +; CHECK-NEXT: ret + %e = extractelement <4 x i32> %x, i32 3 + %z = zext i32 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract0_i16_zext_insert0_i64_undef(<8 x i16> %x) { +; CHECK-LABEL: extract0_i16_zext_insert0_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[0] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: fmov d0, x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 0 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract0_i16_zext_insert0_i64_zero(<8 x i16> %x) { +; CHECK-LABEL: extract0_i16_zext_insert0_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[0] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[0], x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 0 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract1_i16_zext_insert0_i64_undef(<8 x i16> %x) { +; CHECK-LABEL: extract1_i16_zext_insert0_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[1] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: fmov d0, x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 1 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract1_i16_zext_insert0_i64_zero(<8 x i16> %x) { +; CHECK-LABEL: extract1_i16_zext_insert0_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[1] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[0], x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 1 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract2_i16_zext_insert0_i64_undef(<8 x i16> %x) { +; CHECK-LABEL: extract2_i16_zext_insert0_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[2] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: fmov d0, x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 2 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract2_i16_zext_insert0_i64_zero(<8 x i16> %x) { +; CHECK-LABEL: extract2_i16_zext_insert0_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[2] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[0], x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 2 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract3_i16_zext_insert0_i64_undef(<8 x i16> %x) { +; CHECK-LABEL: extract3_i16_zext_insert0_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[3] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: fmov d0, x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 3 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract3_i16_zext_insert0_i64_zero(<8 x i16> %x) { +; CHECK-LABEL: extract3_i16_zext_insert0_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[3] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[0], x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 3 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 0 + ret <2 x i64> %r +} + +define <2 x i64> @extract0_i16_zext_insert1_i64_undef(<8 x i16> %x) { +; CHECK-LABEL: extract0_i16_zext_insert1_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[0] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: dup v0.2d, x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 0 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract0_i16_zext_insert1_i64_zero(<8 x i16> %x) { +; CHECK-LABEL: extract0_i16_zext_insert1_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[0] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[1], x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 0 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract1_i16_zext_insert1_i64_undef(<8 x i16> %x) { +; CHECK-LABEL: extract1_i16_zext_insert1_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[1] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: dup v0.2d, x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 1 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract1_i16_zext_insert1_i64_zero(<8 x i16> %x) { +; CHECK-LABEL: extract1_i16_zext_insert1_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[1] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[1], x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 1 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract2_i16_zext_insert1_i64_undef(<8 x i16> %x) { +; CHECK-LABEL: extract2_i16_zext_insert1_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[2] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: dup v0.2d, x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 2 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract2_i16_zext_insert1_i64_zero(<8 x i16> %x) { +; CHECK-LABEL: extract2_i16_zext_insert1_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[2] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[1], x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 2 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract3_i16_zext_insert1_i64_undef(<8 x i16> %x) { +; CHECK-LABEL: extract3_i16_zext_insert1_i64_undef: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[3] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: dup v0.2d, x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 3 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> undef, i64 %z, i32 1 + ret <2 x i64> %r +} + +define <2 x i64> @extract3_i16_zext_insert1_i64_zero(<8 x i16> %x) { +; CHECK-LABEL: extract3_i16_zext_insert1_i64_zero: +; CHECK: // %bb.0: +; CHECK-NEXT: umov w8, v0.h[3] +; CHECK-NEXT: and x8, x8, #0xffff +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov v0.d[1], x8 +; CHECK-NEXT: ret + %e = extractelement <8 x i16> %x, i32 3 + %z = zext i16 %e to i64 + %r = insertelement <2 x i64> zeroinitializer, i64 %z, i32 1 + ret <2 x i64> %r +} + +; This would crash because we did not expect to create +; a shuffle for a vector where the source operand is +; not the same size as the result. +; TODO: Should we handle this pattern? Ie, is moving to/from +; registers the optimal code? + +define <4 x i32> @larger_bv_than_source(<4 x i16> %t0) { +; CHECK-LABEL: larger_bv_than_source: +; CHECK: // %bb.0: +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: umov w8, v0.h[2] +; CHECK-NEXT: fmov s0, w8 +; CHECK-NEXT: ret + %t1 = extractelement <4 x i16> %t0, i32 2 + %vgetq_lane = zext i16 %t1 to i32 + %t2 = insertelement <4 x i32> undef, i32 %vgetq_lane, i64 0 + ret <4 x i32> %t2 +} + diff --git a/llvm/test/CodeGen/AArch64/cmpxchg-lse-even-regs.ll b/llvm/test/CodeGen/AArch64/cmpxchg-lse-even-regs.ll new file mode 100644 index 0000000000000..9c6d8cc205331 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/cmpxchg-lse-even-regs.ll @@ -0,0 +1,17 @@ +; RUN: llc -mtriple arm64-apple-ios -mattr=+lse %s -o - | FileCheck %s + +; Only "even,even+1" pairs are valid for CASP instructions. Make sure LLVM +; doesn't allocate odd ones and that it can copy them around properly. N.b. we +; don't actually check that they're sequential because FileCheck can't; odd/even +; will have to be good enough. +define void @test_atomic_cmpxchg_i128_register_shuffling(i128* %addr, i128 %desired, i128 %new) nounwind { +; CHECK-LABEL: test_atomic_cmpxchg_i128_register_shuffling: +; CHECK-DAG: mov [[DESIRED_LO:x[0-9]*[02468]]], x1 +; CHECK-DAG: mov [[DESIRED_HI:x[0-9]*[13579]]], x2 +; CHECK-DAG: mov [[NEW_LO:x[0-9]*[02468]]], x3 +; CHECK-DAG: mov [[NEW_HI:x[0-9]*[13579]]], x4 +; CHECK: caspal [[DESIRED_LO]], [[DESIRED_HI]], [[NEW_LO]], [[NEW_HI]], [x0] + + %res = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst seq_cst + ret void +} diff --git a/llvm/test/CodeGen/AArch64/eh_recoverfp.ll b/llvm/test/CodeGen/AArch64/eh_recoverfp.ll new file mode 100644 index 0000000000000..777bcee543827 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/eh_recoverfp.ll @@ -0,0 +1,11 @@ +; RUN: llc -mtriple arm64-windows %s -o - 2>&1 | FileCheck %s + +define i8* @foo(i8* %a) { +; CHECK-LABEL: foo +; CHECK-NOT: llvm.x86.seh.recoverfp + %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @f to i8*), i8* %a) + ret i8* %1 +} + +declare i8* @llvm.x86.seh.recoverfp(i8*, i8*) +declare i32 @f() diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-bad-adrp.mir b/llvm/test/CodeGen/AArch64/machine-outliner-bad-adrp.mir index af89ac5885ebe..2fc2cfd5d492e 100644 --- a/llvm/test/CodeGen/AArch64/machine-outliner-bad-adrp.mir +++ b/llvm/test/CodeGen/AArch64/machine-outliner-bad-adrp.mir @@ -10,6 +10,7 @@ ... --- name: foo +# CHECK-LABEL: name: foo tracksRegLiveness: true constants: - id: 0 diff --git a/llvm/test/CodeGen/AArch64/seh-finally.ll b/llvm/test/CodeGen/AArch64/seh-finally.ll new file mode 100644 index 0000000000000..3cbbd03385c5f --- /dev/null +++ b/llvm/test/CodeGen/AArch64/seh-finally.ll @@ -0,0 +1,67 @@ +; RUN: llc -mtriple arm64-windows -o - %s | FileCheck %s + +; Function Attrs: noinline optnone uwtable +define dso_local i32 @foo() { +entry: +; CHECK-LABEL: foo +; CHECK: orr w8, wzr, #0x1 +; CHECK: mov w0, wzr +; CHECK: mov x1, x29 +; CHECK: .set .Lfoo$frame_escape_0, -4 +; CHECK: stur w8, [x29, #-4] +; CHECK: bl "?fin$0@0@foo@@" +; CHECK: ldur w0, [x29, #-4] + + %count = alloca i32, align 4 + call void (...) @llvm.localescape(i32* %count) + store i32 0, i32* %count, align 4 + %0 = load i32, i32* %count, align 4 + %add = add nsw i32 %0, 1 + store i32 %add, i32* %count, align 4 + %1 = call i8* @llvm.localaddress() + call void @"?fin$0@0@foo@@"(i8 0, i8* %1) + %2 = load i32, i32* %count, align 4 + ret i32 %2 +} + +define internal void @"?fin$0@0@foo@@"(i8 %abnormal_termination, i8* %frame_pointer) { +entry: +; CHECK-LABEL: @"?fin$0@0@foo@@" +; CHECK: sub sp, sp, #16 +; CHECK: str x1, [sp, #8] +; CHECK: strb w0, [sp, #7] +; CHECK: movz x8, #:abs_g1_s:.Lfoo$frame_escape_0 +; CHECK: movk x8, #:abs_g0_nc:.Lfoo$frame_escape_0 +; CHECK: add x8, x1, x8 +; CHECK: ldr w9, [x8] +; CHECK: add w9, w9, #1 +; CHECK: str w9, [x8] + + %frame_pointer.addr = alloca i8*, align 8 + %abnormal_termination.addr = alloca i8, align 1 + %0 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @foo to i8*), i8* %frame_pointer, i32 0) + %count = bitcast i8* %0 to i32* + store i8* %frame_pointer, i8** %frame_pointer.addr, align 8 + store i8 %abnormal_termination, i8* %abnormal_termination.addr, align 1 + %1 = zext i8 %abnormal_termination to i32 + %cmp = icmp eq i32 %1, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + %2 = load i32, i32* %count, align 4 + %add = add nsw i32 %2, 1 + store i32 %add, i32* %count, align 4 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void +} + +; Function Attrs: nounwind readnone +declare i8* @llvm.localrecover(i8*, i8*, i32) + +; Function Attrs: nounwind readnone +declare i8* @llvm.localaddress() + +; Function Attrs: nounwind +declare void @llvm.localescape(...) diff --git a/llvm/test/CodeGen/AArch64/seh-localescape.ll b/llvm/test/CodeGen/AArch64/seh-localescape.ll new file mode 100644 index 0000000000000..0a1675014f62f --- /dev/null +++ b/llvm/test/CodeGen/AArch64/seh-localescape.ll @@ -0,0 +1,30 @@ +; RUN: llc -mtriple arm64-windows %s -o - | FileCheck %s + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local i32 @foo() { +entry: +; CHECK-LABEL: foo +; CHECK: .set .Lfoo$frame_escape_0, -4 + + %count = alloca i32, align 4 + call void (...) @llvm.localescape(i32* %count) + ret i32 0 +} + +define internal i32 @"?filt$0@0@foo@@"(i8* %exception_pointers, i8* %frame_pointer) { +entry: +; CHECK-LABEL: @"?filt$0@0@foo@@" +; CHECK: movz x8, #:abs_g1_s:.Lfoo$frame_escape_0 +; CHECK: movk x8, #:abs_g0_nc:.Lfoo$frame_escape_0 + + %0 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @foo to i8*), i8* %frame_pointer, i32 0) + %count = bitcast i8* %0 to i32* + %1 = load i32, i32* %count, align 4 + ret i32 %1 +} + +; Function Attrs: nounwind readnone +declare i8* @llvm.localrecover(i8*, i8*, i32) #2 + +; Function Attrs: nounwind +declare void @llvm.localescape(...) #3 diff --git a/llvm/test/CodeGen/AArch64/seqpaircopy.mir b/llvm/test/CodeGen/AArch64/seqpaircopy.mir new file mode 100644 index 0000000000000..89511cbf726bd --- /dev/null +++ b/llvm/test/CodeGen/AArch64/seqpaircopy.mir @@ -0,0 +1,23 @@ +# RUN: llc -o - %s -mtriple=aarch64-- -mattr=+v8.1a -run-pass=postrapseudos | FileCheck %s +--- +# CHECK-LABEL: name: copy_xseqpairs +name: copy_xseqpairs +body: | + bb.0: + ; CHECK: $x4_x5 = CASPALX $x4_x5, $x2_x3, $x0 + ; CHECK: $x0 = ORRXrs $xzr, $x4, 0 + ; CHECK: $x1 = ORRXrs $xzr, $x5, 0 + $x4_x5 = CASPALX $x4_x5, $x2_x3, $x0 + $x0_x1 = COPY $x4_x5 +... +--- +# CHECK-LABEL: name: copy_wseqpairs +name: copy_wseqpairs +body: | + bb.0: + ; CHECK: $w4_w5 = CASPALW $w4_w5, $w2_w3, $x0 + ; CHECK: $w0 = ORRWrs $wzr, $w4, 0 + ; CHECK: $w1 = ORRWrs $wzr, $w5, 0 + $w4_w5 = CASPALW $w4_w5, $w2_w3, $x0 + $w0_w1 = COPY $w4_w5 +... diff --git a/llvm/test/CodeGen/AArch64/speculation-hardening-loads.ll b/llvm/test/CodeGen/AArch64/speculation-hardening-loads.ll index 0b8f8d31b3162..e90fb19a522a1 100644 --- a/llvm/test/CodeGen/AArch64/speculation-hardening-loads.ll +++ b/llvm/test/CodeGen/AArch64/speculation-hardening-loads.ll @@ -11,10 +11,10 @@ entry: ; CHECK-NEXT: and x8, x8, x16 ; CHECK-NEXT: and x1, x1, x16 ; CHECK-NEXT: csdb -; CHECK-NEXT: mov x17, sp -; CHECK-NEXT: and x17, x17, x16 +; CHECK-NEXT: mov [[TMPREG:x[0-9]+]], sp +; CHECK-NEXT: and [[TMPREG]], [[TMPREG]], x16 ; CHECK-NEXT: mov x0, x8 -; CHECK-NEXT: mov sp, x17 +; CHECK-NEXT: mov sp, [[TMPREG]] ; CHECK-NEXT: ret } @@ -29,9 +29,9 @@ entry: ; CHECK-NEXT: and x0, x0, x16 ; CHECK-NEXT: csdb ; CHECK-NEXT: ldr d0, [x0] -; CHECK-NEXT: mov x17, sp -; CHECK-NEXT: and x17, x17, x16 -; CHECK-NEXT: mov sp, x17 +; CHECK-NEXT: mov [[TMPREG:x[0-9]+]], sp +; CHECK-NEXT: and [[TMPREG]], [[TMPREG]], x16 +; CHECK-NEXT: mov sp, [[TMPREG]] ; CHECK-NEXT: ret } @@ -51,12 +51,12 @@ entry: ; CHECK-NEXT: and x8, x8, x16 ; csdb instruction must occur before the add instruction with w8 as operand. ; CHECK-NEXT: csdb -; CHECK-NEXT: mov x17, sp ; CHECK-NEXT: add w9, w1, w8 ; CHECK-NEXT: cmp x8, #0 -; CHECK-NEXT: and x17, x17, x16 ; CHECK-NEXT: csel w0, w1, w9, eq -; CHECK-NEXT: mov sp, x17 +; CHECK-NEXT: mov [[TMPREG:x[0-9]+]], sp +; CHECK-NEXT: and [[TMPREG]], [[TMPREG]], x16 +; CHECK-NEXT: mov sp, [[TMPREG]] ; CHECK-NEXT: ret } @@ -76,12 +76,12 @@ entry: ; CHECK-NEXT: and w8, w8, w16 ; csdb instruction must occur before the add instruction with x8 as operand. ; CHECK-NEXT: csdb -; CHECK-NEXT: mov x17, sp ; CHECK-NEXT: add x9, x1, x8 ; CHECK-NEXT: cmp w8, #0 -; CHECK-NEXT: and x17, x17, x16 ; CHECK-NEXT: csel x0, x1, x9, eq -; CHECK-NEXT: mov sp, x17 +; CHECK-NEXT: mov [[TMPREG:x[0-9]+]], sp +; CHECK-NEXT: and [[TMPREG]], [[TMPREG]], x16 +; CHECK-NEXT: mov sp, [[TMPREG]] ; CHECK-NEXT: ret } @@ -112,11 +112,11 @@ entry: ; CHECK-NEXT: and x1, x1, x16 ; CHECK-NEXT: csdb ; CHECK-NEXT: ldr d0, [x1] -; CHECK-NEXT: mov x17, sp -; CHECK-NEXT: and x17, x17, x16 ; CHECK-NEXT: mov v0.d[1], v0.d[0] ; CHECK-NEXT: str q0, [x0] -; CHECK-NEXT: mov sp, x17 +; CHECK-NEXT: mov [[TMPREG:x[0-9]+]], sp +; CHECK-NEXT: and [[TMPREG]], [[TMPREG]], x16 +; CHECK-NEXT: mov sp, [[TMPREG]] ; CHECK-NEXT: ret } @@ -129,9 +129,9 @@ entry: ; CHECK-NEXT: and x1, x1, x16 ; CHECK-NEXT: csdb ; CHECK-NEXT: ld1 { v0.d }[0], [x1] -; CHECK-NEXT: mov x17, sp -; CHECK-NEXT: and x17, x17, x16 -; CHECK-NEXT: mov sp, x17 +; CHECK-NEXT: mov [[TMPREG:x[0-9]+]], sp +; CHECK-NEXT: and [[TMPREG]], [[TMPREG]], x16 +; CHECK-NEXT: mov sp, [[TMPREG]] ; CHECK-NEXT: ret %0 = load double, double* %b, align 16 %vld1_lane = insertelement <2 x double> , double %0, i32 0 @@ -147,9 +147,9 @@ entry: ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: ldr w8, [sp, #12] ; CHECK-NEXT: add sp, sp, #16 -; CHECK-NEXT: mov x17, sp -; CHECK-NEXT: and x17, x17, x16 -; CHECK-NEXT: mov sp, x17 +; CHECK-NEXT: mov [[TMPREG:x[0-9]+]], sp +; CHECK-NEXT: and [[TMPREG]], [[TMPREG]], x16 +; CHECK-NEXT: mov sp, [[TMPREG]] ; CHECK-NEXT: ret %a = alloca i32, align 4 %val = load volatile i32, i32* %a, align 4 diff --git a/llvm/test/CodeGen/AArch64/speculation-hardening.ll b/llvm/test/CodeGen/AArch64/speculation-hardening.ll index 3535b63c32cc8..51156f68dec8c 100644 --- a/llvm/test/CodeGen/AArch64/speculation-hardening.ll +++ b/llvm/test/CodeGen/AArch64/speculation-hardening.ll @@ -1,9 +1,9 @@ -; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,SLH --dump-input-on-failure -; RUN: sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,NOSLH --dump-input-on-failure -; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,SLH --dump-input-on-failure -; RUN sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,NOSLH --dump-input-on-failure -; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -fast-isel | FileCheck %s --check-prefixes=CHECK,SLH --dump-input-on-failure -; RUN: sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -fast-isel | FileCheck %s --check-prefixes=CHECK,NOSLH --dump-input-on-failure +; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,SLH,NOGISELSLH --dump-input-on-failure +; RUN: sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,NOSLH,NOGISELNOSLH --dump-input-on-failure +; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,SLH,GISELSLH --dump-input-on-failure +; RUN sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,NOSLH,GISELNOSLH --dump-input-on-failure +; RUN: sed -e 's/SLHATTR/speculative_load_hardening/' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -fast-isel | FileCheck %s --check-prefixes=CHECK,SLH,NOGISELSLH --dump-input-on-failure +; RUN: sed -e 's/SLHATTR//' %s | llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -fast-isel | FileCheck %s --check-prefixes=CHECK,NOSLH,NOGISELNOSLH --dump-input-on-failure define i32 @f(i8* nocapture readonly %p, i32 %i, i32 %N) local_unnamed_addr SLHATTR { ; CHECK-LABEL: f @@ -13,12 +13,12 @@ entry: ; NOSLH-NOT: cmp sp, #0 ; NOSLH-NOT: csetm x16, ne -; SLH: mov x17, sp -; SLH: and x17, x17, x16 -; SLH: mov sp, x17 -; NOSLH-NOT: mov x17, sp -; NOSLH-NOT: and x17, x17, x16 -; NOSLH-NOT: mov sp, x17 +; SLH: mov [[TMPREG:x[0-9]+]], sp +; SLH: and [[TMPREG]], [[TMPREG]], x16 +; SLH: mov sp, [[TMPREG]] +; NOSLH-NOT: mov [[TMPREG:x[0-9]+]], sp +; NOSLH-NOT: and [[TMPREG]], [[TMPREG]], x16 +; NOSLH-NOT: mov sp, [[TMPREG]] %call = tail call i32 @tail_callee(i32 %i) ; SLH: cmp sp, #0 ; SLH: csetm x16, ne @@ -43,29 +43,37 @@ if.then: ; preds = %entry ; NOSLH-NOT: csel x16, x16, xzr, [[COND]] return: ; preds = %entry, %if.then %retval.0 = phi i32 [ %conv, %if.then ], [ 0, %entry ] -; SLH: mov x17, sp -; SLH: and x17, x17, x16 -; SLH: mov sp, x17 -; NOSLH-NOT: mov x17, sp -; NOSLH-NOT: and x17, x17, x16 -; NOSLH-NOT: mov sp, x17 +; SLH: mov [[TMPREG:x[0-9]+]], sp +; SLH: and [[TMPREG]], [[TMPREG]], x16 +; SLH: mov sp, [[TMPREG]] +; NOSLH-NOT: mov [[TMPREG:x[0-9]+]], sp +; NOSLH-NOT: and [[TMPREG]], [[TMPREG]], x16 +; NOSLH-NOT: mov sp, [[TMPREG]] ret i32 %retval.0 } ; Make sure that for a tail call, taint doesn't get put into SP twice. define i32 @tail_caller(i32 %a) local_unnamed_addr SLHATTR { ; CHECK-LABEL: tail_caller: -; SLH: mov x17, sp -; SLH: and x17, x17, x16 -; SLH: mov sp, x17 -; NOSLH-NOT: mov x17, sp -; NOSLH-NOT: and x17, x17, x16 -; NOSLH-NOT: mov sp, x17 +; NOGISELSLH: mov [[TMPREG:x[0-9]+]], sp +; NOGISELSLH: and [[TMPREG]], [[TMPREG]], x16 +; NOGISELSLH: mov sp, [[TMPREG]] +; NOGISELNOSLH-NOT: mov [[TMPREG:x[0-9]+]], sp +; NOGISELNOSLH-NOT: and [[TMPREG]], [[TMPREG]], x16 +; NOGISELNOSLH-NOT: mov sp, [[TMPREG]] +; GISELSLH: mov [[TMPREG:x[0-9]+]], sp +; GISELSLH: and [[TMPREG]], [[TMPREG]], x16 +; GISELSLH: mov sp, [[TMPREG]] +; GISELNOSLH-NOT: mov [[TMPREG:x[0-9]+]], sp +; GISELNOSLH-NOT: and [[TMPREG]], [[TMPREG]], x16 +; GISELNOSLH-NOT: mov sp, [[TMPREG]] ; GlobalISel doesn't optimize tail calls (yet?), so only check that ; cross-call taint register setup code is missing if a tail call was ; actually produced. -; SLH: {{(bl tail_callee[[:space:]] cmp sp, #0)|(b tail_callee)}} -; SLH-NOT: cmp sp, #0 +; NOGISELSLH: b tail_callee +; GISELSLH: bl tail_callee +; GISELSLH: cmp sp, #0 +; SLH-NOT: cmp sp, #0 %call = tail call i32 @tail_callee(i32 %a) ret i32 %call } diff --git a/llvm/test/CodeGen/AArch64/speculation-hardening.mir b/llvm/test/CodeGen/AArch64/speculation-hardening.mir index cf8357d9558b0..5991c4df0407f 100644 --- a/llvm/test/CodeGen/AArch64/speculation-hardening.mir +++ b/llvm/test/CodeGen/AArch64/speculation-hardening.mir @@ -25,6 +25,22 @@ define void @indirectbranch(i32 %a, i32 %b) speculative_load_hardening { ret void } + ; Also check that a non-default temporary register gets picked correctly to + ; transfer the SP to to and it with the taint register when the default + ; temporary isn't available. + define void @indirect_call_x17(i32 %a, i32 %b) speculative_load_hardening { + ret void + } + @g = common dso_local local_unnamed_addr global i64 (...)* null, align 8 + define void @indirect_tailcall_x17(i32 %a, i32 %b) speculative_load_hardening { + ret void + } + define void @indirect_call_lr(i32 %a, i32 %b) speculative_load_hardening { + ret void + } + define void @RS_cannot_find_available_regs() speculative_load_hardening { + ret void + } ... --- name: nobranch_fallthrough @@ -115,3 +131,72 @@ body: | ; CHECK-NOT: csel RET undef $lr, implicit $x0 ... +--- +name: indirect_call_x17 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x17 + ; CHECK-LABEL: indirect_call_x17 + ; CHECK: mov x0, sp + ; CHECK: and x0, x0, x16 + ; CHECK: mov sp, x0 + ; CHECK: blr x17 + BLR killed renamable $x17, implicit-def dead $lr, implicit $sp + RET undef $lr, implicit undef $w0 +... +--- +name: indirect_tailcall_x17 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x0 + ; CHECK-LABEL: indirect_tailcall_x17 + ; CHECK: mov x1, sp + ; CHECK: and x1, x1, x16 + ; CHECK: mov sp, x1 + ; CHECK: br x17 + $x8 = ADRP target-flags(aarch64-page) @g + $x17 = LDRXui killed $x8, target-flags(aarch64-pageoff, aarch64-nc) @g + TCRETURNri killed $x17, 0, implicit $sp, implicit $x0 +... +--- +name: indirect_call_lr +tracksRegLiveness: true +body: | + bb.0: + ; CHECK-LABEL: indirect_call_lr + ; CHECK: mov x1, sp + ; CHECK-NEXT: and x1, x1, x16 + ; CHECK-NEXT: mov sp, x1 + ; CHECK-NEXT: blr x30 + liveins: $x0, $lr + BLR killed renamable $lr, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $w0 + $w0 = nsw ADDWri killed $w0, 1, 0 + RET undef $lr, implicit $w0 +... +--- +name: RS_cannot_find_available_regs +tracksRegLiveness: true +body: | + bb.0: + ; In the rare case when no free temporary register is available for the + ; propagate taint-to-sp operation, just put in a full speculation barrier + ; (isb+dsb sy) at the start of the basic block. And don't put masks on + ; instructions for the rest of the basic block, since speculation in that + ; basic block was already done, so no need to do masking. + ; CHECK-LABEL: RS_cannot_find_available_regs + ; CHECK: dsb sy + ; CHECK-NEXT: isb + ; CHECK-NEXT: ldr x0, [x0] + ; The following 2 instructions come from propagating the taint encoded in + ; sp at function entry to x16. It turns out the taint info in x16 is not + ; used in this function, so those instructions could be optimized away. An + ; optimization for later if it turns out this situation occurs often enough. + ; CHECK-NEXT: cmp sp, #0 + ; CHECK-NEXT: csetm x16, ne + ; CHECK-NEXT: ret + liveins: $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15, $x17, $x18, $x19, $x20, $x21, $x22, $x23, $x24, $x25, $x26, $x27, $x28, $fp, $lr + $x0 = LDRXui killed $x0, 0 + RET undef $lr, implicit $x0 +... diff --git a/llvm/test/CodeGen/AArch64/win64-jumptable.ll b/llvm/test/CodeGen/AArch64/win64-jumptable.ll new file mode 100644 index 0000000000000..8148a593c91b7 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/win64-jumptable.ll @@ -0,0 +1,48 @@ +; RUN: llc -o - %s -mtriple=aarch64-windows -aarch64-enable-compress-jump-tables=0 | FileCheck %s + +define void @f(i32 %x) { +entry: + switch i32 %x, label %sw.epilog [ + i32 0, label %sw.bb + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + ] + +sw.bb: ; preds = %entry + tail call void @g(i32 0) #2 + br label %sw.epilog + +sw.bb1: ; preds = %entry + tail call void @g(i32 1) #2 + br label %sw.epilog + +sw.bb2: ; preds = %entry + tail call void @g(i32 2) #2 + br label %sw.epilog + +sw.bb3: ; preds = %entry + tail call void @g(i32 3) #2 + br label %sw.epilog + +sw.epilog: ; preds = %entry, %sw.bb3, %sw.bb2, %sw.bb1, %sw.bb + tail call void @g(i32 10) #2 + ret void +} + +declare void @g(i32) + +; CHECK: .text +; CHECK: f: +; CHECK: .seh_proc f +; CHECK: b g +; CHECK-NEXT: .p2align 2 +; CHECK-NEXT: .LJTI0_0: +; CHECK: .word .LBB0_2-.LJTI0_0 +; CHECK: .word .LBB0_3-.LJTI0_0 +; CHECK: .word .LBB0_4-.LJTI0_0 +; CHECK: .word .LBB0_5-.LJTI0_0 +; CHECK: .section .xdata,"dr" +; CHECK: .seh_handlerdata +; CHECK: .text +; CHECK: .seh_endproc diff --git a/llvm/test/CodeGen/AArch64/wineh-try-catch-cbz.ll b/llvm/test/CodeGen/AArch64/wineh-try-catch-cbz.ll new file mode 100644 index 0000000000000..7c64328f0a7d2 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/wineh-try-catch-cbz.ll @@ -0,0 +1,40 @@ +; RUN: llc < %s | FileCheck %s + +; Make sure the prologue is sane. (Doesn't need to exactly match this, +; but the original issue only reproduced if the cbz was immediately +; after the frame setup.) + +; CHECK: sub sp, sp, #32 +; CHECK-NEXT: stp x29, x30, [sp, #16] +; CHECK-NEXT: add x29, sp, #16 +; CHECK-NEXT: orr x1, xzr, #0xfffffffffffffffe +; CHECK-NEXT: stur x1, [x29, #-16] +; CHECK-NEXT: cbz w0, .LBB0_2 + +target datalayout = "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-unknown-windows-msvc19.11.0" + +; Function Attrs: uwtable +define dso_local void @"?f@@YAXH@Z"(i32 %x) local_unnamed_addr #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { +entry: + %cmp = icmp eq i32 %x, 0 + br i1 %cmp, label %try.cont, label %if.then + +if.then: ; preds = %entry + invoke void @"?g@@YAXXZ"() + to label %try.cont unwind label %catch.dispatch + +catch.dispatch: ; preds = %if.then + %0 = catchswitch within none [label %catch] unwind to caller + +catch: ; preds = %catch.dispatch + %1 = catchpad within %0 [i8* null, i32 64, i8* null] + catchret from %1 to label %try.cont + +try.cont: ; preds = %entry, %if.then, %catch + ret void +} + +declare dso_local void @"?g@@YAXXZ"() local_unnamed_addr #1 + +declare dso_local i32 @__CxxFrameHandler3(...) diff --git a/llvm/test/CodeGen/AArch64/wineh-try-catch.ll b/llvm/test/CodeGen/AArch64/wineh-try-catch.ll index 940a86282d39a..f4bb9d50a4347 100644 --- a/llvm/test/CodeGen/AArch64/wineh-try-catch.ll +++ b/llvm/test/CodeGen/AArch64/wineh-try-catch.ll @@ -22,8 +22,8 @@ ; CHECK: add x29, sp, #32 ; CHECK: sub sp, sp, #624 ; CHECK: mov x19, sp -; CHECK: orr x1, xzr, #0xfffffffffffffffe -; CHECK: stur x1, [x19] +; CHECK: orr x0, xzr, #0xfffffffffffffffe +; CHECK: stur x0, [x19] ; Now check that x is stored at fp - 20. We check that this is the same ; location accessed from the funclet to retrieve x. diff --git a/llvm/test/CodeGen/AArch64/wineh4.mir b/llvm/test/CodeGen/AArch64/wineh4.mir index 4d4cc892c2e82..3a324324431c7 100644 --- a/llvm/test/CodeGen/AArch64/wineh4.mir +++ b/llvm/test/CodeGen/AArch64/wineh4.mir @@ -1,7 +1,7 @@ # RUN: llc -o - %s -mtriple=aarch64-windows -start-after=prologepilog \ # RUN: -disable-branch-fold -filetype=obj \ # RUN: | llvm-readobj -unwind | FileCheck %s -# Check that multiple epilgoues are correctly placed in .xdata. +# Check that identical multiple epilgoues are correctly shared in .xdata. # CHECK: ExceptionData { # CHECK-NEXT: FunctionLength: 164 @@ -9,7 +9,7 @@ # CHECK-NEXT: ExceptionData: No # CHECK-NEXT: EpiloguePacked: No # CHECK-NEXT: EpilogueScopes: 2 -# CHECK-NEXT: ByteCodeLength: 48 +# CHECK-NEXT: ByteCodeLength: 32 # CHECK-NEXT: Prologue [ # CHECK-NEXT: 0xc80c ; stp x19, x20, [sp, #96] # CHECK-NEXT: 0xc88a ; stp x21, x22, [sp, #80] @@ -37,7 +37,7 @@ # CHECK-NEXT: } # CHECK-NEXT: EpilogueScope { # CHECK-NEXT: StartOffset: 33 -# CHECK-NEXT: EpilogueStartIndex: 30 +# CHECK-NEXT: EpilogueStartIndex: 15 # CHECK-NEXT: Opcodes [ # CHECK-NEXT: 0xc80c ; ldp x19, x20, [sp, #96] # CHECK-NEXT: 0xc88a ; ldp x21, x22, [sp, #80] diff --git a/llvm/test/CodeGen/AArch64/wineh8.mir b/llvm/test/CodeGen/AArch64/wineh8.mir new file mode 100644 index 0000000000000..606bc140b232d --- /dev/null +++ b/llvm/test/CodeGen/AArch64/wineh8.mir @@ -0,0 +1,225 @@ +# RUN: llc -o - %s -mtriple=aarch64-windows -start-after=prologepilog \ +# RUN: -disable-branch-fold -filetype=obj \ +# RUN: | llvm-readobj -unwind | FileCheck %s +# Check that non-identical multiple epilgoues are correctly shared in .xdata. + +# CHECK: ExceptionData { +# CHECK-NEXT: FunctionLength: 160 +# CHECK-NEXT: Version: 0 +# CHECK-NEXT: ExceptionData: No +# CHECK-NEXT: EpiloguePacked: No +# CHECK-NEXT: EpilogueScopes: 2 +# CHECK-NEXT: ByteCodeLength: 44 +# CHECK-NEXT: Prologue [ +# CHECK-NEXT: 0xc80c ; stp x19, x20, [sp, #96] +# CHECK-NEXT: 0xc88a ; stp x21, x22, [sp, #80] +# CHECK-NEXT: 0xc908 ; stp x23, x24, [sp, #64] +# CHECK-NEXT: 0xc986 ; stp x25, x26, [sp, #48] +# CHECK-NEXT: 0xca04 ; stp x27, x28, [sp, #32] +# CHECK-NEXT: 0xd802 ; stp d8, d9, [sp, #16] +# CHECK-NEXT: 0xda8d ; stp d10, d11, [sp, #-112]! +# CHECK-NEXT: 0xe4 ; end +# CHECK-NEXT: ] +# CHECK-NEXT: EpilogueScopes [ +# CHECK-NEXT: EpilogueScope { +# CHECK-NEXT: StartOffset: 16 +# CHECK-NEXT: EpilogueStartIndex: 15 +# CHECK-NEXT: Opcodes [ +# CHECK-NEXT: 0xc80c ; ldp x19, x20, [sp, #96] +# CHECK-NEXT: 0xc88a ; ldp x21, x22, [sp, #80] +# CHECK-NEXT: 0xc908 ; ldp x23, x24, [sp, #64] +# CHECK-NEXT: 0xc986 ; ldp x25, x26, [sp, #48] +# CHECK-NEXT: 0xd802 ; ldp d8, d9, [sp, #16] +# CHECK-NEXT: 0xda8d ; ldp d10, d11, [sp], #112 +# CHECK-NEXT: 0xe4 ; end +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: EpilogueScope { +# CHECK-NEXT: StartOffset: 32 +# CHECK-NEXT: EpilogueStartIndex: 28 +# CHECK-NEXT: Opcodes [ +# CHECK-NEXT: 0xc80c ; ldp x19, x20, [sp, #96] +# CHECK-NEXT: 0xc88a ; ldp x21, x22, [sp, #80] +# CHECK-NEXT: 0xc908 ; ldp x23, x24, [sp, #64] +# CHECK-NEXT: 0xc986 ; ldp x25, x26, [sp, #48] +# CHECK-NEXT: 0xca04 ; ldp x27, x28, [sp, #32] +# CHECK-NEXT: 0xd802 ; ldp d8, d9, [sp, #16] +# CHECK-NEXT: 0xda8d ; ldp d10, d11, [sp], #112 +# CHECK-NEXT: 0xe4 ; end +# CHECK-NEXT: ] +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } +... +--- +name: test +alignment: 2 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: true +registers: +liveins: + - { reg: '$w0', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 112 + offsetAdjustment: 0 + maxAlignment: 8 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: true + hasVAStart: false + hasMustTailInVarArgFunc: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: +stack: + - { id: 0, name: '', type: spill-slot, offset: -8, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '$x19', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '$x20', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 2, name: '', type: spill-slot, offset: -24, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '$x21', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 3, name: '', type: spill-slot, offset: -32, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '$x22', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 4, name: '', type: spill-slot, offset: -40, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '$x23', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 5, name: '', type: spill-slot, offset: -48, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '$x24', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 6, name: '', type: spill-slot, offset: -56, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '$x25', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 7, name: '', type: spill-slot, offset: -64, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '$x26', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 8, name: '', type: spill-slot, offset: -72, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '$x27', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 9, name: '', type: spill-slot, offset: -80, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '$x28', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 10, name: '', type: spill-slot, offset: -88, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '$d8', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 11, name: '', type: spill-slot, offset: -96, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '$d9', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 12, name: '', type: spill-slot, offset: -104, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '$d10', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 13, name: '', type: spill-slot, offset: -112, size: 8, alignment: 8, + stack-id: 0, callee-saved-register: '$d11', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +constants: +body: | + bb.0.entry: + successors: %bb.2(0x40000000), %bb.1(0x40000000) + liveins: $x0, $x1, $d0, $d1, $d10, $d11, $d8, $d9, $x27, $x28, $x25, $x26, $x23, $x24, $x21, $x22, $x19, $x20 + + early-clobber $sp = frame-setup STPDpre killed $d10, killed $d11, $sp, -14 :: (store 8 into %stack.12), (store 8 into %stack.13) + frame-setup SEH_SaveFRegP_X 10, 11, -112 + frame-setup STPDi killed $d8, killed $d9, $sp, 2 :: (store 8 into %stack.10), (store 8 into %stack.11) + frame-setup SEH_SaveFRegP 8, 9, 16 + frame-setup STPXi killed $x27, killed $x28, $sp, 4 :: (store 8 into %stack.8), (store 8 into %stack.9) + frame-setup SEH_SaveRegP 27, 28, 32 + frame-setup STPXi killed $x25, killed $x26, $sp, 6 :: (store 8 into %stack.6), (store 8 into %stack.7) + frame-setup SEH_SaveRegP 25, 26, 48 + frame-setup STPXi killed $x23, killed $x24, $sp, 8 :: (store 8 into %stack.4), (store 8 into %stack.5) + frame-setup SEH_SaveRegP 23, 24, 64 + frame-setup STPXi killed $x21, killed $x22, $sp, 10 :: (store 8 into %stack.2), (store 8 into %stack.3) + frame-setup SEH_SaveRegP 21, 22, 80 + frame-setup STPXi killed $x19, killed $x20, $sp, 12 :: (store 8 into %stack.0), (store 8 into %stack.1) + frame-setup SEH_SaveRegP 19, 20, 96 + frame-setup SEH_PrologEnd + frame-setup CFI_INSTRUCTION def_cfa_offset 112 + frame-setup CFI_INSTRUCTION offset $w19, -8 + frame-setup CFI_INSTRUCTION offset $w20, -16 + frame-setup CFI_INSTRUCTION offset $w21, -24 + frame-setup CFI_INSTRUCTION offset $w22, -32 + frame-setup CFI_INSTRUCTION offset $w23, -40 + frame-setup CFI_INSTRUCTION offset $w24, -48 + frame-setup CFI_INSTRUCTION offset $w25, -56 + frame-setup CFI_INSTRUCTION offset $w26, -64 + frame-setup CFI_INSTRUCTION offset $w27, -72 + frame-setup CFI_INSTRUCTION offset $w28, -80 + frame-setup CFI_INSTRUCTION offset $b8, -88 + frame-setup CFI_INSTRUCTION offset $b9, -96 + frame-setup CFI_INSTRUCTION offset $b10, -104 + frame-setup CFI_INSTRUCTION offset $b11, -112 + $x19 = ADDXrr $x0, killed $x1 + $d8 = FADDDrr killed $d0, $d1 + $d9 = FADDDrr $d8, $d1 + $d10 = FADDDrr $d9, $d8 + $d11 = FADDDrr killed $d9, $d10 + $x20 = SUBSXrr $x19, killed $x0, implicit-def $nzcv + Bcc 1, %bb.2, implicit killed $nzcv + B %bb.1 + + bb.1: + liveins: $x19, $x20 + + $x21 = ADDXrr $x20, killed $x19 + $x22 = ADDXrr $x21, killed $x20 + $x23 = ADDXrr $x22, killed $x21 + $x24 = ADDXrr $x23, killed $x22 + $x25 = ADDXrr $x24, killed $x23 + $x26 = ADDXrr $x25, killed $x24 + $x27 = ADDXrr $x26, killed $x25 + $x28 = ADDXrr $x27, killed $x26 + $x0 = COPY $x28 + frame-destroy SEH_EpilogStart + $x19, $x20 = frame-destroy LDPXi $sp, 12 :: (load 8 from %stack.0), (load 8 from %stack.1) + frame-destroy SEH_SaveRegP 19, 20, 96 + $x21, $x22 = frame-destroy LDPXi $sp, 10 :: (load 8 from %stack.2), (load 8 from %stack.3) + frame-destroy SEH_SaveRegP 21, 22, 80 + $x23, $x24 = frame-destroy LDPXi $sp, 8 :: (load 8 from %stack.4), (load 8 from %stack.5) + frame-destroy SEH_SaveRegP 23, 24, 64 + $x25, $x26 = frame-destroy LDPXi $sp, 6 :: (load 8 from %stack.6), (load 8 from %stack.7) + frame-destroy SEH_SaveRegP 25, 26, 48 + $x27, $x28 = frame-destroy LDPXi $sp, 4 :: (load 8 from %stack.8), (load 8 from %stack.9) + frame-destroy SEH_SaveRegP 27, 28, 32 + $d8, $d9 = frame-destroy LDPDi $sp, 2 :: (load 8 from %stack.10), (load 8 from %stack.11) + frame-destroy SEH_SaveFRegP 8, 9, 16 + early-clobber $sp, $d10, $d11 = frame-destroy LDPDpost $sp, 14 :: (load 8 from %stack.12), (load 8 from %stack.13) + frame-destroy SEH_SaveFRegP_X 10, 11, -112 + frame-destroy SEH_EpilogEnd + RET_ReallyLR implicit $x0 + + bb.2: + liveins: $x28, $d11 + + $x0 = COPY $d11 + $x0 = ADDXrr $x0, killed $x28 + frame-destroy SEH_EpilogStart + $x19, $x20 = frame-destroy LDPXi $sp, 12 :: (load 8 from %stack.0), (load 8 from %stack.1) + frame-destroy SEH_SaveRegP 19, 20, 96 + $x21, $x22 = frame-destroy LDPXi $sp, 10 :: (load 8 from %stack.2), (load 8 from %stack.3) + frame-destroy SEH_SaveRegP 21, 22, 80 + $x23, $x24 = frame-destroy LDPXi $sp, 8 :: (load 8 from %stack.4), (load 8 from %stack.5) + frame-destroy SEH_SaveRegP 23, 24, 64 + $x25, $x26 = frame-destroy LDPXi $sp, 6 :: (load 8 from %stack.6), (load 8 from %stack.7) + frame-destroy SEH_SaveRegP 25, 26, 48 + $d8, $d9 = frame-destroy LDPDi $sp, 2 :: (load 8 from %stack.10), (load 8 from %stack.11) + frame-destroy SEH_SaveFRegP 8, 9, 16 + early-clobber $sp, $d10, $d11 = frame-destroy LDPDpost $sp, 14 :: (load 8 from %stack.12), (load 8 from %stack.13) + frame-destroy SEH_SaveFRegP_X 10, 11, -112 + frame-destroy SEH_EpilogEnd + RET_ReallyLR implicit $x0 + +... diff --git a/llvm/test/CodeGen/AMDGPU/add.ll b/llvm/test/CodeGen/AMDGPU/add.ll index 6a108db879cc7..bce924ec4a081 100644 --- a/llvm/test/CodeGen/AMDGPU/add.ll +++ b/llvm/test/CodeGen/AMDGPU/add.ll @@ -1,11 +1,8 @@ ; RUN: llc -march=amdgcn -mcpu=verde -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,SIVI,FUNC %s ; RUN: llc -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,SIVI,FUNC %s ; RUN: llc -march=amdgcn -mcpu=gfx900 -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GFX9,FUNC %s -; RUN: llc -march=r600 -mcpu=redwood < %s | FileCheck -enable-var-scope -check-prefix=EG -check-prefix=FUNC %s ; FUNC-LABEL: {{^}}s_add_i32: -; EG: ADD_INT {{[* ]*}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} - ; GCN: s_add_i32 s[[REG:[0-9]+]], {{s[0-9]+, s[0-9]+}} ; GCN: v_mov_b32_e32 v[[V_REG:[0-9]+]], s[[REG]] ; GCN: buffer_store_dword v[[V_REG]], @@ -19,9 +16,6 @@ define amdgpu_kernel void @s_add_i32(i32 addrspace(1)* %out, i32 addrspace(1)* % } ; FUNC-LABEL: {{^}}s_add_v2i32: -; EG: ADD_INT {{[* ]*}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} -; EG: ADD_INT {{[* ]*}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} - ; GCN: s_add_i32 s{{[0-9]+, s[0-9]+, s[0-9]+}} ; GCN: s_add_i32 s{{[0-9]+, s[0-9]+, s[0-9]+}} define amdgpu_kernel void @s_add_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32> addrspace(1)* %in) { @@ -34,11 +28,6 @@ define amdgpu_kernel void @s_add_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32> a } ; FUNC-LABEL: {{^}}s_add_v4i32: -; EG: ADD_INT {{[* ]*}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} -; EG: ADD_INT {{[* ]*}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} -; EG: ADD_INT {{[* ]*}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} -; EG: ADD_INT {{[* ]*}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} - ; GCN: s_add_i32 s{{[0-9]+, s[0-9]+, s[0-9]+}} ; GCN: s_add_i32 s{{[0-9]+, s[0-9]+, s[0-9]+}} ; GCN: s_add_i32 s{{[0-9]+, s[0-9]+, s[0-9]+}} @@ -53,15 +42,6 @@ define amdgpu_kernel void @s_add_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32> a } ; FUNC-LABEL: {{^}}s_add_v8i32: -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT - ; GCN: s_add_i32 ; GCN: s_add_i32 ; GCN: s_add_i32 @@ -78,23 +58,6 @@ entry: } ; FUNC-LABEL: {{^}}s_add_v16i32: -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT -; EG: ADD_INT - ; GCN: s_add_i32 ; GCN: s_add_i32 ; GCN: s_add_i32 @@ -124,7 +87,7 @@ entry: ; SIVI: v_add_{{i|u}}32_e32 v{{[0-9]+}}, vcc, [[A]], [[B]] ; GFX9: v_add_u32_e32 v{{[0-9]+}}, [[A]], [[B]] define amdgpu_kernel void @v_add_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 { - %tid = call i32 @llvm.r600.read.tidig.x() + %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep = getelementptr inbounds i32, i32 addrspace(1)* %in, i32 %tid %b_ptr = getelementptr i32, i32 addrspace(1)* %gep, i32 1 %a = load volatile i32, i32 addrspace(1)* %gep @@ -139,7 +102,7 @@ define amdgpu_kernel void @v_add_i32(i32 addrspace(1)* %out, i32 addrspace(1)* % ; SIVI: v_add_{{i|u}}32_e32 v{{[0-9]+}}, vcc, 0x7b, [[A]] ; GFX9: v_add_u32_e32 v{{[0-9]+}}, 0x7b, [[A]] define amdgpu_kernel void @v_add_imm_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 { - %tid = call i32 @llvm.r600.read.tidig.x() + %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep = getelementptr inbounds i32, i32 addrspace(1)* %in, i32 %tid %b_ptr = getelementptr i32, i32 addrspace(1)* %gep, i32 1 %a = load volatile i32, i32 addrspace(1)* %gep @@ -151,13 +114,6 @@ define amdgpu_kernel void @v_add_imm_i32(i32 addrspace(1)* %out, i32 addrspace(1 ; FUNC-LABEL: {{^}}add64: ; GCN: s_add_u32 ; GCN: s_addc_u32 - -; EG: MEM_RAT_CACHELESS STORE_RAW [[LO:T[0-9]+\.XY]] -; EG-DAG: ADD_INT {{[* ]*}} -; EG-DAG: ADDC_UINT -; EG-DAG: ADD_INT -; EG-DAG: ADD_INT {{[* ]*}} -; EG-NOT: SUB define amdgpu_kernel void @add64(i64 addrspace(1)* %out, i64 %a, i64 %b) { entry: %add = add i64 %a, %b @@ -172,13 +128,6 @@ entry: ; FUNC-LABEL: {{^}}add64_sgpr_vgpr: ; GCN-NOT: v_addc_u32_e32 s - -; EG: MEM_RAT_CACHELESS STORE_RAW [[LO:T[0-9]+\.XY]] -; EG-DAG: ADD_INT {{[* ]*}} -; EG-DAG: ADDC_UINT -; EG-DAG: ADD_INT -; EG-DAG: ADD_INT {{[* ]*}} -; EG-NOT: SUB define amdgpu_kernel void @add64_sgpr_vgpr(i64 addrspace(1)* %out, i64 %a, i64 addrspace(1)* %in) { entry: %0 = load i64, i64 addrspace(1)* %in @@ -191,13 +140,6 @@ entry: ; FUNC-LABEL: {{^}}add64_in_branch: ; GCN: s_add_u32 ; GCN: s_addc_u32 - -; EG: MEM_RAT_CACHELESS STORE_RAW [[LO:T[0-9]+\.XY]] -; EG-DAG: ADD_INT {{[* ]*}} -; EG-DAG: ADDC_UINT -; EG-DAG: ADD_INT -; EG-DAG: ADD_INT {{[* ]*}} -; EG-NOT: SUB define amdgpu_kernel void @add64_in_branch(i64 addrspace(1)* %out, i64 addrspace(1)* %in, i64 %a, i64 %b, i64 %c) { entry: %0 = icmp eq i64 %a, 0 @@ -217,7 +159,26 @@ endif: ret void } -declare i32 @llvm.r600.read.tidig.x() #1 +; Make sure the VOP3 form of add is initially selected. Otherwise pair +; of opies from/to VCC would be necessary + +; GCN-LABEL: {{^}}add_select_vop3: +; SI: v_add_i32_e64 v0, s[0:1], s0, v0 +; VI: v_add_u32_e64 v0, s[0:1], s0, v0 +; GFX9: v_add_u32_e32 v0, s0, v0 + +; GCN: ; def vcc +; GCN: ds_write_b32 +; GCN: ; use vcc +define amdgpu_ps void @add_select_vop3(i32 inreg %s, i32 %v) { + %vcc = call i64 asm sideeffect "; def vcc", "={vcc}"() + %sub = add i32 %v, %s + store i32 %sub, i32 addrspace(3)* undef + call void asm sideeffect "; use vcc", "{vcc}"(i64 %vcc) + ret void +} + +declare i32 @llvm.amdgcn.workitem.id.x() #1 attributes #0 = { nounwind } attributes #1 = { nounwind readnone speculatable } diff --git a/llvm/test/CodeGen/AMDGPU/ds-negative-offset-addressing-mode-loop.ll b/llvm/test/CodeGen/AMDGPU/ds-negative-offset-addressing-mode-loop.ll index 5997e27fd815e..e2c7f1c47cf9f 100644 --- a/llvm/test/CodeGen/AMDGPU/ds-negative-offset-addressing-mode-loop.ll +++ b/llvm/test/CodeGen/AMDGPU/ds-negative-offset-addressing-mode-loop.ll @@ -7,6 +7,8 @@ declare void @llvm.amdgcn.s.barrier() #1 ; Function Attrs: nounwind ; CHECK-LABEL: {{^}}signed_ds_offset_addressing_loop: +; SI: s_movk_i32 [[K_0X88:s[0-9]+]], 0x +; SI: s_movk_i32 [[K_0X100:s[0-9]+]], 0x100 ; CHECK: BB0_1: ; CHECK: v_add_i32_e32 [[VADDR:v[0-9]+]], ; SI-DAG: ds_read_b32 v{{[0-9]+}}, [[VADDR]] @@ -14,9 +16,9 @@ declare void @llvm.amdgcn.s.barrier() #1 ; SI-DAG: ds_read_b32 v{{[0-9]+}}, [[VADDR8]] ; SI-DAG: v_add_i32_e32 [[VADDR0x80:v[0-9]+]], vcc, 0x80, [[VADDR]] ; SI-DAG: ds_read_b32 v{{[0-9]+}}, [[VADDR0x80]] -; SI-DAG: v_add_i32_e32 [[VADDR0x88:v[0-9]+]], vcc, 0x88, [[VADDR]] +; SI-DAG: v_add_i32_e32 [[VADDR0x88:v[0-9]+]], vcc, [[K_0X88]], [[VADDR]] ; SI-DAG: ds_read_b32 v{{[0-9]+}}, [[VADDR0x88]] -; SI-DAG: v_add_i32_e32 [[VADDR0x100:v[0-9]+]], vcc, 0x100, [[VADDR]] +; SI-DAG: v_add_i32_e32 [[VADDR0x100:v[0-9]+]], vcc, [[K_0X100]], [[VADDR]] ; SI-DAG: ds_read_b32 v{{[0-9]+}}, [[VADDR0x100]] ; CI-DAG: ds_read2_b32 v{{\[[0-9]+:[0-9]+\]}}, [[VADDR]] offset1:2 diff --git a/llvm/test/CodeGen/AMDGPU/fence-barrier.ll b/llvm/test/CodeGen/AMDGPU/fence-barrier.ll index 8f5a06d01fa22..7de4f1796b08a 100644 --- a/llvm/test/CodeGen/AMDGPU/fence-barrier.ll +++ b/llvm/test/CodeGen/AMDGPU/fence-barrier.ll @@ -54,7 +54,8 @@ define amdgpu_kernel void @test_local(i32 addrspace(1)*) { } ; GCN-LABEL: {{^}}test_global -; GCN: v_add_u32_e32 v{{[0-9]+}}, vcc, 0x888, v{{[0-9]+}} +; GCN: s_movk_i32 [[K:s[0-9]+]], 0x888 +; GCN: v_add_u32_e32 v{{[0-9]+}}, vcc, [[K]], v{{[0-9]+}} ; GCN: flat_store_dword ; GCN: s_waitcnt vmcnt(0) lgkmcnt(0){{$}} ; GCN-NEXT: s_barrier diff --git a/llvm/test/CodeGen/AMDGPU/fold-fi-operand-shrink.mir b/llvm/test/CodeGen/AMDGPU/fold-fi-operand-shrink.mir new file mode 100644 index 0000000000000..ab544665efb41 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/fold-fi-operand-shrink.mir @@ -0,0 +1,230 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=amdgcn-amd-amdhsa -verify-machineinstrs -run-pass si-fold-operands,dead-mi-elimination %s -o - | FileCheck -check-prefix=GCN %s + +--- + +# First operand is FI is in a VGPR, other operand is a VGPR +name: shrink_vgpr_fi_vgpr_v_add_i32_e64_no_carry_out_use +tracksRegLiveness: true +stack: + - { id: 0, type: default, offset: 0, size: 64, alignment: 16 } +body: | + bb.0: + liveins: $vgpr0 + + ; GCN-LABEL: name: shrink_vgpr_fi_vgpr_v_add_i32_e64_no_carry_out_use + ; GCN: liveins: $vgpr0 + ; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + ; GCN: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN: [[V_ADD_I32_e32_:%[0-9]+]]:vgpr_32 = V_ADD_I32_e32 [[V_MOV_B32_e32_]], [[COPY]], implicit-def $vcc, implicit $exec + ; GCN: S_ENDPGM implicit [[V_ADD_I32_e32_]] + %0:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + %1:vgpr_32 = COPY $vgpr0 + %2:vgpr_32, %3:sreg_64 = V_ADD_I32_e64 %0, %1, implicit $exec + S_ENDPGM implicit %2 + +... + +--- + +# First operand is a VGPR, other operand FI is in a VGPR +name: shrink_vgpr_vgpr_fi_v_add_i32_e64_no_carry_out_use +tracksRegLiveness: true +stack: + - { id: 0, type: default, offset: 0, size: 64, alignment: 16 } +body: | + bb.0: + liveins: $vgpr0 + + ; GCN-LABEL: name: shrink_vgpr_vgpr_fi_v_add_i32_e64_no_carry_out_use + ; GCN: liveins: $vgpr0 + ; GCN: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + ; GCN: [[V_ADD_I32_e32_:%[0-9]+]]:vgpr_32 = V_ADD_I32_e32 [[COPY]], [[V_MOV_B32_e32_]], implicit-def $vcc, implicit $exec + ; GCN: S_ENDPGM implicit [[V_ADD_I32_e32_]] + %0:vgpr_32 = COPY $vgpr0 + %1:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + %2:vgpr_32, %3:sreg_64 = V_ADD_I32_e64 %0, %1, implicit $exec + S_ENDPGM implicit %2 + +... + +--- + +# First operand is FI is in an SGPR, other operand is a VGPR +name: shrink_vgpr_fi_sgpr_v_add_i32_e64_no_carry_out_use +tracksRegLiveness: true +stack: + - { id: 0, type: default, offset: 0, size: 64, alignment: 16 } +body: | + bb.0: + liveins: $sgpr0 + + ; GCN-LABEL: name: shrink_vgpr_fi_sgpr_v_add_i32_e64_no_carry_out_use + ; GCN: liveins: $sgpr0 + ; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + ; GCN: [[COPY:%[0-9]+]]:sreg_32_xm0 = COPY $sgpr0 + ; GCN: [[V_ADD_I32_e64_:%[0-9]+]]:vgpr_32, [[V_ADD_I32_e64_1:%[0-9]+]]:sreg_64 = V_ADD_I32_e64 [[COPY]], [[V_MOV_B32_e32_]], implicit $exec + ; GCN: S_ENDPGM implicit [[V_ADD_I32_e64_]] + %0:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + %1:sreg_32_xm0 = COPY $sgpr0 + %2:vgpr_32, %3:sreg_64 = V_ADD_I32_e64 %0, %1, implicit $exec + S_ENDPGM implicit %2 + +... + +--- + +# First operand is an SGPR, other operand FI is in a VGPR +name: shrink_sgpr_vgpr_fi_v_add_i32_e64_no_carry_out_use +tracksRegLiveness: true +stack: + - { id: 0, type: default, offset: 0, size: 64, alignment: 16 } +body: | + bb.0: + liveins: $sgpr0 + + ; GCN-LABEL: name: shrink_sgpr_vgpr_fi_v_add_i32_e64_no_carry_out_use + ; GCN: liveins: $sgpr0 + ; GCN: [[COPY:%[0-9]+]]:sreg_32_xm0 = COPY $sgpr0 + ; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + ; GCN: [[V_ADD_I32_e64_:%[0-9]+]]:vgpr_32, [[V_ADD_I32_e64_1:%[0-9]+]]:sreg_64 = V_ADD_I32_e64 [[V_MOV_B32_e32_]], [[COPY]], implicit $exec + ; GCN: S_ENDPGM implicit [[V_ADD_I32_e64_]] + %0:sreg_32_xm0 = COPY $sgpr0 + %1:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + %2:vgpr_32, %3:sreg_64 = V_ADD_I32_e64 %0, %1, implicit $exec + S_ENDPGM implicit %2 + +... + +--- + +# First operand is FI is in an SGPR, other operand is a VGPR +name: shrink_sgpr_fi_vgpr_v_add_i32_e64_no_carry_out_use +tracksRegLiveness: true +stack: + - { id: 0, type: default, offset: 0, size: 64, alignment: 16 } +body: | + bb.0: + liveins: $vgpr0 + + ; GCN-LABEL: name: shrink_sgpr_fi_vgpr_v_add_i32_e64_no_carry_out_use + ; GCN: liveins: $vgpr0 + ; GCN: [[S_MOV_B32_:%[0-9]+]]:sreg_32_xm0 = S_MOV_B32 %stack.0 + ; GCN: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN: [[V_ADD_I32_e32_:%[0-9]+]]:vgpr_32 = V_ADD_I32_e32 [[S_MOV_B32_]], [[COPY]], implicit-def $vcc, implicit $exec + ; GCN: S_ENDPGM implicit [[V_ADD_I32_e32_]] + %0:sreg_32_xm0 = S_MOV_B32 %stack.0 + %1:vgpr_32 = COPY $vgpr0 + %2:vgpr_32, %3:sreg_64 = V_ADD_I32_e64 %0, %1, implicit $exec + S_ENDPGM implicit %2 + +... + +--- + +# First operand is a VGPR, other operand FI is in an SGPR +name: shrink_vgpr_sgpr_fi_v_add_i32_e64_no_carry_out_use +tracksRegLiveness: true +stack: + - { id: 0, type: default, offset: 0, size: 64, alignment: 16} +body: | + bb.0: + liveins: $vgpr0 + + ; GCN-LABEL: name: shrink_vgpr_sgpr_fi_v_add_i32_e64_no_carry_out_use + ; GCN: liveins: $vgpr0 + ; GCN: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN: [[S_MOV_B32_:%[0-9]+]]:sreg_32_xm0 = S_MOV_B32 %stack.0 + ; GCN: [[V_ADD_I32_e32_:%[0-9]+]]:vgpr_32 = V_ADD_I32_e32 [[S_MOV_B32_]], [[COPY]], implicit-def $vcc, implicit $exec + ; GCN: S_ENDPGM implicit [[V_ADD_I32_e32_]] + %0:vgpr_32 = COPY $vgpr0 + %1:sreg_32_xm0 = S_MOV_B32 %stack.0 + %2:vgpr_32, %3:sreg_64 = V_ADD_I32_e64 %0, %1, implicit $exec + S_ENDPGM implicit %2 + +... + +--- + +# First operand is FI is in a VGPR, other operand is an inline imm in a VGPR +name: shrink_vgpr_imm_fi_vgpr_v_add_i32_e64_no_carry_out_use +tracksRegLiveness: true +stack: + - { id: 0, type: default, offset: 0, size: 64, alignment: 16 } +body: | + bb.0: + + ; GCN-LABEL: name: shrink_vgpr_imm_fi_vgpr_v_add_i32_e64_no_carry_out_use + ; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + ; GCN: [[V_ADD_I32_e32_:%[0-9]+]]:vgpr_32 = V_ADD_I32_e32 16, [[V_MOV_B32_e32_]], implicit-def $vcc, implicit $exec + ; GCN: S_ENDPGM implicit [[V_ADD_I32_e32_]] + %0:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + %1:vgpr_32 = V_MOV_B32_e32 16, implicit $exec + %2:vgpr_32, %3:sreg_64 = V_ADD_I32_e64 %0, %1, implicit $exec + S_ENDPGM implicit %2 + +... + +--- + +# First operand is an inline imm in a VGPR, other operand FI is in a VGPR +name: shrink_vgpr_imm_vgpr_fi_v_add_i32_e64_no_carry_out_use +tracksRegLiveness: true +stack: + - { id: 0, type: default, offset: 0, size: 64, alignment: 16 } +body: | + bb.0: + + ; GCN-LABEL: name: shrink_vgpr_imm_vgpr_fi_v_add_i32_e64_no_carry_out_use + ; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + ; GCN: [[V_ADD_I32_e64_:%[0-9]+]]:vgpr_32, [[V_ADD_I32_e64_1:%[0-9]+]]:sreg_64 = V_ADD_I32_e64 16, [[V_MOV_B32_e32_]], implicit $exec + ; GCN: S_ENDPGM implicit [[V_ADD_I32_e64_]] + %0:vgpr_32 = V_MOV_B32_e32 16, implicit $exec + %1:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + %2:vgpr_32, %3:sreg_64 = V_ADD_I32_e64 %0, %1, implicit $exec + S_ENDPGM implicit %2 + +... + +--- + +# First operand is FI is in a VGPR, other operand is an literal constant in a VGPR +name: shrink_vgpr_k_fi_vgpr_v_add_i32_e64_no_carry_out_use +tracksRegLiveness: true +stack: + - { id: 0, type: default, offset: 0, size: 64, alignment: 16 } +body: | + bb.0: + + ; GCN-LABEL: name: shrink_vgpr_k_fi_vgpr_v_add_i32_e64_no_carry_out_use + ; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + ; GCN: [[V_ADD_I32_e32_:%[0-9]+]]:vgpr_32 = V_ADD_I32_e32 1234, [[V_MOV_B32_e32_]], implicit-def $vcc, implicit $exec + ; GCN: S_ENDPGM implicit [[V_ADD_I32_e32_]] + %0:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + %1:vgpr_32 = V_MOV_B32_e32 1234, implicit $exec + %2:vgpr_32, %3:sreg_64 = V_ADD_I32_e64 %0, %1, implicit $exec + S_ENDPGM implicit %2 + +... + +--- + +# First operand is a literal constant in a VGPR, other operand FI is in a VGPR +name: shrink_vgpr_k_vgpr_fi_v_add_i32_e64_no_carry_out_use +tracksRegLiveness: true +stack: + - { id: 0, type: default, offset: 0, size: 64, alignment: 16 } +body: | + bb.0: + + ; GCN-LABEL: name: shrink_vgpr_k_vgpr_fi_v_add_i32_e64_no_carry_out_use + ; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 1234, implicit $exec + ; GCN: [[V_ADD_I32_e32_:%[0-9]+]]:vgpr_32 = V_ADD_I32_e32 %stack.0, [[V_MOV_B32_e32_]], implicit-def $vcc, implicit $exec + ; GCN: S_ENDPGM implicit [[V_ADD_I32_e32_]] + %0:vgpr_32 = V_MOV_B32_e32 1234, implicit $exec + %1:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec + %2:vgpr_32, %3:sreg_64 = V_ADD_I32_e64 %0, %1, implicit $exec + S_ENDPGM implicit %2 + +... diff --git a/llvm/test/CodeGen/AMDGPU/fold-immediate-operand-shrink.mir b/llvm/test/CodeGen/AMDGPU/fold-immediate-operand-shrink.mir index 847c2b720cd4e..15c453f36f631 100644 --- a/llvm/test/CodeGen/AMDGPU/fold-immediate-operand-shrink.mir +++ b/llvm/test/CodeGen/AMDGPU/fold-immediate-operand-shrink.mir @@ -250,8 +250,8 @@ body: | ; GCN-LABEL: name: shrink_scalar_imm_vgpr_v_sub_i32_e64_no_carry_out_use ; GCN: [[S_MOV_B32_:%[0-9]+]]:sreg_32_xm0 = S_MOV_B32 12345 ; GCN: [[DEF:%[0-9]+]]:vgpr_32 = IMPLICIT_DEF - ; GCN: [[V_SUBREV_I32_e32_:%[0-9]+]]:vgpr_32 = V_SUBREV_I32_e32 [[S_MOV_B32_]], [[DEF]], implicit-def $vcc, implicit $exec - ; GCN: S_ENDPGM implicit [[V_SUBREV_I32_e32_]] + ; GCN: [[V_SUB_I32_e32_:%[0-9]+]]:vgpr_32 = V_SUB_I32_e32 [[S_MOV_B32_]], [[DEF]], implicit-def $vcc, implicit $exec + ; GCN: S_ENDPGM implicit [[V_SUB_I32_e32_]] %0:sreg_32_xm0 = S_MOV_B32 12345 %1:vgpr_32 = IMPLICIT_DEF %2:vgpr_32, %3:sreg_64 = V_SUB_I32_e64 %0, %1, implicit $exec @@ -269,8 +269,8 @@ body: | ; GCN-LABEL: name: shrink_vgpr_scalar_imm_v_sub_i32_e64_no_carry_out_use ; GCN: [[DEF:%[0-9]+]]:vgpr_32 = IMPLICIT_DEF ; GCN: [[S_MOV_B32_:%[0-9]+]]:sreg_32_xm0 = S_MOV_B32 12345 - ; GCN: [[V_SUB_I32_e32_:%[0-9]+]]:vgpr_32 = V_SUB_I32_e32 [[S_MOV_B32_]], [[DEF]], implicit-def $vcc, implicit $exec - ; GCN: S_ENDPGM implicit [[V_SUB_I32_e32_]] + ; GCN: [[V_SUBREV_I32_e32_:%[0-9]+]]:vgpr_32 = V_SUBREV_I32_e32 [[S_MOV_B32_]], [[DEF]], implicit-def $vcc, implicit $exec + ; GCN: S_ENDPGM implicit [[V_SUBREV_I32_e32_]] %0:vgpr_32 = IMPLICIT_DEF %1:sreg_32_xm0 = S_MOV_B32 12345 %2:vgpr_32, %3:sreg_64 = V_SUB_I32_e64 %0, %1, implicit $exec @@ -288,8 +288,8 @@ body: | ; GCN-LABEL: name: shrink_scalar_imm_vgpr_v_subrev_i32_e64_no_carry_out_use ; GCN: [[S_MOV_B32_:%[0-9]+]]:sreg_32_xm0 = S_MOV_B32 12345 ; GCN: [[DEF:%[0-9]+]]:vgpr_32 = IMPLICIT_DEF - ; GCN: [[V_SUB_I32_e32_:%[0-9]+]]:vgpr_32 = V_SUB_I32_e32 [[S_MOV_B32_]], [[DEF]], implicit-def $vcc, implicit $exec - ; GCN: S_ENDPGM implicit [[V_SUB_I32_e32_]] + ; GCN: [[V_SUBREV_I32_e32_:%[0-9]+]]:vgpr_32 = V_SUBREV_I32_e32 [[S_MOV_B32_]], [[DEF]], implicit-def $vcc, implicit $exec + ; GCN: S_ENDPGM implicit [[V_SUBREV_I32_e32_]] %0:sreg_32_xm0 = S_MOV_B32 12345 %1:vgpr_32 = IMPLICIT_DEF %2:vgpr_32, %3:sreg_64 = V_SUBREV_I32_e64 %0, %1, implicit $exec @@ -307,8 +307,8 @@ body: | ; GCN-LABEL: name: shrink_vgpr_scalar_imm_v_subrev_i32_e64_no_carry_out_use ; GCN: [[DEF:%[0-9]+]]:vgpr_32 = IMPLICIT_DEF ; GCN: [[S_MOV_B32_:%[0-9]+]]:sreg_32_xm0 = S_MOV_B32 12345 - ; GCN: [[V_SUBREV_I32_e32_:%[0-9]+]]:vgpr_32 = V_SUBREV_I32_e32 [[S_MOV_B32_]], [[DEF]], implicit-def $vcc, implicit $exec - ; GCN: S_ENDPGM implicit [[V_SUBREV_I32_e32_]] + ; GCN: [[V_SUB_I32_e32_:%[0-9]+]]:vgpr_32 = V_SUB_I32_e32 [[S_MOV_B32_]], [[DEF]], implicit-def $vcc, implicit $exec + ; GCN: S_ENDPGM implicit [[V_SUB_I32_e32_]] %0:vgpr_32 = IMPLICIT_DEF %1:sreg_32_xm0 = S_MOV_B32 12345 %2:vgpr_32, %3:sreg_64 = V_SUBREV_I32_e64 %0, %1, implicit $exec @@ -590,3 +590,59 @@ body: | S_ENDPGM implicit %2 ... + +--- +name: shrink_add_kill_flags_src0 +tracksRegLiveness: true +body: | + bb.0: + liveins: $vgpr0 + ; GCN-LABEL: name: shrink_add_kill_flags_src0 + ; GCN: liveins: $vgpr0 + ; GCN: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 518144, implicit $exec + ; GCN: [[V_ADD_I32_e32_:%[0-9]+]]:vgpr_32 = V_ADD_I32_e32 killed [[V_MOV_B32_e32_]], [[COPY]], implicit-def $vcc, implicit $exec + ; GCN: S_ENDPGM implicit [[V_ADD_I32_e32_]] + %0:vgpr_32 = COPY $vgpr0 + %1:vgpr_32 = V_MOV_B32_e32 518144, implicit $exec + %2:vgpr_32, %3:sreg_64_xexec = V_ADD_I32_e64 killed %1, %0, implicit $exec + S_ENDPGM implicit %2 +... + +--- +name: shrink_add_kill_flags_src1 +tracksRegLiveness: true +body: | + bb.0: + liveins: $vgpr0 + ; GCN-LABEL: name: shrink_add_kill_flags_src1 + ; GCN: liveins: $vgpr0 + ; GCN: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 518144, implicit $exec + ; GCN: [[V_ADD_I32_e32_:%[0-9]+]]:vgpr_32 = V_ADD_I32_e32 [[V_MOV_B32_e32_]], killed [[COPY]], implicit-def $vcc, implicit $exec + ; GCN: S_ENDPGM implicit [[V_ADD_I32_e32_]] + %0:vgpr_32 = COPY $vgpr0 + %1:vgpr_32 = V_MOV_B32_e32 518144, implicit $exec + %2:vgpr_32, %3:sreg_64_xexec = V_ADD_I32_e64 %1, killed %0, implicit $exec + S_ENDPGM implicit %2 +... + +--- +name: shrink_addc_kill_flags_src2 +tracksRegLiveness: true +body: | + bb.0: + liveins: $vgpr0, $vcc + ; GCN-LABEL: name: shrink_addc_kill_flags_src2 + ; GCN: liveins: $vgpr0, $vcc + ; GCN: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 518144, implicit $exec + ; GCN: [[COPY1:%[0-9]+]]:sreg_64_xexec = COPY $vcc + ; GCN: [[V_ADDC_U32_e64_:%[0-9]+]]:vgpr_32, [[V_ADDC_U32_e64_1:%[0-9]+]]:sreg_64_xexec = V_ADDC_U32_e64 [[V_MOV_B32_e32_]], [[COPY]], [[COPY1]], implicit $exec + ; GCN: S_ENDPGM implicit [[V_ADDC_U32_e64_]] + %0:vgpr_32 = COPY $vgpr0 + %1:vgpr_32 = V_MOV_B32_e32 518144, implicit $exec + %2:sreg_64_xexec = COPY $vcc + %3:vgpr_32, %4:sreg_64_xexec = V_ADDC_U32_e64 %1, %0, %2, implicit $exec + S_ENDPGM implicit %3 +... diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ds.ordered.add.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ds.ordered.add.ll new file mode 100644 index 0000000000000..ad489debc46cb --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ds.ordered.add.ll @@ -0,0 +1,96 @@ +; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,FUNC %s +; RUN: llc -march=amdgcn -mcpu=bonaire -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,FUNC %s +; RUN: llc -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,VIGFX9,FUNC %s +; RUN: llc -march=amdgcn -mcpu=gfx900 -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,VIGFX9,FUNC %s + +; FUNC-LABEL: {{^}}ds_ordered_add: +; GCN-DAG: v_mov_b32_e32 v[[INCR:[0-9]+]], 31 +; GCN-DAG: s_mov_b32 m0, +; GCN: ds_ordered_count v{{[0-9]+}}, v[[INCR]] offset:772 gds +define amdgpu_kernel void @ds_ordered_add(i32 addrspace(2)* inreg %gds, i32 addrspace(1)* %out) { + %val = call i32@llvm.amdgcn.ds.ordered.add(i32 addrspace(2)* %gds, i32 31, i32 0, i32 0, i1 false, i32 1, i1 true, i1 true) + store i32 %val, i32 addrspace(1)* %out + ret void +} + +; Below are various modifications of input operands and shader types. + +; FUNC-LABEL: {{^}}ds_ordered_add_counter2: +; GCN-DAG: v_mov_b32_e32 v[[INCR:[0-9]+]], 31 +; GCN-DAG: s_mov_b32 m0, +; GCN: ds_ordered_count v{{[0-9]+}}, v[[INCR]] offset:776 gds +define amdgpu_kernel void @ds_ordered_add_counter2(i32 addrspace(2)* inreg %gds, i32 addrspace(1)* %out) { + %val = call i32@llvm.amdgcn.ds.ordered.add(i32 addrspace(2)* %gds, i32 31, i32 0, i32 0, i1 false, i32 2, i1 true, i1 true) + store i32 %val, i32 addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}ds_ordered_add_nodone: +; GCN-DAG: v_mov_b32_e32 v[[INCR:[0-9]+]], 31 +; GCN-DAG: s_mov_b32 m0, +; GCN: ds_ordered_count v{{[0-9]+}}, v[[INCR]] offset:260 gds +define amdgpu_kernel void @ds_ordered_add_nodone(i32 addrspace(2)* inreg %gds, i32 addrspace(1)* %out) { + %val = call i32@llvm.amdgcn.ds.ordered.add(i32 addrspace(2)* %gds, i32 31, i32 0, i32 0, i1 false, i32 1, i1 true, i1 false) + store i32 %val, i32 addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}ds_ordered_add_norelease: +; GCN-DAG: v_mov_b32_e32 v[[INCR:[0-9]+]], 31 +; GCN-DAG: s_mov_b32 m0, +; GCN: ds_ordered_count v{{[0-9]+}}, v[[INCR]] offset:4 gds +define amdgpu_kernel void @ds_ordered_add_norelease(i32 addrspace(2)* inreg %gds, i32 addrspace(1)* %out) { + %val = call i32@llvm.amdgcn.ds.ordered.add(i32 addrspace(2)* %gds, i32 31, i32 0, i32 0, i1 false, i32 1, i1 false, i1 false) + store i32 %val, i32 addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}ds_ordered_add_cs: +; GCN: v_mov_b32_e32 v[[INCR:[0-9]+]], 31 +; GCN: s_mov_b32 m0, s0 +; VIGFX9-NEXT: s_nop 0 +; GCN-NEXT: ds_ordered_count v{{[0-9]+}}, v[[INCR]] offset:772 gds +; GCN-NEXT: s_waitcnt expcnt(0) lgkmcnt(0) +define amdgpu_cs float @ds_ordered_add_cs(i32 addrspace(2)* inreg %gds) { + %val = call i32@llvm.amdgcn.ds.ordered.add(i32 addrspace(2)* %gds, i32 31, i32 0, i32 0, i1 false, i32 1, i1 true, i1 true) + %r = bitcast i32 %val to float + ret float %r +} + +; FUNC-LABEL: {{^}}ds_ordered_add_ps: +; GCN: v_mov_b32_e32 v[[INCR:[0-9]+]], 31 +; GCN: s_mov_b32 m0, s0 +; VIGFX9-NEXT: s_nop 0 +; GCN-NEXT: ds_ordered_count v{{[0-9]+}}, v[[INCR]] offset:1796 gds +; GCN-NEXT: s_waitcnt expcnt(0) lgkmcnt(0) +define amdgpu_ps float @ds_ordered_add_ps(i32 addrspace(2)* inreg %gds) { + %val = call i32@llvm.amdgcn.ds.ordered.add(i32 addrspace(2)* %gds, i32 31, i32 0, i32 0, i1 false, i32 1, i1 true, i1 true) + %r = bitcast i32 %val to float + ret float %r +} + +; FUNC-LABEL: {{^}}ds_ordered_add_vs: +; GCN: v_mov_b32_e32 v[[INCR:[0-9]+]], 31 +; GCN: s_mov_b32 m0, s0 +; VIGFX9-NEXT: s_nop 0 +; GCN-NEXT: ds_ordered_count v{{[0-9]+}}, v[[INCR]] offset:2820 gds +; GCN-NEXT: s_waitcnt expcnt(0) lgkmcnt(0) +define amdgpu_vs float @ds_ordered_add_vs(i32 addrspace(2)* inreg %gds) { + %val = call i32@llvm.amdgcn.ds.ordered.add(i32 addrspace(2)* %gds, i32 31, i32 0, i32 0, i1 false, i32 1, i1 true, i1 true) + %r = bitcast i32 %val to float + ret float %r +} + +; FUNC-LABEL: {{^}}ds_ordered_add_gs: +; GCN: v_mov_b32_e32 v[[INCR:[0-9]+]], 31 +; GCN: s_mov_b32 m0, s0 +; VIGFX9-NEXT: s_nop 0 +; GCN-NEXT: ds_ordered_count v{{[0-9]+}}, v[[INCR]] offset:3844 gds +; GCN-NEXT: s_waitcnt expcnt(0) lgkmcnt(0) +define amdgpu_gs float @ds_ordered_add_gs(i32 addrspace(2)* inreg %gds) { + %val = call i32@llvm.amdgcn.ds.ordered.add(i32 addrspace(2)* %gds, i32 31, i32 0, i32 0, i1 false, i32 1, i1 true, i1 true) + %r = bitcast i32 %val to float + ret float %r +} + +declare i32 @llvm.amdgcn.ds.ordered.add(i32 addrspace(2)* nocapture, i32, i32, i32, i1, i32, i1, i1) diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ds.ordered.swap.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ds.ordered.swap.ll new file mode 100644 index 0000000000000..acb1133c6a0b8 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ds.ordered.swap.ll @@ -0,0 +1,45 @@ +; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,FUNC %s +; RUN: llc -march=amdgcn -mcpu=bonaire -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,FUNC %s +; RUN: llc -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,VIGFX9,FUNC %s +; RUN: llc -march=amdgcn -mcpu=gfx900 -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,VIGFX9,FUNC %s + +; FUNC-LABEL: {{^}}ds_ordered_swap: +; GCN: s_mov_b32 m0, s0 +; VIGFX9-NEXT: s_nop 0 +; GCN-NEXT: ds_ordered_count v{{[0-9]+}}, v0 offset:4868 gds +; GCN-NEXT: s_waitcnt expcnt(0) lgkmcnt(0) +define amdgpu_cs float @ds_ordered_swap(i32 addrspace(2)* inreg %gds, i32 %value) { + %val = call i32@llvm.amdgcn.ds.ordered.swap(i32 addrspace(2)* %gds, i32 %value, i32 0, i32 0, i1 false, i32 1, i1 true, i1 true) + %r = bitcast i32 %val to float + ret float %r +} + +; FUNC-LABEL: {{^}}ds_ordered_swap_conditional: +; GCN: v_cmp_ne_u32_e32 vcc, 0, v0 +; GCN: s_and_saveexec_b64 s[[SAVED:\[[0-9]+:[0-9]+\]]], vcc +; // We have to use s_cbranch, because ds_ordered_count has side effects with EXEC=0 +; GCN: s_cbranch_execz [[BB:BB._.]] +; GCN: s_mov_b32 m0, s0 +; VIGFX9-NEXT: s_nop 0 +; GCN-NEXT: ds_ordered_count v{{[0-9]+}}, v0 offset:4868 gds +; GCN-NEXT: [[BB]]: +; // Wait for expcnt(0) before modifying EXEC +; GCN-NEXT: s_waitcnt expcnt(0) +; GCN-NEXT: s_or_b64 exec, exec, s[[SAVED]] +; GCN-NEXT: s_waitcnt lgkmcnt(0) +define amdgpu_cs float @ds_ordered_swap_conditional(i32 addrspace(2)* inreg %gds, i32 %value) { +entry: + %c = icmp ne i32 %value, 0 + br i1 %c, label %if-true, label %endif + +if-true: + %val = call i32@llvm.amdgcn.ds.ordered.swap(i32 addrspace(2)* %gds, i32 %value, i32 0, i32 0, i1 false, i32 1, i1 true, i1 true) + br label %endif + +endif: + %v = phi i32 [ %val, %if-true ], [ undef, %entry ] + %r = bitcast i32 %v to float + ret float %r +} + +declare i32 @llvm.amdgcn.ds.ordered.swap(i32 addrspace(2)* nocapture, i32, i32, i32, i1, i32, i1, i1) diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.update.dpp.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.update.dpp.ll index 18abf607aea5a..77d518f503ab7 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.update.dpp.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.update.dpp.ll @@ -15,7 +15,8 @@ define amdgpu_kernel void @dpp_test(i32 addrspace(1)* %out, i32 %in1, i32 %in2) } ; VI-LABEL: {{^}}dpp_test1: -; VI: v_add_u32_e32 [[REG:v[0-9]+]], vcc, v{{[0-9]+}}, v{{[0-9]+}} +; VI-OPT: v_add_u32_e32 [[REG:v[0-9]+]], vcc, v{{[0-9]+}}, v{{[0-9]+}} +; VI-NOOPT: v_add_u32_e64 [[REG:v[0-9]+]], s{{\[[0-9]+:[0-9]+\]}}, v{{[0-9]+}}, v{{[0-9]+}} ; VI-NOOPT: v_mov_b32_e32 v{{[0-9]+}}, 0 ; VI-NEXT: s_nop 0 ; VI-NEXT: s_nop 0 diff --git a/llvm/test/CodeGen/AMDGPU/r600.add.ll b/llvm/test/CodeGen/AMDGPU/r600.add.ll new file mode 100644 index 0000000000000..73eea3ef21774 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/r600.add.ll @@ -0,0 +1,167 @@ +; RUN: llc -march=r600 -mcpu=redwood < %s | FileCheck -enable-var-scope -check-prefix=EG -check-prefix=FUNC %s + +; FUNC-LABEL: {{^}}s_add_i32: +; EG: ADD_INT {{[* ]*}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} +define amdgpu_kernel void @s_add_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 { + %b_ptr = getelementptr i32, i32 addrspace(1)* %in, i32 1 + %a = load i32, i32 addrspace(1)* %in + %b = load i32, i32 addrspace(1)* %b_ptr + %result = add i32 %a, %b + store i32 %result, i32 addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}s_add_v2i32: +; EG: ADD_INT {{[* ]*}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} +; EG: ADD_INT {{[* ]*}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} +define amdgpu_kernel void @s_add_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32> addrspace(1)* %in) { + %b_ptr = getelementptr <2 x i32>, <2 x i32> addrspace(1)* %in, i32 1 + %a = load <2 x i32>, <2 x i32> addrspace(1)* %in + %b = load <2 x i32>, <2 x i32> addrspace(1)* %b_ptr + %result = add <2 x i32> %a, %b + store <2 x i32> %result, <2 x i32> addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}s_add_v4i32: +; EG: ADD_INT {{[* ]*}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} +; EG: ADD_INT {{[* ]*}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} +; EG: ADD_INT {{[* ]*}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} +; EG: ADD_INT {{[* ]*}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} +define amdgpu_kernel void @s_add_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32> addrspace(1)* %in) { + %b_ptr = getelementptr <4 x i32>, <4 x i32> addrspace(1)* %in, i32 1 + %a = load <4 x i32>, <4 x i32> addrspace(1)* %in + %b = load <4 x i32>, <4 x i32> addrspace(1)* %b_ptr + %result = add <4 x i32> %a, %b + store <4 x i32> %result, <4 x i32> addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}s_add_v8i32: +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +define amdgpu_kernel void @s_add_v8i32(<8 x i32> addrspace(1)* %out, <8 x i32> %a, <8 x i32> %b) { +entry: + %0 = add <8 x i32> %a, %b + store <8 x i32> %0, <8 x i32> addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}s_add_v16i32: +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +; EG: ADD_INT +define amdgpu_kernel void @s_add_v16i32(<16 x i32> addrspace(1)* %out, <16 x i32> %a, <16 x i32> %b) { +entry: + %0 = add <16 x i32> %a, %b + store <16 x i32> %0, <16 x i32> addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}v_add_i32: +define amdgpu_kernel void @v_add_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 { + %tid = call i32 @llvm.r600.read.tidig.x() + %gep = getelementptr inbounds i32, i32 addrspace(1)* %in, i32 %tid + %b_ptr = getelementptr i32, i32 addrspace(1)* %gep, i32 1 + %a = load volatile i32, i32 addrspace(1)* %gep + %b = load volatile i32, i32 addrspace(1)* %b_ptr + %result = add i32 %a, %b + store i32 %result, i32 addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}v_add_imm_i32: +define amdgpu_kernel void @v_add_imm_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 { + %tid = call i32 @llvm.r600.read.tidig.x() + %gep = getelementptr inbounds i32, i32 addrspace(1)* %in, i32 %tid + %b_ptr = getelementptr i32, i32 addrspace(1)* %gep, i32 1 + %a = load volatile i32, i32 addrspace(1)* %gep + %result = add i32 %a, 123 + store i32 %result, i32 addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}add64: +; EG: MEM_RAT_CACHELESS STORE_RAW [[LO:T[0-9]+\.XY]] +; EG-DAG: ADD_INT {{[* ]*}} +; EG-DAG: ADDC_UINT +; EG-DAG: ADD_INT +; EG-DAG: ADD_INT {{[* ]*}} +; EG-NOT: SUB +define amdgpu_kernel void @add64(i64 addrspace(1)* %out, i64 %a, i64 %b) { +entry: + %add = add i64 %a, %b + store i64 %add, i64 addrspace(1)* %out + ret void +} + +; The v_addc_u32 and v_add_i32 instruction can't read SGPRs, because they +; use VCC. The test is designed so that %a will be stored in an SGPR and +; %0 will be stored in a VGPR, so the comiler will be forced to copy %a +; to a VGPR before doing the add. + +; FUNC-LABEL: {{^}}add64_sgpr_vgpr: +; EG: MEM_RAT_CACHELESS STORE_RAW [[LO:T[0-9]+\.XY]] +; EG-DAG: ADD_INT {{[* ]*}} +; EG-DAG: ADDC_UINT +; EG-DAG: ADD_INT +; EG-DAG: ADD_INT {{[* ]*}} +; EG-NOT: SUB +define amdgpu_kernel void @add64_sgpr_vgpr(i64 addrspace(1)* %out, i64 %a, i64 addrspace(1)* %in) { +entry: + %0 = load i64, i64 addrspace(1)* %in + %1 = add i64 %a, %0 + store i64 %1, i64 addrspace(1)* %out + ret void +} + +; Test i64 add inside a branch. +; FUNC-LABEL: {{^}}add64_in_branch: +; EG: MEM_RAT_CACHELESS STORE_RAW [[LO:T[0-9]+\.XY]] +; EG-DAG: ADD_INT {{[* ]*}} +; EG-DAG: ADDC_UINT +; EG-DAG: ADD_INT +; EG-DAG: ADD_INT {{[* ]*}} +; EG-NOT: SUB +define amdgpu_kernel void @add64_in_branch(i64 addrspace(1)* %out, i64 addrspace(1)* %in, i64 %a, i64 %b, i64 %c) { +entry: + %0 = icmp eq i64 %a, 0 + br i1 %0, label %if, label %else + +if: + %1 = load i64, i64 addrspace(1)* %in + br label %endif + +else: + %2 = add i64 %a, %b + br label %endif + +endif: + %3 = phi i64 [%1, %if], [%2, %else] + store i64 %3, i64 addrspace(1)* %out + ret void +} + +declare i32 @llvm.r600.read.tidig.x() #1 + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone speculatable } diff --git a/llvm/test/CodeGen/AMDGPU/r600.sub.ll b/llvm/test/CodeGen/AMDGPU/r600.sub.ll new file mode 100644 index 0000000000000..2ded4f64328d4 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/r600.sub.ll @@ -0,0 +1,152 @@ +; RUN: llc -amdgpu-scalarize-global-loads=false -march=r600 -mcpu=redwood -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=EG,FUNC %s + +declare i32 @llvm.r600.read.tidig.x() readnone + +; FUNC-LABEL: {{^}}s_sub_i32: +define amdgpu_kernel void @s_sub_i32(i32 addrspace(1)* %out, i32 %a, i32 %b) { + %result = sub i32 %a, %b + store i32 %result, i32 addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}s_sub_imm_i32: +define amdgpu_kernel void @s_sub_imm_i32(i32 addrspace(1)* %out, i32 %a) { + %result = sub i32 1234, %a + store i32 %result, i32 addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}test_sub_i32: +; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} +define amdgpu_kernel void @test_sub_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) { + %b_ptr = getelementptr i32, i32 addrspace(1)* %in, i32 1 + %a = load i32, i32 addrspace(1)* %in + %b = load i32, i32 addrspace(1)* %b_ptr + %result = sub i32 %a, %b + store i32 %result, i32 addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}test_sub_imm_i32: +; EG: SUB_INT +define amdgpu_kernel void @test_sub_imm_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) { + %a = load i32, i32 addrspace(1)* %in + %result = sub i32 123, %a + store i32 %result, i32 addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}test_sub_v2i32: +; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} +; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} +define amdgpu_kernel void @test_sub_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32> addrspace(1)* %in) { + %b_ptr = getelementptr <2 x i32>, <2 x i32> addrspace(1)* %in, i32 1 + %a = load <2 x i32>, <2 x i32> addrspace(1) * %in + %b = load <2 x i32>, <2 x i32> addrspace(1) * %b_ptr + %result = sub <2 x i32> %a, %b + store <2 x i32> %result, <2 x i32> addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}test_sub_v4i32: +; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} +; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} +; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} +; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} +define amdgpu_kernel void @test_sub_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32> addrspace(1)* %in) { + %b_ptr = getelementptr <4 x i32>, <4 x i32> addrspace(1)* %in, i32 1 + %a = load <4 x i32>, <4 x i32> addrspace(1) * %in + %b = load <4 x i32>, <4 x i32> addrspace(1) * %b_ptr + %result = sub <4 x i32> %a, %b + store <4 x i32> %result, <4 x i32> addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}test_sub_i16: +define amdgpu_kernel void @test_sub_i16(i16 addrspace(1)* %out, i16 addrspace(1)* %in) { + %tid = call i32 @llvm.r600.read.tidig.x() + %gep = getelementptr i16, i16 addrspace(1)* %in, i32 %tid + %b_ptr = getelementptr i16, i16 addrspace(1)* %gep, i32 1 + %a = load volatile i16, i16 addrspace(1)* %gep + %b = load volatile i16, i16 addrspace(1)* %b_ptr + %result = sub i16 %a, %b + store i16 %result, i16 addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}test_sub_v2i16: +define amdgpu_kernel void @test_sub_v2i16(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(1)* %in) { + %tid = call i32 @llvm.r600.read.tidig.x() + %gep = getelementptr <2 x i16>, <2 x i16> addrspace(1)* %in, i32 %tid + %b_ptr = getelementptr <2 x i16>, <2 x i16> addrspace(1)* %gep, i16 1 + %a = load <2 x i16>, <2 x i16> addrspace(1)* %gep + %b = load <2 x i16>, <2 x i16> addrspace(1)* %b_ptr + %result = sub <2 x i16> %a, %b + store <2 x i16> %result, <2 x i16> addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}test_sub_v4i16: +define amdgpu_kernel void @test_sub_v4i16(<4 x i16> addrspace(1)* %out, <4 x i16> addrspace(1)* %in) { + %tid = call i32 @llvm.r600.read.tidig.x() + %gep = getelementptr <4 x i16>, <4 x i16> addrspace(1)* %in, i32 %tid + %b_ptr = getelementptr <4 x i16>, <4 x i16> addrspace(1)* %gep, i16 1 + %a = load <4 x i16>, <4 x i16> addrspace(1) * %gep + %b = load <4 x i16>, <4 x i16> addrspace(1) * %b_ptr + %result = sub <4 x i16> %a, %b + store <4 x i16> %result, <4 x i16> addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}s_sub_i64: +; EG: MEM_RAT_CACHELESS STORE_RAW T{{[0-9]+}}.XY +; EG-DAG: SUB_INT {{[* ]*}} +; EG-DAG: SUBB_UINT +; EG-DAG: SUB_INT +; EG-DAG: SUB_INT {{[* ]*}} +define amdgpu_kernel void @s_sub_i64(i64 addrspace(1)* noalias %out, i64 %a, i64 %b) nounwind { + %result = sub i64 %a, %b + store i64 %result, i64 addrspace(1)* %out, align 8 + ret void +} + +; FUNC-LABEL: {{^}}v_sub_i64: +; EG: MEM_RAT_CACHELESS STORE_RAW T{{[0-9]+}}.XY +; EG-DAG: SUB_INT {{[* ]*}} +; EG-DAG: SUBB_UINT +; EG-DAG: SUB_INT +; EG-DAG: SUB_INT {{[* ]*}} +define amdgpu_kernel void @v_sub_i64(i64 addrspace(1)* noalias %out, i64 addrspace(1)* noalias %inA, i64 addrspace(1)* noalias %inB) nounwind { + %tid = call i32 @llvm.r600.read.tidig.x() readnone + %a_ptr = getelementptr i64, i64 addrspace(1)* %inA, i32 %tid + %b_ptr = getelementptr i64, i64 addrspace(1)* %inB, i32 %tid + %a = load i64, i64 addrspace(1)* %a_ptr + %b = load i64, i64 addrspace(1)* %b_ptr + %result = sub i64 %a, %b + store i64 %result, i64 addrspace(1)* %out, align 8 + ret void +} + +; FUNC-LABEL: {{^}}v_test_sub_v2i64: +define amdgpu_kernel void @v_test_sub_v2i64(<2 x i64> addrspace(1)* %out, <2 x i64> addrspace(1)* noalias %inA, <2 x i64> addrspace(1)* noalias %inB) { + %tid = call i32 @llvm.r600.read.tidig.x() readnone + %a_ptr = getelementptr <2 x i64>, <2 x i64> addrspace(1)* %inA, i32 %tid + %b_ptr = getelementptr <2 x i64>, <2 x i64> addrspace(1)* %inB, i32 %tid + %a = load <2 x i64>, <2 x i64> addrspace(1)* %a_ptr + %b = load <2 x i64>, <2 x i64> addrspace(1)* %b_ptr + %result = sub <2 x i64> %a, %b + store <2 x i64> %result, <2 x i64> addrspace(1)* %out + ret void +} + +; FUNC-LABEL: {{^}}v_test_sub_v4i64: +define amdgpu_kernel void @v_test_sub_v4i64(<4 x i64> addrspace(1)* %out, <4 x i64> addrspace(1)* noalias %inA, <4 x i64> addrspace(1)* noalias %inB) { + %tid = call i32 @llvm.r600.read.tidig.x() readnone + %a_ptr = getelementptr <4 x i64>, <4 x i64> addrspace(1)* %inA, i32 %tid + %b_ptr = getelementptr <4 x i64>, <4 x i64> addrspace(1)* %inB, i32 %tid + %a = load <4 x i64>, <4 x i64> addrspace(1)* %a_ptr + %b = load <4 x i64>, <4 x i64> addrspace(1)* %b_ptr + %result = sub <4 x i64> %a, %b + store <4 x i64> %result, <4 x i64> addrspace(1)* %out + ret void +} diff --git a/llvm/test/CodeGen/AMDGPU/salu-to-valu.ll b/llvm/test/CodeGen/AMDGPU/salu-to-valu.ll index 9b46962108c28..cf42ee9b39ba0 100644 --- a/llvm/test/CodeGen/AMDGPU/salu-to-valu.ll +++ b/llvm/test/CodeGen/AMDGPU/salu-to-valu.ll @@ -458,7 +458,7 @@ bb7: ; preds = %bb3 } ; GCN-LABEL: {{^}}phi_visit_order: -; GCN: v_add_i32_e32 v{{[0-9]+}}, vcc, 1, v{{[0-9]+}} +; GCN: v_add_i32_e64 v{{[0-9]+}}, s{{\[[0-9]+:[0-9]+\]}}, 1, v{{[0-9]+}} define amdgpu_kernel void @phi_visit_order() { bb: br label %bb1 diff --git a/llvm/test/CodeGen/AMDGPU/sub.ll b/llvm/test/CodeGen/AMDGPU/sub.ll index 4bd346dc586d1..485b374454de6 100644 --- a/llvm/test/CodeGen/AMDGPU/sub.ll +++ b/llvm/test/CodeGen/AMDGPU/sub.ll @@ -1,11 +1,10 @@ -; RUN: llc -amdgpu-scalarize-global-loads=false -march=amdgcn -mcpu=verde -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,SI,FUNC %s -; RUN: llc -amdgpu-scalarize-global-loads=false -march=amdgcn -mcpu=fiji -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,VI,GFX89,FUNC %s -; RUN: llc -amdgpu-scalarize-global-loads=false -march=amdgcn -mcpu=gfx900 -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GFX9,GFX89,FUNC %s -; RUN: llc -amdgpu-scalarize-global-loads=false -march=r600 -mcpu=redwood -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=EG,FUNC %s +; RUN: llc -amdgpu-scalarize-global-loads=false -march=amdgcn -mcpu=verde -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,SI %s +; RUN: llc -amdgpu-scalarize-global-loads=false -march=amdgcn -mcpu=fiji -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,VI,GFX89 %s +; RUN: llc -amdgpu-scalarize-global-loads=false -march=amdgcn -mcpu=gfx900 -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GFX9,GFX89 %s -declare i32 @llvm.r600.read.tidig.x() readnone +declare i32 @llvm.amdgcn.workitem.id.x() nounwind readnone speculatable -; FUNC-LABEL: {{^}}s_sub_i32: +; GCN-LABEL: {{^}}s_sub_i32: ; GCN: s_load_dwordx2 ; GCN: s_load_dwordx2 s{{\[}}[[A:[0-9]+]]:[[B:[0-9]+]]{{\]}} ; GCN: s_sub_i32 s{{[0-9]+}}, s[[A]], s[[B]] @@ -15,7 +14,7 @@ define amdgpu_kernel void @s_sub_i32(i32 addrspace(1)* %out, i32 %a, i32 %b) { ret void } -; FUNC-LABEL: {{^}}s_sub_imm_i32: +; GCN-LABEL: {{^}}s_sub_imm_i32: ; GCN: s_load_dword [[A:s[0-9]+]] ; GCN: s_sub_i32 s{{[0-9]+}}, 0x4d2, [[A]] define amdgpu_kernel void @s_sub_imm_i32(i32 addrspace(1)* %out, i32 %a) { @@ -24,9 +23,7 @@ define amdgpu_kernel void @s_sub_imm_i32(i32 addrspace(1)* %out, i32 %a) { ret void } -; FUNC-LABEL: {{^}}test_sub_i32: -; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} - +; GCN-LABEL: {{^}}test_sub_i32: ; SI: v_subrev_i32_e32 v{{[0-9]+, vcc, v[0-9]+, v[0-9]+}} ; GFX9: v_sub_u32_e32 v{{[0-9]+, v[0-9]+, v[0-9]+}} define amdgpu_kernel void @test_sub_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) { @@ -38,9 +35,7 @@ define amdgpu_kernel void @test_sub_i32(i32 addrspace(1)* %out, i32 addrspace(1) ret void } -; FUNC-LABEL: {{^}}test_sub_imm_i32: -; EG: SUB_INT - +; GCN-LABEL: {{^}}test_sub_imm_i32: ; SI: v_sub_i32_e32 v{{[0-9]+}}, vcc, 0x7b, v{{[0-9]+}} ; GFX9: v_sub_u32_e32 v{{[0-9]+}}, 0x7b, v{{[0-9]+}} define amdgpu_kernel void @test_sub_imm_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) { @@ -50,10 +45,7 @@ define amdgpu_kernel void @test_sub_imm_i32(i32 addrspace(1)* %out, i32 addrspac ret void } -; FUNC-LABEL: {{^}}test_sub_v2i32: -; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} -; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} - +; GCN-LABEL: {{^}}test_sub_v2i32: ; SI: v_sub_i32_e32 v{{[0-9]+, vcc, v[0-9]+, v[0-9]+}} ; SI: v_sub_i32_e32 v{{[0-9]+, vcc, v[0-9]+, v[0-9]+}} @@ -68,12 +60,7 @@ define amdgpu_kernel void @test_sub_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32 ret void } -; FUNC-LABEL: {{^}}test_sub_v4i32: -; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} -; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} -; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} -; EG: SUB_INT {{\** *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} - +; GCN-LABEL: {{^}}test_sub_v4i32: ; SI: v_sub_i32_e32 v{{[0-9]+, vcc, v[0-9]+, v[0-9]+}} ; SI: v_sub_i32_e32 v{{[0-9]+, vcc, v[0-9]+, v[0-9]+}} ; SI: v_sub_i32_e32 v{{[0-9]+, vcc, v[0-9]+, v[0-9]+}} @@ -92,11 +79,11 @@ define amdgpu_kernel void @test_sub_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32 ret void } -; FUNC-LABEL: {{^}}test_sub_i16: +; GCN-LABEL: {{^}}test_sub_i16: ; SI: v_sub_i32_e32 v{{[0-9]+}}, vcc, ; GFX89: v_sub_u16_e32 v{{[0-9]+, v[0-9]+, v[0-9]+}} define amdgpu_kernel void @test_sub_i16(i16 addrspace(1)* %out, i16 addrspace(1)* %in) { - %tid = call i32 @llvm.r600.read.tidig.x() + %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep = getelementptr i16, i16 addrspace(1)* %in, i32 %tid %b_ptr = getelementptr i16, i16 addrspace(1)* %gep, i32 1 %a = load volatile i16, i16 addrspace(1)* %gep @@ -106,13 +93,13 @@ define amdgpu_kernel void @test_sub_i16(i16 addrspace(1)* %out, i16 addrspace(1) ret void } -; FUNC-LABEL: {{^}}test_sub_v2i16: +; GCN-LABEL: {{^}}test_sub_v2i16: ; VI: v_sub_u16_e32 v{{[0-9]+, v[0-9]+, v[0-9]+}} ; VI: v_sub_u16_sdwa v{{[0-9]+, v[0-9]+, v[0-9]+}} ; GFX9: v_pk_sub_i16 define amdgpu_kernel void @test_sub_v2i16(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(1)* %in) { - %tid = call i32 @llvm.r600.read.tidig.x() + %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep = getelementptr <2 x i16>, <2 x i16> addrspace(1)* %in, i32 %tid %b_ptr = getelementptr <2 x i16>, <2 x i16> addrspace(1)* %gep, i16 1 %a = load <2 x i16>, <2 x i16> addrspace(1)* %gep @@ -122,7 +109,7 @@ define amdgpu_kernel void @test_sub_v2i16(<2 x i16> addrspace(1)* %out, <2 x i16 ret void } -; FUNC-LABEL: {{^}}test_sub_v4i16: +; GCN-LABEL: {{^}}test_sub_v4i16: ; VI: v_sub_u16_e32 v{{[0-9]+, v[0-9]+, v[0-9]+}} ; VI: v_sub_u16_sdwa v{{[0-9]+, v[0-9]+, v[0-9]+}} ; VI: v_sub_u16_e32 v{{[0-9]+, v[0-9]+, v[0-9]+}} @@ -131,7 +118,7 @@ define amdgpu_kernel void @test_sub_v2i16(<2 x i16> addrspace(1)* %out, <2 x i16 ; GFX9: v_pk_sub_i16 ; GFX9: v_pk_sub_i16 define amdgpu_kernel void @test_sub_v4i16(<4 x i16> addrspace(1)* %out, <4 x i16> addrspace(1)* %in) { - %tid = call i32 @llvm.r600.read.tidig.x() + %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep = getelementptr <4 x i16>, <4 x i16> addrspace(1)* %in, i32 %tid %b_ptr = getelementptr <4 x i16>, <4 x i16> addrspace(1)* %gep, i16 1 %a = load <4 x i16>, <4 x i16> addrspace(1) * %gep @@ -141,22 +128,16 @@ define amdgpu_kernel void @test_sub_v4i16(<4 x i16> addrspace(1)* %out, <4 x i16 ret void } -; FUNC-LABEL: {{^}}s_sub_i64: +; GCN-LABEL: {{^}}s_sub_i64: ; GCN: s_sub_u32 ; GCN: s_subb_u32 - -; EG: MEM_RAT_CACHELESS STORE_RAW T{{[0-9]+}}.XY -; EG-DAG: SUB_INT {{[* ]*}} -; EG-DAG: SUBB_UINT -; EG-DAG: SUB_INT -; EG-DAG: SUB_INT {{[* ]*}} define amdgpu_kernel void @s_sub_i64(i64 addrspace(1)* noalias %out, i64 %a, i64 %b) nounwind { %result = sub i64 %a, %b store i64 %result, i64 addrspace(1)* %out, align 8 ret void } -; FUNC-LABEL: {{^}}v_sub_i64: +; GCN-LABEL: {{^}}v_sub_i64: ; SI: v_sub_i32_e32 ; SI: v_subb_u32_e32 @@ -165,14 +146,8 @@ define amdgpu_kernel void @s_sub_i64(i64 addrspace(1)* noalias %out, i64 %a, i64 ; GFX9: v_sub_co_u32_e32 ; GFX9: v_subb_co_u32_e32 - -; EG: MEM_RAT_CACHELESS STORE_RAW T{{[0-9]+}}.XY -; EG-DAG: SUB_INT {{[* ]*}} -; EG-DAG: SUBB_UINT -; EG-DAG: SUB_INT -; EG-DAG: SUB_INT {{[* ]*}} define amdgpu_kernel void @v_sub_i64(i64 addrspace(1)* noalias %out, i64 addrspace(1)* noalias %inA, i64 addrspace(1)* noalias %inB) nounwind { - %tid = call i32 @llvm.r600.read.tidig.x() readnone + %tid = call i32 @llvm.amdgcn.workitem.id.x() readnone %a_ptr = getelementptr i64, i64 addrspace(1)* %inA, i32 %tid %b_ptr = getelementptr i64, i64 addrspace(1)* %inB, i32 %tid %a = load i64, i64 addrspace(1)* %a_ptr @@ -182,7 +157,7 @@ define amdgpu_kernel void @v_sub_i64(i64 addrspace(1)* noalias %out, i64 addrspa ret void } -; FUNC-LABEL: {{^}}v_test_sub_v2i64: +; GCN-LABEL: {{^}}v_test_sub_v2i64: ; SI: v_sub_i32_e32 v{{[0-9]+}}, vcc, ; SI: v_subb_u32_e32 v{{[0-9]+}}, vcc, ; SI: v_sub_i32_e32 v{{[0-9]+}}, vcc, @@ -198,7 +173,7 @@ define amdgpu_kernel void @v_sub_i64(i64 addrspace(1)* noalias %out, i64 addrspa ; GFX9: v_sub_co_u32_e32 v{{[0-9]+}}, vcc, ; GFX9: v_subb_co_u32_e32 v{{[0-9]+}}, vcc, define amdgpu_kernel void @v_test_sub_v2i64(<2 x i64> addrspace(1)* %out, <2 x i64> addrspace(1)* noalias %inA, <2 x i64> addrspace(1)* noalias %inB) { - %tid = call i32 @llvm.r600.read.tidig.x() readnone + %tid = call i32 @llvm.amdgcn.workitem.id.x() readnone %a_ptr = getelementptr <2 x i64>, <2 x i64> addrspace(1)* %inA, i32 %tid %b_ptr = getelementptr <2 x i64>, <2 x i64> addrspace(1)* %inB, i32 %tid %a = load <2 x i64>, <2 x i64> addrspace(1)* %a_ptr @@ -208,7 +183,7 @@ define amdgpu_kernel void @v_test_sub_v2i64(<2 x i64> addrspace(1)* %out, <2 x i ret void } -; FUNC-LABEL: {{^}}v_test_sub_v4i64: +; GCN-LABEL: {{^}}v_test_sub_v4i64: ; SI: v_sub_i32_e32 v{{[0-9]+}}, vcc, ; SI: v_subb_u32_e32 v{{[0-9]+}}, vcc, ; SI: v_sub_i32_e32 v{{[0-9]+}}, vcc, @@ -236,7 +211,7 @@ define amdgpu_kernel void @v_test_sub_v2i64(<2 x i64> addrspace(1)* %out, <2 x i ; GFX9: v_sub_co_u32_e32 v{{[0-9]+}}, vcc, ; GFX9: v_subb_co_u32_e32 v{{[0-9]+}}, vcc, define amdgpu_kernel void @v_test_sub_v4i64(<4 x i64> addrspace(1)* %out, <4 x i64> addrspace(1)* noalias %inA, <4 x i64> addrspace(1)* noalias %inB) { - %tid = call i32 @llvm.r600.read.tidig.x() readnone + %tid = call i32 @llvm.amdgcn.workitem.id.x() readnone %a_ptr = getelementptr <4 x i64>, <4 x i64> addrspace(1)* %inA, i32 %tid %b_ptr = getelementptr <4 x i64>, <4 x i64> addrspace(1)* %inB, i32 %tid %a = load <4 x i64>, <4 x i64> addrspace(1)* %a_ptr @@ -245,3 +220,22 @@ define amdgpu_kernel void @v_test_sub_v4i64(<4 x i64> addrspace(1)* %out, <4 x i store <4 x i64> %result, <4 x i64> addrspace(1)* %out ret void } + +; Make sure the VOP3 form of sub is initially selected. Otherwise pair +; of opies from/to VCC would be necessary + +; GCN-LABEL: {{^}}sub_select_vop3: +; SI: v_subrev_i32_e64 v0, s[0:1], s0, v0 +; VI: v_subrev_u32_e64 v0, s[0:1], s0, v0 +; GFX9: v_subrev_u32_e32 v0, s0, v0 + +; GCN: ; def vcc +; GCN: ds_write_b32 +; GCN: ; use vcc +define amdgpu_ps void @sub_select_vop3(i32 inreg %s, i32 %v) { + %vcc = call i64 asm sideeffect "; def vcc", "={vcc}"() + %sub = sub i32 %v, %s + store i32 %sub, i32 addrspace(3)* undef + call void asm sideeffect "; use vcc", "{vcc}"(i64 %vcc) + ret void +} diff --git a/llvm/test/CodeGen/ARM/tail-call-scheduling.ll b/llvm/test/CodeGen/ARM/tail-call-scheduling.ll new file mode 100644 index 0000000000000..591da10256ba4 --- /dev/null +++ b/llvm/test/CodeGen/ARM/tail-call-scheduling.ll @@ -0,0 +1,35 @@ +; RUN: llc < %s | FileCheck %s +target triple = "armv6kz-unknown-unknown-gnueabihf" + +; Make sure this doesn't crash, and we actually emit a tail call. +; Unfortunately, this test is sort of fragile... the original issue only +; shows up if scheduling happens in a very specific order. But including +; it anyway just to demonstrate the issue. +; CHECK: pop {r4, lr} + +@e = external local_unnamed_addr constant [0 x i32 (i32, i32)*], align 4 + +; Function Attrs: nounwind sspstrong +define i32 @AVI_ChunkRead_p_chk(i32 %g) nounwind sspstrong "target-cpu"="arm1176jzf-s" { +entry: + %b = alloca i8, align 1 + %tobool = icmp eq i32 %g, 0 + br i1 %tobool, label %if.end, label %if.then + +if.then: ; preds = %entry + %add = add nsw i32 %g, 1 + %arrayidx = getelementptr inbounds [0 x i32 (i32, i32)*], [0 x i32 (i32, i32)*]* @e, i32 0, i32 %add + %0 = load i32 (i32, i32)*, i32 (i32, i32)** %arrayidx, align 4 + %call = tail call i32 %0(i32 0, i32 0) #3 + br label %return + +if.end: ; preds = %entry + call void @c(i8* nonnull %b) + br label %return + +return: ; preds = %if.end, %if.then + %retval.0 = phi i32 [ %call, %if.then ], [ 0, %if.end ] + ret i32 %retval.0 +} + +declare void @c(i8*) diff --git a/llvm/test/CodeGen/AVR/mul.ll b/llvm/test/CodeGen/AVR/hardware-mul.ll similarity index 90% rename from llvm/test/CodeGen/AVR/mul.ll rename to llvm/test/CodeGen/AVR/hardware-mul.ll index 2f169347c46e0..650697857b76b 100644 --- a/llvm/test/CodeGen/AVR/mul.ll +++ b/llvm/test/CodeGen/AVR/hardware-mul.ll @@ -1,5 +1,7 @@ ; RUN: llc -mattr=mul,movw < %s -march=avr | FileCheck %s +; Tests lowering of multiplication to hardware instructions. + define i8 @mult8(i8 %a, i8 %b) { ; CHECK-LABEL: mult8: ; CHECK: muls r22, r24 diff --git a/llvm/test/CodeGen/AVR/smul-with-overflow.ll b/llvm/test/CodeGen/AVR/smul-with-overflow.ll index 745e93005cc2f..9eb2c7411dee8 100644 --- a/llvm/test/CodeGen/AVR/smul-with-overflow.ll +++ b/llvm/test/CodeGen/AVR/smul-with-overflow.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=avr | FileCheck %s +; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s define i1 @signed_multiplication_did_overflow(i8, i8) unnamed_addr { ; CHECK-LABEL: signed_multiplication_did_overflow: diff --git a/llvm/test/CodeGen/AVR/software-mul.ll b/llvm/test/CodeGen/AVR/software-mul.ll new file mode 100644 index 0000000000000..9a4d28127eb87 --- /dev/null +++ b/llvm/test/CodeGen/AVR/software-mul.ll @@ -0,0 +1,28 @@ +; RUN: llc -mattr=avr6,-mul < %s -march=avr | FileCheck %s +; RUN: llc -mcpu=attiny85 < %s -march=avr | FileCheck %s +; RUN: llc -mcpu=ata5272 < %s -march=avr | FileCheck %s +; RUN: llc -mcpu=attiny861a < %s -march=avr | FileCheck %s +; RUN: llc -mcpu=at90usb82 < %s -march=avr | FileCheck %s + +; Tests lowering of multiplication to compiler support routines. + +; CHECK-LABEL: mul8: +define i8 @mul8(i8 %a, i8 %b) { +; CHECK: mov r25, r24 +; CHECK: mov r24, r22 +; CHECK: mov r22, r25 +; CHECK: call __mulqi3 + %mul = mul i8 %b, %a + ret i8 %mul +} + +; CHECK-LABEL: mul16: +define i16 @mul16(i16 %a, i16 %b) { +; CHECK: movw r18, r24 +; CHECK: movw r24, r22 +; CHECK: movw r22, r18 +; CHECK: call __mulhi3 + %mul = mul nsw i16 %b, %a + ret i16 %mul +} + diff --git a/llvm/test/CodeGen/AVR/umul-with-overflow.ll b/llvm/test/CodeGen/AVR/umul-with-overflow.ll index aa8b10a313d38..c6457552dea88 100644 --- a/llvm/test/CodeGen/AVR/umul-with-overflow.ll +++ b/llvm/test/CodeGen/AVR/umul-with-overflow.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=avr | FileCheck %s +; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s define i1 @unsigned_multiplication_did_overflow(i8, i8) unnamed_addr { ; CHECK-LABEL: unsigned_multiplication_did_overflow: diff --git a/llvm/test/CodeGen/MIR/X86/memory-operands.mir b/llvm/test/CodeGen/MIR/X86/memory-operands.mir index 2ac7bea2fc9b9..89b28126b9167 100644 --- a/llvm/test/CodeGen/MIR/X86/memory-operands.mir +++ b/llvm/test/CodeGen/MIR/X86/memory-operands.mir @@ -359,8 +359,8 @@ body: | CFI_INSTRUCTION def_cfa_offset 32 LD_F80m $rsp, 1, $noreg, 32, $noreg, implicit-def dead $fpsw ; CHECK: name: stack_psv - ; CHECK: ST_FP80m $rsp, 1, $noreg, 0, $noreg, implicit-def dead $fpsw :: (store 10 into stack, align 16) - ST_FP80m $rsp, 1, _, 0, _, implicit-def dead $fpsw :: (store 10 into stack, align 16) + ; CHECK: ST_FP80m $rsp, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (store 10 into stack, align 16) + ST_FP80m $rsp, 1, _, 0, _, implicit-def dead $fpsw, implicit $fpcw :: (store 10 into stack, align 16) CALL64pcrel32 &cosl, csr_64, implicit $rsp, implicit-def $rsp, implicit-def $fp0 $rsp = ADD64ri8 $rsp, 24, implicit-def dead $eflags RETQ diff --git a/llvm/test/CodeGen/MSP430/2009-12-21-FrameAddr.ll b/llvm/test/CodeGen/MSP430/2009-12-21-FrameAddr.ll index c3d69c7c0db5e..be82e98dffe37 100644 --- a/llvm/test/CodeGen/MSP430/2009-12-21-FrameAddr.ll +++ b/llvm/test/CodeGen/MSP430/2009-12-21-FrameAddr.ll @@ -3,7 +3,7 @@ target datalayout = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8" target triple = "msp430-unknown-linux-gnu" -define msp430_intrcc void @foo() nounwind { +define msp430_intrcc void @foo() nounwind #0 { entry: %fa = call i8* @llvm.frameaddress(i32 0) store i8 0, i8* %fa @@ -11,3 +11,5 @@ entry: } declare i8* @llvm.frameaddress(i32) + +attributes #0 = { noinline nounwind optnone "interrupt"="2" } diff --git a/llvm/test/CodeGen/MSP430/fp.ll b/llvm/test/CodeGen/MSP430/fp.ll index e7d7c519657ee..bf603704a91b6 100644 --- a/llvm/test/CodeGen/MSP430/fp.ll +++ b/llvm/test/CodeGen/MSP430/fp.ll @@ -27,3 +27,5 @@ define msp430_intrcc void @fpb_alloced() #0 { call void asm sideeffect "nop", "r"(i8 0) ret void } + +attributes #0 = { noinline nounwind optnone "interrupt"="2" } diff --git a/llvm/test/CodeGen/MSP430/interrupt.ll b/llvm/test/CodeGen/MSP430/interrupt.ll index 5fa0c849c2602..94fb3bc457a35 100644 --- a/llvm/test/CodeGen/MSP430/interrupt.ll +++ b/llvm/test/CodeGen/MSP430/interrupt.ll @@ -13,6 +13,9 @@ target triple = "msp430-generic-generic" ; instruction RETI, which restores the SR register and branches to the PC where ; the interrupt occurred. +; CHECK: .section __interrupt_vector_2,"ax",@progbits +; CHECK-NEXT: .short ISR + @g = global float 0.0 define msp430_intrcc void @ISR() #0 { @@ -47,3 +50,4 @@ entry: ret void } +attributes #0 = { noinline nounwind optnone "interrupt"="2" } diff --git a/llvm/test/CodeGen/Mips/Fast-ISel/icmpbr1.ll b/llvm/test/CodeGen/Mips/Fast-ISel/icmpbr1.ll index ef8e1c2b0140c..e44ab36532c5b 100644 --- a/llvm/test/CodeGen/Mips/Fast-ISel/icmpbr1.ll +++ b/llvm/test/CodeGen/Mips/Fast-ISel/icmpbr1.ll @@ -17,7 +17,8 @@ bb0: bb1: ; CHECK: # %bb.1: # %bb1 ; CHECK-NEXT: lw $[[REG2:[0-9]+]], [[SPILL]]($sp) # 4-byte Folded Reload -; CHECK-NEXT: bgtz $[[REG2]], $BB0_3 +; CHECK-NEXT: andi $[[REG3:[0-9]+]], $[[REG2]], 1 +; CHECK-NEXT: bgtz $[[REG3]], $BB0_3 br i1 %2, label %bb2, label %bb3 bb2: ; CHECK: $BB0_3: # %bb2 diff --git a/llvm/test/CodeGen/Mips/Fast-ISel/pr40325.ll b/llvm/test/CodeGen/Mips/Fast-ISel/pr40325.ll new file mode 100644 index 0000000000000..a9ce70fe8afc5 --- /dev/null +++ b/llvm/test/CodeGen/Mips/Fast-ISel/pr40325.ll @@ -0,0 +1,23 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=mipsel -relocation-model=pic -O0 -mcpu=mips32 < %s | FileCheck %s + +define void @test(i32 %x, i1* %p) nounwind { +; CHECK-LABEL: test: +; CHECK: # %bb.0: +; CHECK-NEXT: move $1, $4 +; CHECK-NEXT: andi $4, $4, 1 +; CHECK-NEXT: sb $4, 0($5) +; CHECK-NEXT: andi $1, $1, 1 +; CHECK-NEXT: bgtz $1, $BB0_1 +; CHECK-NEXT: nop +; CHECK-NEXT: # %bb.1: # %foo +; CHECK-NEXT: jr $ra +; CHECK-NEXT: nop + %y = and i32 %x, 1 + %c = icmp eq i32 %y, 1 + store i1 %c, i1* %p + br i1 %c, label %foo, label %foo + +foo: + ret void +} diff --git a/llvm/test/CodeGen/Mips/abiflags32.ll b/llvm/test/CodeGen/Mips/abiflags32.ll index 39e2a90151e3e..65201ec03814d 100644 --- a/llvm/test/CodeGen/Mips/abiflags32.ll +++ b/llvm/test/CodeGen/Mips/abiflags32.ll @@ -1,6 +1,12 @@ ; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips32 %s -o - | FileCheck %s ; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips32 -mattr=fp64 %s -o - | FileCheck -check-prefix=CHECK-64 %s ; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips64 -target-abi n32 %s -o - | FileCheck -check-prefix=CHECK-64n %s +; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips32 \ +; RUN: -mattr=soft-float %s -o - | FileCheck -check-prefix=SOFT %s +; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips32r6 \ +; RUN: -mattr=soft-float %s -o - | FileCheck -check-prefix=SOFT %s +; RUN: llc -filetype=asm -mtriple mipsel-unknown-linux -mcpu=mips64 \ +; RUN: -mattr=soft-float -target-abi n64 %s -o - | FileCheck -check-prefix=SOFT %s ; CHECK: .nan legacy ; We don't emit '.module fp=32' for compatibility with binutils 2.24 which @@ -15,3 +21,5 @@ ; We don't emit '.module fp=64' for compatibility with binutils 2.24 which ; doesn't accept .module. ; CHECK-64n-NOT: .module fp=64 + +; SOFT: .module softfloat diff --git a/llvm/test/CodeGen/Mips/cconv/vector.ll b/llvm/test/CodeGen/Mips/cconv/vector.ll index 6a07c4f34564d..5c7c3f424c380 100644 --- a/llvm/test/CodeGen/Mips/cconv/vector.ll +++ b/llvm/test/CodeGen/Mips/cconv/vector.ll @@ -1,12 +1,12 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32 -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS32,MIPS32EB -; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -relocation-model=pic -mcpu=mips64 -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS64,MIPS64EB +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -relocation-model=pic -mcpu=mips64 -disable-mips-delay-filler -mips-jalr-reloc=false | FileCheck %s --check-prefixes=ALL,MIPS64,MIPS64EB ; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32r5 -mattr=+fp64,+msa -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS32R5,MIPS32R5EB -; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -relocation-model=pic -mcpu=mips64r5 -mattr=+fp64,+msa -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS64R5,MIPS64R5EB +; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -relocation-model=pic -mcpu=mips64r5 -mattr=+fp64,+msa -disable-mips-delay-filler -mips-jalr-reloc=false | FileCheck %s --check-prefixes=ALL,MIPS64R5,MIPS64R5EB ; RUN: llc < %s -mtriple=mipsel-unknown-linux-gnu -mcpu=mips32 -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS32,MIPS32EL -; RUN: llc < %s -mtriple=mips64el-unknown-linux-gnu -relocation-model=pic -mcpu=mips64 -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS64,MIPS64EL +; RUN: llc < %s -mtriple=mips64el-unknown-linux-gnu -relocation-model=pic -mcpu=mips64 -disable-mips-delay-filler -mips-jalr-reloc=false | FileCheck %s --check-prefixes=ALL,MIPS64,MIPS64EL ; RUN: llc < %s -mtriple=mipsel-unknown-linux-gnu -mcpu=mips32r5 -mattr=+fp64,+msa -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS32R5,MIPS32R5EL -; RUN: llc < %s -mtriple=mips64el-unknown-linux-gnu -relocation-model=pic -mcpu=mips64r5 -mattr=+fp64,+msa -disable-mips-delay-filler | FileCheck %s --check-prefixes=ALL,MIPS64R5,MIPS64R5EL +; RUN: llc < %s -mtriple=mips64el-unknown-linux-gnu -relocation-model=pic -mcpu=mips64r5 -mattr=+fp64,+msa -disable-mips-delay-filler -mips-jalr-reloc=false | FileCheck %s --check-prefixes=ALL,MIPS64R5,MIPS64R5EL ; Test that vector types are passed through the integer register set whether or ; not MSA is enabled. This is a ABI requirement for MIPS. For GCC compatibility diff --git a/llvm/test/CodeGen/Mips/gprestore.ll b/llvm/test/CodeGen/Mips/gprestore.ll index 88ac047b66095..a1e696b0ac08b 100644 --- a/llvm/test/CodeGen/Mips/gprestore.ll +++ b/llvm/test/CodeGen/Mips/gprestore.ll @@ -1,10 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=mips-mti-linux-gnu < %s -relocation-model=pic | FileCheck %s --check-prefix=O32 -; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic | FileCheck %s --check-prefix=N64 -; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -target-abi n32 | FileCheck %s --check-prefix=N32 -; RUN: llc -mtriple=mips-mti-linux-gnu < %s -relocation-model=pic -O3 | FileCheck %s --check-prefix=O3O32 -; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -O3 | FileCheck %s --check-prefix=O3N64 -; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -target-abi n32 -O3 | FileCheck %s --check-prefix=O3N32 +; RUN: llc -mtriple=mips-mti-linux-gnu < %s -relocation-model=pic -mips-jalr-reloc=false | FileCheck %s --check-prefix=O32 +; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -mips-jalr-reloc=false | FileCheck %s --check-prefix=N64 +; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -target-abi n32 -mips-jalr-reloc=false | FileCheck %s --check-prefix=N32 +; RUN: llc -mtriple=mips-mti-linux-gnu < %s -relocation-model=pic -O3 -mips-jalr-reloc=false | FileCheck %s --check-prefix=O3O32 +; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -O3 -mips-jalr-reloc=false | FileCheck %s --check-prefix=O3N64 +; RUN: llc -mtriple=mips64-mti-linux-gnu < %s -relocation-model=pic -target-abi n32 -O3 -mips-jalr-reloc=false | FileCheck %s --check-prefix=O3N32 ; Test that PIC calls use the $25 register. This is an ABI requirement. diff --git a/llvm/test/CodeGen/Mips/llvm-ir/fptosi.ll b/llvm/test/CodeGen/Mips/llvm-ir/fptosi.ll new file mode 100644 index 0000000000000..03a0de7466452 --- /dev/null +++ b/llvm/test/CodeGen/Mips/llvm-ir/fptosi.ll @@ -0,0 +1,418 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=mips-linux-gnu -mcpu=mips32 -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=M32 +; RUN: llc < %s -mtriple=mips-linux-gnu -mcpu=mips32r2 -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=M32 +; RUN: llc < %s -mtriple=mips-linux-gnu -mcpu=mips32r2 -mattr=+fp64 -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=M32R2-FP64 +; RUN: llc < %s -mtriple=mips-linux-gnu -mcpu=mips32r2 -mattr=+soft-float -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=M32R2-SF +; RUN: llc < %s -mtriple=mips-linux-gnu -mcpu=mips32r3 -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=M32R3R5 +; RUN: llc < %s -mtriple=mips-linux-gnu -mcpu=mips32r5 -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=M32R3R5 +; RUN: llc < %s -mtriple=mips-linux-gnu -mcpu=mips32r6 -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=M32R6 +; RUN: llc < %s -mtriple=mips64-linux-gnu -mcpu=mips3 -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=M64 +; RUN: llc < %s -mtriple=mips64-linux-gnu -mcpu=mips64 -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=M64 +; RUN: llc < %s -mtriple=mips64-linux-gnu -mcpu=mips64r2 -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=M64 +; RUN: llc < %s -mtriple=mips64-linux-gnu -mcpu=mips64r6 -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=M64R6 +; RUN: llc < %s -mtriple=mips-linux-gnu -mcpu=mips32r2 -mattr=+micromips -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=MMR2-FP32 +; RUN: llc < %s -mtriple=mips-linux-gnu -mcpu=mips32r2 -mattr=+micromips,fp64 -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=MMR2-FP64 +; RUN: llc < %s -mtriple=mips-linux-gnu -mcpu=mips32r2 -mattr=+micromips,soft-float -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=MMR2-SF +; RUN: llc < %s -mtriple=mips-linux-gnu -mcpu=mips32r6 -mattr=+micromips -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=MMR6 +; RUN: llc < %s -mtriple=mips-linux-gnu -mcpu=mips32r6 -mattr=+micromips,soft-float -asm-show-inst |\ +; RUN: FileCheck %s -check-prefixes=MMR6-SF + +; Test that fptosi can be matched for MIPS targets for various FPU +; configurations + +define i32 @test1(float %t) { +; M32-LABEL: test1: +; M32: # %bb.0: # %entry +; M32-NEXT: trunc.w.s $f0, $f12 # +; M32-NEXT: # > +; M32-NEXT: jr $ra # > +; M32-NEXT: mfc1 $2, $f0 # +; M32-NEXT: # > +; +; M32R2-FP64-LABEL: test1: +; M32R2-FP64: # %bb.0: # %entry +; M32R2-FP64-NEXT: trunc.w.s $f0, $f12 # +; M32R2-FP64-NEXT: # > +; M32R2-FP64-NEXT: jr $ra # > +; M32R2-FP64-NEXT: mfc1 $2, $f0 # +; M32R2-FP64-NEXT: # > +; +; M32R2-SF-LABEL: test1: +; M32R2-SF: # %bb.0: # %entry +; M32R2-SF-NEXT: addiu $sp, $sp, -24 # +; M32R2-SF-NEXT: # +; M32R2-SF-NEXT: # > +; M32R2-SF-NEXT: .cfi_def_cfa_offset 24 +; M32R2-SF-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill +; M32R2-SF-NEXT: # +; M32R2-SF-NEXT: # +; M32R2-SF-NEXT: # > +; M32R2-SF-NEXT: .cfi_offset 31, -4 +; M32R2-SF-NEXT: jal __fixsfsi # > +; M32R2-SF-NEXT: nop # +; M32R2-SF-NEXT: # +; M32R2-SF-NEXT: # > +; M32R2-SF-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload +; M32R2-SF-NEXT: # +; M32R2-SF-NEXT: # +; M32R2-SF-NEXT: # > +; M32R2-SF-NEXT: jr $ra # > +; M32R2-SF-NEXT: addiu $sp, $sp, 24 # +; M32R2-SF-NEXT: # +; M32R2-SF-NEXT: # > +; +; M32R3R5-LABEL: test1: +; M32R3R5: # %bb.0: # %entry +; M32R3R5-NEXT: trunc.w.s $f0, $f12 # +; M32R3R5-NEXT: # > +; M32R3R5-NEXT: jr $ra # > +; M32R3R5-NEXT: mfc1 $2, $f0 # +; M32R3R5-NEXT: # > +; +; M32R6-LABEL: test1: +; M32R6: # %bb.0: # %entry +; M32R6-NEXT: trunc.w.s $f0, $f12 # +; M32R6-NEXT: # > +; M32R6-NEXT: jr $ra # +; M32R6-NEXT: # > +; M32R6-NEXT: mfc1 $2, $f0 # +; M32R6-NEXT: # > +; +; M64-LABEL: test1: +; M64: # %bb.0: # %entry +; M64-NEXT: trunc.w.s $f0, $f12 # +; M64-NEXT: # > +; M64-NEXT: jr $ra # > +; M64-NEXT: mfc1 $2, $f0 # +; M64-NEXT: # > +; +; M64R6-LABEL: test1: +; M64R6: # %bb.0: # %entry +; M64R6-NEXT: trunc.w.s $f0, $f12 # +; M64R6-NEXT: # > +; M64R6-NEXT: jr $ra # +; M64R6-NEXT: # > +; M64R6-NEXT: mfc1 $2, $f0 # +; M64R6-NEXT: # > +; +; MMR2-FP32-LABEL: test1: +; MMR2-FP32: # %bb.0: # %entry +; MMR2-FP32-NEXT: trunc.w.s $f0, $f12 # +; MMR2-FP32-NEXT: # > +; MMR2-FP32-NEXT: jr $ra # > +; MMR2-FP32-NEXT: mfc1 $2, $f0 # +; MMR2-FP32-NEXT: # > +; +; MMR2-FP64-LABEL: test1: +; MMR2-FP64: # %bb.0: # %entry +; MMR2-FP64-NEXT: trunc.w.s $f0, $f12 # +; MMR2-FP64-NEXT: # > +; MMR2-FP64-NEXT: jr $ra # > +; MMR2-FP64-NEXT: mfc1 $2, $f0 # +; MMR2-FP64-NEXT: # > +; +; MMR2-SF-LABEL: test1: +; MMR2-SF: # %bb.0: # %entry +; MMR2-SF-NEXT: addiusp -24 # > +; MMR2-SF-NEXT: .cfi_def_cfa_offset 24 +; MMR2-SF-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill +; MMR2-SF-NEXT: # +; MMR2-SF-NEXT: # +; MMR2-SF-NEXT: # > +; MMR2-SF-NEXT: .cfi_offset 31, -4 +; MMR2-SF-NEXT: jal __fixsfsi # > +; MMR2-SF-NEXT: nop # +; MMR2-SF-NEXT: # +; MMR2-SF-NEXT: # > +; MMR2-SF-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload +; MMR2-SF-NEXT: # +; MMR2-SF-NEXT: # +; MMR2-SF-NEXT: # > +; MMR2-SF-NEXT: addiusp 24 # > +; MMR2-SF-NEXT: jrc $ra # > +; +; MMR6-LABEL: test1: +; MMR6: # %bb.0: # %entry +; MMR6-NEXT: trunc.w.s $f0, $f12 # +; MMR6-NEXT: # > +; MMR6-NEXT: mfc1 $2, $f0 # +; MMR6-NEXT: # > +; MMR6-NEXT: jrc $ra # > +; +; MMR6-SF-LABEL: test1: +; MMR6-SF: # %bb.0: # %entry +; MMR6-SF-NEXT: addiu $sp, $sp, -24 # +; MMR6-SF-NEXT: # +; MMR6-SF-NEXT: # > +; MMR6-SF-NEXT: .cfi_def_cfa_offset 24 +; MMR6-SF-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill +; MMR6-SF-NEXT: # +; MMR6-SF-NEXT: # +; MMR6-SF-NEXT: # > +; MMR6-SF-NEXT: .cfi_offset 31, -4 +; MMR6-SF-NEXT: jalr __fixsfsi # > +; MMR6-SF-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload +; MMR6-SF-NEXT: # +; MMR6-SF-NEXT: # +; MMR6-SF-NEXT: # > +; MMR6-SF-NEXT: addiu $sp, $sp, 24 # +; MMR6-SF-NEXT: # +; MMR6-SF-NEXT: # > +; MMR6-SF-NEXT: jrc $ra # > +entry: + %conv = fptosi float %t to i32 + ret i32 %conv +} + +define i32 @test2(double %t) { +; M32-LABEL: test2: +; M32: # %bb.0: # %entry +; M32-NEXT: trunc.w.d $f0, $f12 # +; M32-NEXT: # > +; M32-NEXT: jr $ra # > +; M32-NEXT: mfc1 $2, $f0 # +; M32-NEXT: # > +; +; M32R2-FP64-LABEL: test2: +; M32R2-FP64: # %bb.0: # %entry +; M32R2-FP64-NEXT: trunc.w.d $f0, $f12 # +; M32R2-FP64-NEXT: # > +; M32R2-FP64-NEXT: jr $ra # > +; M32R2-FP64-NEXT: mfc1 $2, $f0 # +; M32R2-FP64-NEXT: # > +; +; M32R2-SF-LABEL: test2: +; M32R2-SF: # %bb.0: # %entry +; M32R2-SF-NEXT: addiu $sp, $sp, -24 # +; M32R2-SF-NEXT: # +; M32R2-SF-NEXT: # > +; M32R2-SF-NEXT: .cfi_def_cfa_offset 24 +; M32R2-SF-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill +; M32R2-SF-NEXT: # +; M32R2-SF-NEXT: # +; M32R2-SF-NEXT: # > +; M32R2-SF-NEXT: .cfi_offset 31, -4 +; M32R2-SF-NEXT: jal __fixdfsi # > +; M32R2-SF-NEXT: nop # +; M32R2-SF-NEXT: # +; M32R2-SF-NEXT: # > +; M32R2-SF-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload +; M32R2-SF-NEXT: # +; M32R2-SF-NEXT: # +; M32R2-SF-NEXT: # > +; M32R2-SF-NEXT: jr $ra # > +; M32R2-SF-NEXT: addiu $sp, $sp, 24 # +; M32R2-SF-NEXT: # +; M32R2-SF-NEXT: # > +; +; M32R3R5-LABEL: test2: +; M32R3R5: # %bb.0: # %entry +; M32R3R5-NEXT: trunc.w.d $f0, $f12 # +; M32R3R5-NEXT: # > +; M32R3R5-NEXT: jr $ra # > +; M32R3R5-NEXT: mfc1 $2, $f0 # +; M32R3R5-NEXT: # > +; +; M32R6-LABEL: test2: +; M32R6: # %bb.0: # %entry +; M32R6-NEXT: trunc.w.d $f0, $f12 # +; M32R6-NEXT: # > +; M32R6-NEXT: jr $ra # +; M32R6-NEXT: # > +; M32R6-NEXT: mfc1 $2, $f0 # +; M32R6-NEXT: # > +; +; M64-LABEL: test2: +; M64: # %bb.0: # %entry +; M64-NEXT: trunc.w.d $f0, $f12 # +; M64-NEXT: # > +; M64-NEXT: jr $ra # > +; M64-NEXT: mfc1 $2, $f0 # +; M64-NEXT: # > +; +; M64R6-LABEL: test2: +; M64R6: # %bb.0: # %entry +; M64R6-NEXT: trunc.w.d $f0, $f12 # +; M64R6-NEXT: # > +; M64R6-NEXT: jr $ra # +; M64R6-NEXT: # > +; M64R6-NEXT: mfc1 $2, $f0 # +; M64R6-NEXT: # > +; +; MMR2-FP32-LABEL: test2: +; MMR2-FP32: # %bb.0: # %entry +; MMR2-FP32-NEXT: trunc.w.d $f0, $f12 # +; MMR2-FP32-NEXT: # > +; MMR2-FP32-NEXT: jr $ra # > +; MMR2-FP32-NEXT: mfc1 $2, $f0 # +; MMR2-FP32-NEXT: # > +; +; MMR2-FP64-LABEL: test2: +; MMR2-FP64: # %bb.0: # %entry +; MMR2-FP64-NEXT: cvt.w.d $f0, $f12 # +; MMR2-FP64-NEXT: # > +; MMR2-FP64-NEXT: jr $ra # > +; MMR2-FP64-NEXT: mfc1 $2, $f0 # +; MMR2-FP64-NEXT: # > +; +; MMR2-SF-LABEL: test2: +; MMR2-SF: # %bb.0: # %entry +; MMR2-SF-NEXT: addiusp -24 # > +; MMR2-SF-NEXT: .cfi_def_cfa_offset 24 +; MMR2-SF-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill +; MMR2-SF-NEXT: # +; MMR2-SF-NEXT: # +; MMR2-SF-NEXT: # > +; MMR2-SF-NEXT: .cfi_offset 31, -4 +; MMR2-SF-NEXT: jal __fixdfsi # > +; MMR2-SF-NEXT: nop # +; MMR2-SF-NEXT: # +; MMR2-SF-NEXT: # > +; MMR2-SF-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload +; MMR2-SF-NEXT: # +; MMR2-SF-NEXT: # +; MMR2-SF-NEXT: # > +; MMR2-SF-NEXT: addiusp 24 # > +; MMR2-SF-NEXT: jrc $ra # > +; +; MMR6-LABEL: test2: +; MMR6: # %bb.0: # %entry +; MMR6-NEXT: trunc.w.d $f0, $f12 # +; MMR6-NEXT: # > +; MMR6-NEXT: mfc1 $2, $f0 # +; MMR6-NEXT: # > +; MMR6-NEXT: jrc $ra # > +; +; MMR6-SF-LABEL: test2: +; MMR6-SF: # %bb.0: # %entry +; MMR6-SF-NEXT: addiu $sp, $sp, -24 # +; MMR6-SF-NEXT: # +; MMR6-SF-NEXT: # > +; MMR6-SF-NEXT: .cfi_def_cfa_offset 24 +; MMR6-SF-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill +; MMR6-SF-NEXT: # +; MMR6-SF-NEXT: # +; MMR6-SF-NEXT: # > +; MMR6-SF-NEXT: .cfi_offset 31, -4 +; MMR6-SF-NEXT: jalr __fixdfsi # > +; MMR6-SF-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload +; MMR6-SF-NEXT: # +; MMR6-SF-NEXT: # +; MMR6-SF-NEXT: # > +; MMR6-SF-NEXT: addiu $sp, $sp, 24 # +; MMR6-SF-NEXT: # +; MMR6-SF-NEXT: # > +; MMR6-SF-NEXT: jrc $ra # > +entry: + %conv = fptosi double %t to i32 + ret i32 %conv +} diff --git a/llvm/test/CodeGen/Mips/llvm-ir/sdiv.ll b/llvm/test/CodeGen/Mips/llvm-ir/sdiv.ll index e54eaa63222a0..af3d4f50f3fe4 100644 --- a/llvm/test/CodeGen/Mips/llvm-ir/sdiv.ll +++ b/llvm/test/CodeGen/Mips/llvm-ir/sdiv.ll @@ -1,36 +1,38 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R2 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2 ; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R2 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r2 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r5 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=GP32R6 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP32R6 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips4 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r2 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r3 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r5 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r6 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=GP64R6 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP64R6 -; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=MMR3 -; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=MMR6 +; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips \ +; RUN: -relocation-model=pic -mips-jalr-reloc=false | \ +; RUN: FileCheck %s -check-prefix=MMR3 +; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips \ +; RUN: -relocation-model=pic -mips-jalr-reloc=false | \ +; RUN: FileCheck %s -check-prefix=MMR6 define signext i1 @sdiv_i1(i1 signext %a, i1 signext %b) { ; GP32-LABEL: sdiv_i1: diff --git a/llvm/test/CodeGen/Mips/llvm-ir/srem.ll b/llvm/test/CodeGen/Mips/llvm-ir/srem.ll index ef0502c85d59b..487a5b9b6cbc5 100644 --- a/llvm/test/CodeGen/Mips/llvm-ir/srem.ll +++ b/llvm/test/CodeGen/Mips/llvm-ir/srem.ll @@ -1,36 +1,38 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R2 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2 ; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R2 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r2 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r5 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=GP32R6 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP32R6 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips4 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r2 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r3 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r5 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r6 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=GP64R6 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP64R6 -; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=MMR3 -; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=MMR6 +; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips \ +; RUN: -relocation-model=pic -mips-jalr-reloc=false | \ +; RUN: FileCheck %s -check-prefix=MMR3 +; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips \ +; RUN: -relocation-model=pic -mips-jalr-reloc=false | \ +; RUN: FileCheck %s -check-prefix=MMR6 define signext i1 @srem_i1(i1 signext %a, i1 signext %b) { ; GP32-LABEL: srem_i1: diff --git a/llvm/test/CodeGen/Mips/llvm-ir/udiv.ll b/llvm/test/CodeGen/Mips/llvm-ir/udiv.ll index 8694a9f92b65a..3b7243712024b 100644 --- a/llvm/test/CodeGen/Mips/llvm-ir/udiv.ll +++ b/llvm/test/CodeGen/Mips/llvm-ir/udiv.ll @@ -1,36 +1,38 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R1 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R1 ; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R1 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R1 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r2 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r5 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=GP32R6 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP32R6 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips4 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R2 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R2 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r2 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r3 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r5 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r6 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=GP64R6 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP64R6 -; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=MMR3 -; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=MMR6 +; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips \ +; RUN: -relocation-model=pic -mips-jalr-reloc=false | \ +; RUN: FileCheck %s -check-prefix=MMR3 +; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips \ +; RUN: -relocation-model=pic -mips-jalr-reloc=false | \ +; RUN: FileCheck %s -check-prefix=MMR6 define zeroext i1 @udiv_i1(i1 zeroext %a, i1 zeroext %b) { ; GP32-LABEL: udiv_i1: diff --git a/llvm/test/CodeGen/Mips/llvm-ir/urem.ll b/llvm/test/CodeGen/Mips/llvm-ir/urem.ll index b744f706cbf9c..4105d67da6f1a 100644 --- a/llvm/test/CodeGen/Mips/llvm-ir/urem.ll +++ b/llvm/test/CodeGen/Mips/llvm-ir/urem.ll @@ -1,36 +1,38 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=mips -mcpu=mips2 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R2 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2 ; RUN: llc < %s -mtriple=mips -mcpu=mips32 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R0R2 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R0R2 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r2 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r5 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP32,GP32R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP32,GP32R2R5 ; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=GP32R6 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP32R6 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips3 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips4 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R0R1 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R0R1 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r2 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r3 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r5 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefixes=GP64,GP64R2R5 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefixes=GP64,GP64R2R5 ; RUN: llc < %s -mtriple=mips64 -mcpu=mips64r6 -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=GP64R6 +; RUN: -mips-jalr-reloc=false | FileCheck %s -check-prefix=GP64R6 -; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=MMR3 -; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips -relocation-model=pic \ -; RUN: | FileCheck %s -check-prefix=MMR6 +; RUN: llc < %s -mtriple=mips -mcpu=mips32r3 -mattr=+micromips \ +; RUN: -relocation-model=pic -mips-jalr-reloc=false | \ +; RUN: FileCheck %s -check-prefix=MMR3 +; RUN: llc < %s -mtriple=mips -mcpu=mips32r6 -mattr=+micromips \ +; RUN: -relocation-model=pic -mips-jalr-reloc=false | \ +; RUN: FileCheck %s -check-prefix=MMR6 define signext i1 @urem_i1(i1 signext %a, i1 signext %b) { ; GP32-LABEL: urem_i1: diff --git a/llvm/test/CodeGen/Mips/long-call-attr.ll b/llvm/test/CodeGen/Mips/long-call-attr.ll index 5b6ba94aaa356..beda290a9725b 100644 --- a/llvm/test/CodeGen/Mips/long-call-attr.ll +++ b/llvm/test/CodeGen/Mips/long-call-attr.ll @@ -1,11 +1,11 @@ ; RUN: llc -march=mips -target-abi o32 --mattr=+long-calls,+noabicalls < %s \ -; RUN: | FileCheck -check-prefix=O32 %s +; RUN: -mips-jalr-reloc=false | FileCheck -check-prefix=O32 %s ; RUN: llc -march=mips -target-abi o32 --mattr=-long-calls,+noabicalls < %s \ -; RUN: | FileCheck -check-prefix=O32 %s +; RUN: -mips-jalr-reloc=false | FileCheck -check-prefix=O32 %s ; RUN: llc -march=mips64 -target-abi n64 --mattr=+long-calls,+noabicalls < %s \ -; RUN: | FileCheck -check-prefix=N64 %s +; RUN: -mips-jalr-reloc=false | FileCheck -check-prefix=N64 %s ; RUN: llc -march=mips64 -target-abi n64 --mattr=-long-calls,+noabicalls < %s \ -; RUN: | FileCheck -check-prefix=N64 %s +; RUN: -mips-jalr-reloc=false | FileCheck -check-prefix=N64 %s declare void @far() #0 diff --git a/llvm/test/CodeGen/Mips/long-call-mcount.ll b/llvm/test/CodeGen/Mips/long-call-mcount.ll index 70a4410d060ba..580f452526f73 100644 --- a/llvm/test/CodeGen/Mips/long-call-mcount.ll +++ b/llvm/test/CodeGen/Mips/long-call-mcount.ll @@ -1,8 +1,8 @@ ; Check call to mcount in case of long/short call options. ; RUN: llc -march=mips -target-abi o32 --mattr=+long-calls,+noabicalls < %s \ -; RUN: | FileCheck -check-prefixes=CHECK,LONG %s +; RUN: -mips-jalr-reloc=false | FileCheck -check-prefixes=CHECK,LONG %s ; RUN: llc -march=mips -target-abi o32 --mattr=-long-calls,+noabicalls < %s \ -; RUN: | FileCheck -check-prefixes=CHECK,SHORT %s +; RUN: -mips-jalr-reloc=false | FileCheck -check-prefixes=CHECK,SHORT %s ; Function Attrs: noinline nounwind optnone define void @foo() #0 { diff --git a/llvm/test/CodeGen/Mips/micromips-b-range.ll b/llvm/test/CodeGen/Mips/micromips-b-range.ll index 5831ae81baeda..27a0db545f743 100644 --- a/llvm/test/CodeGen/Mips/micromips-b-range.ll +++ b/llvm/test/CodeGen/Mips/micromips-b-range.ll @@ -13,7 +13,7 @@ ; CHECK-NEXT: 1e: fb fd 00 00 sw $ra, 0($sp) ; CHECK-NEXT: 22: 41 a1 00 01 lui $1, 1 ; CHECK-NEXT: 26: 40 60 00 02 bal 8 -; CHECK-NEXT: 2a: 30 21 04 68 addiu $1, $1, 1128 +; CHECK-NEXT: 2a: 30 21 04 69 addiu $1, $1, 1129 ; CHECK-NEXT: 2e: 00 3f 09 50 addu $1, $ra, $1 ; CHECK-NEXT: 32: ff fd 00 00 lw $ra, 0($sp) ; CHECK-NEXT: 36: 00 01 0f 3c jr $1 @@ -27,7 +27,7 @@ ; CHECK-NEXT: 56: fb fd 00 00 sw $ra, 0($sp) ; CHECK-NEXT: 5a: 41 a1 00 01 lui $1, 1 ; CHECK-NEXT: 5e: 40 60 00 02 bal 8 -; CHECK-NEXT: 62: 30 21 04 5c addiu $1, $1, 1116 +; CHECK-NEXT: 62: 30 21 04 5d addiu $1, $1, 1117 ; CHECK-NEXT: 66: 00 3f 09 50 addu $1, $ra, $1 ; CHECK-NEXT: 6a: ff fd 00 00 lw $ra, 0($sp) ; CHECK-NEXT: 6e: 00 01 0f 3c jr $1 @@ -39,7 +39,7 @@ ; CHECK-NEXT: 86: fb fd 00 00 sw $ra, 0($sp) ; CHECK-NEXT: 8a: 41 a1 00 01 lui $1, 1 ; CHECK-NEXT: 8e: 40 60 00 02 bal 8 -; CHECK-NEXT: 92: 30 21 04 2c addiu $1, $1, 1068 +; CHECK-NEXT: 92: 30 21 04 2d addiu $1, $1, 1069 ; CHECK-NEXT: 96: 00 3f 09 50 addu $1, $ra, $1 ; CHECK-NEXT: 9a: ff fd 00 00 lw $ra, 0($sp) ; CHECK-NEXT: 9e: 00 01 0f 3c jr $1 @@ -51,7 +51,7 @@ ; CHECK-NEXT: 10476: fb fd 00 00 sw $ra, 0($sp) ; CHECK-NEXT: 1047a: 41 a1 00 01 lui $1, 1 ; CHECK-NEXT: 1047e: 40 60 00 02 bal 8 -; CHECK-NEXT: 10482: 30 21 04 00 addiu $1, $1, 1024 +; CHECK-NEXT: 10482: 30 21 04 01 addiu $1, $1, 1025 ; CHECK-NEXT: 10486: 00 3f 09 50 addu $1, $ra, $1 ; CHECK-NEXT: 1048a: ff fd 00 00 lw $ra, 0($sp) ; CHECK-NEXT: 1048e: 00 01 0f 3c jr $1 diff --git a/llvm/test/CodeGen/Mips/micromips-pseudo-mtlohi-expand.ll b/llvm/test/CodeGen/Mips/micromips-pseudo-mtlohi-expand.ll new file mode 100644 index 0000000000000..3f86bd24f34ff --- /dev/null +++ b/llvm/test/CodeGen/Mips/micromips-pseudo-mtlohi-expand.ll @@ -0,0 +1,63 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=mipsel-linux-gnu -mcpu=mips32r2 -mattr=+micromips -asm-show-inst < %s |\ +; RUN: FileCheck %s -check-prefixes=MMR2 +; RUN: llc -mtriple=mipsel-linux-gnu -mcpu=mips32r2 -mattr=+dsp,+micromips -asm-show-inst < %s |\ +; RUN: FileCheck %s -check-prefixes=MMR2-DSP + +define i64 @test(i32 signext %a, i32 signext %b) { +; MMR2-LABEL: test: +; MMR2: # %bb.0: # %entry +; MMR2-NEXT: li16 $2, 0 # +; MMR2-NEXT: # > +; MMR2-NEXT: li16 $3, 1 # +; MMR2-NEXT: # > +; MMR2-NEXT: mtlo $3 # > +; MMR2-NEXT: mthi $2 # > +; MMR2-NEXT: madd $4, $5 # +; MMR2-NEXT: # > +; MMR2-NEXT: mflo16 $2 # > +; MMR2-NEXT: mfhi16 $3 # > +; MMR2-NEXT: jrc $ra # > +; +; MMR2-DSP-LABEL: test: +; MMR2-DSP: # %bb.0: # %entry +; MMR2-DSP-NEXT: li16 $2, 0 # +; MMR2-DSP-NEXT: # > +; MMR2-DSP-NEXT: li16 $3, 1 # +; MMR2-DSP-NEXT: # > +; MMR2-DSP-NEXT: mtlo $3, $ac0 # +; MMR2-DSP-NEXT: # > +; MMR2-DSP-NEXT: mthi $2, $ac0 # +; MMR2-DSP-NEXT: # > +; MMR2-DSP-NEXT: madd $ac0, $4, $5 # +; MMR2-DSP-NEXT: # +; MMR2-DSP-NEXT: # +; MMR2-DSP-NEXT: # > +; MMR2-DSP-NEXT: mflo $2, $ac0 # +; MMR2-DSP-NEXT: # > +; MMR2-DSP-NEXT: jr $ra # > +; MMR2-DSP-NEXT: mfhi $3, $ac0 # +; MMR2-DSP-NEXT: # > +entry: + %conv = sext i32 %a to i64 + %conv1 = sext i32 %b to i64 + %mul = mul nsw i64 %conv, %conv1 + %add = add nsw i64 %mul, 1 + ret i64 %add +} diff --git a/llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll b/llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll index 9105e9249d4f0..8544a75c50a62 100644 --- a/llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll +++ b/llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll @@ -1,22 +1,22 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -relocation-model=pic -mtriple=mipsel-- -mcpu=mips32r5 \ -; RUN: -mattr=+fp64,+msa -verify-machineinstrs < %s | FileCheck %s \ +; RUN: -mattr=+fp64,+msa -verify-machineinstrs -mips-jalr-reloc=false < %s | FileCheck %s \ ; RUN: --check-prefixes=ALL,MIPS32,MIPSR5,MIPS32-O32,MIPS32R5-O32 ; RUN: llc -relocation-model=pic -mtriple=mips64el-- -mcpu=mips64r5 \ -; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n32 < %s | FileCheck %s \ +; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n32 -mips-jalr-reloc=false < %s | FileCheck %s \ ; RUN: --check-prefixes=ALL,MIPS64,MIPSR5,MIPS64-N32,MIPS64R5-N32 ; RUN: llc -relocation-model=pic -mtriple=mips64el-- -mcpu=mips64r5 \ -; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n64 < %s | FileCheck %s \ +; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n64 -mips-jalr-reloc=false < %s | FileCheck %s \ ; RUN: --check-prefixes=ALL,MIPS64,MIPSR5,MIPS64-N64,MIPS64R5-N64 ; RUN: llc -relocation-model=pic -mtriple=mipsel-- -mcpu=mips32r6 \ -; RUN: -mattr=+fp64,+msa -verify-machineinstrs < %s | FileCheck %s \ +; RUN: -mattr=+fp64,+msa -verify-machineinstrs -mips-jalr-reloc=false < %s | FileCheck %s \ ; RUN: --check-prefixes=ALL,MIPS32,MIPSR6,MIPSR6-O32 ; RUN: llc -relocation-model=pic -mtriple=mips64el-- -mcpu=mips64r6 \ -; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n32 < %s | FileCheck %s \ +; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n32 -mips-jalr-reloc=false < %s | FileCheck %s \ ; RUN: --check-prefixes=ALL,MIPS64,MIPSR6,MIPS64-N32,MIPSR6-N32 ; RUN: llc -relocation-model=pic -mtriple=mips64el-- -mcpu=mips64r6 \ -; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n64 < %s | FileCheck %s \ +; RUN: -mattr=+fp64,+msa -verify-machineinstrs -target-abi n64 -mips-jalr-reloc=false < %s | FileCheck %s \ ; RUN: --check-prefixes=ALL,MIPS64,MIPSR6,MIPS64-N64,MIPSR6-N64 diff --git a/llvm/test/CodeGen/Mips/o32_cc_byval.ll b/llvm/test/CodeGen/Mips/o32_cc_byval.ll index 19eb80b79bafe..d9951ebeaf3a9 100644 --- a/llvm/test/CodeGen/Mips/o32_cc_byval.ll +++ b/llvm/test/CodeGen/Mips/o32_cc_byval.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=mipsel-unknown-linux-gnu -relocation-model=pic < %s | FileCheck %s +; RUN: llc -mtriple=mipsel-unknown-linux-gnu -relocation-model=pic \ +; RUN: -mips-jalr-reloc=false < %s | FileCheck %s %0 = type { i8, i16, i32, i64, double, i32, [4 x i8] } %struct.S1 = type { i8, i16, i32, i64, double, i32 } diff --git a/llvm/test/CodeGen/Mips/pseudo-jump-fill.ll b/llvm/test/CodeGen/Mips/pseudo-jump-fill.ll new file mode 100644 index 0000000000000..31f077d57a933 --- /dev/null +++ b/llvm/test/CodeGen/Mips/pseudo-jump-fill.ll @@ -0,0 +1,68 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=mipsel-linux-gnu -mattr=+micromips -relocation-model=pic < %s | FileCheck %s + +; Test that the delay slot filler correctly handles indirect branches for +; microMIPS in regard to incorrectly using 16bit instructions in delay slots of +; 32bit instructions. + +define i32 @test(i32 signext %x, i32 signext %c) { +; CHECK-LABEL: test: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lui $2, %hi(_gp_disp) +; CHECK-NEXT: addiu $2, $2, %lo(_gp_disp) +; CHECK-NEXT: addiur2 $5, $5, -1 +; CHECK-NEXT: sltiu $1, $5, 4 +; CHECK-NEXT: beqz $1, $BB0_3 +; CHECK-NEXT: addu $3, $2, $25 +; CHECK-NEXT: $BB0_1: # %entry +; CHECK-NEXT: li16 $2, 0 +; CHECK-NEXT: sll16 $5, $5, 2 +; CHECK-NEXT: lw $6, %got($JTI0_0)($3) +; CHECK-NEXT: addu16 $5, $5, $6 +; CHECK-NEXT: lw $5, %lo($JTI0_0)($5) +; CHECK-NEXT: addu16 $3, $5, $3 +; CHECK-NEXT: jr $3 +; CHECK-NEXT: nop +; CHECK-NEXT: $BB0_2: # %sw.bb2 +; CHECK-NEXT: addiur2 $2, $4, 1 +; CHECK-NEXT: jrc $ra +; CHECK-NEXT: $BB0_3: +; CHECK-NEXT: move $2, $4 +; CHECK-NEXT: jrc $ra +; CHECK-NEXT: $BB0_4: # %sw.bb3 +; CHECK-NEXT: addius5 $4, 2 +; CHECK-NEXT: move $2, $4 +; CHECK-NEXT: jrc $ra +; CHECK-NEXT: $BB0_5: # %sw.bb5 +; CHECK-NEXT: addius5 $4, 3 +; CHECK-NEXT: move $2, $4 +; CHECK-NEXT: $BB0_6: # %for.cond.cleanup +; CHECK-NEXT: jrc $ra +entry: + switch i32 %c, label %sw.epilog [ + i32 4, label %sw.bb5 + i32 1, label %for.cond.cleanup + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + ] + +sw.bb2: + %add = add nsw i32 %x, 1 + br label %sw.epilog + +sw.bb3: + %add4 = add nsw i32 %x, 2 + br label %sw.epilog + +sw.bb5: + %add6 = add nsw i32 %x, 3 + br label %sw.epilog + +sw.epilog: + %a.0 = phi i32 [ %add6, %sw.bb5 ], [ %add4, %sw.bb3 ], [ %add, %sw.bb2 ], [ %x, %entry ] + br label %for.cond.cleanup + +for.cond.cleanup: + %a.028 = phi i32 [ %a.0, %sw.epilog ], [ 0, %entry ] + ret i32 %a.028 +} diff --git a/llvm/test/CodeGen/Mips/reloc-jalr.ll b/llvm/test/CodeGen/Mips/reloc-jalr.ll new file mode 100644 index 0000000000000..f8fd903110045 --- /dev/null +++ b/llvm/test/CodeGen/Mips/reloc-jalr.ll @@ -0,0 +1,154 @@ +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic -mips-tail-calls=1 \ +; RUN: -O2 < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,JALR-32R2,TAILCALL-32R2 + +; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic -mips-tail-calls=1 \ +; RUN: -O2 < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,JALR-64R2,TAILCALL-64R2 + +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic -mips-tail-calls=1 \ +; RUN: -O2 -mcpu=mips32r6 -mips-compact-branches=always < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,JALR-32R6,TAILCALL-32R6 + +; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic -mips-tail-calls=1 \ +; RUN: -O2 -mcpu=mips64r6 -mips-compact-branches=always < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,JALR-64R6,TAILCALL-64R6 + +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic -mips-tail-calls=1 \ +; RUN: -O2 -mcpu=mips32r6 -mips-compact-branches=never < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,JALR-32R2,TAILCALL-32R2 + +; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic -mips-tail-calls=1 \ +; RUN: -O2 -mcpu=mips64r6 -mips-compact-branches=never < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,JALR-64R2,TAILCALL-64R2 + +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic -mips-tail-calls=1 \ +; RUN: -O2 -mattr=+micromips -mcpu=mips32r2 < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,JALR-MM,TAILCALL-MM + +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic -mips-tail-calls=1 \ +; RUN: -O2 -mattr=+micromips -mcpu=mips32r6 < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,JALR-MM + +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic \ +; RUN: -O0 < %s | FileCheck %s -check-prefixes=ALL,JALR-32R2 + +; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic \ +; RUN: -O0 < %s | FileCheck %s -check-prefixes=ALL,JALR-64R2 + +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic \ +; RUN: -O0 -mcpu=mips32r6 -mips-compact-branches=always < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,JALR-32R6 + +; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic \ +; RUN: -O0 -mcpu=mips64r6 -mips-compact-branches=always < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,JALR-64R6 + +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic \ +; RUN: -O0 -mcpu=mips32r6 -mips-compact-branches=never < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,JALR-32R2 + +; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic \ +; RUN: -O0 -mcpu=mips64r6 -mips-compact-branches=never < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,JALR-64R2 + +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic \ +; RUN: -O0 -mattr=+micromips -mcpu=mips32r2 < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,JALR-MM + +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic \ +; RUN: -O0 -mattr=+micromips -mcpu=mips32r6 < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,JALR-MM + +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic -mips-tail-calls=1 \ +; RUN: -O2 -mips-jalr-reloc=false < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,NORELOC + +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=static -mips-tail-calls=1 \ +; RUN: -O2 < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,NORELOC + +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=pic -mips-tail-calls=1 \ +; RUN: -O0 -mips-jalr-reloc=false < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,NORELOC + +; RUN: llc -mtriple=mips-linux-gnu -relocation-model=static -mips-tail-calls=1 \ +; RUN: -O0 < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,NORELOC + +; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic -mips-tail-calls=1 \ +; RUN: -O2 -mips-jalr-reloc=false < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,NORELOC + +; RUN: llc -mtriple=mips64-linux-gnu -mips-tail-calls=1 \ +; RUN: -O2 -relocation-model=static < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,NORELOC + +; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=pic \ +; RUN: -O0 -mips-jalr-reloc=false < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,NORELOC + +; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static \ +; RUN: -O0 < %s | \ +; RUN: FileCheck %s -check-prefixes=ALL,NORELOC + +define internal void @foo() noinline { +entry: + ret void +} + +define void @checkCall() { +entry: +; ALL-LABEL: checkCall: + call void @foo() +; JALR-32R2: .reloc ([[TMPLABEL:.*]]), R_MIPS_JALR, foo +; JALR-32R2-NEXT: [[TMPLABEL]]: +; JALR-32R2-NEXT: jalr $25 + +; JALR-64R2: .reloc [[TMPLABEL:.*]], R_MIPS_JALR, foo +; JALR-64R2-NEXT: [[TMPLABEL]]: +; JALR-64R2-NEXT: jalr $25 + +; JALR-MM: .reloc ([[TMPLABEL:.*]]), R_MICROMIPS_JALR, foo +; JALR-MM-NEXT: [[TMPLABEL]]: +; JALR-MM-NEXT: jalr $25 + +; JALR-32R6: .reloc ([[TMPLABEL:.*]]), R_MIPS_JALR, foo +; JALR-32R6-NEXT: [[TMPLABEL]]: +; JALR-32R6-NEXT: jalrc $25 + +; JALR-64R6: .reloc [[TMPLABEL:.*]], R_MIPS_JALR, foo +; JALR-64R6-NEXT: [[TMPLABEL]]: +; JALR-64R6-NEXT: jalrc $25 + +; NORELOC-NOT: R_MIPS_JALR + ret void +} + +define void @checkTailCall() { +entry: +; ALL-LABEL: checkTailCall: + tail call void @foo() +; TAILCALL-32R2: .reloc ([[TMPLABEL:.*]]), R_MIPS_JALR, foo +; TAILCALL-32R2-NEXT: [[TMPLABEL]]: +; TAILCALL-32R2-NEXT: jr $25 + +; TAILCALL-64R2: .reloc [[TMPLABEL:.*]], R_MIPS_JALR, foo +; TAILCALL-64R2-NEXT: [[TMPLABEL]]: +; TAILCALL-64R2-NEXT: jr $25 + +; TAILCALL-MM: .reloc ([[TMPLABEL:.*]]), R_MICROMIPS_JALR, foo +; TAILCALL-MM-NEXT: [[TMPLABEL]]: +; TAILCALL-MM-NEXT: jrc $25 + +; TAILCALL-32R6: .reloc ([[TMPLABEL:.*]]), R_MIPS_JALR, foo +; TAILCALL-32R6-NEXT: [[TMPLABEL]]: +; TAILCALL-32R6-NEXT: jrc $25 + +; TAILCALL-64R6: .reloc [[TMPLABEL:.*]], R_MIPS_JALR, foo +; TAILCALL-64R6-NEXT: [[TMPLABEL]]: +; TAILCALL-64R6-NEXT: jrc $25 + +; NORELOC-NOT: R_MIPS_JALR + ret void +} diff --git a/llvm/test/CodeGen/Mips/shrink-wrapping.ll b/llvm/test/CodeGen/Mips/shrink-wrapping.ll index 54ae8699d1c19..b08d2f1b64678 100644 --- a/llvm/test/CodeGen/Mips/shrink-wrapping.ll +++ b/llvm/test/CodeGen/Mips/shrink-wrapping.ll @@ -9,11 +9,11 @@ ; RUN: FileCheck %s -check-prefix=NO-SHRINK-WRAP-STATIC ; RUN: llc -mtriple=mips-unknown-linux-gnu -enable-shrink-wrap=true \ -; RUN: -relocation-model=pic < %s | \ +; RUN: -relocation-model=pic -mips-jalr-reloc=false < %s | \ ; RUN: FileCheck %s -check-prefix=SHRINK-WRAP-PIC ; RUN: llc -mtriple=mips-unknown-linux-gnu -enable-shrink-wrap=false \ -; RUN: -relocation-model=pic < %s | \ +; RUN: -relocation-model=pic -mips-jalr-reloc=false < %s | \ ; RUN: FileCheck %s -check-prefix=NO-SHRINK-WRAP-PIC ; RUN: llc -mtriple=mips64-unknown-linux-gnu -enable-shrink-wrap=true \ @@ -25,11 +25,11 @@ ; RUN: FileCheck %s -check-prefix=NO-SHRINK-WRAP-64-STATIC ; RUN: llc -mtriple=mips64-unknown-linux-gnu -enable-shrink-wrap=true \ -; RUN: -relocation-model=pic < %s | \ +; RUN: -relocation-model=pic -mips-jalr-reloc=false < %s | \ ; RUN: FileCheck %s -check-prefix=SHRINK-WRAP-64-PIC ; RUN: llc -mtriple=mips64-unknown-linux-gnu -enable-shrink-wrap=false \ -; RUN: -relocation-model=pic < %s | \ +; RUN: -relocation-model=pic -mips-jalr-reloc=false < %s | \ ; RUN: FileCheck %s -check-prefix=NO-SHRINK-WRAP-64-PIC declare void @f(i32 signext) diff --git a/llvm/test/CodeGen/PowerPC/ppc32-pic-large.ll b/llvm/test/CodeGen/PowerPC/ppc32-pic-large.ll index d6e491ea2734c..272138e5121bf 100644 --- a/llvm/test/CodeGen/PowerPC/ppc32-pic-large.ll +++ b/llvm/test/CodeGen/PowerPC/ppc32-pic-large.ll @@ -1,5 +1,9 @@ ; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -relocation-model=pic | FileCheck -check-prefix=LARGE-BSS %s ; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -mattr=+secure-plt -relocation-model=pic | FileCheck -check-prefix=LARGE-SECUREPLT %s +; RUN: llc < %s -mtriple=powerpc-unknown-netbsd -mattr=+secure-plt -relocation-model=pic | FileCheck -check-prefix=LARGE-SECUREPLT %s +; RUN: llc < %s -mtriple=powerpc-unknown-netbsd -relocation-model=pic | FileCheck -check-prefix=LARGE-SECUREPLT %s +; RUN: llc < %s -mtriple=powerpc-unknown-openbsd -mattr=+secure-plt -relocation-model=pic | FileCheck -check-prefix=LARGE-SECUREPLT %s +; RUN: llc < %s -mtriple=powerpc-unknown-openbsd -relocation-model=pic | FileCheck -check-prefix=LARGE-SECUREPLT %s @bar = common global i32 0, align 4 declare i32 @call_foo(i32, ...) diff --git a/llvm/test/CodeGen/SPARC/fp128.ll b/llvm/test/CodeGen/SPARC/fp128.ll index 535f0ef60c404..21a9cdf77e0de 100644 --- a/llvm/test/CodeGen/SPARC/fp128.ll +++ b/llvm/test/CodeGen/SPARC/fp128.ll @@ -53,6 +53,29 @@ entry: ret void } +; CHECK-LABEL: f128_spill_large: +; CHECK: sethi 4, %g1 +; CHECK: sethi 4, %g1 +; CHECK-NEXT: add %g1, %sp, %g1 +; CHECK-NEXT: std %f{{.+}}, [%g1] +; CHECK: sethi 4, %g1 +; CHECK-NEXT: add %g1, %sp, %g1 +; CHECK-NEXT: std %f{{.+}}, [%g1+8] +; CHECK: sethi 4, %g1 +; CHECK-NEXT: add %g1, %sp, %g1 +; CHECK-NEXT: ldd [%g1], %f{{.+}} +; CHECK: sethi 4, %g1 +; CHECK-NEXT: add %g1, %sp, %g1 +; CHECK-NEXT: ldd [%g1+8], %f{{.+}} + +define void @f128_spill_large(<251 x fp128>* noalias sret %scalar.result, <251 x fp128>* byval %a) { +entry: + %0 = load <251 x fp128>, <251 x fp128>* %a, align 8 + call void asm sideeffect "", "~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f8},~{f9},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f18},~{f19},~{f20},~{f21},~{f22},~{f23},~{f24},~{f25},~{f26},~{f27},~{f28},~{f29},~{f30},~{f31}"() + store <251 x fp128> %0, <251 x fp128>* %scalar.result, align 8 + ret void +} + ; CHECK-LABEL: f128_compare: ; HARD: fcmpq ; HARD-NEXT: nop diff --git a/llvm/test/CodeGen/SystemZ/memcmp-01.ll b/llvm/test/CodeGen/SystemZ/memcmp-01.ll index ac980e49d60bc..740a86750dd8a 100644 --- a/llvm/test/CodeGen/SystemZ/memcmp-01.ll +++ b/llvm/test/CodeGen/SystemZ/memcmp-01.ll @@ -16,10 +16,10 @@ define i32 @f1(i8 *%src1, i8 *%src2) { ; Check a case where the result is used as an integer. define i32 @f2(i8 *%src1, i8 *%src2) { ; CHECK-LABEL: f2: -; CHECK: clc 0(2,%r2), 0(%r3) -; CHECK: ipm [[REG:%r[0-5]]] -; CHECK: srl [[REG]], 28 -; CHECK: rll %r2, [[REG]], 31 +; CHECK: clc 0(2,%r3), 0(%r2) +; CHECK: ipm %r2 +; CHECK: sll %r2, 2 +; CHECK: sra %r2, 30 ; CHECK: br %r14 %res = call i32 @memcmp(i8 *%src1, i8 *%src2, i64 2) ret i32 %res @@ -28,7 +28,7 @@ define i32 @f2(i8 *%src1, i8 *%src2) { ; Check a case where the result is tested for equality. define void @f3(i8 *%src1, i8 *%src2, i32 *%dest) { ; CHECK-LABEL: f3: -; CHECK: clc 0(3,%r2), 0(%r3) +; CHECK: clc 0(3,%r3), 0(%r2) ; CHECK-NEXT: ber %r14 ; CHECK: br %r14 %res = call i32 @memcmp(i8 *%src1, i8 *%src2, i64 3) @@ -46,7 +46,7 @@ exit: ; Check a case where the result is tested for inequality. define void @f4(i8 *%src1, i8 *%src2, i32 *%dest) { ; CHECK-LABEL: f4: -; CHECK: clc 0(4,%r2), 0(%r3) +; CHECK: clc 0(4,%r3), 0(%r2) ; CHECK-NEXT: blhr %r14 ; CHECK: br %r14 entry: @@ -65,8 +65,8 @@ exit: ; Check a case where the result is tested via slt. define void @f5(i8 *%src1, i8 *%src2, i32 *%dest) { ; CHECK-LABEL: f5: -; CHECK: clc 0(5,%r2), 0(%r3) -; CHECK-NEXT: blr %r14 +; CHECK: clc 0(5,%r3), 0(%r2) +; CHECK-NEXT: bhr %r14 ; CHECK: br %r14 entry: %res = call i32 @memcmp(i8 *%src1, i8 *%src2, i64 5) @@ -84,8 +84,8 @@ exit: ; Check a case where the result is tested for sgt. define void @f6(i8 *%src1, i8 *%src2, i32 *%dest) { ; CHECK-LABEL: f6: -; CHECK: clc 0(6,%r2), 0(%r3) -; CHECK-NEXT: bhr %r14 +; CHECK: clc 0(6,%r3), 0(%r2) +; CHECK-NEXT: blr %r14 ; CHECK: br %r14 entry: %res = call i32 @memcmp(i8 *%src1, i8 *%src2, i64 6) @@ -104,10 +104,10 @@ exit: ; an integer and for branching. define i32 @f7(i8 *%src1, i8 *%src2, i32 *%dest) { ; CHECK-LABEL: f7: -; CHECK: clc 0(256,%r2), 0(%r3) -; CHECK: ipm [[REG:%r[0-5]]] -; CHECK: srl [[REG]], 28 -; CHECK: rll %r2, [[REG]], 31 +; CHECK: clc 0(256,%r3), 0(%r2) +; CHECK: ipm %r2 +; CHECK: sll %r2, 2 +; CHECK: sra %r2, 30 ; CHECK: blr %r14 ; CHECK: br %r14 entry: @@ -126,9 +126,9 @@ exit: ; 257 bytes needs two CLCs. define i32 @f8(i8 *%src1, i8 *%src2) { ; CHECK-LABEL: f8: -; CHECK: clc 0(256,%r2), 0(%r3) +; CHECK: clc 0(256,%r3), 0(%r2) ; CHECK: jlh [[LABEL:\..*]] -; CHECK: clc 256(1,%r2), 256(%r3) +; CHECK: clc 256(1,%r3), 256(%r2) ; CHECK: [[LABEL]]: ; CHECK: ipm [[REG:%r[0-5]]] ; CHECK: br %r14 @@ -139,11 +139,11 @@ define i32 @f8(i8 *%src1, i8 *%src2) { ; Test a comparison of 258 bytes in which the CC result can be used directly. define void @f9(i8 *%src1, i8 *%src2, i32 *%dest) { ; CHECK-LABEL: f9: -; CHECK: clc 0(256,%r2), 0(%r3) +; CHECK: clc 0(256,%r3), 0(%r2) ; CHECK: jlh [[LABEL:\..*]] -; CHECK: clc 256(1,%r2), 256(%r3) +; CHECK: clc 256(1,%r3), 256(%r2) ; CHECK: [[LABEL]]: -; CHECK-NEXT: blr %r14 +; CHECK-NEXT: bhr %r14 ; CHECK: br %r14 entry: %res = call i32 @memcmp(i8 *%src1, i8 *%src2, i64 257) @@ -161,9 +161,9 @@ exit: ; Test the largest size that can use two CLCs. define i32 @f10(i8 *%src1, i8 *%src2) { ; CHECK-LABEL: f10: -; CHECK: clc 0(256,%r2), 0(%r3) +; CHECK: clc 0(256,%r3), 0(%r2) ; CHECK: jlh [[LABEL:\..*]] -; CHECK: clc 256(256,%r2), 256(%r3) +; CHECK: clc 256(256,%r3), 256(%r2) ; CHECK: [[LABEL]]: ; CHECK: ipm [[REG:%r[0-5]]] ; CHECK: br %r14 @@ -174,11 +174,11 @@ define i32 @f10(i8 *%src1, i8 *%src2) { ; Test the smallest size that needs 3 CLCs. define i32 @f11(i8 *%src1, i8 *%src2) { ; CHECK-LABEL: f11: -; CHECK: clc 0(256,%r2), 0(%r3) +; CHECK: clc 0(256,%r3), 0(%r2) ; CHECK: jlh [[LABEL:\..*]] -; CHECK: clc 256(256,%r2), 256(%r3) +; CHECK: clc 256(256,%r3), 256(%r2) ; CHECK: jlh [[LABEL]] -; CHECK: clc 512(1,%r2), 512(%r3) +; CHECK: clc 512(1,%r3), 512(%r2) ; CHECK: [[LABEL]]: ; CHECK: ipm [[REG:%r[0-5]]] ; CHECK: br %r14 @@ -189,11 +189,11 @@ define i32 @f11(i8 *%src1, i8 *%src2) { ; Test the largest size than can use 3 CLCs. define i32 @f12(i8 *%src1, i8 *%src2) { ; CHECK-LABEL: f12: -; CHECK: clc 0(256,%r2), 0(%r3) +; CHECK: clc 0(256,%r3), 0(%r2) ; CHECK: jlh [[LABEL:\..*]] -; CHECK: clc 256(256,%r2), 256(%r3) +; CHECK: clc 256(256,%r3), 256(%r2) ; CHECK: jlh [[LABEL]] -; CHECK: clc 512(256,%r2), 512(%r3) +; CHECK: clc 512(256,%r3), 512(%r2) ; CHECK: [[LABEL]]: ; CHECK: ipm [[REG:%r[0-5]]] ; CHECK: br %r14 @@ -207,12 +207,12 @@ define i32 @f13(i8 *%src1, i8 *%src2) { ; CHECK-LABEL: f13: ; CHECK: lghi [[COUNT:%r[0-5]]], 3 ; CHECK: [[LOOP:.L[^:]*]]: -; CHECK: clc 0(256,%r2), 0(%r3) +; CHECK: clc 0(256,%r3), 0(%r2) ; CHECK: jlh [[LABEL:\..*]] ; CHECK-DAG: la %r2, 256(%r2) ; CHECK-DAG: la %r3, 256(%r3) ; CHECK: brctg [[COUNT]], [[LOOP]] -; CHECK: clc 0(1,%r2), 0(%r3) +; CHECK: clc 0(1,%r3), 0(%r2) ; CHECK: [[LABEL]]: ; CHECK: ipm [[REG:%r[0-5]]] ; CHECK: br %r14 diff --git a/llvm/test/CodeGen/SystemZ/strcmp-01.ll b/llvm/test/CodeGen/SystemZ/strcmp-01.ll index ef05d832e73e9..a3e3bbbb23be7 100644 --- a/llvm/test/CodeGen/SystemZ/strcmp-01.ll +++ b/llvm/test/CodeGen/SystemZ/strcmp-01.ll @@ -9,12 +9,12 @@ define i32 @f1(i8 *%src1, i8 *%src2) { ; CHECK-LABEL: f1: ; CHECK: lhi %r0, 0 ; CHECK: [[LABEL:\.[^:]*]]: -; CHECK: clst %r2, %r3 +; CHECK: clst %r3, %r2 ; CHECK-NEXT: jo [[LABEL]] ; CHECK-NEXT: %bb.{{[0-9]+}} -; CHECK-NEXT: ipm [[REG:%r[0-5]]] -; CHECK: srl [[REG]], 28 -; CHECK: rll %r2, [[REG]], 31 +; CHECK-NEXT: ipm %r2 +; CHECK: sll %r2, 2 +; CHECK: sra %r2, 30 ; CHECK: br %r14 %res = call i32 @strcmp(i8 *%src1, i8 *%src2) ret i32 %res @@ -25,7 +25,7 @@ define void @f2(i8 *%src1, i8 *%src2, i32 *%dest) { ; CHECK-LABEL: f2: ; CHECK: lhi %r0, 0 ; CHECK: [[LABEL:\.[^:]*]]: -; CHECK: clst %r2, %r3 +; CHECK: clst %r3, %r2 ; CHECK-NEXT: jo [[LABEL]] ; CHECK-NEXT: %bb.{{[0-9]+}} ; CHECK-NEXT: ber %r14 @@ -48,12 +48,12 @@ define i32 @f3(i8 *%src1, i8 *%src2, i32 *%dest) { ; CHECK-LABEL: f3: ; CHECK: lhi %r0, 0 ; CHECK: [[LABEL:\.[^:]*]]: -; CHECK: clst %r2, %r3 +; CHECK: clst %r3, %r2 ; CHECK-NEXT: jo [[LABEL]] ; CHECK-NEXT: %bb.{{[0-9]+}} -; CHECK-NEXT: ipm [[REG:%r[0-5]]] -; CHECK: srl [[REG]], 28 -; CHECK: rll %r2, [[REG]], 31 +; CHECK-NEXT: ipm %r2 +; CHECK: sll %r2, 2 +; CHECK: sra %r2, 30 ; CHECK: blr %r14 ; CHECK: br %r14 entry: diff --git a/llvm/test/CodeGen/WebAssembly/call.ll b/llvm/test/CodeGen/WebAssembly/call.ll index db666a6c36686..77f17c850edab 100644 --- a/llvm/test/CodeGen/WebAssembly/call.ll +++ b/llvm/test/CodeGen/WebAssembly/call.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -wasm-temporary-workarounds=false -mattr=+sign-ext,+simd128 | FileCheck %s -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel -fast-isel-abort=1 -wasm-temporary-workarounds=false -mattr=+sign-ext,+simd128 | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -mattr=+sign-ext,+simd128 | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel -fast-isel-abort=1 -mattr=+sign-ext,+simd128 | FileCheck %s ; Test that basic call operations assemble as expected. diff --git a/llvm/test/CodeGen/WebAssembly/function-bitcasts-varargs.ll b/llvm/test/CodeGen/WebAssembly/function-bitcasts-varargs.ll index 515c5703d86c0..b542276e068f6 100644 --- a/llvm/test/CodeGen/WebAssembly/function-bitcasts-varargs.ll +++ b/llvm/test/CodeGen/WebAssembly/function-bitcasts-varargs.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false -wasm-keep-registers | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck %s ; Test that function pointer casts casting away varargs are replaced with ; wrappers. diff --git a/llvm/test/CodeGen/WebAssembly/function-bitcasts.ll b/llvm/test/CodeGen/WebAssembly/function-bitcasts.ll index a779cbe414225..813e8420ae54b 100644 --- a/llvm/test/CodeGen/WebAssembly/function-bitcasts.ll +++ b/llvm/test/CodeGen/WebAssembly/function-bitcasts.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers -enable-emscripten-cxx-exceptions -wasm-temporary-workarounds=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers -enable-emscripten-cxx-exceptions | FileCheck %s ; Test that function pointer casts are replaced with wrappers. diff --git a/llvm/test/CodeGen/WebAssembly/import-module.ll b/llvm/test/CodeGen/WebAssembly/import-module.ll index a8202a77acb5a..0cf0f2f25e0b9 100644 --- a/llvm/test/CodeGen/WebAssembly/import-module.ll +++ b/llvm/test/CodeGen/WebAssembly/import-module.ll @@ -12,8 +12,9 @@ define void @test() { declare void @foo() #0 declare void @plain() -attributes #0 = { "wasm-import-module"="bar" } +attributes #0 = { "wasm-import-module"="bar" "wasm-import-name"="qux" } ; CHECK-NOT: .import_module plain ; CHECK: .import_module foo, bar +; CHECK: .import_name foo, qux ; CHECK-NOT: .import_module plain diff --git a/llvm/test/CodeGen/WebAssembly/main-declaration.ll b/llvm/test/CodeGen/WebAssembly/main-declaration.ll index f9d68db2bae8e..544f5588c5043 100644 --- a/llvm/test/CodeGen/WebAssembly/main-declaration.ll +++ b/llvm/test/CodeGen/WebAssembly/main-declaration.ll @@ -1,20 +1,18 @@ -; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false | FileCheck %s ; Test main functions with alternate signatures. target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" -declare void @main() +declare i32 @main() -define void @foo() { - call void @main() - ret void +define i32 @foo() { + %t = call i32 @main() + ret i32 %t } -; CHECK-NOT: __original_main ; CHECK-LABEL: foo: -; CHECK-NEXT: .functype foo () -> () -; CHECK-NEXT: call main@FUNCTION +; CHECK-NEXT: .functype foo () -> (i32) +; CHECK-NEXT: call __original_main@FUNCTION ; CHECK-NEXT: end_function -; CHECK-NOT: __original_main diff --git a/llvm/test/CodeGen/WebAssembly/main-no-args.ll b/llvm/test/CodeGen/WebAssembly/main-no-args.ll index 0bc46717d97be..97023e269454b 100644 --- a/llvm/test/CodeGen/WebAssembly/main-no-args.ll +++ b/llvm/test/CodeGen/WebAssembly/main-no-args.ll @@ -1,18 +1,19 @@ -; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false | FileCheck %s ; Test main functions with alternate signatures. target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" -define void @main() { - ret void +define i32 @main() { + ret i32 0 } -; CHECK-LABEL: .L__original_main: -; CHECK-NEXT: .functype .L__original_main () -> () +; CHECK-LABEL: __original_main: +; CHECK-NEXT: .functype __original_main () -> (i32) +; CHECK-NEXT: i32.const 0 ; CHECK-NEXT: end_function ; CHECK-LABEL: main: ; CHECK-NEXT: .functype main (i32, i32) -> (i32) -; CHECK: call .L__original_main@FUNCTION +; CHECK: call __original_main@FUNCTION diff --git a/llvm/test/CodeGen/WebAssembly/main-three-args.ll b/llvm/test/CodeGen/WebAssembly/main-three-args.ll new file mode 100644 index 0000000000000..77b3e5b8c3063 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/main-three-args.ll @@ -0,0 +1,16 @@ +; RUN: llc < %s -asm-verbose=false | FileCheck %s + +; Test that main function with a non-standard third argument is +; not wrapped. + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +define i32 @main(i32 %a, i8** %b, i8** %c) { + ret i32 0 +} + +; CHECK-LABEL: main: +; CHECK-NEXT: .functype main (i32, i32, i32) -> (i32) + +; CHECK-NOT: __original_main: diff --git a/llvm/test/CodeGen/WebAssembly/main-with-args.ll b/llvm/test/CodeGen/WebAssembly/main-with-args.ll index d4a11ef14d46e..205cb133f8ca6 100644 --- a/llvm/test/CodeGen/WebAssembly/main-with-args.ll +++ b/llvm/test/CodeGen/WebAssembly/main-with-args.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false | FileCheck %s ; Test that main function with expected signature is not wrapped diff --git a/llvm/test/CodeGen/WebAssembly/select.ll b/llvm/test/CodeGen/WebAssembly/select.ll index daa934f448448..ef18d9183e50d 100644 --- a/llvm/test/CodeGen/WebAssembly/select.ll +++ b/llvm/test/CodeGen/WebAssembly/select.ll @@ -17,8 +17,10 @@ define i32 @select_i32_bool(i1 zeroext %a, i32 %b, i32 %c) { ; CHECK-LABEL: select_i32_bool_nozext: ; CHECK-NEXT: .functype select_i32_bool_nozext (i32, i32, i32) -> (i32){{$}} -; SLOW-NEXT: i32.select $push0=, $1, $2, $0{{$}} -; SLOW-NEXT: return $pop0{{$}} +; SLOW-NEXT: i32.const $push0=, 1{{$}} +; SLOW-NEXT: i32.and $push1=, $0, $pop0{{$}} +; SLOW-NEXT: i32.select $push2=, $1, $2, $pop1{{$}} +; SLOW-NEXT: return $pop2{{$}} define i32 @select_i32_bool_nozext(i1 %a, i32 %b, i32 %c) { %cond = select i1 %a, i32 %b, i32 %c ret i32 %cond @@ -55,8 +57,10 @@ define i64 @select_i64_bool(i1 zeroext %a, i64 %b, i64 %c) { ; CHECK-LABEL: select_i64_bool_nozext: ; CHECK-NEXT: .functype select_i64_bool_nozext (i32, i64, i64) -> (i64){{$}} -; SLOW-NEXT: i64.select $push0=, $1, $2, $0{{$}} -; SLOW-NEXT: return $pop0{{$}} +; SLOW-NEXT: i32.const $push0=, 1{{$}} +; SLOW-NEXT: i32.and $push1=, $0, $pop0{{$}} +; SLOW-NEXT: i64.select $push2=, $1, $2, $pop1{{$}} +; SLOW-NEXT: return $pop2{{$}} define i64 @select_i64_bool_nozext(i1 %a, i64 %b, i64 %c) { %cond = select i1 %a, i64 %b, i64 %c ret i64 %cond @@ -157,3 +161,16 @@ define double @select_f64_ne(i32 %a, double %b, double %c) { %cond = select i1 %cmp, double %b, double %c ret double %cond } + +; CHECK-LABEL: pr40805: +; CHECK-NEXT: .functype pr40805 (i32, i32, i32) -> (i32){{$}} +; SLOW-NEXT: i32.const $push0=, 1{{$}} +; SLOW-NEXT: i32.and $push1=, $0, $pop0{{$}} +; SLOW-NEXT: i32.select $push2=, $1, $2, $pop1{{$}} +; SLOW-NEXT: return $pop2{{$}} +define i32 @pr40805(i32 %x, i32 %y, i32 %z) { + %a = and i32 %x, 1 + %b = icmp ne i32 %a, 0 + %c = select i1 %b, i32 %y, i32 %z + ret i32 %c +} diff --git a/llvm/test/CodeGen/WebAssembly/simd-select.ll b/llvm/test/CodeGen/WebAssembly/simd-select.ll index c871f60e6454c..c3af6f9abe60b 100644 --- a/llvm/test/CodeGen/WebAssembly/simd-select.ll +++ b/llvm/test/CodeGen/WebAssembly/simd-select.ll @@ -29,7 +29,7 @@ define <16 x i8> @vselect_v16i8(<16 x i1> %c, <16 x i8> %x, <16 x i8> %y) { ; CHECK-NEXT: i8x16.splat $push[[L3:[0-9]+]]=, $pop[[L2]]{{$}} ; CHECK-NEXT: v128.bitselect $push[[R:[0-9]+]]=, $1, $2, $pop[[L3]]{{$}} ; CHECK-NEXT: return $pop[[R]]{{$}} -define <16 x i8> @select_v16i8(i1 %c, <16 x i8> %x, <16 x i8> %y) { +define <16 x i8> @select_v16i8(i1 zeroext %c, <16 x i8> %x, <16 x i8> %y) { %res = select i1 %c, <16 x i8> %x, <16 x i8> %y ret <16 x i8> %res } @@ -99,7 +99,7 @@ define <8 x i16> @vselect_v8i16(<8 x i1> %c, <8 x i16> %x, <8 x i16> %y) { ; CHECK-NEXT: i16x8.splat $push[[L3:[0-9]+]]=, $pop[[L2]]{{$}} ; CHECK-NEXT: v128.bitselect $push[[R:[0-9]+]]=, $1, $2, $pop[[L3]]{{$}} ; CHECK-NEXT: return $pop[[R]]{{$}} -define <8 x i16> @select_v8i16(i1 %c, <8 x i16> %x, <8 x i16> %y) { +define <8 x i16> @select_v8i16(i1 zeroext %c, <8 x i16> %x, <8 x i16> %y) { %res = select i1 %c, <8 x i16> %x, <8 x i16> %y ret <8 x i16> %res } @@ -170,7 +170,7 @@ define <4 x i32> @vselect_v4i32(<4 x i1> %c, <4 x i32> %x, <4 x i32> %y) { ; CHECK-NEXT: i32x4.splat $push[[L3:[0-9]+]]=, $pop[[L2]]{{$}} ; CHECK-NEXT: v128.bitselect $push[[R:[0-9]+]]=, $1, $2, $pop[[L3]]{{$}} ; CHECK-NEXT: return $pop[[R]]{{$}} -define <4 x i32> @select_v4i32(i1 %c, <4 x i32> %x, <4 x i32> %y) { +define <4 x i32> @select_v4i32(i1 zeroext %c, <4 x i32> %x, <4 x i32> %y) { %res = select i1 %c, <4 x i32> %x, <4 x i32> %y ret <4 x i32> %res } @@ -240,7 +240,7 @@ define <2 x i64> @vselect_v2i64(<2 x i1> %c, <2 x i64> %x, <2 x i64> %y) { ; CHECK-NEXT: i64x2.splat $push[[L3:[0-9]+]]=, $pop[[L2]]{{$}} ; CHECK-NEXT: v128.bitselect $push[[R:[0-9]+]]=, $1, $2, $pop[[L3]]{{$}} ; CHECK-NEXT: return $pop[[R]]{{$}} -define <2 x i64> @select_v2i64(i1 %c, <2 x i64> %x, <2 x i64> %y) { +define <2 x i64> @select_v2i64(i1 zeroext %c, <2 x i64> %x, <2 x i64> %y) { %res = select i1 %c, <2 x i64> %x, <2 x i64> %y ret <2 x i64> %res } @@ -313,7 +313,7 @@ define <4 x float> @vselect_v4f32(<4 x i1> %c, <4 x float> %x, <4 x float> %y) { ; CHECK-NEXT: i32x4.splat $push[[L3:[0-9]+]]=, $pop[[L2]]{{$}} ; CHECK-NEXT: v128.bitselect $push[[R:[0-9]+]]=, $1, $2, $pop[[L3]]{{$}} ; CHECK-NEXT: return $pop[[R]]{{$}} -define <4 x float> @select_v4f32(i1 %c, <4 x float> %x, <4 x float> %y) { +define <4 x float> @select_v4f32(i1 zeroext %c, <4 x float> %x, <4 x float> %y) { %res = select i1 %c, <4 x float> %x, <4 x float> %y ret <4 x float> %res } @@ -383,7 +383,7 @@ define <2 x double> @vselect_v2f64(<2 x i1> %c, <2 x double> %x, <2 x double> %y ; CHECK-NEXT: i64x2.splat $push[[L3:[0-9]+]]=, $pop[[L2]]{{$}} ; CHECK-NEXT: v128.bitselect $push[[R:[0-9]+]]=, $1, $2, $pop[[L3]]{{$}} ; CHECK-NEXT: return $pop[[R]]{{$}} -define <2 x double> @select_v2f64(i1 %c, <2 x double> %x, <2 x double> %y) { +define <2 x double> @select_v2f64(i1 zeroext %c, <2 x double> %x, <2 x double> %y) { %res = select i1 %c, <2 x double> %x, <2 x double> %y ret <2 x double> %res } diff --git a/llvm/test/CodeGen/WebAssembly/varargs.ll b/llvm/test/CodeGen/WebAssembly/varargs.ll index 1a73716c2a67c..5a8df4cd2fec4 100644 --- a/llvm/test/CodeGen/WebAssembly/varargs.ll +++ b/llvm/test/CodeGen/WebAssembly/varargs.ll @@ -163,6 +163,32 @@ define void @nonlegal_fixed(fp128 %x, ...) nounwind { ret void } +; Test that an fp128 argument is properly aligned and allocated +; within a vararg buffer. + +; CHECK-LABEL: call_fp128_alignment: +; CHECK: global.get $push7=, __stack_pointer +; CHECK-NEXT: i32.const $push8=, 32 +; CHECK-NEXT: i32.sub $push12=, $pop7, $pop8 +; CHECK-NEXT: local.tee $push11=, $1=, $pop12 +; CHECK-NEXT: global.set __stack_pointer@GLOBAL, $pop11 +; CHECK-NEXT: i32.const $push0=, 24 +; CHECK-NEXT: i32.add $push1=, $1, $pop0 +; CHECK-NEXT: i64.const $push2=, -9223372036854775808 +; CHECK-NEXT: i64.store 0($pop1), $pop2 +; CHECK-NEXT: i32.const $push3=, 16 +; CHECK-NEXT: i32.add $push4=, $1, $pop3 +; CHECK-NEXT: i64.const $push5=, 1 +; CHECK-NEXT: i64.store 0($pop4), $pop5 +; CHECK-NEXT: i32.const $push6=, 7 +; CHECK-NEXT: i32.store 0($1), $pop6 +; CHECK-NEXT: call callee@FUNCTION, $1 +define void @call_fp128_alignment(i8* %p) { +entry: + call void (...) @callee(i8 7, fp128 0xL00000000000000018000000000000000) + ret void +} + declare void @llvm.va_start(i8*) declare void @llvm.va_end(i8*) declare void @llvm.va_copy(i8*, i8*) diff --git a/llvm/test/CodeGen/X86/PR40322.ll b/llvm/test/CodeGen/X86/PR40322.ll new file mode 100644 index 0000000000000..22bf1822c65af --- /dev/null +++ b/llvm/test/CodeGen/X86/PR40322.ll @@ -0,0 +1,164 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=i686-windows-gnu | FileCheck %s --check-prefix=CHECK-MINGW-X86 + +%struct.as = type { i32* } + +@_ZZ2amiE2au = internal unnamed_addr global %struct.as zeroinitializer, align 4 +@_ZGVZ2amiE2au = internal global i64 0, align 8 +@_ZTIi = external constant i8* + +define void @_Z2ami(i32) #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +; CHECK-MINGW-X86-LABEL: _Z2ami: +; CHECK-MINGW-X86: # %bb.0: # %entry +; CHECK-MINGW-X86-NEXT: pushl %edi +; CHECK-MINGW-X86-NEXT: .cfi_def_cfa_offset 8 +; CHECK-MINGW-X86-NEXT: pushl %esi +; CHECK-MINGW-X86-NEXT: .cfi_def_cfa_offset 12 +; CHECK-MINGW-X86-NEXT: .cfi_offset %esi, -12 +; CHECK-MINGW-X86-NEXT: .cfi_offset %edi, -8 +; CHECK-MINGW-X86-NEXT: movb __ZGVZ2amiE2au, %al +; CHECK-MINGW-X86-NEXT: testb %al, %al +; CHECK-MINGW-X86-NEXT: jne LBB0_4 +; CHECK-MINGW-X86-NEXT: # %bb.1: # %init.check +; CHECK-MINGW-X86-NEXT: .cfi_escape 0x2e, 0x04 +; CHECK-MINGW-X86-NEXT: pushl $__ZGVZ2amiE2au +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset 4 +; CHECK-MINGW-X86-NEXT: calll ___cxa_guard_acquire +; CHECK-MINGW-X86-NEXT: addl $4, %esp +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset -4 +; CHECK-MINGW-X86-NEXT: testl %eax, %eax +; CHECK-MINGW-X86-NEXT: je LBB0_4 +; CHECK-MINGW-X86-NEXT: # %bb.2: # %init +; CHECK-MINGW-X86-NEXT: Ltmp0: +; CHECK-MINGW-X86-NEXT: .cfi_escape 0x2e, 0x04 +; CHECK-MINGW-X86-NEXT: pushl $4 +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset 4 +; CHECK-MINGW-X86-NEXT: calll __Znwj +; CHECK-MINGW-X86-NEXT: addl $4, %esp +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset -4 +; CHECK-MINGW-X86-NEXT: Ltmp1: +; CHECK-MINGW-X86-NEXT: # %bb.3: # %invoke.cont +; CHECK-MINGW-X86-NEXT: movl %eax, __ZZ2amiE2au +; CHECK-MINGW-X86-NEXT: .cfi_escape 0x2e, 0x04 +; CHECK-MINGW-X86-NEXT: pushl $__ZGVZ2amiE2au +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset 4 +; CHECK-MINGW-X86-NEXT: calll ___cxa_guard_release +; CHECK-MINGW-X86-NEXT: addl $4, %esp +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset -4 +; CHECK-MINGW-X86-NEXT: LBB0_4: # %init.end +; CHECK-MINGW-X86-NEXT: .cfi_escape 0x2e, 0x04 +; CHECK-MINGW-X86-NEXT: pushl $4 +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset 4 +; CHECK-MINGW-X86-NEXT: calll __Znwj +; CHECK-MINGW-X86-NEXT: addl $4, %esp +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset -4 +; CHECK-MINGW-X86-NEXT: movl %eax, %esi +; CHECK-MINGW-X86-NEXT: .cfi_escape 0x2e, 0x04 +; CHECK-MINGW-X86-NEXT: pushl $4 +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset 4 +; CHECK-MINGW-X86-NEXT: calll ___cxa_allocate_exception +; CHECK-MINGW-X86-NEXT: addl $4, %esp +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset -4 +; CHECK-MINGW-X86-NEXT: movl $0, (%eax) +; CHECK-MINGW-X86-NEXT: Ltmp3: +; CHECK-MINGW-X86-NEXT: .cfi_escape 0x2e, 0x0c +; CHECK-MINGW-X86-NEXT: movl .refptr.__ZTIi, %ecx +; CHECK-MINGW-X86-NEXT: pushl $0 +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset 4 +; CHECK-MINGW-X86-NEXT: pushl %ecx +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset 4 +; CHECK-MINGW-X86-NEXT: pushl %eax +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset 4 +; CHECK-MINGW-X86-NEXT: calll ___cxa_throw +; CHECK-MINGW-X86-NEXT: addl $12, %esp +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset -12 +; CHECK-MINGW-X86-NEXT: Ltmp4: +; CHECK-MINGW-X86-NEXT: # %bb.8: # %unreachable +; CHECK-MINGW-X86-NEXT: LBB0_5: # %lpad +; CHECK-MINGW-X86-NEXT: Ltmp2: +; CHECK-MINGW-X86-NEXT: movl %eax, %edi +; CHECK-MINGW-X86-NEXT: .cfi_escape 0x2e, 0x04 +; CHECK-MINGW-X86-NEXT: pushl $__ZGVZ2amiE2au +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset 4 +; CHECK-MINGW-X86-NEXT: calll ___cxa_guard_abort +; CHECK-MINGW-X86-NEXT: jmp LBB0_7 +; CHECK-MINGW-X86-NEXT: LBB0_6: # %lpad1 +; CHECK-MINGW-X86-NEXT: .cfi_def_cfa_offset 12 +; CHECK-MINGW-X86-NEXT: Ltmp5: +; CHECK-MINGW-X86-NEXT: movl %eax, %edi +; CHECK-MINGW-X86-NEXT: .cfi_escape 0x2e, 0x04 +; CHECK-MINGW-X86-NEXT: pushl %esi +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset 4 +; CHECK-MINGW-X86-NEXT: calll __ZdlPv +; CHECK-MINGW-X86-NEXT: LBB0_7: # %eh.resume +; CHECK-MINGW-X86-NEXT: addl $4, %esp +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset -4 +; CHECK-MINGW-X86-NEXT: .cfi_escape 0x2e, 0x04 +; CHECK-MINGW-X86-NEXT: pushl %edi +; CHECK-MINGW-X86-NEXT: .cfi_adjust_cfa_offset 4 +; CHECK-MINGW-X86-NEXT: calll __Unwind_Resume +; CHECK-MINGW-X86-NEXT: Lfunc_end0: +entry: + %1 = load atomic i8, i8* bitcast (i64* @_ZGVZ2amiE2au to i8*) acquire, align 8 + %guard.uninitialized = icmp eq i8 %1, 0 + br i1 %guard.uninitialized, label %init.check, label %init.end + +init.check: ; preds = %entry + %2 = tail call i32 @__cxa_guard_acquire(i64* nonnull @_ZGVZ2amiE2au) + %tobool = icmp eq i32 %2, 0 + br i1 %tobool, label %init.end, label %init + +init: ; preds = %init.check + %call.i3 = invoke i8* @_Znwj(i32 4) + to label %invoke.cont unwind label %lpad + +invoke.cont: ; preds = %init + store i8* %call.i3, i8** bitcast (%struct.as* @_ZZ2amiE2au to i8**), align 4 + tail call void @__cxa_guard_release(i64* nonnull @_ZGVZ2amiE2au) + br label %init.end + +init.end: ; preds = %init.check, %invoke.cont, %entry + %call.i = tail call i8* @_Znwj(i32 4) + %exception = tail call i8* @__cxa_allocate_exception(i32 4) + %3 = bitcast i8* %exception to i32* + store i32 0, i32* %3, align 16 + invoke void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null) + to label %unreachable unwind label %lpad1 + +lpad: ; preds = %init + %4 = landingpad { i8*, i32 } + cleanup + %5 = extractvalue { i8*, i32 } %4, 0 + %6 = extractvalue { i8*, i32 } %4, 1 + tail call void @__cxa_guard_abort(i64* nonnull @_ZGVZ2amiE2au) #1 + br label %eh.resume + +lpad1: ; preds = %init.end + %7 = landingpad { i8*, i32 } + cleanup + %8 = extractvalue { i8*, i32 } %7, 0 + %9 = extractvalue { i8*, i32 } %7, 1 + tail call void @_ZdlPv(i8* nonnull %call.i) + br label %eh.resume + +eh.resume: ; preds = %lpad1, %lpad + %exn.slot.0 = phi i8* [ %8, %lpad1 ], [ %5, %lpad ] + %ehselector.slot.0 = phi i32 [ %9, %lpad1 ], [ %6, %lpad ] + %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn.slot.0, 0 + %lpad.val2 = insertvalue { i8*, i32 } %lpad.val, i32 %ehselector.slot.0, 1 + resume { i8*, i32 } %lpad.val2 + +unreachable: ; preds = %init.end + unreachable +} + +declare i32 @__cxa_guard_acquire(i64*) +declare i32 @__gxx_personality_v0(...) +declare void @__cxa_guard_abort(i64*) +declare void @__cxa_guard_release(i64*) +declare i8* @__cxa_allocate_exception(i32) +declare void @__cxa_throw(i8*, i8*, i8*) +declare noalias nonnull i8* @_Znwj(i32) +declare i8* @__cxa_begin_catch(i8*) +declare void @__cxa_end_catch() +declare void @_ZdlPv(i8*) diff --git a/llvm/test/CodeGen/X86/and-su.ll b/llvm/test/CodeGen/X86/and-su.ll index 55bfa8def44f2..de384368bfca5 100644 --- a/llvm/test/CodeGen/X86/and-su.ll +++ b/llvm/test/CodeGen/X86/and-su.ll @@ -49,7 +49,7 @@ define fastcc double @bar(i32 %hash, double %x, double %y) nounwind { ; CHECK-NEXT: fchs ; CHECK-NEXT: fxch %st(1) ; CHECK-NEXT: .LBB1_5: # %bb16 -; CHECK-NEXT: faddp %st(1) +; CHECK-NEXT: faddp %st, %st(1) ; CHECK-NEXT: movl %ebp, %esp ; CHECK-NEXT: popl %ebp ; CHECK-NEXT: retl diff --git a/llvm/test/CodeGen/X86/avx2-intrinsics-x86.ll b/llvm/test/CodeGen/X86/avx2-intrinsics-x86.ll index 617e198bce4c1..de20c07d41399 100644 --- a/llvm/test/CodeGen/X86/avx2-intrinsics-x86.ll +++ b/llvm/test/CodeGen/X86/avx2-intrinsics-x86.ll @@ -1183,38 +1183,58 @@ define <4 x i32> @test_x86_avx2_psllv_d(<4 x i32> %a0, <4 x i32> %a1) { define <4 x i32> @test_x86_avx2_psllv_d_const() { ; X86-AVX-LABEL: test_x86_avx2_psllv_d_const: ; X86-AVX: # %bb.0: -; X86-AVX-NEXT: vpbroadcastd {{.*#+}} xmm0 = [2,2,2,2] -; X86-AVX-NEXT: # encoding: [0xc4,0xe2,0x79,0x58,0x05,A,A,A,A] +; X86-AVX-NEXT: vmovdqa {{.*#+}} xmm0 = [2,9,0,4294967295] +; X86-AVX-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] +; X86-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX-NEXT: vpsllvd {{\.LCPI.*}}, %xmm0, %xmm0 # encoding: [0xc4,0xe2,0x79,0x47,0x05,A,A,A,A] ; X86-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 -; X86-AVX-NEXT: vpaddd {{\.LCPI.*}}, %xmm0, %xmm0 # encoding: [0xc5,0xf9,0xfe,0x05,A,A,A,A] +; X86-AVX-NEXT: vmovdqa {{.*#+}} xmm1 = [1,1,1,4294967295] +; X86-AVX-NEXT: # encoding: [0xc5,0xf9,0x6f,0x0d,A,A,A,A] ; X86-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX-NEXT: vpsllvd %xmm1, %xmm1, %xmm1 # encoding: [0xc4,0xe2,0x71,0x47,0xc9] +; X86-AVX-NEXT: vpaddd %xmm1, %xmm0, %xmm0 # encoding: [0xc5,0xf9,0xfe,0xc1] ; X86-AVX-NEXT: retl # encoding: [0xc3] ; ; X86-AVX512VL-LABEL: test_x86_avx2_psllv_d_const: ; X86-AVX512VL: # %bb.0: -; X86-AVX512VL-NEXT: vmovdqa {{\.LCPI.*}}, %xmm0 # EVEX TO VEX Compression xmm0 = <4,9,0,u> +; X86-AVX512VL-NEXT: vmovdqa {{\.LCPI.*}}, %xmm0 # EVEX TO VEX Compression xmm0 = [2,9,0,4294967295] ; X86-AVX512VL-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] ; X86-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 -; X86-AVX512VL-NEXT: vpaddd {{\.LCPI.*}}{1to4}, %xmm0, %xmm0 # encoding: [0x62,0xf1,0x7d,0x18,0xfe,0x05,A,A,A,A] -; X86-AVX512VL-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vpsllvd {{\.LCPI.*}}, %xmm0, %xmm0 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x79,0x47,0x05,A,A,A,A] +; X86-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vmovdqa {{\.LCPI.*}}, %xmm1 # EVEX TO VEX Compression xmm1 = [1,1,1,4294967295] +; X86-AVX512VL-NEXT: # encoding: [0xc5,0xf9,0x6f,0x0d,A,A,A,A] +; X86-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vpsllvd %xmm1, %xmm1, %xmm1 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x71,0x47,0xc9] +; X86-AVX512VL-NEXT: vpaddd %xmm1, %xmm0, %xmm0 # EVEX TO VEX Compression encoding: [0xc5,0xf9,0xfe,0xc1] ; X86-AVX512VL-NEXT: retl # encoding: [0xc3] ; ; X64-AVX-LABEL: test_x86_avx2_psllv_d_const: ; X64-AVX: # %bb.0: -; X64-AVX-NEXT: vpbroadcastd {{.*#+}} xmm0 = [2,2,2,2] -; X64-AVX-NEXT: # encoding: [0xc4,0xe2,0x79,0x58,0x05,A,A,A,A] +; X64-AVX-NEXT: vmovdqa {{.*#+}} xmm0 = [2,9,0,4294967295] +; X64-AVX-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] +; X64-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpsllvd {{.*}}(%rip), %xmm0, %xmm0 # encoding: [0xc4,0xe2,0x79,0x47,0x05,A,A,A,A] ; X64-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte -; X64-AVX-NEXT: vpaddd {{.*}}(%rip), %xmm0, %xmm0 # encoding: [0xc5,0xf9,0xfe,0x05,A,A,A,A] +; X64-AVX-NEXT: vmovdqa {{.*#+}} xmm1 = [1,1,1,4294967295] +; X64-AVX-NEXT: # encoding: [0xc5,0xf9,0x6f,0x0d,A,A,A,A] ; X64-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpsllvd %xmm1, %xmm1, %xmm1 # encoding: [0xc4,0xe2,0x71,0x47,0xc9] +; X64-AVX-NEXT: vpaddd %xmm1, %xmm0, %xmm0 # encoding: [0xc5,0xf9,0xfe,0xc1] ; X64-AVX-NEXT: retq # encoding: [0xc3] ; ; X64-AVX512VL-LABEL: test_x86_avx2_psllv_d_const: ; X64-AVX512VL: # %bb.0: -; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %xmm0 # EVEX TO VEX Compression xmm0 = <4,9,0,u> +; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %xmm0 # EVEX TO VEX Compression xmm0 = [2,9,0,4294967295] ; X64-AVX512VL-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] ; X64-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte -; X64-AVX512VL-NEXT: vpaddd {{.*}}(%rip){1to4}, %xmm0, %xmm0 # encoding: [0x62,0xf1,0x7d,0x18,0xfe,0x05,A,A,A,A] -; X64-AVX512VL-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpsllvd {{.*}}(%rip), %xmm0, %xmm0 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x79,0x47,0x05,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %xmm1 # EVEX TO VEX Compression xmm1 = [1,1,1,4294967295] +; X64-AVX512VL-NEXT: # encoding: [0xc5,0xf9,0x6f,0x0d,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpsllvd %xmm1, %xmm1, %xmm1 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x71,0x47,0xc9] +; X64-AVX512VL-NEXT: vpaddd %xmm1, %xmm0, %xmm0 # EVEX TO VEX Compression encoding: [0xc5,0xf9,0xfe,0xc1] ; X64-AVX512VL-NEXT: retq # encoding: [0xc3] %res0 = call <4 x i32> @llvm.x86.avx2.psllv.d(<4 x i32> , <4 x i32> ) %res1 = call <4 x i32> @llvm.x86.avx2.psllv.d(<4 x i32> , <4 x i32> ) @@ -1241,38 +1261,62 @@ define <8 x i32> @test_x86_avx2_psllv_d_256(<8 x i32> %a0, <8 x i32> %a1) { define <8 x i32> @test_x86_avx2_psllv_d_256_const() { ; X86-AVX-LABEL: test_x86_avx2_psllv_d_256_const: ; X86-AVX: # %bb.0: -; X86-AVX-NEXT: vpbroadcastd {{.*#+}} ymm0 = [8,8,8,8,8,8,8,8] -; X86-AVX-NEXT: # encoding: [0xc4,0xe2,0x7d,0x58,0x05,A,A,A,A] +; X86-AVX-NEXT: vmovdqa {{.*#+}} ymm0 = [2,9,0,4294967295,3,7,4294967295,0] +; X86-AVX-NEXT: # encoding: [0xc5,0xfd,0x6f,0x05,A,A,A,A] +; X86-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX-NEXT: vpsllvd {{\.LCPI.*}}, %ymm0, %ymm0 # encoding: [0xc4,0xe2,0x7d,0x47,0x05,A,A,A,A] ; X86-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 -; X86-AVX-NEXT: vpaddd {{\.LCPI.*}}, %ymm0, %ymm0 # encoding: [0xc5,0xfd,0xfe,0x05,A,A,A,A] +; X86-AVX-NEXT: vmovdqa {{.*#+}} ymm1 = [4,4,4,4,4,4,4,4294967295] +; X86-AVX-NEXT: # encoding: [0xc5,0xfd,0x6f,0x0d,A,A,A,A] ; X86-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX-NEXT: vpsllvd {{\.LCPI.*}}, %ymm1, %ymm1 # encoding: [0xc4,0xe2,0x75,0x47,0x0d,A,A,A,A] +; X86-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX-NEXT: vpaddd %ymm1, %ymm0, %ymm0 # encoding: [0xc5,0xfd,0xfe,0xc1] ; X86-AVX-NEXT: retl # encoding: [0xc3] ; ; X86-AVX512VL-LABEL: test_x86_avx2_psllv_d_256_const: ; X86-AVX512VL: # %bb.0: -; X86-AVX512VL-NEXT: vmovdqa {{\.LCPI.*}}, %ymm0 # EVEX TO VEX Compression ymm0 = <4,9,0,u,12,7,u,0> +; X86-AVX512VL-NEXT: vmovdqa {{\.LCPI.*}}, %ymm0 # EVEX TO VEX Compression ymm0 = [2,9,0,4294967295,3,7,4294967295,0] ; X86-AVX512VL-NEXT: # encoding: [0xc5,0xfd,0x6f,0x05,A,A,A,A] ; X86-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 -; X86-AVX512VL-NEXT: vpaddd {{\.LCPI.*}}{1to8}, %ymm0, %ymm0 # encoding: [0x62,0xf1,0x7d,0x38,0xfe,0x05,A,A,A,A] -; X86-AVX512VL-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vpsllvd {{\.LCPI.*}}, %ymm0, %ymm0 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x7d,0x47,0x05,A,A,A,A] +; X86-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vmovdqa {{\.LCPI.*}}, %ymm1 # EVEX TO VEX Compression ymm1 = [4,4,4,4,4,4,4,4294967295] +; X86-AVX512VL-NEXT: # encoding: [0xc5,0xfd,0x6f,0x0d,A,A,A,A] +; X86-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vpsllvd {{\.LCPI.*}}, %ymm1, %ymm1 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x75,0x47,0x0d,A,A,A,A] +; X86-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vpaddd %ymm1, %ymm0, %ymm0 # EVEX TO VEX Compression encoding: [0xc5,0xfd,0xfe,0xc1] ; X86-AVX512VL-NEXT: retl # encoding: [0xc3] ; ; X64-AVX-LABEL: test_x86_avx2_psllv_d_256_const: ; X64-AVX: # %bb.0: -; X64-AVX-NEXT: vpbroadcastd {{.*#+}} ymm0 = [8,8,8,8,8,8,8,8] -; X64-AVX-NEXT: # encoding: [0xc4,0xe2,0x7d,0x58,0x05,A,A,A,A] +; X64-AVX-NEXT: vmovdqa {{.*#+}} ymm0 = [2,9,0,4294967295,3,7,4294967295,0] +; X64-AVX-NEXT: # encoding: [0xc5,0xfd,0x6f,0x05,A,A,A,A] +; X64-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpsllvd {{.*}}(%rip), %ymm0, %ymm0 # encoding: [0xc4,0xe2,0x7d,0x47,0x05,A,A,A,A] ; X64-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte -; X64-AVX-NEXT: vpaddd {{.*}}(%rip), %ymm0, %ymm0 # encoding: [0xc5,0xfd,0xfe,0x05,A,A,A,A] +; X64-AVX-NEXT: vmovdqa {{.*#+}} ymm1 = [4,4,4,4,4,4,4,4294967295] +; X64-AVX-NEXT: # encoding: [0xc5,0xfd,0x6f,0x0d,A,A,A,A] ; X64-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpsllvd {{.*}}(%rip), %ymm1, %ymm1 # encoding: [0xc4,0xe2,0x75,0x47,0x0d,A,A,A,A] +; X64-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpaddd %ymm1, %ymm0, %ymm0 # encoding: [0xc5,0xfd,0xfe,0xc1] ; X64-AVX-NEXT: retq # encoding: [0xc3] ; ; X64-AVX512VL-LABEL: test_x86_avx2_psllv_d_256_const: ; X64-AVX512VL: # %bb.0: -; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %ymm0 # EVEX TO VEX Compression ymm0 = <4,9,0,u,12,7,u,0> +; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %ymm0 # EVEX TO VEX Compression ymm0 = [2,9,0,4294967295,3,7,4294967295,0] ; X64-AVX512VL-NEXT: # encoding: [0xc5,0xfd,0x6f,0x05,A,A,A,A] ; X64-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte -; X64-AVX512VL-NEXT: vpaddd {{.*}}(%rip){1to8}, %ymm0, %ymm0 # encoding: [0x62,0xf1,0x7d,0x38,0xfe,0x05,A,A,A,A] -; X64-AVX512VL-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpsllvd {{.*}}(%rip), %ymm0, %ymm0 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x7d,0x47,0x05,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %ymm1 # EVEX TO VEX Compression ymm1 = [4,4,4,4,4,4,4,4294967295] +; X64-AVX512VL-NEXT: # encoding: [0xc5,0xfd,0x6f,0x0d,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpsllvd {{.*}}(%rip), %ymm1, %ymm1 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x75,0x47,0x0d,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpaddd %ymm1, %ymm0, %ymm0 # EVEX TO VEX Compression encoding: [0xc5,0xfd,0xfe,0xc1] ; X64-AVX512VL-NEXT: retq # encoding: [0xc3] %res0 = call <8 x i32> @llvm.x86.avx2.psllv.d.256(<8 x i32> , <8 x i32> ) %res1 = call <8 x i32> @llvm.x86.avx2.psllv.d.256(<8 x i32> , <8 x i32> ) @@ -1316,14 +1360,20 @@ define <2 x i64> @test_x86_avx2_psllv_q_const() { ; ; X64-AVX-LABEL: test_x86_avx2_psllv_q_const: ; X64-AVX: # %bb.0: -; X64-AVX-NEXT: movl $8, %eax # encoding: [0xb8,0x08,0x00,0x00,0x00] -; X64-AVX-NEXT: vmovq %rax, %xmm0 # encoding: [0xc4,0xe1,0xf9,0x6e,0xc0] +; X64-AVX-NEXT: vmovdqa {{.*#+}} xmm0 = [4,18446744073709551615] +; X64-AVX-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] +; X64-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpsllvq {{.*}}(%rip), %xmm0, %xmm0 # encoding: [0xc4,0xe2,0xf9,0x47,0x05,A,A,A,A] +; X64-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte ; X64-AVX-NEXT: retq # encoding: [0xc3] ; ; X64-AVX512VL-LABEL: test_x86_avx2_psllv_q_const: ; X64-AVX512VL: # %bb.0: -; X64-AVX512VL-NEXT: movl $8, %eax # encoding: [0xb8,0x08,0x00,0x00,0x00] -; X64-AVX512VL-NEXT: vmovq %rax, %xmm0 # EVEX TO VEX Compression encoding: [0xc4,0xe1,0xf9,0x6e,0xc0] +; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %xmm0 # EVEX TO VEX Compression xmm0 = [4,18446744073709551615] +; X64-AVX512VL-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpsllvq {{.*}}(%rip), %xmm0, %xmm0 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0xf9,0x47,0x05,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte ; X64-AVX512VL-NEXT: retq # encoding: [0xc3] %res = call <2 x i64> @llvm.x86.avx2.psllv.q(<2 x i64> , <2 x i64> ) ret <2 x i64> %res @@ -1366,15 +1416,19 @@ define <4 x i64> @test_x86_avx2_psllv_q_256_const() { ; ; X64-AVX-LABEL: test_x86_avx2_psllv_q_256_const: ; X64-AVX: # %bb.0: -; X64-AVX-NEXT: vbroadcastsd {{.*#+}} ymm0 = [8,8,8,8] -; X64-AVX-NEXT: # encoding: [0xc4,0xe2,0x7d,0x19,0x05,A,A,A,A] +; X64-AVX-NEXT: vmovdqa {{.*#+}} ymm0 = [4,4,4,18446744073709551615] +; X64-AVX-NEXT: # encoding: [0xc5,0xfd,0x6f,0x05,A,A,A,A] +; X64-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpsllvq {{.*}}(%rip), %ymm0, %ymm0 # encoding: [0xc4,0xe2,0xfd,0x47,0x05,A,A,A,A] ; X64-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte ; X64-AVX-NEXT: retq # encoding: [0xc3] ; ; X64-AVX512VL-LABEL: test_x86_avx2_psllv_q_256_const: ; X64-AVX512VL: # %bb.0: -; X64-AVX512VL-NEXT: vbroadcastsd {{.*}}(%rip), %ymm0 # EVEX TO VEX Compression ymm0 = [8,8,8,8] -; X64-AVX512VL-NEXT: # encoding: [0xc4,0xe2,0x7d,0x19,0x05,A,A,A,A] +; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %ymm0 # EVEX TO VEX Compression ymm0 = [4,4,4,18446744073709551615] +; X64-AVX512VL-NEXT: # encoding: [0xc5,0xfd,0x6f,0x05,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpsllvq {{.*}}(%rip), %ymm0, %ymm0 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0xfd,0x47,0x05,A,A,A,A] ; X64-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte ; X64-AVX512VL-NEXT: retq # encoding: [0xc3] %res = call <4 x i64> @llvm.x86.avx2.psllv.q.256(<4 x i64> , <4 x i64> ) @@ -1400,38 +1454,62 @@ define <4 x i32> @test_x86_avx2_psrlv_d(<4 x i32> %a0, <4 x i32> %a1) { define <4 x i32> @test_x86_avx2_psrlv_d_const() { ; X86-AVX-LABEL: test_x86_avx2_psrlv_d_const: ; X86-AVX: # %bb.0: -; X86-AVX-NEXT: vpbroadcastd {{.*#+}} xmm0 = [2,2,2,2] -; X86-AVX-NEXT: # encoding: [0xc4,0xe2,0x79,0x58,0x05,A,A,A,A] +; X86-AVX-NEXT: vmovdqa {{.*#+}} xmm0 = [2,9,0,4294967295] +; X86-AVX-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] +; X86-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX-NEXT: vpsrlvd {{\.LCPI.*}}, %xmm0, %xmm0 # encoding: [0xc4,0xe2,0x79,0x45,0x05,A,A,A,A] ; X86-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 -; X86-AVX-NEXT: vpaddd {{\.LCPI.*}}, %xmm0, %xmm0 # encoding: [0xc5,0xf9,0xfe,0x05,A,A,A,A] +; X86-AVX-NEXT: vmovdqa {{.*#+}} xmm1 = [4,4,4,4294967295] +; X86-AVX-NEXT: # encoding: [0xc5,0xf9,0x6f,0x0d,A,A,A,A] ; X86-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX-NEXT: vpsrlvd {{\.LCPI.*}}, %xmm1, %xmm1 # encoding: [0xc4,0xe2,0x71,0x45,0x0d,A,A,A,A] +; X86-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX-NEXT: vpaddd %xmm1, %xmm0, %xmm0 # encoding: [0xc5,0xf9,0xfe,0xc1] ; X86-AVX-NEXT: retl # encoding: [0xc3] ; ; X86-AVX512VL-LABEL: test_x86_avx2_psrlv_d_const: ; X86-AVX512VL: # %bb.0: -; X86-AVX512VL-NEXT: vmovdqa {{\.LCPI.*}}, %xmm0 # EVEX TO VEX Compression xmm0 = <1,9,0,u> +; X86-AVX512VL-NEXT: vmovdqa {{\.LCPI.*}}, %xmm0 # EVEX TO VEX Compression xmm0 = [2,9,0,4294967295] ; X86-AVX512VL-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] ; X86-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 -; X86-AVX512VL-NEXT: vpaddd {{\.LCPI.*}}{1to4}, %xmm0, %xmm0 # encoding: [0x62,0xf1,0x7d,0x18,0xfe,0x05,A,A,A,A] -; X86-AVX512VL-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vpsrlvd {{\.LCPI.*}}, %xmm0, %xmm0 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x79,0x45,0x05,A,A,A,A] +; X86-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vmovdqa {{\.LCPI.*}}, %xmm1 # EVEX TO VEX Compression xmm1 = [4,4,4,4294967295] +; X86-AVX512VL-NEXT: # encoding: [0xc5,0xf9,0x6f,0x0d,A,A,A,A] +; X86-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vpsrlvd {{\.LCPI.*}}, %xmm1, %xmm1 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x71,0x45,0x0d,A,A,A,A] +; X86-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vpaddd %xmm1, %xmm0, %xmm0 # EVEX TO VEX Compression encoding: [0xc5,0xf9,0xfe,0xc1] ; X86-AVX512VL-NEXT: retl # encoding: [0xc3] ; ; X64-AVX-LABEL: test_x86_avx2_psrlv_d_const: ; X64-AVX: # %bb.0: -; X64-AVX-NEXT: vpbroadcastd {{.*#+}} xmm0 = [2,2,2,2] -; X64-AVX-NEXT: # encoding: [0xc4,0xe2,0x79,0x58,0x05,A,A,A,A] +; X64-AVX-NEXT: vmovdqa {{.*#+}} xmm0 = [2,9,0,4294967295] +; X64-AVX-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] +; X64-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpsrlvd {{.*}}(%rip), %xmm0, %xmm0 # encoding: [0xc4,0xe2,0x79,0x45,0x05,A,A,A,A] ; X64-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte -; X64-AVX-NEXT: vpaddd {{.*}}(%rip), %xmm0, %xmm0 # encoding: [0xc5,0xf9,0xfe,0x05,A,A,A,A] +; X64-AVX-NEXT: vmovdqa {{.*#+}} xmm1 = [4,4,4,4294967295] +; X64-AVX-NEXT: # encoding: [0xc5,0xf9,0x6f,0x0d,A,A,A,A] ; X64-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpsrlvd {{.*}}(%rip), %xmm1, %xmm1 # encoding: [0xc4,0xe2,0x71,0x45,0x0d,A,A,A,A] +; X64-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpaddd %xmm1, %xmm0, %xmm0 # encoding: [0xc5,0xf9,0xfe,0xc1] ; X64-AVX-NEXT: retq # encoding: [0xc3] ; ; X64-AVX512VL-LABEL: test_x86_avx2_psrlv_d_const: ; X64-AVX512VL: # %bb.0: -; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %xmm0 # EVEX TO VEX Compression xmm0 = <1,9,0,u> +; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %xmm0 # EVEX TO VEX Compression xmm0 = [2,9,0,4294967295] ; X64-AVX512VL-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] ; X64-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte -; X64-AVX512VL-NEXT: vpaddd {{.*}}(%rip){1to4}, %xmm0, %xmm0 # encoding: [0x62,0xf1,0x7d,0x18,0xfe,0x05,A,A,A,A] -; X64-AVX512VL-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpsrlvd {{.*}}(%rip), %xmm0, %xmm0 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x79,0x45,0x05,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %xmm1 # EVEX TO VEX Compression xmm1 = [4,4,4,4294967295] +; X64-AVX512VL-NEXT: # encoding: [0xc5,0xf9,0x6f,0x0d,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpsrlvd {{.*}}(%rip), %xmm1, %xmm1 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x71,0x45,0x0d,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpaddd %xmm1, %xmm0, %xmm0 # EVEX TO VEX Compression encoding: [0xc5,0xf9,0xfe,0xc1] ; X64-AVX512VL-NEXT: retq # encoding: [0xc3] %res0 = call <4 x i32> @llvm.x86.avx2.psrlv.d(<4 x i32> , <4 x i32> ) %res1 = call <4 x i32> @llvm.x86.avx2.psrlv.d(<4 x i32> , <4 x i32> ) @@ -1458,38 +1536,62 @@ define <8 x i32> @test_x86_avx2_psrlv_d_256(<8 x i32> %a0, <8 x i32> %a1) { define <8 x i32> @test_x86_avx2_psrlv_d_256_const() { ; X86-AVX-LABEL: test_x86_avx2_psrlv_d_256_const: ; X86-AVX: # %bb.0: -; X86-AVX-NEXT: vpbroadcastd {{.*#+}} ymm0 = [2,2,2,2,2,2,2,2] -; X86-AVX-NEXT: # encoding: [0xc4,0xe2,0x7d,0x58,0x05,A,A,A,A] +; X86-AVX-NEXT: vmovdqa {{.*#+}} ymm0 = [2,9,0,4294967295,3,7,4294967295,0] +; X86-AVX-NEXT: # encoding: [0xc5,0xfd,0x6f,0x05,A,A,A,A] +; X86-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX-NEXT: vpsrlvd {{\.LCPI.*}}, %ymm0, %ymm0 # encoding: [0xc4,0xe2,0x7d,0x45,0x05,A,A,A,A] ; X86-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 -; X86-AVX-NEXT: vpaddd {{\.LCPI.*}}, %ymm0, %ymm0 # encoding: [0xc5,0xfd,0xfe,0x05,A,A,A,A] +; X86-AVX-NEXT: vmovdqa {{.*#+}} ymm1 = [4,4,4,4,4,4,4,4294967295] +; X86-AVX-NEXT: # encoding: [0xc5,0xfd,0x6f,0x0d,A,A,A,A] ; X86-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX-NEXT: vpsrlvd {{\.LCPI.*}}, %ymm1, %ymm1 # encoding: [0xc4,0xe2,0x75,0x45,0x0d,A,A,A,A] +; X86-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX-NEXT: vpaddd %ymm1, %ymm0, %ymm0 # encoding: [0xc5,0xfd,0xfe,0xc1] ; X86-AVX-NEXT: retl # encoding: [0xc3] ; ; X86-AVX512VL-LABEL: test_x86_avx2_psrlv_d_256_const: ; X86-AVX512VL: # %bb.0: -; X86-AVX512VL-NEXT: vmovdqa {{\.LCPI.*}}, %ymm0 # EVEX TO VEX Compression ymm0 = <1,9,0,u,0,7,u,0> +; X86-AVX512VL-NEXT: vmovdqa {{\.LCPI.*}}, %ymm0 # EVEX TO VEX Compression ymm0 = [2,9,0,4294967295,3,7,4294967295,0] ; X86-AVX512VL-NEXT: # encoding: [0xc5,0xfd,0x6f,0x05,A,A,A,A] ; X86-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 -; X86-AVX512VL-NEXT: vpaddd {{\.LCPI.*}}{1to8}, %ymm0, %ymm0 # encoding: [0x62,0xf1,0x7d,0x38,0xfe,0x05,A,A,A,A] -; X86-AVX512VL-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vpsrlvd {{\.LCPI.*}}, %ymm0, %ymm0 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x7d,0x45,0x05,A,A,A,A] +; X86-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vmovdqa {{\.LCPI.*}}, %ymm1 # EVEX TO VEX Compression ymm1 = [4,4,4,4,4,4,4,4294967295] +; X86-AVX512VL-NEXT: # encoding: [0xc5,0xfd,0x6f,0x0d,A,A,A,A] +; X86-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vpsrlvd {{\.LCPI.*}}, %ymm1, %ymm1 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x75,0x45,0x0d,A,A,A,A] +; X86-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-AVX512VL-NEXT: vpaddd %ymm1, %ymm0, %ymm0 # EVEX TO VEX Compression encoding: [0xc5,0xfd,0xfe,0xc1] ; X86-AVX512VL-NEXT: retl # encoding: [0xc3] ; ; X64-AVX-LABEL: test_x86_avx2_psrlv_d_256_const: ; X64-AVX: # %bb.0: -; X64-AVX-NEXT: vpbroadcastd {{.*#+}} ymm0 = [2,2,2,2,2,2,2,2] -; X64-AVX-NEXT: # encoding: [0xc4,0xe2,0x7d,0x58,0x05,A,A,A,A] +; X64-AVX-NEXT: vmovdqa {{.*#+}} ymm0 = [2,9,0,4294967295,3,7,4294967295,0] +; X64-AVX-NEXT: # encoding: [0xc5,0xfd,0x6f,0x05,A,A,A,A] +; X64-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpsrlvd {{.*}}(%rip), %ymm0, %ymm0 # encoding: [0xc4,0xe2,0x7d,0x45,0x05,A,A,A,A] ; X64-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte -; X64-AVX-NEXT: vpaddd {{.*}}(%rip), %ymm0, %ymm0 # encoding: [0xc5,0xfd,0xfe,0x05,A,A,A,A] +; X64-AVX-NEXT: vmovdqa {{.*#+}} ymm1 = [4,4,4,4,4,4,4,4294967295] +; X64-AVX-NEXT: # encoding: [0xc5,0xfd,0x6f,0x0d,A,A,A,A] ; X64-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpsrlvd {{.*}}(%rip), %ymm1, %ymm1 # encoding: [0xc4,0xe2,0x75,0x45,0x0d,A,A,A,A] +; X64-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpaddd %ymm1, %ymm0, %ymm0 # encoding: [0xc5,0xfd,0xfe,0xc1] ; X64-AVX-NEXT: retq # encoding: [0xc3] ; ; X64-AVX512VL-LABEL: test_x86_avx2_psrlv_d_256_const: ; X64-AVX512VL: # %bb.0: -; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %ymm0 # EVEX TO VEX Compression ymm0 = <1,9,0,u,0,7,u,0> +; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %ymm0 # EVEX TO VEX Compression ymm0 = [2,9,0,4294967295,3,7,4294967295,0] ; X64-AVX512VL-NEXT: # encoding: [0xc5,0xfd,0x6f,0x05,A,A,A,A] ; X64-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte -; X64-AVX512VL-NEXT: vpaddd {{.*}}(%rip){1to8}, %ymm0, %ymm0 # encoding: [0x62,0xf1,0x7d,0x38,0xfe,0x05,A,A,A,A] -; X64-AVX512VL-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpsrlvd {{.*}}(%rip), %ymm0, %ymm0 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x7d,0x45,0x05,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %ymm1 # EVEX TO VEX Compression ymm1 = [4,4,4,4,4,4,4,4294967295] +; X64-AVX512VL-NEXT: # encoding: [0xc5,0xfd,0x6f,0x0d,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpsrlvd {{.*}}(%rip), %ymm1, %ymm1 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x75,0x45,0x0d,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpaddd %ymm1, %ymm0, %ymm0 # EVEX TO VEX Compression encoding: [0xc5,0xfd,0xfe,0xc1] ; X64-AVX512VL-NEXT: retq # encoding: [0xc3] %res0 = call <8 x i32> @llvm.x86.avx2.psrlv.d.256(<8 x i32> , <8 x i32> ) %res1 = call <8 x i32> @llvm.x86.avx2.psrlv.d.256(<8 x i32> , <8 x i32> ) @@ -1534,14 +1636,20 @@ define <2 x i64> @test_x86_avx2_psrlv_q_const() { ; ; X64-AVX-LABEL: test_x86_avx2_psrlv_q_const: ; X64-AVX: # %bb.0: -; X64-AVX-NEXT: movl $2, %eax # encoding: [0xb8,0x02,0x00,0x00,0x00] -; X64-AVX-NEXT: vmovq %rax, %xmm0 # encoding: [0xc4,0xe1,0xf9,0x6e,0xc0] +; X64-AVX-NEXT: vmovdqa {{.*#+}} xmm0 = [4,4] +; X64-AVX-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] +; X64-AVX-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpsrlvq {{.*}}(%rip), %xmm0, %xmm0 # encoding: [0xc4,0xe2,0xf9,0x45,0x05,A,A,A,A] +; X64-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte ; X64-AVX-NEXT: retq # encoding: [0xc3] ; ; X64-AVX512VL-LABEL: test_x86_avx2_psrlv_q_const: ; X64-AVX512VL: # %bb.0: -; X64-AVX512VL-NEXT: movl $2, %eax # encoding: [0xb8,0x02,0x00,0x00,0x00] -; X64-AVX512VL-NEXT: vmovq %rax, %xmm0 # EVEX TO VEX Compression encoding: [0xc4,0xe1,0xf9,0x6e,0xc0] +; X64-AVX512VL-NEXT: vmovdqa {{.*}}(%rip), %xmm0 # EVEX TO VEX Compression xmm0 = [4,4] +; X64-AVX512VL-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpsrlvq {{.*}}(%rip), %xmm0, %xmm0 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0xf9,0x45,0x05,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte ; X64-AVX512VL-NEXT: retq # encoding: [0xc3] %res = call <2 x i64> @llvm.x86.avx2.psrlv.q(<2 x i64> , <2 x i64> ) ret <2 x i64> %res @@ -1585,15 +1693,19 @@ define <4 x i64> @test_x86_avx2_psrlv_q_256_const() { ; ; X64-AVX-LABEL: test_x86_avx2_psrlv_q_256_const: ; X64-AVX: # %bb.0: -; X64-AVX-NEXT: vbroadcastsd {{.*#+}} ymm0 = [2,2,2,2] -; X64-AVX-NEXT: # encoding: [0xc4,0xe2,0x7d,0x19,0x05,A,A,A,A] +; X64-AVX-NEXT: vpbroadcastq {{.*#+}} ymm0 = [4,4,4,4] +; X64-AVX-NEXT: # encoding: [0xc4,0xe2,0x7d,0x59,0x05,A,A,A,A] +; X64-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX-NEXT: vpsrlvq {{.*}}(%rip), %ymm0, %ymm0 # encoding: [0xc4,0xe2,0xfd,0x45,0x05,A,A,A,A] ; X64-AVX-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte ; X64-AVX-NEXT: retq # encoding: [0xc3] ; ; X64-AVX512VL-LABEL: test_x86_avx2_psrlv_q_256_const: ; X64-AVX512VL: # %bb.0: -; X64-AVX512VL-NEXT: vbroadcastsd {{.*}}(%rip), %ymm0 # EVEX TO VEX Compression ymm0 = [2,2,2,2] -; X64-AVX512VL-NEXT: # encoding: [0xc4,0xe2,0x7d,0x19,0x05,A,A,A,A] +; X64-AVX512VL-NEXT: vpbroadcastq {{.*}}(%rip), %ymm0 # EVEX TO VEX Compression ymm0 = [4,4,4,4] +; X64-AVX512VL-NEXT: # encoding: [0xc4,0xe2,0x7d,0x59,0x05,A,A,A,A] +; X64-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-AVX512VL-NEXT: vpsrlvq {{.*}}(%rip), %ymm0, %ymm0 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0xfd,0x45,0x05,A,A,A,A] ; X64-AVX512VL-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte ; X64-AVX512VL-NEXT: retq # encoding: [0xc3] %res = call <4 x i64> @llvm.x86.avx2.psrlv.q.256(<4 x i64> , <4 x i64> ) diff --git a/llvm/test/CodeGen/X86/avx512-intrinsics.ll b/llvm/test/CodeGen/X86/avx512-intrinsics.ll index a0e8393309de0..6a1d9d3da9170 100644 --- a/llvm/test/CodeGen/X86/avx512-intrinsics.ll +++ b/llvm/test/CodeGen/X86/avx512-intrinsics.ll @@ -5229,8 +5229,11 @@ define <16 x i32> @test_x86_avx512_psllv_d_512(<16 x i32> %a0, <16 x i32> %a1) { define <16 x i32> @test_x86_avx512_psllv_d_512_const() { ; CHECK-LABEL: test_x86_avx512_psllv_d_512_const: ; CHECK: ## %bb.0: -; CHECK-NEXT: vmovdqa64 {{.*#+}} zmm0 = <4,9,0,u,12,7,u,0,32,5,u,0,80,3,u,0> -; CHECK-NEXT: vpaddd {{.*}}(%rip){1to16}, %zmm0, %zmm0 +; CHECK-NEXT: vmovdqa64 {{.*#+}} zmm0 = [2,9,0,4294967295,3,7,4294967295,0,4,5,4294967294,0,5,3,4294967293,0] +; CHECK-NEXT: vpsllvd {{.*}}(%rip), %zmm0, %zmm0 +; CHECK-NEXT: vmovdqa64 {{.*#+}} zmm1 = [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4294967295] +; CHECK-NEXT: vpsllvd {{.*}}(%rip), %zmm1, %zmm1 +; CHECK-NEXT: vpaddd %zmm1, %zmm0, %zmm0 ; CHECK-NEXT: retq %res0 = call <16 x i32> @llvm.x86.avx512.psllv.d.512(<16 x i32> , <16 x i32> ) %res1 = call <16 x i32> @llvm.x86.avx512.psllv.d.512(<16 x i32> , <16 x i32> ) @@ -5277,8 +5280,11 @@ define <8 x i64> @test_x86_avx512_psllv_q_512(<8 x i64> %a0, <8 x i64> %a1) { define <8 x i64> @test_x86_avx512_psllv_q_512_const() { ; CHECK-LABEL: test_x86_avx512_psllv_q_512_const: ; CHECK: ## %bb.0: -; CHECK-NEXT: vmovdqa64 {{.*#+}} zmm0 = <4,9,0,u,12,7,18446744056529682432,0> -; CHECK-NEXT: vpaddq {{.*}}(%rip){1to8}, %zmm0, %zmm0 +; CHECK-NEXT: vmovdqa64 {{.*#+}} zmm0 = [2,9,0,18446744073709551615,3,7,18446744073709551615,0] +; CHECK-NEXT: vpsllvq {{.*}}(%rip), %zmm0, %zmm0 +; CHECK-NEXT: vmovdqa64 {{.*#+}} zmm1 = [4,4,4,4,4,4,4,18446744073709551615] +; CHECK-NEXT: vpsllvq {{.*}}(%rip), %zmm1, %zmm1 +; CHECK-NEXT: vpaddq %zmm1, %zmm0, %zmm0 ; CHECK-NEXT: retq %res0 = call <8 x i64> @llvm.x86.avx512.psllv.q.512(<8 x i64> , <8 x i64> ) %res1 = call <8 x i64> @llvm.x86.avx512.psllv.q.512(<8 x i64> , <8 x i64> ) @@ -5397,8 +5403,11 @@ define <16 x i32> @test_x86_avx512_psrlv_d_512(<16 x i32> %a0, <16 x i32> %a1) { define <16 x i32> @test_x86_avx512_psrlv_d_512_const() { ; CHECK-LABEL: test_x86_avx512_psrlv_d_512_const: ; CHECK: ## %bb.0: -; CHECK-NEXT: vmovdqa64 {{.*#+}} zmm0 = <1,9,0,u,0,7,u,0,0,5,u,0,0,3,u,0> -; CHECK-NEXT: vpaddd {{.*}}(%rip){1to16}, %zmm0, %zmm0 +; CHECK-NEXT: vmovdqa64 {{.*#+}} zmm0 = [2,9,0,4294967295,3,7,4294967295,0,4,5,4294967294,0,5,3,4294967293,0] +; CHECK-NEXT: vpsrlvd {{.*}}(%rip), %zmm0, %zmm0 +; CHECK-NEXT: vmovdqa64 {{.*#+}} zmm1 = [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4294967295] +; CHECK-NEXT: vpsrlvd {{.*}}(%rip), %zmm1, %zmm1 +; CHECK-NEXT: vpaddd %zmm1, %zmm0, %zmm0 ; CHECK-NEXT: retq %res0 = call <16 x i32> @llvm.x86.avx512.psrlv.d.512(<16 x i32> , <16 x i32> ) %res1 = call <16 x i32> @llvm.x86.avx512.psrlv.d.512(<16 x i32> , <16 x i32> ) @@ -5445,8 +5454,11 @@ define <8 x i64> @test_x86_avx512_psrlv_q_512(<8 x i64> %a0, <8 x i64> %a1) { define <8 x i64> @test_x86_avx512_psrlv_q_512_const() { ; CHECK-LABEL: test_x86_avx512_psrlv_q_512_const: ; CHECK: ## %bb.0: -; CHECK-NEXT: vmovdqa64 {{.*#+}} zmm0 = <1,9,0,u,0,7,1073741823,0> -; CHECK-NEXT: vpaddq {{.*}}(%rip){1to8}, %zmm0, %zmm0 +; CHECK-NEXT: vmovdqa64 {{.*#+}} zmm0 = [2,9,0,18446744073709551615,3,7,18446744073709551615,0] +; CHECK-NEXT: vpsrlvq {{.*}}(%rip), %zmm0, %zmm0 +; CHECK-NEXT: vmovdqa64 {{.*#+}} zmm1 = [4,4,4,4,4,4,4,18446744073709551615] +; CHECK-NEXT: vpsrlvq {{.*}}(%rip), %zmm1, %zmm1 +; CHECK-NEXT: vpaddq %zmm1, %zmm0, %zmm0 ; CHECK-NEXT: retq %res0 = call <8 x i64> @llvm.x86.avx512.psrlv.q.512(<8 x i64> , <8 x i64> ) %res1 = call <8 x i64> @llvm.x86.avx512.psrlv.q.512(<8 x i64> , <8 x i64> ) diff --git a/llvm/test/CodeGen/X86/avx512-regcall-NoMask.ll b/llvm/test/CodeGen/X86/avx512-regcall-NoMask.ll index 1136a3a50693e..985860166a3f2 100644 --- a/llvm/test/CodeGen/X86/avx512-regcall-NoMask.ll +++ b/llvm/test/CodeGen/X86/avx512-regcall-NoMask.ll @@ -508,17 +508,17 @@ define x86_regcallcc double @test_CallargRetDouble(double %a) { define x86_regcallcc x86_fp80 @test_argRetf80(x86_fp80 %a0) nounwind { ; X32-LABEL: test_argRetf80: ; X32: # %bb.0: -; X32-NEXT: fadd %st(0), %st(0) +; X32-NEXT: fadd %st, %st(0) ; X32-NEXT: retl ; ; WIN64-LABEL: test_argRetf80: ; WIN64: # %bb.0: -; WIN64-NEXT: fadd %st(0), %st(0) +; WIN64-NEXT: fadd %st, %st(0) ; WIN64-NEXT: retq ; ; LINUXOSX64-LABEL: test_argRetf80: ; LINUXOSX64: # %bb.0: -; LINUXOSX64-NEXT: fadd %st(0), %st(0) +; LINUXOSX64-NEXT: fadd %st, %st(0) ; LINUXOSX64-NEXT: retq %r0 = fadd x86_fp80 %a0, %a0 ret x86_fp80 %r0 @@ -529,9 +529,9 @@ define x86_regcallcc x86_fp80 @test_CallargRetf80(x86_fp80 %a) { ; X32-LABEL: test_CallargRetf80: ; X32: # %bb.0: ; X32-NEXT: pushl %esp -; X32-NEXT: fadd %st(0), %st(0) +; X32-NEXT: fadd %st, %st(0) ; X32-NEXT: calll _test_argRetf80 -; X32-NEXT: fadd %st(0), %st(0) +; X32-NEXT: fadd %st, %st(0) ; X32-NEXT: popl %esp ; X32-NEXT: retl ; @@ -540,9 +540,9 @@ define x86_regcallcc x86_fp80 @test_CallargRetf80(x86_fp80 %a) { ; WIN64-NEXT: pushq %rsp ; WIN64-NEXT: .seh_pushreg 4 ; WIN64-NEXT: .seh_endprologue -; WIN64-NEXT: fadd %st(0), %st(0) +; WIN64-NEXT: fadd %st, %st(0) ; WIN64-NEXT: callq test_argRetf80 -; WIN64-NEXT: fadd %st(0), %st(0) +; WIN64-NEXT: fadd %st, %st(0) ; WIN64-NEXT: popq %rsp ; WIN64-NEXT: retq ; WIN64-NEXT: .seh_handlerdata @@ -554,9 +554,9 @@ define x86_regcallcc x86_fp80 @test_CallargRetf80(x86_fp80 %a) { ; LINUXOSX64-NEXT: pushq %rsp ; LINUXOSX64-NEXT: .cfi_def_cfa_offset 16 ; LINUXOSX64-NEXT: .cfi_offset %rsp, -16 -; LINUXOSX64-NEXT: fadd %st(0), %st(0) +; LINUXOSX64-NEXT: fadd %st, %st(0) ; LINUXOSX64-NEXT: callq test_argRetf80 -; LINUXOSX64-NEXT: fadd %st(0), %st(0) +; LINUXOSX64-NEXT: fadd %st, %st(0) ; LINUXOSX64-NEXT: popq %rsp ; LINUXOSX64-NEXT: .cfi_def_cfa_offset 8 ; LINUXOSX64-NEXT: retq diff --git a/llvm/test/CodeGen/X86/avx512bw-intrinsics.ll b/llvm/test/CodeGen/X86/avx512bw-intrinsics.ll index 8bcdc5d5c0298..a220ab0ad7349 100644 --- a/llvm/test/CodeGen/X86/avx512bw-intrinsics.ll +++ b/llvm/test/CodeGen/X86/avx512bw-intrinsics.ll @@ -1158,15 +1158,19 @@ declare <32 x i16> @llvm.x86.avx512.psrlv.w.512(<32 x i16>, <32 x i16>) nounwind define <32 x i16> @test_x86_avx512_psrlv_w_512_const() optsize { ; X86-LABEL: test_x86_avx512_psrlv_w_512_const: ; X86: # %bb.0: -; X86-NEXT: vpbroadcastw {{.*#+}} zmm0 = [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2] -; X86-NEXT: # encoding: [0x62,0xf2,0x7d,0x48,0x79,0x05,A,A,A,A] +; X86-NEXT: vmovdqa64 {{.*#+}} zmm0 = [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,65535] +; X86-NEXT: # encoding: [0x62,0xf1,0xfd,0x48,0x6f,0x05,A,A,A,A] +; X86-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-NEXT: vpsrlvw {{\.LCPI.*}}, %zmm0, %zmm0 # encoding: [0x62,0xf2,0xfd,0x48,0x10,0x05,A,A,A,A] ; X86-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}, kind: FK_Data_4 ; X86-NEXT: retl # encoding: [0xc3] ; ; X64-LABEL: test_x86_avx512_psrlv_w_512_const: ; X64: # %bb.0: -; X64-NEXT: vpbroadcastw {{.*#+}} zmm0 = [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2] -; X64-NEXT: # encoding: [0x62,0xf2,0x7d,0x48,0x79,0x05,A,A,A,A] +; X64-NEXT: vmovdqa64 {{.*#+}} zmm0 = [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,65535] +; X64-NEXT: # encoding: [0x62,0xf1,0xfd,0x48,0x6f,0x05,A,A,A,A] +; X64-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-NEXT: vpsrlvw {{.*}}(%rip), %zmm0, %zmm0 # encoding: [0x62,0xf2,0xfd,0x48,0x10,0x05,A,A,A,A] ; X64-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte ; X64-NEXT: retq # encoding: [0xc3] %res1 = call <32 x i16> @llvm.x86.avx512.psrlv.w.512(<32 x i16> , <32 x i16> ) @@ -1377,15 +1381,19 @@ declare <32 x i16> @llvm.x86.avx512.psll.w.512(<32 x i16>, <8 x i16>) nounwind r define <32 x i16> @test_x86_avx512_psllv_w_512_const() optsize { ; X86-LABEL: test_x86_avx512_psllv_w_512_const: ; X86: # %bb.0: -; X86-NEXT: vpbroadcastw {{.*#+}} zmm0 = [8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8] -; X86-NEXT: # encoding: [0x62,0xf2,0x7d,0x48,0x79,0x05,A,A,A,A] +; X86-NEXT: vmovdqa64 {{.*#+}} zmm0 = [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,65535] +; X86-NEXT: # encoding: [0x62,0xf1,0xfd,0x48,0x6f,0x05,A,A,A,A] +; X86-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-NEXT: vpsllvw {{\.LCPI.*}}, %zmm0, %zmm0 # encoding: [0x62,0xf2,0xfd,0x48,0x12,0x05,A,A,A,A] ; X86-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}, kind: FK_Data_4 ; X86-NEXT: retl # encoding: [0xc3] ; ; X64-LABEL: test_x86_avx512_psllv_w_512_const: ; X64: # %bb.0: -; X64-NEXT: vpbroadcastw {{.*#+}} zmm0 = [8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8] -; X64-NEXT: # encoding: [0x62,0xf2,0x7d,0x48,0x79,0x05,A,A,A,A] +; X64-NEXT: vmovdqa64 {{.*#+}} zmm0 = [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,65535] +; X64-NEXT: # encoding: [0x62,0xf1,0xfd,0x48,0x6f,0x05,A,A,A,A] +; X64-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-NEXT: vpsllvw {{.*}}(%rip), %zmm0, %zmm0 # encoding: [0x62,0xf2,0xfd,0x48,0x12,0x05,A,A,A,A] ; X64-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte ; X64-NEXT: retq # encoding: [0xc3] %res1 = call <32 x i16> @llvm.x86.avx512.psllv.w.512(<32 x i16> , <32 x i16> ) diff --git a/llvm/test/CodeGen/X86/avx512bwvl-intrinsics.ll b/llvm/test/CodeGen/X86/avx512bwvl-intrinsics.ll index 10ba0e646055f..a01252f7d494b 100644 --- a/llvm/test/CodeGen/X86/avx512bwvl-intrinsics.ll +++ b/llvm/test/CodeGen/X86/avx512bwvl-intrinsics.ll @@ -2021,16 +2021,20 @@ define <8 x i16>@test_int_x86_avx512_mask_psrlv8_hi(<8 x i16> %x0, <8 x i16> %x1 define <8 x i16> @test_int_x86_avx512_psrlv_w_128_const() optsize { ; X86-LABEL: test_int_x86_avx512_psrlv_w_128_const: ; X86: # %bb.0: -; X86-NEXT: vpbroadcastw {{\.LCPI.*}}, %xmm0 # EVEX TO VEX Compression xmm0 = [2,2,2,2,2,2,2,2] -; X86-NEXT: # encoding: [0xc4,0xe2,0x79,0x79,0x05,A,A,A,A] -; X86-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-NEXT: vmovdqa {{\.LCPI.*}}, %xmm0 # EVEX TO VEX Compression xmm0 = [4,4,4,4,4,4,4,65535] +; X86-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] +; X86-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-NEXT: vpsrlvw {{\.LCPI.*}}, %xmm0, %xmm0 # encoding: [0x62,0xf2,0xfd,0x08,0x10,0x05,A,A,A,A] +; X86-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}, kind: FK_Data_4 ; X86-NEXT: retl # encoding: [0xc3] ; ; X64-LABEL: test_int_x86_avx512_psrlv_w_128_const: ; X64: # %bb.0: -; X64-NEXT: vpbroadcastw {{.*}}(%rip), %xmm0 # EVEX TO VEX Compression xmm0 = [2,2,2,2,2,2,2,2] -; X64-NEXT: # encoding: [0xc4,0xe2,0x79,0x79,0x05,A,A,A,A] -; X64-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-NEXT: vmovdqa {{.*}}(%rip), %xmm0 # EVEX TO VEX Compression xmm0 = [4,4,4,4,4,4,4,65535] +; X64-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] +; X64-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-NEXT: vpsrlvw {{.*}}(%rip), %xmm0, %xmm0 # encoding: [0x62,0xf2,0xfd,0x08,0x10,0x05,A,A,A,A] +; X64-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte ; X64-NEXT: retq # encoding: [0xc3] %res = call <8 x i16> @llvm.x86.avx512.psrlv.w.128(<8 x i16> , <8 x i16> ) ret <8 x i16> %res @@ -2041,16 +2045,20 @@ declare <8 x i16> @llvm.x86.avx512.psrlv.w.128(<8 x i16>, <8 x i16>) define <16 x i16> @test_int_x86_avx512_psrlv_w_256_const() optsize { ; X86-LABEL: test_int_x86_avx512_psrlv_w_256_const: ; X86: # %bb.0: -; X86-NEXT: vpbroadcastw {{\.LCPI.*}}, %ymm0 # EVEX TO VEX Compression ymm0 = [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2] -; X86-NEXT: # encoding: [0xc4,0xe2,0x7d,0x79,0x05,A,A,A,A] -; X86-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-NEXT: vmovdqa {{\.LCPI.*}}, %ymm0 # EVEX TO VEX Compression ymm0 = [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,65535] +; X86-NEXT: # encoding: [0xc5,0xfd,0x6f,0x05,A,A,A,A] +; X86-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-NEXT: vpsrlvw {{\.LCPI.*}}, %ymm0, %ymm0 # encoding: [0x62,0xf2,0xfd,0x28,0x10,0x05,A,A,A,A] +; X86-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}, kind: FK_Data_4 ; X86-NEXT: retl # encoding: [0xc3] ; ; X64-LABEL: test_int_x86_avx512_psrlv_w_256_const: ; X64: # %bb.0: -; X64-NEXT: vpbroadcastw {{.*}}(%rip), %ymm0 # EVEX TO VEX Compression ymm0 = [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2] -; X64-NEXT: # encoding: [0xc4,0xe2,0x7d,0x79,0x05,A,A,A,A] -; X64-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-NEXT: vmovdqa {{.*}}(%rip), %ymm0 # EVEX TO VEX Compression ymm0 = [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,65535] +; X64-NEXT: # encoding: [0xc5,0xfd,0x6f,0x05,A,A,A,A] +; X64-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-NEXT: vpsrlvw {{.*}}(%rip), %ymm0, %ymm0 # encoding: [0x62,0xf2,0xfd,0x28,0x10,0x05,A,A,A,A] +; X64-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte ; X64-NEXT: retq # encoding: [0xc3] %res = call <16 x i16> @llvm.x86.avx512.psrlv.w.256(<16 x i16> , <16 x i16> ) ret <16 x i16> %res @@ -2195,16 +2203,20 @@ define <8 x i16>@test_int_x86_avx512_mask_psllv8_hi(<8 x i16> %x0, <8 x i16> %x1 define <8 x i16> @test_int_x86_avx512_psllv_w_128_const() optsize { ; X86-LABEL: test_int_x86_avx512_psllv_w_128_const: ; X86: # %bb.0: -; X86-NEXT: vpbroadcastw {{\.LCPI.*}}, %xmm0 # EVEX TO VEX Compression xmm0 = [8,8,8,8,8,8,8,8] -; X86-NEXT: # encoding: [0xc4,0xe2,0x79,0x79,0x05,A,A,A,A] -; X86-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-NEXT: vmovdqa {{\.LCPI.*}}, %xmm0 # EVEX TO VEX Compression xmm0 = [4,4,4,4,4,4,4,65535] +; X86-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] +; X86-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-NEXT: vpsllvw {{\.LCPI.*}}, %xmm0, %xmm0 # encoding: [0x62,0xf2,0xfd,0x08,0x12,0x05,A,A,A,A] +; X86-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}, kind: FK_Data_4 ; X86-NEXT: retl # encoding: [0xc3] ; ; X64-LABEL: test_int_x86_avx512_psllv_w_128_const: ; X64: # %bb.0: -; X64-NEXT: vpbroadcastw {{.*}}(%rip), %xmm0 # EVEX TO VEX Compression xmm0 = [8,8,8,8,8,8,8,8] -; X64-NEXT: # encoding: [0xc4,0xe2,0x79,0x79,0x05,A,A,A,A] -; X64-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-NEXT: vmovdqa {{.*}}(%rip), %xmm0 # EVEX TO VEX Compression xmm0 = [4,4,4,4,4,4,4,65535] +; X64-NEXT: # encoding: [0xc5,0xf9,0x6f,0x05,A,A,A,A] +; X64-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-NEXT: vpsllvw {{.*}}(%rip), %xmm0, %xmm0 # encoding: [0x62,0xf2,0xfd,0x08,0x12,0x05,A,A,A,A] +; X64-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte ; X64-NEXT: retq # encoding: [0xc3] %res = call <8 x i16> @llvm.x86.avx512.psllv.w.128(<8 x i16> , <8 x i16> ) ret <8 x i16> %res @@ -2216,16 +2228,20 @@ declare <8 x i16> @llvm.x86.avx512.psllv.w.128(<8 x i16>, <8 x i16>) define <16 x i16> @test_int_x86_avx512_psllv_w_256_const() optsize { ; X86-LABEL: test_int_x86_avx512_psllv_w_256_const: ; X86: # %bb.0: -; X86-NEXT: vpbroadcastw {{\.LCPI.*}}, %ymm0 # EVEX TO VEX Compression ymm0 = [8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8] -; X86-NEXT: # encoding: [0xc4,0xe2,0x7d,0x79,0x05,A,A,A,A] -; X86-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-NEXT: vmovdqa {{\.LCPI.*}}, %ymm0 # EVEX TO VEX Compression ymm0 = [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,65535] +; X86-NEXT: # encoding: [0xc5,0xfd,0x6f,0x05,A,A,A,A] +; X86-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}, kind: FK_Data_4 +; X86-NEXT: vpsllvw {{\.LCPI.*}}, %ymm0, %ymm0 # encoding: [0x62,0xf2,0xfd,0x28,0x12,0x05,A,A,A,A] +; X86-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}, kind: FK_Data_4 ; X86-NEXT: retl # encoding: [0xc3] ; ; X64-LABEL: test_int_x86_avx512_psllv_w_256_const: ; X64: # %bb.0: -; X64-NEXT: vpbroadcastw {{.*}}(%rip), %ymm0 # EVEX TO VEX Compression ymm0 = [8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8] -; X64-NEXT: # encoding: [0xc4,0xe2,0x7d,0x79,0x05,A,A,A,A] -; X64-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-NEXT: vmovdqa {{.*}}(%rip), %ymm0 # EVEX TO VEX Compression ymm0 = [4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,65535] +; X64-NEXT: # encoding: [0xc5,0xfd,0x6f,0x05,A,A,A,A] +; X64-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; X64-NEXT: vpsllvw {{.*}}(%rip), %ymm0, %ymm0 # encoding: [0x62,0xf2,0xfd,0x28,0x12,0x05,A,A,A,A] +; X64-NEXT: # fixup A - offset: 6, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte ; X64-NEXT: retq # encoding: [0xc3] %res = call <16 x i16> @llvm.x86.avx512.psllv.w.256(<16 x i16> , <16 x i16> ) ret <16 x i16> %res diff --git a/llvm/test/CodeGen/X86/code-model-elf.ll b/llvm/test/CodeGen/X86/code-model-elf.ll index 56d3f4c102f0f..f7ffd6ea1eb7c 100644 --- a/llvm/test/CodeGen/X86/code-model-elf.ll +++ b/llvm/test/CodeGen/X86/code-model-elf.ll @@ -37,6 +37,8 @@ target triple = "x86_64--linux" @global_data = dso_local global [10 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0], align 16 @static_data = internal global [10 x i32] zeroinitializer, align 16 @extern_data = external global [10 x i32], align 16 +@thread_data = external thread_local global i32, align 4 + define dso_local i32* @lea_static_data() #0 { ; SMALL-STATIC-LABEL: lea_static_data: @@ -373,6 +375,70 @@ define dso_local void ()* @lea_extern_fn() #0 { ret void ()* @extern_fn } +; FIXME: The result is same for small, medium and large model, because we +; specify pie option in the test case. And the type of tls is initial exec tls. +; For pic code. The large model code for pic tls should be emitted as below. + +; .L3: +; leaq .L3(%rip), %rbx +; movabsq $_GLOBAL_OFFSET_TABLE_-.L3, %r11 +; addq %r11, %rbx +; leaq thread_data@TLSGD(%rip), %rdi +; movabsq $__tls_get_addr@PLTOFF, %rax +; addq %rbx, %rax +; call *%rax +; movl (%rax), %eax + +; The medium and small model code for pic tls should be emitted as below. +; data16 +; leaq thread_data@TLSGD(%rip), %rdi +; data16 +; data16 +; rex64 +; callq __tls_get_addr@PLT +; movl (%rax), %eax + +define dso_local i32 @load_thread_data() #0 { +; SMALL-STATIC-LABEL: load_thread_data: +; SMALL-STATIC: # %bb.0: +; SMALL-STATIC-NEXT: movq thread_data@GOTTPOFF(%rip), %rax +; SMALL-STATIC-NEXT: movl %fs:(%rax), %eax +; SMALL-STATIC-NEXT: retq +; +; MEDIUM-STATIC-LABEL: load_thread_data: +; MEDIUM-STATIC: # %bb.0: +; MEDIUM-STATIC-NEXT: movq thread_data@GOTTPOFF(%rip), %rax +; MEDIUM-STATIC-NEXT: movl %fs:(%rax), %eax +; MEDIUM-STATIC-NEXT: retq +; +; LARGE-STATIC-LABEL: load_thread_data: +; LARGE-STATIC: # %bb.0: +; LARGE-STATIC-NEXT: movq thread_data@GOTTPOFF(%rip), %rax +; LARGE-STATIC-NEXT: movl %fs:(%rax), %eax +; LARGE-STATIC-NEXT: retq +; +; SMALL-PIC-LABEL: load_thread_data: +; SMALL-PIC: # %bb.0: +; SMALL-PIC-NEXT: movq thread_data@GOTTPOFF(%rip), %rax +; SMALL-PIC-NEXT: movl %fs:(%rax), %eax +; SMALL-PIC-NEXT: retq +; +; MEDIUM-PIC-LABEL: load_thread_data: +; MEDIUM-PIC: # %bb.0: +; MEDIUM-PIC-NEXT: movq thread_data@GOTTPOFF(%rip), %rax +; MEDIUM-PIC-NEXT: movl %fs:(%rax), %eax +; MEDIUM-PIC-NEXT: retq +; +; LARGE-PIC-LABEL: load_thread_data: +; LARGE-PIC: # %bb.0: +; LARGE-PIC-NEXT: movq thread_data@GOTTPOFF(%rip), %rax +; LARGE-PIC-NEXT: movl %fs:(%rax), %eax +; LARGE-PIC-NEXT: retq +; + %1 = load i32, i32* @thread_data, align 4 + ret i32 %1 +} + attributes #0 = { noinline nounwind uwtable } !llvm.module.flags = !{!0, !1, !2} diff --git a/llvm/test/CodeGen/X86/debug-loclists.ll b/llvm/test/CodeGen/X86/debug-loclists.ll index 20bc0c40378b9..0c2ab3dfad5a9 100644 --- a/llvm/test/CodeGen/X86/debug-loclists.ll +++ b/llvm/test/CodeGen/X86/debug-loclists.ll @@ -11,7 +11,7 @@ ; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0040 => {0x00000040} "A") ; CHECK: .debug_loclists contents: -; CHECK-NEXT: 0x00000000: locations list header: length = 0x00000017, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 +; CHECK-NEXT: 0x00000000: locations list header: length = 0x00000015, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 ; CHECK-NEXT: 0x00000000: ; CHECK-NEXT: [0x0000000000000000, 0x0000000000000004): DW_OP_breg5 RDI+0 ; CHECK-NEXT: [0x0000000000000004, 0x0000000000000012): DW_OP_breg3 RBX+0 @@ -32,13 +32,13 @@ ; ASM-NEXT: .byte 4 # DW_LLE_offset_pair ; ASM-NEXT: .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset ; ASM-NEXT: .uleb128 .Ltmp0-.Lfunc_begin0 # ending offset -; ASM-NEXT: .short 2 # Loc expr size +; ASM-NEXT: .byte 2 # Loc expr size ; ASM-NEXT: .byte 117 # DW_OP_breg5 ; ASM-NEXT: .byte 0 # 0 ; ASM-NEXT: .byte 4 # DW_LLE_offset_pair ; ASM-NEXT: .uleb128 .Ltmp0-.Lfunc_begin0 # starting offset ; ASM-NEXT: .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset -; ASM-NEXT: .short 2 # Loc expr size +; ASM-NEXT: .byte 2 # Loc expr size ; ASM-NEXT: .byte 115 # DW_OP_breg3 ; ASM-NEXT: .byte 0 # 0 ; ASM-NEXT: .byte 0 # DW_LLE_end_of_list diff --git a/llvm/test/CodeGen/X86/discriminate-mem-ops.ll b/llvm/test/CodeGen/X86/discriminate-mem-ops.ll index b77a91fafd2cd..a30dc22a0d9c0 100644 --- a/llvm/test/CodeGen/X86/discriminate-mem-ops.ll +++ b/llvm/test/CodeGen/X86/discriminate-mem-ops.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s | FileCheck %s +; RUN: llc -x86-discriminate-memops < %s | FileCheck %s ; ; original source, compiled with -O3 -gmlt -fdebug-info-for-profiling: ; int sum(int* arr, int pos1, int pos2) { diff --git a/llvm/test/CodeGen/X86/fast-isel-nontemporal.ll b/llvm/test/CodeGen/X86/fast-isel-nontemporal.ll index db1ebfe6060f8..37e380b2b48c9 100644 --- a/llvm/test/CodeGen/X86/fast-isel-nontemporal.ll +++ b/llvm/test/CodeGen/X86/fast-isel-nontemporal.ll @@ -300,10 +300,20 @@ entry: } define <16 x i8> @test_load_nt16xi8(<16 x i8>* nocapture %ptr) { -; SSE-LABEL: test_load_nt16xi8: -; SSE: # %bb.0: # %entry -; SSE-NEXT: movntdqa (%rdi), %xmm0 -; SSE-NEXT: retq +; SSE2-LABEL: test_load_nt16xi8: +; SSE2: # %bb.0: # %entry +; SSE2-NEXT: movdqa (%rdi), %xmm0 +; SSE2-NEXT: retq +; +; SSE4A-LABEL: test_load_nt16xi8: +; SSE4A: # %bb.0: # %entry +; SSE4A-NEXT: movdqa (%rdi), %xmm0 +; SSE4A-NEXT: retq +; +; SSE41-LABEL: test_load_nt16xi8: +; SSE41: # %bb.0: # %entry +; SSE41-NEXT: movntdqa (%rdi), %xmm0 +; SSE41-NEXT: retq ; ; AVX-LABEL: test_load_nt16xi8: ; AVX: # %bb.0: # %entry @@ -320,10 +330,20 @@ entry: } define <8 x i16> @test_load_nt8xi16(<8 x i16>* nocapture %ptr) { -; SSE-LABEL: test_load_nt8xi16: -; SSE: # %bb.0: # %entry -; SSE-NEXT: movntdqa (%rdi), %xmm0 -; SSE-NEXT: retq +; SSE2-LABEL: test_load_nt8xi16: +; SSE2: # %bb.0: # %entry +; SSE2-NEXT: movdqa (%rdi), %xmm0 +; SSE2-NEXT: retq +; +; SSE4A-LABEL: test_load_nt8xi16: +; SSE4A: # %bb.0: # %entry +; SSE4A-NEXT: movdqa (%rdi), %xmm0 +; SSE4A-NEXT: retq +; +; SSE41-LABEL: test_load_nt8xi16: +; SSE41: # %bb.0: # %entry +; SSE41-NEXT: movntdqa (%rdi), %xmm0 +; SSE41-NEXT: retq ; ; AVX-LABEL: test_load_nt8xi16: ; AVX: # %bb.0: # %entry @@ -340,10 +360,20 @@ entry: } define <4 x i32> @test_load_nt4xi32(<4 x i32>* nocapture %ptr) { -; SSE-LABEL: test_load_nt4xi32: -; SSE: # %bb.0: # %entry -; SSE-NEXT: movntdqa (%rdi), %xmm0 -; SSE-NEXT: retq +; SSE2-LABEL: test_load_nt4xi32: +; SSE2: # %bb.0: # %entry +; SSE2-NEXT: movdqa (%rdi), %xmm0 +; SSE2-NEXT: retq +; +; SSE4A-LABEL: test_load_nt4xi32: +; SSE4A: # %bb.0: # %entry +; SSE4A-NEXT: movdqa (%rdi), %xmm0 +; SSE4A-NEXT: retq +; +; SSE41-LABEL: test_load_nt4xi32: +; SSE41: # %bb.0: # %entry +; SSE41-NEXT: movntdqa (%rdi), %xmm0 +; SSE41-NEXT: retq ; ; AVX-LABEL: test_load_nt4xi32: ; AVX: # %bb.0: # %entry @@ -360,10 +390,20 @@ entry: } define <2 x i64> @test_load_nt2xi64(<2 x i64>* nocapture %ptr) { -; SSE-LABEL: test_load_nt2xi64: -; SSE: # %bb.0: # %entry -; SSE-NEXT: movntdqa (%rdi), %xmm0 -; SSE-NEXT: retq +; SSE2-LABEL: test_load_nt2xi64: +; SSE2: # %bb.0: # %entry +; SSE2-NEXT: movdqa (%rdi), %xmm0 +; SSE2-NEXT: retq +; +; SSE4A-LABEL: test_load_nt2xi64: +; SSE4A: # %bb.0: # %entry +; SSE4A-NEXT: movdqa (%rdi), %xmm0 +; SSE4A-NEXT: retq +; +; SSE41-LABEL: test_load_nt2xi64: +; SSE41: # %bb.0: # %entry +; SSE41-NEXT: movntdqa (%rdi), %xmm0 +; SSE41-NEXT: retq ; ; AVX-LABEL: test_load_nt2xi64: ; AVX: # %bb.0: # %entry diff --git a/llvm/test/CodeGen/X86/fcmove.ll b/llvm/test/CodeGen/X86/fcmove.ll index 35dbb68117ba2..6bb014858d048 100644 --- a/llvm/test/CodeGen/X86/fcmove.ll +++ b/llvm/test/CodeGen/X86/fcmove.ll @@ -6,7 +6,7 @@ target triple = "x86_64-unknown-unknown" ; Test that we can generate an fcmove, and also that it passes verification. ; CHECK-LABEL: cmove_f -; CHECK: fcmove %st({{[0-7]}}), %st(0) +; CHECK: fcmove %st({{[0-7]}}), %st define x86_fp80 @cmove_f(x86_fp80 %a, x86_fp80 %b, i32 %c) { %test = icmp eq i32 %c, 0 %add = fadd x86_fp80 %a, %b diff --git a/llvm/test/CodeGen/X86/fmf-flags.ll b/llvm/test/CodeGen/X86/fmf-flags.ll index 4fb2040b338d9..bb883e92dc110 100644 --- a/llvm/test/CodeGen/X86/fmf-flags.ll +++ b/llvm/test/CodeGen/X86/fmf-flags.ll @@ -20,7 +20,7 @@ define float @fast_recip_sqrt(float %x) { ; X86-NEXT: flds {{[0-9]+}}(%esp) ; X86-NEXT: fsqrt ; X86-NEXT: fld1 -; X86-NEXT: fdivp %st(1) +; X86-NEXT: fdivp %st, %st(1) ; X86-NEXT: retl %y = call fast float @llvm.sqrt.f32(float %x) %z = fdiv fast float 1.0, %y @@ -95,7 +95,7 @@ define float @not_so_fast_recip_sqrt(float %x) { ; X86-NEXT: flds {{[0-9]+}}(%esp) ; X86-NEXT: fsqrt ; X86-NEXT: fld1 -; X86-NEXT: fdiv %st(1) +; X86-NEXT: fdiv %st(1), %st ; X86-NEXT: fxch %st(1) ; X86-NEXT: fstps sqrt1 ; X86-NEXT: retl diff --git a/llvm/test/CodeGen/X86/fp-cvt.ll b/llvm/test/CodeGen/X86/fp-cvt.ll index ab3d40ddcaa52..71738cb85d2e4 100644 --- a/llvm/test/CodeGen/X86/fp-cvt.ll +++ b/llvm/test/CodeGen/X86/fp-cvt.ll @@ -486,7 +486,7 @@ define i64 @fptoui_i64_fp80(x86_fp80 %a0) nounwind { ; X64-X87-NEXT: xorl %eax, %eax ; X64-X87-NEXT: fxch %st(1) ; X64-X87-NEXT: fucompi %st(2) -; X64-X87-NEXT: fcmovnbe %st(1), %st(0) +; X64-X87-NEXT: fcmovnbe %st(1), %st ; X64-X87-NEXT: fstp %st(1) ; X64-X87-NEXT: fnstcw -{{[0-9]+}}(%rsp) ; X64-X87-NEXT: movzwl -{{[0-9]+}}(%rsp), %ecx @@ -509,7 +509,7 @@ define i64 @fptoui_i64_fp80(x86_fp80 %a0) nounwind { ; X64-SSSE3-NEXT: xorl %eax, %eax ; X64-SSSE3-NEXT: fxch %st(1) ; X64-SSSE3-NEXT: fucompi %st(2) -; X64-SSSE3-NEXT: fcmovnbe %st(1), %st(0) +; X64-SSSE3-NEXT: fcmovnbe %st(1), %st ; X64-SSSE3-NEXT: fstp %st(1) ; X64-SSSE3-NEXT: fisttpll -{{[0-9]+}}(%rsp) ; X64-SSSE3-NEXT: setbe %al @@ -568,7 +568,7 @@ define i64 @fptoui_i64_fp80_ld(x86_fp80 *%a0) nounwind { ; X64-X87-NEXT: xorl %eax, %eax ; X64-X87-NEXT: fxch %st(1) ; X64-X87-NEXT: fucompi %st(2) -; X64-X87-NEXT: fcmovnbe %st(1), %st(0) +; X64-X87-NEXT: fcmovnbe %st(1), %st ; X64-X87-NEXT: fstp %st(1) ; X64-X87-NEXT: fnstcw -{{[0-9]+}}(%rsp) ; X64-X87-NEXT: movzwl -{{[0-9]+}}(%rsp), %ecx @@ -591,7 +591,7 @@ define i64 @fptoui_i64_fp80_ld(x86_fp80 *%a0) nounwind { ; X64-SSSE3-NEXT: xorl %eax, %eax ; X64-SSSE3-NEXT: fxch %st(1) ; X64-SSSE3-NEXT: fucompi %st(2) -; X64-SSSE3-NEXT: fcmovnbe %st(1), %st(0) +; X64-SSSE3-NEXT: fcmovnbe %st(1), %st ; X64-SSSE3-NEXT: fstp %st(1) ; X64-SSSE3-NEXT: fisttpll -{{[0-9]+}}(%rsp) ; X64-SSSE3-NEXT: setbe %al diff --git a/llvm/test/CodeGen/X86/inline-asm-default-clobbers.ll b/llvm/test/CodeGen/X86/inline-asm-default-clobbers.ll new file mode 100644 index 0000000000000..34a77ea5fecdb --- /dev/null +++ b/llvm/test/CodeGen/X86/inline-asm-default-clobbers.ll @@ -0,0 +1,8 @@ +; RUN: llc < %s -mtriple=i686 -stop-after=expand-isel-pseudos | FileCheck %s + +; CHECK: INLINEASM &"", 1, 12, implicit-def early-clobber $df, 12, implicit-def early-clobber $fpsw, 12, implicit-def early-clobber $eflags +define void @foo() { +entry: + call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"() + ret void +} diff --git a/llvm/test/CodeGen/X86/inline-asm-fpstack.ll b/llvm/test/CodeGen/X86/inline-asm-fpstack.ll index 1c36d31c480b5..db6127acb0ae7 100644 --- a/llvm/test/CodeGen/X86/inline-asm-fpstack.ll +++ b/llvm/test/CodeGen/X86/inline-asm-fpstack.ll @@ -75,20 +75,20 @@ define void @test6(double %A, double %B, double %C, double %D, double %E) nounwi ; CHECK-NEXT: fldl {{[0-9]+}}(%esp) ; CHECK-NEXT: fldl {{[0-9]+}}(%esp) ; CHECK-NEXT: ## InlineAsm Start -; CHECK-NEXT: foo %st(0) %st(0) +; CHECK-NEXT: foo %st %st ; CHECK-NEXT: ## InlineAsm End ; CHECK-NEXT: fstp %st(0) ; CHECK-NEXT: ## InlineAsm Start -; CHECK-NEXT: bar %st(1) %st(0) +; CHECK-NEXT: bar %st(1) %st ; CHECK-NEXT: ## InlineAsm End ; CHECK-NEXT: fstp %st(1) ; CHECK-NEXT: fstp %st(0) ; CHECK-NEXT: ## InlineAsm Start -; CHECK-NEXT: baz %st(1) %st(0) +; CHECK-NEXT: baz %st(1) %st ; CHECK-NEXT: ## InlineAsm End ; CHECK-NEXT: fstp %st(0) ; CHECK-NEXT: ## InlineAsm Start -; CHECK-NEXT: baz %st(0) +; CHECK-NEXT: baz %st ; CHECK-NEXT: ## InlineAsm End ; CHECK-NEXT: fstp %st(0) ; CHECK-NEXT: retl @@ -117,10 +117,10 @@ define void @testPR4185() { ; CHECK-NEXT: flds LCPI6_0 ; CHECK-NEXT: fld %st(0) ; CHECK-NEXT: ## InlineAsm Start -; CHECK-NEXT: fistpl %st(0) +; CHECK-NEXT: fistpl %st ; CHECK-NEXT: ## InlineAsm End ; CHECK-NEXT: ## InlineAsm Start -; CHECK-NEXT: fistpl %st(0) +; CHECK-NEXT: fistpl %st ; CHECK-NEXT: ## InlineAsm End ; CHECK-NEXT: retl return: @@ -138,10 +138,10 @@ define void @testPR4185b() { ; CHECK: ## %bb.0: ## %return ; CHECK-NEXT: flds LCPI7_0 ; CHECK-NEXT: ## InlineAsm Start -; CHECK-NEXT: fistl %st(0) +; CHECK-NEXT: fistl %st ; CHECK-NEXT: ## InlineAsm End ; CHECK-NEXT: ## InlineAsm Start -; CHECK-NEXT: fistpl %st(0) +; CHECK-NEXT: fistpl %st ; CHECK-NEXT: ## InlineAsm End ; CHECK-NEXT: retl return: @@ -163,7 +163,7 @@ define void @testPR4459(x86_fp80 %a) { ; CHECK-NEXT: fld %st(0) ; CHECK-NEXT: fxch %st(1) ; CHECK-NEXT: ## InlineAsm Start -; CHECK-NEXT: fistpl %st(0) +; CHECK-NEXT: fistpl %st ; CHECK-NEXT: ## InlineAsm End ; CHECK-NEXT: fstpt (%esp) ; CHECK-NEXT: calll _test3 @@ -191,7 +191,7 @@ define void @testPR4484(x86_fp80 %a) { ; CHECK-NEXT: calll _test1 ; CHECK-NEXT: fldt {{[0-9]+}}(%esp) ## 10-byte Folded Reload ; CHECK-NEXT: ## InlineAsm Start -; CHECK-NEXT: fistpl %st(0) +; CHECK-NEXT: fistpl %st ; CHECK-NEXT: ## InlineAsm End ; CHECK-NEXT: fstpt (%esp) ; CHECK-NEXT: calll _test3 @@ -211,18 +211,18 @@ define void @testPR4485(x86_fp80* %a) { ; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax ; CHECK-NEXT: fldt (%eax) ; CHECK-NEXT: flds LCPI10_0 -; CHECK-NEXT: fmul %st(0), %st(1) +; CHECK-NEXT: fmul %st, %st(1) ; CHECK-NEXT: flds LCPI10_1 -; CHECK-NEXT: fmul %st(0), %st(2) +; CHECK-NEXT: fmul %st, %st(2) ; CHECK-NEXT: fxch %st(2) ; CHECK-NEXT: ## InlineAsm Start -; CHECK-NEXT: fistpl %st(0) +; CHECK-NEXT: fistpl %st ; CHECK-NEXT: ## InlineAsm End ; CHECK-NEXT: fldt (%eax) -; CHECK-NEXT: fmulp %st(1) -; CHECK-NEXT: fmulp %st(1) +; CHECK-NEXT: fmulp %st, %st(1) +; CHECK-NEXT: fmulp %st, %st(1) ; CHECK-NEXT: ## InlineAsm Start -; CHECK-NEXT: fistpl %st(0) +; CHECK-NEXT: fistpl %st ; CHECK-NEXT: ## InlineAsm End ; CHECK-NEXT: retl entry: @@ -422,7 +422,7 @@ define i32 @PR10602() nounwind ssp { ; CHECK-NEXT: fld %st(0) ; CHECK-NEXT: fxch %st(1) ; CHECK-NEXT: ## InlineAsm Start -; CHECK-NEXT: fcomi %st(1), %st(0); pushf; pop %eax +; CHECK-NEXT: fcomi %st(1), %st; pushf; pop %eax ; CHECK-NEXT: ## InlineAsm End ; CHECK-NEXT: fstp %st(0) ; CHECK-NEXT: fstp %st(0) @@ -505,9 +505,9 @@ define double @test_operand_rewrite() { ; CHECK-LABEL: test_operand_rewrite: ; CHECK: ## %bb.0: ## %entry ; CHECK-NEXT: ## InlineAsm Start -; CHECK-NEXT: foo %st(0), %st(1) +; CHECK-NEXT: foo %st, %st(1) ; CHECK-NEXT: ## InlineAsm End -; CHECK-NEXT: fsubp %st(1) +; CHECK-NEXT: fsubp %st, %st(1) ; CHECK-NEXT: retl entry: %0 = tail call { double, double } asm sideeffect "foo $0, $1", "={st},={st(1)},~{dirflag},~{fpsr},~{flags}"() diff --git a/llvm/test/CodeGen/X86/insert-prefetch-inline.ll b/llvm/test/CodeGen/X86/insert-prefetch-inline.ll index 5f8373f9480c9..62c02fa33291d 100644 --- a/llvm/test/CodeGen/X86/insert-prefetch-inline.ll +++ b/llvm/test/CodeGen/X86/insert-prefetch-inline.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -prefetch-hints-file=%S/insert-prefetch-inline.afdo | FileCheck %s +; RUN: llc < %s -x86-discriminate-memops -prefetch-hints-file=%S/insert-prefetch-inline.afdo | FileCheck %s ; ; Verify we can insert prefetch instructions in code belonging to inlined ; functions. diff --git a/llvm/test/CodeGen/X86/insert-prefetch-invalid-instr.ll b/llvm/test/CodeGen/X86/insert-prefetch-invalid-instr.ll index 004fb56a56eb8..d0c4ac378b63b 100644 --- a/llvm/test/CodeGen/X86/insert-prefetch-invalid-instr.ll +++ b/llvm/test/CodeGen/X86/insert-prefetch-invalid-instr.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -prefetch-hints-file=%S/insert-prefetch-invalid-instr.afdo | FileCheck %s +; RUN: llc < %s -x86-discriminate-memops -prefetch-hints-file=%S/insert-prefetch-invalid-instr.afdo | FileCheck %s ; ModuleID = 'prefetch.cc' source_filename = "prefetch.cc" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/test/CodeGen/X86/insert-prefetch.ll b/llvm/test/CodeGen/X86/insert-prefetch.ll index 9e77772df7746..fe0fd9877f193 100644 --- a/llvm/test/CodeGen/X86/insert-prefetch.ll +++ b/llvm/test/CodeGen/X86/insert-prefetch.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -prefetch-hints-file=%S/insert-prefetch.afdo | FileCheck %s -; RUN: llc < %s -prefetch-hints-file=%S/insert-prefetch-other.afdo | FileCheck %s -check-prefix=OTHERS +; RUN: llc < %s -x86-discriminate-memops -prefetch-hints-file=%S/insert-prefetch.afdo | FileCheck %s +; RUN: llc < %s -x86-discriminate-memops -prefetch-hints-file=%S/insert-prefetch-other.afdo | FileCheck %s -check-prefix=OTHERS ; ; original source, compiled with -O3 -gmlt -fdebug-info-for-profiling: ; int sum(int* arr, int pos1, int pos2) { diff --git a/llvm/test/CodeGen/X86/ipra-reg-usage.ll b/llvm/test/CodeGen/X86/ipra-reg-usage.ll index 3e57ef2184426..2a557f2902a21 100644 --- a/llvm/test/CodeGen/X86/ipra-reg-usage.ll +++ b/llvm/test/CodeGen/X86/ipra-reg-usage.ll @@ -3,7 +3,7 @@ target triple = "x86_64-unknown-unknown" declare void @bar1() define preserve_allcc void @foo()#0 { -; CHECK: foo Clobbered Registers: $cs $df $ds $eflags $eip $eiz $es $fpsw $fs $gs $hip $ip $rip $riz $ss $ssp $bnd0 $bnd1 $bnd2 $bnd3 $cr0 $cr1 $cr2 $cr3 $cr4 $cr5 $cr6 $cr7 $cr8 $cr9 $cr10 $cr11 $cr12 $cr13 $cr14 $cr15 $dr0 $dr1 $dr2 $dr3 $dr4 $dr5 $dr6 $dr7 $dr8 $dr9 $dr10 $dr11 $dr12 $dr13 $dr14 $dr15 $fp0 $fp1 $fp2 $fp3 $fp4 $fp5 $fp6 $fp7 $k0 $k1 $k2 $k3 $k4 $k5 $k6 $k7 $mm0 $mm1 $mm2 $mm3 $mm4 $mm5 $mm6 $mm7 $r11 $st0 $st1 $st2 $st3 $st4 $st5 $st6 $st7 $xmm16 $xmm17 $xmm18 $xmm19 $xmm20 $xmm21 $xmm22 $xmm23 $xmm24 $xmm25 $xmm26 $xmm27 $xmm28 $xmm29 $xmm30 $xmm31 $ymm0 $ymm1 $ymm2 $ymm3 $ymm4 $ymm5 $ymm6 $ymm7 $ymm8 $ymm9 $ymm10 $ymm11 $ymm12 $ymm13 $ymm14 $ymm15 $ymm16 $ymm17 $ymm18 $ymm19 $ymm20 $ymm21 $ymm22 $ymm23 $ymm24 $ymm25 $ymm26 $ymm27 $ymm28 $ymm29 $ymm30 $ymm31 $zmm0 $zmm1 $zmm2 $zmm3 $zmm4 $zmm5 $zmm6 $zmm7 $zmm8 $zmm9 $zmm10 $zmm11 $zmm12 $zmm13 $zmm14 $zmm15 $zmm16 $zmm17 $zmm18 $zmm19 $zmm20 $zmm21 $zmm22 $zmm23 $zmm24 $zmm25 $zmm26 $zmm27 $zmm28 $zmm29 $zmm30 $zmm31 $r11b $r11bh $r11d $r11w $r11wh +; CHECK: foo Clobbered Registers: $cs $df $ds $eflags $eip $eiz $es $fpcw $fpsw $fs $gs $hip $ip $rip $riz $ss $ssp $bnd0 $bnd1 $bnd2 $bnd3 $cr0 $cr1 $cr2 $cr3 $cr4 $cr5 $cr6 $cr7 $cr8 $cr9 $cr10 $cr11 $cr12 $cr13 $cr14 $cr15 $dr0 $dr1 $dr2 $dr3 $dr4 $dr5 $dr6 $dr7 $dr8 $dr9 $dr10 $dr11 $dr12 $dr13 $dr14 $dr15 $fp0 $fp1 $fp2 $fp3 $fp4 $fp5 $fp6 $fp7 $k0 $k1 $k2 $k3 $k4 $k5 $k6 $k7 $mm0 $mm1 $mm2 $mm3 $mm4 $mm5 $mm6 $mm7 $r11 $st0 $st1 $st2 $st3 $st4 $st5 $st6 $st7 $xmm16 $xmm17 $xmm18 $xmm19 $xmm20 $xmm21 $xmm22 $xmm23 $xmm24 $xmm25 $xmm26 $xmm27 $xmm28 $xmm29 $xmm30 $xmm31 $ymm0 $ymm1 $ymm2 $ymm3 $ymm4 $ymm5 $ymm6 $ymm7 $ymm8 $ymm9 $ymm10 $ymm11 $ymm12 $ymm13 $ymm14 $ymm15 $ymm16 $ymm17 $ymm18 $ymm19 $ymm20 $ymm21 $ymm22 $ymm23 $ymm24 $ymm25 $ymm26 $ymm27 $ymm28 $ymm29 $ymm30 $ymm31 $zmm0 $zmm1 $zmm2 $zmm3 $zmm4 $zmm5 $zmm6 $zmm7 $zmm8 $zmm9 $zmm10 $zmm11 $zmm12 $zmm13 $zmm14 $zmm15 $zmm16 $zmm17 $zmm18 $zmm19 $zmm20 $zmm21 $zmm22 $zmm23 $zmm24 $zmm25 $zmm26 $zmm27 $zmm28 $zmm29 $zmm30 $zmm31 $r11b $r11bh $r11d $r11w $r11wh call void @bar1() call void @bar2() ret void diff --git a/llvm/test/CodeGen/X86/pr13577.ll b/llvm/test/CodeGen/X86/pr13577.ll index e0e90f81bc42c..3f9e2f953bae3 100644 --- a/llvm/test/CodeGen/X86/pr13577.ll +++ b/llvm/test/CodeGen/X86/pr13577.ll @@ -14,7 +14,7 @@ define x86_fp80 @foo(x86_fp80 %a) { ; CHECK-NEXT: testb $-128, -{{[0-9]+}}(%rsp) ; CHECK-NEXT: flds {{.*}}(%rip) ; CHECK-NEXT: flds {{.*}}(%rip) -; CHECK-NEXT: fcmovne %st(1), %st(0) +; CHECK-NEXT: fcmovne %st(1), %st ; CHECK-NEXT: fstp %st(1) ; CHECK-NEXT: retq %1 = tail call x86_fp80 @copysignl(x86_fp80 0xK7FFF8000000000000000, x86_fp80 %a) nounwind readnone diff --git a/llvm/test/CodeGen/X86/pr33349.ll b/llvm/test/CodeGen/X86/pr33349.ll index 63edae044f87c..9aa28384f4e81 100644 --- a/llvm/test/CodeGen/X86/pr33349.ll +++ b/llvm/test/CodeGen/X86/pr33349.ll @@ -19,18 +19,18 @@ target triple = "x86_64-unknown-linux-gnu" ; KNL-NEXT: fld1 ; KNL-NEXT: fldz ; KNL-NEXT: fld %st(0) -; KNL-NEXT: fcmovne %st(2), %st(0) +; KNL-NEXT: fcmovne %st(2), %st ; KNL-NEXT: testb $1, %cl ; KNL-NEXT: fld %st(1) -; KNL-NEXT: fcmovne %st(3), %st(0) +; KNL-NEXT: fcmovne %st(3), %st ; KNL-NEXT: kmovw %k2, %eax ; KNL-NEXT: testb $1, %al ; KNL-NEXT: fld %st(2) -; KNL-NEXT: fcmovne %st(4), %st(0) +; KNL-NEXT: fcmovne %st(4), %st ; KNL-NEXT: kmovw %k0, %eax ; KNL-NEXT: testb $1, %al ; KNL-NEXT: fxch %st(3) -; KNL-NEXT: fcmovne %st(4), %st(0) +; KNL-NEXT: fcmovne %st(4), %st ; KNL-NEXT: fstp %st(4) ; KNL-NEXT: fxch %st(3) ; KNL-NEXT: fstpt (%rdi) @@ -55,18 +55,18 @@ target triple = "x86_64-unknown-linux-gnu" ; SKX-NEXT: fld1 ; SKX-NEXT: fldz ; SKX-NEXT: fld %st(0) -; SKX-NEXT: fcmovne %st(2), %st(0) +; SKX-NEXT: fcmovne %st(2), %st ; SKX-NEXT: testb $1, %cl ; SKX-NEXT: fld %st(1) -; SKX-NEXT: fcmovne %st(3), %st(0) +; SKX-NEXT: fcmovne %st(3), %st ; SKX-NEXT: kmovd %k2, %eax ; SKX-NEXT: testb $1, %al ; SKX-NEXT: fld %st(2) -; SKX-NEXT: fcmovne %st(4), %st(0) +; SKX-NEXT: fcmovne %st(4), %st ; SKX-NEXT: kmovd %k0, %eax ; SKX-NEXT: testb $1, %al ; SKX-NEXT: fxch %st(3) -; SKX-NEXT: fcmovne %st(4), %st(0) +; SKX-NEXT: fcmovne %st(4), %st ; SKX-NEXT: fstp %st(4) ; SKX-NEXT: fxch %st(3) ; SKX-NEXT: fstpt (%rdi) diff --git a/llvm/test/CodeGen/X86/pr34080.ll b/llvm/test/CodeGen/X86/pr34080.ll index a709a4840e530..0b23ab7d4b5d7 100644 --- a/llvm/test/CodeGen/X86/pr34080.ll +++ b/llvm/test/CodeGen/X86/pr34080.ll @@ -27,7 +27,7 @@ define void @_Z1fe(x86_fp80 %z) local_unnamed_addr #0 { ; SSE2-NEXT: movsd %xmm0, -32(%rbp) ; SSE2-NEXT: fsubl -32(%rbp) ; SSE2-NEXT: flds {{.*}}(%rip) -; SSE2-NEXT: fmul %st(0), %st(1) +; SSE2-NEXT: fmul %st, %st(1) ; SSE2-NEXT: fnstcw -2(%rbp) ; SSE2-NEXT: movzwl -2(%rbp), %eax ; SSE2-NEXT: movw $3199, -2(%rbp) ## imm = 0xC7F @@ -41,7 +41,7 @@ define void @_Z1fe(x86_fp80 %z) local_unnamed_addr #0 { ; SSE2-NEXT: movsd %xmm0, -56(%rbp) ; SSE2-NEXT: movsd %xmm0, -24(%rbp) ; SSE2-NEXT: fsubl -24(%rbp) -; SSE2-NEXT: fmulp %st(1) +; SSE2-NEXT: fmulp %st, %st(1) ; SSE2-NEXT: fstpl -48(%rbp) ; SSE2-NEXT: popq %rbp ; SSE2-NEXT: retq @@ -65,12 +65,12 @@ define void @_Z1fe(x86_fp80 %z) local_unnamed_addr #0 { ; SSE2-SCHEDULE-NEXT: movsd %xmm0, -64(%rbp) ; SSE2-SCHEDULE-NEXT: movsd %xmm0, -32(%rbp) ; SSE2-SCHEDULE-NEXT: fsubl -32(%rbp) -; SSE2-SCHEDULE-NEXT: fnstcw -2(%rbp) ; SSE2-SCHEDULE-NEXT: flds {{.*}}(%rip) +; SSE2-SCHEDULE-NEXT: fnstcw -2(%rbp) +; SSE2-SCHEDULE-NEXT: fmul %st, %st(1) ; SSE2-SCHEDULE-NEXT: movzwl -2(%rbp), %eax ; SSE2-SCHEDULE-NEXT: movw $3199, -2(%rbp) ## imm = 0xC7F ; SSE2-SCHEDULE-NEXT: fldcw -2(%rbp) -; SSE2-SCHEDULE-NEXT: fmul %st(0), %st(1) ; SSE2-SCHEDULE-NEXT: movw %ax, -2(%rbp) ; SSE2-SCHEDULE-NEXT: fxch %st(1) ; SSE2-SCHEDULE-NEXT: fistl -12(%rbp) @@ -80,7 +80,7 @@ define void @_Z1fe(x86_fp80 %z) local_unnamed_addr #0 { ; SSE2-SCHEDULE-NEXT: movsd %xmm0, -56(%rbp) ; SSE2-SCHEDULE-NEXT: movsd %xmm0, -24(%rbp) ; SSE2-SCHEDULE-NEXT: fsubl -24(%rbp) -; SSE2-SCHEDULE-NEXT: fmulp %st(1) +; SSE2-SCHEDULE-NEXT: fmulp %st, %st(1) ; SSE2-SCHEDULE-NEXT: fstpl -48(%rbp) ; SSE2-SCHEDULE-NEXT: popq %rbp ; SSE2-SCHEDULE-NEXT: retq @@ -100,7 +100,7 @@ define void @_Z1fe(x86_fp80 %z) local_unnamed_addr #0 { ; SSE3-NEXT: movsd %xmm0, -24(%rbp) ; SSE3-NEXT: fsubl -24(%rbp) ; SSE3-NEXT: flds {{.*}}(%rip) -; SSE3-NEXT: fmul %st(0), %st(1) +; SSE3-NEXT: fmul %st, %st(1) ; SSE3-NEXT: fld %st(1) ; SSE3-NEXT: fisttpl -8(%rbp) ; SSE3-NEXT: xorps %xmm0, %xmm0 @@ -109,7 +109,7 @@ define void @_Z1fe(x86_fp80 %z) local_unnamed_addr #0 { ; SSE3-NEXT: movsd %xmm0, -16(%rbp) ; SSE3-NEXT: fxch %st(1) ; SSE3-NEXT: fsubl -16(%rbp) -; SSE3-NEXT: fmulp %st(1) +; SSE3-NEXT: fmulp %st, %st(1) ; SSE3-NEXT: fstpl -32(%rbp) ; SSE3-NEXT: popq %rbp ; SSE3-NEXT: retq @@ -129,7 +129,7 @@ define void @_Z1fe(x86_fp80 %z) local_unnamed_addr #0 { ; AVX-NEXT: vmovsd %xmm0, -24(%rbp) ; AVX-NEXT: fsubl -24(%rbp) ; AVX-NEXT: flds {{.*}}(%rip) -; AVX-NEXT: fmul %st(0), %st(1) +; AVX-NEXT: fmul %st, %st(1) ; AVX-NEXT: fld %st(1) ; AVX-NEXT: fisttpl -8(%rbp) ; AVX-NEXT: vcvtsi2sdl -8(%rbp), %xmm1, %xmm0 @@ -137,7 +137,7 @@ define void @_Z1fe(x86_fp80 %z) local_unnamed_addr #0 { ; AVX-NEXT: vmovsd %xmm0, -16(%rbp) ; AVX-NEXT: fxch %st(1) ; AVX-NEXT: fsubl -16(%rbp) -; AVX-NEXT: fmulp %st(1) +; AVX-NEXT: fmulp %st, %st(1) ; AVX-NEXT: fstpl -32(%rbp) ; AVX-NEXT: popq %rbp ; AVX-NEXT: retq diff --git a/llvm/test/CodeGen/X86/pr34177.ll b/llvm/test/CodeGen/X86/pr34177.ll index 3fe56277fb4b3..f6b8dec3c3b39 100644 --- a/llvm/test/CodeGen/X86/pr34177.ll +++ b/llvm/test/CodeGen/X86/pr34177.ll @@ -20,17 +20,17 @@ define void @test(<4x i64> %a, <4 x x86_fp80> %b, <8 x x86_fp80>* %c) local_unna ; CHECK-NEXT: fld1 ; CHECK-NEXT: fldz ; CHECK-NEXT: fld %st(0) -; CHECK-NEXT: fcmove %st(2), %st(0) +; CHECK-NEXT: fcmove %st(2), %st ; CHECK-NEXT: cmpq %rax, %rsi ; CHECK-NEXT: fld %st(1) -; CHECK-NEXT: fcmove %st(3), %st(0) +; CHECK-NEXT: fcmove %st(3), %st ; CHECK-NEXT: cmpq %rdx, %r9 ; CHECK-NEXT: fld %st(2) -; CHECK-NEXT: fcmove %st(4), %st(0) +; CHECK-NEXT: fcmove %st(4), %st ; CHECK-NEXT: movl $1, %eax ; CHECK-NEXT: cmpq %r8, %rax ; CHECK-NEXT: fxch %st(3) -; CHECK-NEXT: fcmove %st(4), %st(0) +; CHECK-NEXT: fcmove %st(4), %st ; CHECK-NEXT: fstp %st(4) ; CHECK-NEXT: fldt {{[0-9]+}}(%rsp) ; CHECK-NEXT: fstpt 70(%rdi) @@ -40,15 +40,15 @@ define void @test(<4x i64> %a, <4 x x86_fp80> %b, <8 x x86_fp80>* %c) local_unna ; CHECK-NEXT: fstpt 30(%rdi) ; CHECK-NEXT: fldt {{[0-9]+}}(%rsp) ; CHECK-NEXT: fstpt 10(%rdi) -; CHECK-NEXT: fadd %st(0), %st(0) +; CHECK-NEXT: fadd %st, %st(0) ; CHECK-NEXT: fstpt 60(%rdi) ; CHECK-NEXT: fxch %st(1) -; CHECK-NEXT: fadd %st(0), %st(0) +; CHECK-NEXT: fadd %st, %st(0) ; CHECK-NEXT: fstpt 40(%rdi) ; CHECK-NEXT: fxch %st(1) -; CHECK-NEXT: fadd %st(0), %st(0) +; CHECK-NEXT: fadd %st, %st(0) ; CHECK-NEXT: fstpt 20(%rdi) -; CHECK-NEXT: fadd %st(0), %st(0) +; CHECK-NEXT: fadd %st, %st(0) ; CHECK-NEXT: fstpt (%rdi) %1 = icmp eq <4 x i64> , %a %2 = select <4 x i1> %1, <4 x x86_fp80> , <4 x x86_fp80> zeroinitializer diff --git a/llvm/test/CodeGen/X86/pr40529.ll b/llvm/test/CodeGen/X86/pr40529.ll new file mode 100644 index 0000000000000..9520ac22d7491 --- /dev/null +++ b/llvm/test/CodeGen/X86/pr40529.ll @@ -0,0 +1,43 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-linux -mcpu=x86-64 | FileCheck %s + +define x86_fp80 @rem_pio2l_min(x86_fp80 %z) { +; CHECK-LABEL: rem_pio2l_min: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; CHECK-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; CHECK-NEXT: movw $3199, -{{[0-9]+}}(%rsp) # imm = 0xC7F +; CHECK-NEXT: fldcw -{{[0-9]+}}(%rsp) +; CHECK-NEXT: fldt {{[0-9]+}}(%rsp) +; CHECK-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; CHECK-NEXT: fistl -{{[0-9]+}}(%rsp) +; CHECK-NEXT: fldcw -{{[0-9]+}}(%rsp) +; CHECK-NEXT: movl -{{[0-9]+}}(%rsp), %eax +; CHECK-NEXT: movl %eax, -{{[0-9]+}}(%rsp) +; CHECK-NEXT: fisubl -{{[0-9]+}}(%rsp) +; CHECK-NEXT: flds {{.*}}(%rip) +; CHECK-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; CHECK-NEXT: fmul %st, %st(1) +; CHECK-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; CHECK-NEXT: movw $3199, -{{[0-9]+}}(%rsp) # imm = 0xC7F +; CHECK-NEXT: fldcw -{{[0-9]+}}(%rsp) +; CHECK-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; CHECK-NEXT: fxch %st(1) +; CHECK-NEXT: fistl -{{[0-9]+}}(%rsp) +; CHECK-NEXT: fldcw -{{[0-9]+}}(%rsp) +; CHECK-NEXT: movl -{{[0-9]+}}(%rsp), %eax +; CHECK-NEXT: movl %eax, -{{[0-9]+}}(%rsp) +; CHECK-NEXT: fisubl -{{[0-9]+}}(%rsp) +; CHECK-NEXT: fmulp %st, %st(1) +; CHECK-NEXT: retq +entry: + %conv = fptosi x86_fp80 %z to i32 + %conv1 = sitofp i32 %conv to x86_fp80 + %sub = fsub x86_fp80 %z, %conv1 + %mul = fmul x86_fp80 %sub, 0xK40178000000000000000 + %conv2 = fptosi x86_fp80 %mul to i32 + %conv3 = sitofp i32 %conv2 to x86_fp80 + %sub4 = fsub x86_fp80 %mul, %conv3 + %mul5 = fmul x86_fp80 %sub4, 0xK40178000000000000000 + ret x86_fp80 %mul5 +} diff --git a/llvm/test/CodeGen/X86/pr40730.ll b/llvm/test/CodeGen/X86/pr40730.ll new file mode 100644 index 0000000000000..12b372dea33bb --- /dev/null +++ b/llvm/test/CodeGen/X86/pr40730.ll @@ -0,0 +1,36 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s + +define <8 x i32> @shuffle_v8i32_0dcd3f14(<8 x i32> %a, <8 x i32> %b) { +; CHECK-LABEL: shuffle_v8i32_0dcd3f14: +; CHECK: # %bb.0: +; CHECK-NEXT: vextractf128 $1, %ymm0, %xmm2 +; CHECK-NEXT: vblendps {{.*#+}} xmm2 = xmm2[0],xmm0[1,2,3] +; CHECK-NEXT: vpermilps {{.*#+}} xmm2 = xmm2[3,1,1,0] +; CHECK-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; CHECK-NEXT: vperm2f128 {{.*#+}} ymm1 = ymm1[2,3,2,3] +; CHECK-NEXT: vpermilpd {{.*#+}} ymm1 = ymm1[0,0,3,2] +; CHECK-NEXT: vblendps {{.*#+}} ymm0 = ymm0[0],ymm1[1,2,3],ymm0[4],ymm1[5],ymm0[6,7] +; CHECK-NEXT: retq + %shuffle = shufflevector <8 x i32> %a, <8 x i32> %b, <8 x i32> + ret <8 x i32> %shuffle +} + +; CHECK: .LCPI1_0: +; CHECK-NEXT: .quad 60129542157 +; CHECK-NEXT: .quad 60129542157 +; CHECK-NEXT: .quad 68719476736 +; CHECK-NEXT: .quad 60129542157 + +define <8 x i32> @shuffle_v8i32_0dcd3f14_constant(<8 x i32> %a0) { +; CHECK-LABEL: shuffle_v8i32_0dcd3f14_constant: +; CHECK: # %bb.0: +; CHECK-NEXT: vextractf128 $1, %ymm0, %xmm1 +; CHECK-NEXT: vblendps {{.*#+}} xmm1 = xmm1[0],xmm0[1,2,3] +; CHECK-NEXT: vpermilps {{.*#+}} xmm1 = xmm1[3,1,1,0] +; CHECK-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; CHECK-NEXT: vblendps {{.*#+}} ymm0 = ymm0[0],mem[1,2,3],ymm0[4],mem[5],ymm0[6,7] +; CHECK-NEXT: retq + %res = shufflevector <8 x i32> %a0, <8 x i32> , <8 x i32> + ret <8 x i32> %res +} diff --git a/llvm/test/CodeGen/X86/pr40891.ll b/llvm/test/CodeGen/X86/pr40891.ll new file mode 100644 index 0000000000000..3f3cfb23d03d9 --- /dev/null +++ b/llvm/test/CodeGen/X86/pr40891.ll @@ -0,0 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=avx2 | FileCheck %s + +; Make sure this sequence doesn't hang in DAG combine. + +define <8 x i32> @foo(<8 x i64> %x, <4 x i64> %y) { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: +; CHECK-NEXT: vandps %ymm2, %ymm0, %ymm0 +; CHECK-NEXT: vandps {{\.LCPI.*}}, %ymm1, %ymm1 +; CHECK-NEXT: vpermilps {{.*#+}} ymm0 = ymm0[0,2,2,3,4,6,6,7] +; CHECK-NEXT: vpermpd {{.*#+}} ymm0 = ymm0[0,2,2,3] +; CHECK-NEXT: vpermilps {{.*#+}} ymm1 = ymm1[0,2,2,3,4,6,6,7] +; CHECK-NEXT: vpermpd {{.*#+}} ymm1 = ymm1[0,2,2,3] +; CHECK-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; CHECK-NEXT: retl + %a = shufflevector <4 x i64> %y, <4 x i64> , <8 x i32> + %b = and <8 x i64> %x, %a + %c = trunc <8 x i64> %b to <8 x i32> + ret <8 x i32> %c +} + diff --git a/llvm/test/CodeGen/X86/regalloc-copy-hints.mir b/llvm/test/CodeGen/X86/regalloc-copy-hints.mir new file mode 100644 index 0000000000000..6287066e64fe0 --- /dev/null +++ b/llvm/test/CodeGen/X86/regalloc-copy-hints.mir @@ -0,0 +1,805 @@ +# RUN: llc -mtriple=i386-unknown-unknown -mcpu=i486 %s -o - -run-pass greedy \ +# RUN: -debug-only=regalloc 2>&1 | FileCheck %s +# REQUIRES: asserts + +--- | + %0 = type { %1 } + %1 = type { %2, %23, %23*, %27*, %28*, %29, %33*, %34, %42, i8, i32, i32, i32 } + %2 = type { %3, %6, %14, %14, i8, i8*, i8*, %16 } + %3 = type { i32 (...)**, %4*, %5* } + %4 = type { i32 (...)**, %3* } + %5 = type { i32 (...)** } + %6 = type { %7 } + %7 = type { %8, i32, %12 } + %8 = type { %9**, %9**, %9**, %10 } + %9 = type { i32, i32, i32, i8* } + %10 = type { %11 } + %11 = type { %9** } + %12 = type { %13 } + %13 = type { i32 } + %14 = type { i32, %15* } + %15 = type { i32, i32, i8* } + %16 = type { %17 } + %17 = type { %18*, %20, %22 } + %18 = type { %19* } + %19 = type <{ %18, %19*, %18*, i8, [3 x i8] }> + %20 = type { %21 } + %21 = type { %18 } + %22 = type { %13 } + %23 = type { %24 } + %24 = type { %18*, %25, %26 } + %25 = type { %21 } + %26 = type { %13 } + %27 = type { i32 (...)** } + %28 = type { i32 (...)** } + %29 = type { %30 } + %30 = type { %18*, %31, %32 } + %31 = type { %21 } + %32 = type { %13 } + %33 = type { i32 (...)** } + %34 = type { %35 } + %35 = type { %36 } + %36 = type { %37, i32, %41 } + %37 = type { %38**, %38**, %38**, %39 } + %38 = type { %42, i32 } + %39 = type { %40 } + %40 = type { %38** } + %41 = type { %13 } + %42 = type { %43 } + %43 = type { %18*, %44, %45 } + %44 = type { %21 } + %45 = type { %13 } + %46 = type { %47, %48 } + %47 = type <{ %18, %19*, %18*, i8 }> + %48 = type { %49 } + %49 = type { i32, %50 } + %50 = type { { i32, i32 }, { i32, i32 }, { i32, i32 }, { i32, i32 }, { i32, i32 }, { i32, i32 } } + + define void @fun(%0* %arg) local_unnamed_addr #0 align 2 personality i32 (...)* @__gxx_personality_v0 { + bb: + %tmp = getelementptr inbounds %0, %0* %arg, i32 0, i32 0, i32 1 + %tmp1 = getelementptr inbounds %0, %0* %arg, i32 0, i32 0, i32 1, i32 0, i32 1, i32 0, i32 0 + br i1 undef, label %bb5, label %bb6 + + bb5: ; preds = %bb + unreachable + + bb6: ; preds = %bb + %tmp8 = getelementptr inbounds %0, %0* %arg, i32 0, i32 0, i32 8, i32 0, i32 1, i32 0, i32 0 + br i1 undef, label %bb10, label %bb9 + + bb9: ; preds = %bb6 + unreachable + + bb10: ; preds = %bb6 + store %18* %tmp8, %18** undef + br i1 undef, label %bb14, label %bb13 + + bb13: ; preds = %bb10 + unreachable + + bb14: ; preds = %bb10 + br i1 undef, label %bb17, label %bb18 + + bb17: ; preds = %bb14 + unreachable + + bb18: ; preds = %bb14 + br i1 undef, label %bb20, label %bb19 + + bb19: ; preds = %bb18 + unreachable + + bb20: ; preds = %bb18 + br i1 undef, label %bb25, label %bb24 + + bb24: ; preds = %bb20 + unreachable + + bb25: ; preds = %bb20 + br i1 undef, label %bb29, label %bb30 + + bb29: ; preds = %bb25 + unreachable + + bb30: ; preds = %bb25 + br i1 undef, label %bb38, label %bb31 + + bb31: ; preds = %bb30 + %tmp32 = getelementptr inbounds %0, %0* %arg, i32 0, i32 0, i32 1, i32 0, i32 1, i32 0, i32 0, i32 0 + br i1 undef, label %bb34, label %bb35 + + bb34: ; preds = %bb31 + unreachable + + bb35: ; preds = %bb31 + br i1 undef, label %bb40, label %bb36 + + bb36: ; preds = %bb35 + unreachable + + bb38: ; preds = %bb30 + %tmp391 = bitcast %18* %tmp1 to %19** + br label %bb40 + + bb40: ; preds = %bb35, %bb38 + %tmp41 = phi %18* [ %tmp1, %bb38 ], [ null, %bb35 ] + %tmp42 = phi %19** [ %tmp391, %bb38 ], [ %tmp32, %bb35 ] + br i1 undef, label %bb43, label %bb48 + + bb43: ; preds = %bb40 + %tmp44 = tail call i8* @_Znwj() + store %18* %tmp41, %18** undef + %tmp46 = bitcast %19** %tmp42 to i8** + store i8* %tmp44, i8** %tmp46 + %0 = bitcast i8* %tmp44 to %46* + tail call void @_ZNSt3__127__tree_balance_after_insertIPNS_16__tree_node_baseIPvEEEEvT_S5_() + br label %bb48 + + bb48: ; preds = %bb43, %bb40 + %tmp49 = phi %46* [ %0, %bb43 ], [ undef, %bb40 ] + %tmp50 = getelementptr inbounds %46, %46* %tmp49, i32 0, i32 1, i32 0, i32 1, i32 4, i32 0 + store i32 ptrtoint (i1 (%0*)* @_ZN15COLLADASaxFWL1429ColladaParserAutoGen14Private15_preEnd__authorEv to i32), i32* %tmp50 + br i1 undef, label %bb52, label %bb53 + + bb52: ; preds = %bb48 + unreachable + + bb53: ; preds = %bb48 + br i1 undef, label %bb55, label %bb54 + + bb54: ; preds = %bb53 + unreachable + + bb55: ; preds = %bb53 + br i1 undef, label %bb59, label %bb58 + + bb58: ; preds = %bb55 + unreachable + + bb59: ; preds = %bb55 + br i1 undef, label %bb62, label %bb61 + + bb61: ; preds = %bb59 + unreachable + + bb62: ; preds = %bb59 + br i1 undef, label %bb64, label %bb65 + + bb64: ; preds = %bb62 + unreachable + + bb65: ; preds = %bb62 + %tmp66 = icmp eq %46* null, null + br i1 %tmp66, label %bb72, label %bb67 + + bb67: ; preds = %bb65 + %tmp68 = getelementptr inbounds %0, %0* %arg, i32 0, i32 0, i32 1, i32 0, i32 1, i32 0, i32 0, i32 0 + br i1 undef, label %bb70, label %bb74 + + bb70: ; preds = %bb67 + unreachable + + bb72: ; preds = %bb65 + %tmp732 = bitcast %18* %tmp1 to %19** + br label %bb74 + + bb74: ; preds = %bb67, %bb72 + %tmp75 = phi %18* [ %tmp1, %bb72 ], [ null, %bb67 ] + %tmp76 = phi %19** [ %tmp732, %bb72 ], [ %tmp68, %bb67 ] + %tmp77 = tail call i8* @_Znwj() + store %18* %tmp75, %18** undef + %tmp79 = bitcast %19** %tmp76 to i8** + store i8* %tmp77, i8** %tmp79 + %1 = bitcast i8* %tmp77 to %46* + tail call void @_ZNSt3__127__tree_balance_after_insertIPNS_16__tree_node_baseIPvEEEEvT_S5_() + %tmp81 = getelementptr inbounds %46, %46* %1, i32 0, i32 1, i32 0, i32 1, i32 2, i32 0 + store i32 ptrtoint (i1 (%0*)* @_ZN15COLLADASaxFWL1429ColladaParserAutoGen14Private14_end__commentsEv to i32), i32* %tmp81 + store %18* %tmp8, %18** undef + %2 = bitcast %0* %arg to i8* + %sunkaddr = getelementptr i8, i8* %2, i32 140 + %3 = bitcast i8* %sunkaddr to %18** + %tmp85 = load %18*, %18** %3 + %tmp864 = bitcast %18* %tmp85 to %19** + %tmp87 = load %19*, %19** %tmp864 + %tmp88 = icmp eq %19* %tmp87, null + br i1 %tmp88, label %bb90, label %bb89 + + bb89: ; preds = %bb74 + unreachable + + bb90: ; preds = %bb74 + br i1 undef, label %bb94, label %bb92 + + bb92: ; preds = %bb90 + br i1 undef, label %bb96, label %bb97 + + bb94: ; preds = %bb90 + unreachable + + bb96: ; preds = %bb92 + unreachable + + bb97: ; preds = %bb92 + br i1 undef, label %bb101, label %bb102 + + bb101: ; preds = %bb97 + unreachable + + bb102: ; preds = %bb97 + br i1 undef, label %bb104, label %bb103 + + bb103: ; preds = %bb102 + unreachable + + bb104: ; preds = %bb102 + br i1 undef, label %bb109, label %bb108 + + bb108: ; preds = %bb104 + unreachable + + bb109: ; preds = %bb104 + br i1 undef, label %bb111, label %bb112 + + bb111: ; preds = %bb109 + unreachable + + bb112: ; preds = %bb109 + br i1 undef, label %bb118, label %bb117 + + bb117: ; preds = %bb112 + unreachable + + bb118: ; preds = %bb112 + br i1 undef, label %bb120, label %bb121 + + bb120: ; preds = %bb118 + unreachable + + bb121: ; preds = %bb118 + br i1 undef, label %bb124, label %bb125 + + bb124: ; preds = %bb121 + unreachable + + bb125: ; preds = %bb121 + %4 = bitcast %18* %tmp1 to %46** + %tmp126 = load %46*, %46** %4 + %tmp127 = icmp eq %46* %tmp126, null + br i1 %tmp127, label %bb135, label %bb128 + + bb128: ; preds = %bb125 + br label %bb129 + + bb129: ; preds = %bb131, %bb128 + %tmp130 = icmp ugt i32 undef, 95406324 + br i1 %tmp130, label %bb131, label %bb133 + + bb131: ; preds = %bb129 + br label %bb129 + + bb133: ; preds = %bb129 + unreachable + + bb135: ; preds = %bb125 + br i1 undef, label %bb137, label %bb138 + + bb137: ; preds = %bb135 + unreachable + + bb138: ; preds = %bb135 + unreachable + } + + declare zeroext i1 @_ZN15COLLADASaxFWL1429ColladaParserAutoGen14Private15_preEnd__authorEv(%0*) #0 + + declare zeroext i1 @_ZN15COLLADASaxFWL1429ColladaParserAutoGen14Private14_end__commentsEv(%0*) #0 align 2 + + declare i32 @__gxx_personality_v0(...) #0 + + declare noalias nonnull i8* @_Znwj() local_unnamed_addr #0 + + declare void @_ZNSt3__127__tree_balance_after_insertIPNS_16__tree_node_baseIPvEEEEvT_S5_() local_unnamed_addr #0 + + ; Function Attrs: nounwind + declare void @llvm.stackprotector(i8*, i8**) #1 + + attributes #0 = { "target-cpu"="i486" } + attributes #1 = { nounwind } + +... +--- +# A physreg should always only be hinted once per getRegAllocationHints() query. +# CHECK: hints: $ebx $edi +# CHECK-NOT: hints: $ebx $edi $ebx $edi +name: fun +alignment: 4 +tracksRegLiveness: true +registers: + - { id: 0, class: gr32 } + - { id: 1, class: gr32 } + - { id: 2, class: gr32 } + - { id: 3, class: gr32 } + - { id: 4, class: gr32 } + - { id: 5, class: gr32 } + - { id: 6, class: gr32 } + - { id: 7, class: gr32 } + - { id: 8, class: gr32 } + - { id: 9, class: gr32 } + - { id: 10, class: gr32 } + - { id: 11, class: gr32 } + - { id: 12, class: gr32 } + - { id: 13, class: gr32_abcd } + - { id: 14, class: gr8 } + - { id: 15, class: gr32_abcd } + - { id: 16, class: gr8 } + - { id: 17, class: gr32 } + - { id: 18, class: gr32_abcd } + - { id: 19, class: gr8 } + - { id: 20, class: gr32_abcd } + - { id: 21, class: gr8 } + - { id: 22, class: gr32_abcd } + - { id: 23, class: gr8 } + - { id: 24, class: gr32_abcd } + - { id: 25, class: gr8 } + - { id: 26, class: gr32_abcd } + - { id: 27, class: gr8 } + - { id: 28, class: gr32_abcd } + - { id: 29, class: gr8 } + - { id: 30, class: gr32_abcd } + - { id: 31, class: gr8 } + - { id: 32, class: gr32_abcd } + - { id: 33, class: gr8 } + - { id: 34, class: gr32 } + - { id: 35, class: gr32_abcd } + - { id: 36, class: gr8 } + - { id: 37, class: gr32 } + - { id: 38, class: gr32 } + - { id: 39, class: gr32_abcd } + - { id: 40, class: gr8 } + - { id: 41, class: gr32_abcd } + - { id: 42, class: gr8 } + - { id: 43, class: gr32_abcd } + - { id: 44, class: gr8 } + - { id: 45, class: gr32_abcd } + - { id: 46, class: gr8 } + - { id: 47, class: gr32_abcd } + - { id: 48, class: gr8 } + - { id: 49, class: gr8 } + - { id: 50, class: gr32_abcd } + - { id: 51, class: gr8 } + - { id: 52, class: gr32 } + - { id: 53, class: gr32 } + - { id: 54, class: gr32 } + - { id: 55, class: gr32 } + - { id: 56, class: gr32_abcd } + - { id: 57, class: gr8 } + - { id: 58, class: gr32_abcd } + - { id: 59, class: gr8 } + - { id: 60, class: gr32_abcd } + - { id: 61, class: gr8 } + - { id: 62, class: gr32_abcd } + - { id: 63, class: gr8 } + - { id: 64, class: gr32_abcd } + - { id: 65, class: gr8 } + - { id: 66, class: gr32_abcd } + - { id: 67, class: gr8 } + - { id: 68, class: gr32_abcd } + - { id: 69, class: gr8 } + - { id: 70, class: gr32_abcd } + - { id: 71, class: gr8 } + - { id: 72, class: gr32_abcd } + - { id: 73, class: gr8 } + - { id: 74, class: gr32 } + - { id: 75, class: gr32 } + - { id: 76, class: gr32_abcd } + - { id: 77, class: gr8 } + - { id: 78, class: gr32_abcd } + - { id: 79, class: gr32 } + - { id: 80, class: gr32 } + - { id: 81, class: gr32_abcd } + - { id: 82, class: gr32 } +frameInfo: + maxAlignment: 4 + hasCalls: true +fixedStack: + - { id: 0, size: 4, alignment: 4, stack-id: 0, isImmutable: true } +body: | + bb.0.bb: + successors: %bb.1(0x00000001), %bb.2(0x7fffffff) + + %13:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %13.sub_8bit, %13.sub_8bit, implicit-def $eflags + JNE_1 %bb.2, implicit killed $eflags + JMP_1 %bb.1 + + bb.1.bb5: + successors: + + + bb.2.bb6: + successors: %bb.4(0x7fffffff), %bb.3(0x00000001) + + %15:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %15.sub_8bit, %15.sub_8bit, implicit-def $eflags + JNE_1 %bb.4, implicit killed $eflags + JMP_1 %bb.3 + + bb.3.bb9: + successors: + + + bb.4.bb10: + successors: %bb.6(0x7fffffff), %bb.5(0x00000001) + + %12:gr32 = MOV32rm %fixed-stack.0, 1, $noreg, 0, $noreg :: (load 4 from %fixed-stack.0) + %1:gr32 = LEA32r %12, 1, $noreg, 144, $noreg + MOV32mr undef %17:gr32, 1, $noreg, 0, $noreg, %1 :: (store 4 into `%18** undef`) + %18:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %18.sub_8bit, %18.sub_8bit, implicit-def $eflags + JNE_1 %bb.6, implicit killed $eflags + JMP_1 %bb.5 + + bb.5.bb13: + successors: + + + bb.6.bb14: + successors: %bb.7(0x00000001), %bb.8(0x7fffffff) + + %20:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %20.sub_8bit, %20.sub_8bit, implicit-def $eflags + JNE_1 %bb.8, implicit killed $eflags + JMP_1 %bb.7 + + bb.7.bb17: + successors: + + + bb.8.bb18: + successors: %bb.10(0x7fffffff), %bb.9(0x00000001) + + %22:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %22.sub_8bit, %22.sub_8bit, implicit-def $eflags + JNE_1 %bb.10, implicit killed $eflags + JMP_1 %bb.9 + + bb.9.bb19: + successors: + + + bb.10.bb20: + successors: %bb.12(0x7fffffff), %bb.11(0x00000001) + + %24:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %24.sub_8bit, %24.sub_8bit, implicit-def $eflags + JNE_1 %bb.12, implicit killed $eflags + JMP_1 %bb.11 + + bb.11.bb24: + successors: + + + bb.12.bb25: + successors: %bb.13(0x00000001), %bb.14(0x7fffffff) + + %26:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %26.sub_8bit, %26.sub_8bit, implicit-def $eflags + JNE_1 %bb.14, implicit killed $eflags + JMP_1 %bb.13 + + bb.13.bb29: + successors: + + + bb.14.bb30: + %0:gr32 = LEA32r %12, 1, $noreg, 80, $noreg + %28:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %28.sub_8bit, %28.sub_8bit, implicit-def $eflags + JNE_1 %bb.20, implicit killed $eflags + JMP_1 %bb.15 + + bb.15.bb31: + successors: %bb.16(0x00000001), %bb.17(0x7fffffff) + + %78:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %78.sub_8bit, %78.sub_8bit, implicit-def $eflags + JNE_1 %bb.17, implicit killed $eflags + JMP_1 %bb.16 + + bb.16.bb34: + successors: + + + bb.17.bb35: + successors: %bb.18(0x7fffffff), %bb.19(0x00000001) + + TEST8rr %78.sub_8bit, %78.sub_8bit, implicit-def $eflags + JE_1 %bb.19, implicit killed $eflags + + bb.18: + %79:gr32 = LEA32r %12, 1, $noreg, 80, $noreg + JMP_1 %bb.21 + + bb.19.bb36: + successors: + + + bb.20.bb38: + %78:gr32_abcd = COPY %0 + %79:gr32 = COPY %0 + + bb.21.bb40: + successors: %bb.22, %bb.23 + + %35:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %35.sub_8bit, %35.sub_8bit, implicit-def $eflags + %80:gr32 = IMPLICIT_DEF + JNE_1 %bb.23, implicit killed $eflags + JMP_1 %bb.22 + + bb.22.bb43: + ADJCALLSTACKDOWN32 0, 0, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp + CALLpcrel32 @_Znwj, csr_32, implicit $esp, implicit $ssp, implicit-def $esp, implicit-def $ssp, implicit-def $eax + ADJCALLSTACKUP32 0, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp + %80:gr32 = COPY killed $eax + MOV32mr undef %38:gr32, 1, $noreg, 0, $noreg, %78 :: (store 4 into `%18** undef`) + MOV32mr %79, 1, $noreg, 0, $noreg, %80 :: (store 4 into %ir.tmp46) + ADJCALLSTACKDOWN32 0, 0, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp + CALLpcrel32 @_ZNSt3__127__tree_balance_after_insertIPNS_16__tree_node_baseIPvEEEEvT_S5_, csr_32, implicit $esp, implicit $ssp, implicit-def $esp, implicit-def $ssp + ADJCALLSTACKUP32 0, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp + + bb.23.bb48: + successors: %bb.24(0x00000001), %bb.25(0x7fffffff) + + MOV32mi %80, 1, $noreg, 52, $noreg, @_ZN15COLLADASaxFWL1429ColladaParserAutoGen14Private15_preEnd__authorEv :: (store 4 into %ir.tmp50) + %39:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %39.sub_8bit, %39.sub_8bit, implicit-def $eflags + JNE_1 %bb.25, implicit killed $eflags + JMP_1 %bb.24 + + bb.24.bb52: + successors: + + + bb.25.bb53: + successors: %bb.27(0x7fffffff), %bb.26(0x00000001) + + %41:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %41.sub_8bit, %41.sub_8bit, implicit-def $eflags + JNE_1 %bb.27, implicit killed $eflags + JMP_1 %bb.26 + + bb.26.bb54: + successors: + + + bb.27.bb55: + successors: %bb.29(0x7fffffff), %bb.28(0x00000001) + + %43:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %43.sub_8bit, %43.sub_8bit, implicit-def $eflags + JNE_1 %bb.29, implicit killed $eflags + JMP_1 %bb.28 + + bb.28.bb58: + successors: + + + bb.29.bb59: + successors: %bb.31(0x7fffffff), %bb.30(0x00000001) + + %45:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %45.sub_8bit, %45.sub_8bit, implicit-def $eflags + JNE_1 %bb.31, implicit killed $eflags + JMP_1 %bb.30 + + bb.30.bb61: + successors: + + + bb.31.bb62: + successors: %bb.32(0x00000001), %bb.33(0x7fffffff) + + %47:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %47.sub_8bit, %47.sub_8bit, implicit-def $eflags + JNE_1 %bb.33, implicit killed $eflags + JMP_1 %bb.32 + + bb.32.bb64: + successors: + + + bb.33.bb65: + successors: %bb.37(0x30000000), %bb.34(0x50000000) + + %49:gr8 = MOV8ri 1 + TEST8rr %49, %49, implicit-def $eflags + JNE_1 %bb.37, implicit killed $eflags + JMP_1 %bb.34 + + bb.34.bb67: + successors: %bb.36(0x00000001), %bb.35(0x7fffffff) + + %81:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %81.sub_8bit, %81.sub_8bit, implicit-def $eflags + JE_1 %bb.36, implicit killed $eflags + + bb.35: + %82:gr32 = LEA32r %12, 1, $noreg, 80, $noreg + JMP_1 %bb.38 + + bb.36.bb70: + successors: + + + bb.37.bb72: + %81:gr32_abcd = COPY %0 + %82:gr32 = COPY %0 + + bb.38.bb74: + successors: %bb.40(0x7fffffff), %bb.39(0x00000001) + + ADJCALLSTACKDOWN32 0, 0, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp + CALLpcrel32 @_Znwj, csr_32, implicit $esp, implicit $ssp, implicit-def $esp, implicit-def $ssp, implicit-def $eax + ADJCALLSTACKUP32 0, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp + %52:gr32 = COPY killed $eax + MOV32mr undef %53:gr32, 1, $noreg, 0, $noreg, %81 :: (store 4 into `%18** undef`) + MOV32mr %82, 1, $noreg, 0, $noreg, %52 :: (store 4 into %ir.tmp79) + ADJCALLSTACKDOWN32 0, 0, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp + CALLpcrel32 @_ZNSt3__127__tree_balance_after_insertIPNS_16__tree_node_baseIPvEEEEvT_S5_, csr_32, implicit $esp, implicit $ssp, implicit-def $esp, implicit-def $ssp + ADJCALLSTACKUP32 0, 0, implicit-def dead $esp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $esp, implicit $ssp + MOV32mi %52, 1, $noreg, 36, $noreg, @_ZN15COLLADASaxFWL1429ColladaParserAutoGen14Private14_end__commentsEv :: (store 4 into %ir.tmp81) + MOV32mr undef %54:gr32, 1, $noreg, 0, $noreg, %1 :: (store 4 into `%18** undef`) + %55:gr32 = MOV32rm %12, 1, $noreg, 140, $noreg :: (load 4 from %ir.3) + CMP32mi8 %55, 1, $noreg, 0, $noreg, 0, implicit-def $eflags :: (load 4 from %ir.tmp864) + JE_1 %bb.40, implicit killed $eflags + JMP_1 %bb.39 + + bb.39.bb89: + successors: + + + bb.40.bb90: + successors: %bb.42(0x00000001), %bb.41(0x7fffffff) + + %56:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %56.sub_8bit, %56.sub_8bit, implicit-def $eflags + JNE_1 %bb.42, implicit killed $eflags + JMP_1 %bb.41 + + bb.41.bb92: + successors: %bb.43(0x00000001), %bb.44(0x7fffffff) + + %58:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %58.sub_8bit, %58.sub_8bit, implicit-def $eflags + JNE_1 %bb.43, implicit killed $eflags + JMP_1 %bb.44 + + bb.42.bb94: + successors: + + + bb.43.bb96: + successors: + + + bb.44.bb97: + successors: %bb.45(0x00000001), %bb.46(0x7fffffff) + + %60:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %60.sub_8bit, %60.sub_8bit, implicit-def $eflags + JNE_1 %bb.46, implicit killed $eflags + JMP_1 %bb.45 + + bb.45.bb101: + successors: + + + bb.46.bb102: + successors: %bb.48(0x7fffffff), %bb.47(0x00000001) + + %62:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %62.sub_8bit, %62.sub_8bit, implicit-def $eflags + JNE_1 %bb.48, implicit killed $eflags + JMP_1 %bb.47 + + bb.47.bb103: + successors: + + + bb.48.bb104: + successors: %bb.50(0x7fffffff), %bb.49(0x00000001) + + %64:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %64.sub_8bit, %64.sub_8bit, implicit-def $eflags + JNE_1 %bb.50, implicit killed $eflags + JMP_1 %bb.49 + + bb.49.bb108: + successors: + + + bb.50.bb109: + successors: %bb.51(0x00000001), %bb.52(0x7fffffff) + + %66:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %66.sub_8bit, %66.sub_8bit, implicit-def $eflags + JNE_1 %bb.52, implicit killed $eflags + JMP_1 %bb.51 + + bb.51.bb111: + successors: + + + bb.52.bb112: + successors: %bb.54(0x7fffffff), %bb.53(0x00000001) + + %68:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %68.sub_8bit, %68.sub_8bit, implicit-def $eflags + JNE_1 %bb.54, implicit killed $eflags + JMP_1 %bb.53 + + bb.53.bb117: + successors: + + + bb.54.bb118: + successors: %bb.55(0x00000001), %bb.56(0x7fffffff) + + %70:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %70.sub_8bit, %70.sub_8bit, implicit-def $eflags + JNE_1 %bb.56, implicit killed $eflags + JMP_1 %bb.55 + + bb.55.bb120: + successors: + + + bb.56.bb121: + successors: %bb.57(0x00000001), %bb.58(0x7fffffff) + + %72:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %72.sub_8bit, %72.sub_8bit, implicit-def $eflags + JNE_1 %bb.58, implicit killed $eflags + JMP_1 %bb.57 + + bb.57.bb124: + successors: + + + bb.58.bb125: + successors: %bb.62(0x00000001), %bb.59(0x7fffffff) + + CMP32mi8 %0, 1, $noreg, 0, $noreg, 0, implicit-def $eflags :: (load 4 from %ir.4) + JE_1 %bb.62, implicit killed $eflags + JMP_1 %bb.59 + + bb.59.bb128: + + bb.60.bb129: + successors: %bb.60(0x7fffffff), %bb.61(0x00000001) + + CMP32ri undef %75:gr32, 95406325, implicit-def $eflags + JB_1 %bb.61, implicit killed $eflags + JMP_1 %bb.60 + + bb.61.bb133: + successors: + + + bb.62.bb135: + successors: %bb.63, %bb.64 + + %76:gr32_abcd = MOV32r0 implicit-def dead $eflags + TEST8rr %76.sub_8bit, %76.sub_8bit, implicit-def $eflags + JNE_1 %bb.64, implicit killed $eflags + JMP_1 %bb.63 + + bb.63.bb137: + successors: + + + bb.64.bb138: + +... diff --git a/llvm/test/CodeGen/X86/scalar-fp-to-i64.ll b/llvm/test/CodeGen/X86/scalar-fp-to-i64.ll index 7ed61f8fdc7d2..92361efa49fac 100644 --- a/llvm/test/CodeGen/X86/scalar-fp-to-i64.ll +++ b/llvm/test/CodeGen/X86/scalar-fp-to-i64.ll @@ -1028,7 +1028,7 @@ define i64 @x_to_u64(x86_fp80 %a) nounwind { ; AVX512_32_WIN-NEXT: xorl %edx, %edx ; AVX512_32_WIN-NEXT: fxch %st(1) ; AVX512_32_WIN-NEXT: fucompi %st(2) -; AVX512_32_WIN-NEXT: fcmovnbe %st(1), %st(0) +; AVX512_32_WIN-NEXT: fcmovnbe %st(1), %st ; AVX512_32_WIN-NEXT: fstp %st(1) ; AVX512_32_WIN-NEXT: fisttpll (%esp) ; AVX512_32_WIN-NEXT: setbe %dl @@ -1049,7 +1049,7 @@ define i64 @x_to_u64(x86_fp80 %a) nounwind { ; AVX512_32_LIN-NEXT: xorl %edx, %edx ; AVX512_32_LIN-NEXT: fxch %st(1) ; AVX512_32_LIN-NEXT: fucompi %st(2) -; AVX512_32_LIN-NEXT: fcmovnbe %st(1), %st(0) +; AVX512_32_LIN-NEXT: fcmovnbe %st(1), %st ; AVX512_32_LIN-NEXT: fstp %st(1) ; AVX512_32_LIN-NEXT: fisttpll (%esp) ; AVX512_32_LIN-NEXT: setbe %dl @@ -1069,7 +1069,7 @@ define i64 @x_to_u64(x86_fp80 %a) nounwind { ; AVX512_64_WIN-NEXT: xorl %ecx, %ecx ; AVX512_64_WIN-NEXT: fxch %st(1) ; AVX512_64_WIN-NEXT: fucompi %st(2) -; AVX512_64_WIN-NEXT: fcmovnbe %st(1), %st(0) +; AVX512_64_WIN-NEXT: fcmovnbe %st(1), %st ; AVX512_64_WIN-NEXT: fstp %st(1) ; AVX512_64_WIN-NEXT: fisttpll (%rsp) ; AVX512_64_WIN-NEXT: setbe %cl @@ -1090,7 +1090,7 @@ define i64 @x_to_u64(x86_fp80 %a) nounwind { ; AVX512_64_LIN-NEXT: xorl %ecx, %ecx ; AVX512_64_LIN-NEXT: fxch %st(1) ; AVX512_64_LIN-NEXT: fucompi %st(2) -; AVX512_64_LIN-NEXT: fcmovnbe %st(1), %st(0) +; AVX512_64_LIN-NEXT: fcmovnbe %st(1), %st ; AVX512_64_LIN-NEXT: fstp %st(1) ; AVX512_64_LIN-NEXT: fisttpll -{{[0-9]+}}(%rsp) ; AVX512_64_LIN-NEXT: setbe %cl @@ -1114,7 +1114,7 @@ define i64 @x_to_u64(x86_fp80 %a) nounwind { ; SSE3_32_WIN-NEXT: xorl %edx, %edx ; SSE3_32_WIN-NEXT: fxch %st(1) ; SSE3_32_WIN-NEXT: fucompi %st(2) -; SSE3_32_WIN-NEXT: fcmovnbe %st(1), %st(0) +; SSE3_32_WIN-NEXT: fcmovnbe %st(1), %st ; SSE3_32_WIN-NEXT: fstp %st(1) ; SSE3_32_WIN-NEXT: fisttpll (%esp) ; SSE3_32_WIN-NEXT: setbe %dl @@ -1135,7 +1135,7 @@ define i64 @x_to_u64(x86_fp80 %a) nounwind { ; SSE3_32_LIN-NEXT: xorl %edx, %edx ; SSE3_32_LIN-NEXT: fxch %st(1) ; SSE3_32_LIN-NEXT: fucompi %st(2) -; SSE3_32_LIN-NEXT: fcmovnbe %st(1), %st(0) +; SSE3_32_LIN-NEXT: fcmovnbe %st(1), %st ; SSE3_32_LIN-NEXT: fstp %st(1) ; SSE3_32_LIN-NEXT: fisttpll (%esp) ; SSE3_32_LIN-NEXT: setbe %dl @@ -1155,7 +1155,7 @@ define i64 @x_to_u64(x86_fp80 %a) nounwind { ; SSE3_64_WIN-NEXT: xorl %eax, %eax ; SSE3_64_WIN-NEXT: fxch %st(1) ; SSE3_64_WIN-NEXT: fucompi %st(2) -; SSE3_64_WIN-NEXT: fcmovnbe %st(1), %st(0) +; SSE3_64_WIN-NEXT: fcmovnbe %st(1), %st ; SSE3_64_WIN-NEXT: fstp %st(1) ; SSE3_64_WIN-NEXT: fisttpll (%rsp) ; SSE3_64_WIN-NEXT: setbe %al @@ -1173,7 +1173,7 @@ define i64 @x_to_u64(x86_fp80 %a) nounwind { ; SSE3_64_LIN-NEXT: xorl %eax, %eax ; SSE3_64_LIN-NEXT: fxch %st(1) ; SSE3_64_LIN-NEXT: fucompi %st(2) -; SSE3_64_LIN-NEXT: fcmovnbe %st(1), %st(0) +; SSE3_64_LIN-NEXT: fcmovnbe %st(1), %st ; SSE3_64_LIN-NEXT: fstp %st(1) ; SSE3_64_LIN-NEXT: fisttpll -{{[0-9]+}}(%rsp) ; SSE3_64_LIN-NEXT: setbe %al @@ -1194,7 +1194,7 @@ define i64 @x_to_u64(x86_fp80 %a) nounwind { ; SSE2_32_WIN-NEXT: xorl %edx, %edx ; SSE2_32_WIN-NEXT: fxch %st(1) ; SSE2_32_WIN-NEXT: fucompi %st(2) -; SSE2_32_WIN-NEXT: fcmovnbe %st(1), %st(0) +; SSE2_32_WIN-NEXT: fcmovnbe %st(1), %st ; SSE2_32_WIN-NEXT: fstp %st(1) ; SSE2_32_WIN-NEXT: fnstcw {{[0-9]+}}(%esp) ; SSE2_32_WIN-NEXT: movzwl {{[0-9]+}}(%esp), %eax @@ -1221,7 +1221,7 @@ define i64 @x_to_u64(x86_fp80 %a) nounwind { ; SSE2_32_LIN-NEXT: xorl %edx, %edx ; SSE2_32_LIN-NEXT: fxch %st(1) ; SSE2_32_LIN-NEXT: fucompi %st(2) -; SSE2_32_LIN-NEXT: fcmovnbe %st(1), %st(0) +; SSE2_32_LIN-NEXT: fcmovnbe %st(1), %st ; SSE2_32_LIN-NEXT: fstp %st(1) ; SSE2_32_LIN-NEXT: fnstcw {{[0-9]+}}(%esp) ; SSE2_32_LIN-NEXT: movzwl {{[0-9]+}}(%esp), %eax @@ -1247,7 +1247,7 @@ define i64 @x_to_u64(x86_fp80 %a) nounwind { ; SSE2_64_WIN-NEXT: xorl %eax, %eax ; SSE2_64_WIN-NEXT: fxch %st(1) ; SSE2_64_WIN-NEXT: fucompi %st(2) -; SSE2_64_WIN-NEXT: fcmovnbe %st(1), %st(0) +; SSE2_64_WIN-NEXT: fcmovnbe %st(1), %st ; SSE2_64_WIN-NEXT: fstp %st(1) ; SSE2_64_WIN-NEXT: fnstcw {{[0-9]+}}(%rsp) ; SSE2_64_WIN-NEXT: movzwl {{[0-9]+}}(%rsp), %ecx @@ -1271,7 +1271,7 @@ define i64 @x_to_u64(x86_fp80 %a) nounwind { ; SSE2_64_LIN-NEXT: xorl %eax, %eax ; SSE2_64_LIN-NEXT: fxch %st(1) ; SSE2_64_LIN-NEXT: fucompi %st(2) -; SSE2_64_LIN-NEXT: fcmovnbe %st(1), %st(0) +; SSE2_64_LIN-NEXT: fcmovnbe %st(1), %st ; SSE2_64_LIN-NEXT: fstp %st(1) ; SSE2_64_LIN-NEXT: fnstcw -{{[0-9]+}}(%rsp) ; SSE2_64_LIN-NEXT: movzwl -{{[0-9]+}}(%rsp), %ecx diff --git a/llvm/test/CodeGen/X86/select.ll b/llvm/test/CodeGen/X86/select.ll index 947c95137206d..9429e1854d44c 100644 --- a/llvm/test/CodeGen/X86/select.ll +++ b/llvm/test/CodeGen/X86/select.ll @@ -293,25 +293,25 @@ define void @test6(i32 %C, <4 x float>* %A, <4 x float>* %B) nounwind { ; ATHLON-NEXT: flds 4(%ecx) ; ATHLON-NEXT: flds (%ecx) ; ATHLON-NEXT: flds (%eax) -; ATHLON-NEXT: fmul %st(0), %st(0) +; ATHLON-NEXT: fmul %st, %st(0) ; ATHLON-NEXT: cmpl $0, {{[0-9]+}}(%esp) ; ATHLON-NEXT: fxch %st(1) -; ATHLON-NEXT: fcmove %st(1), %st(0) +; ATHLON-NEXT: fcmove %st(1), %st ; ATHLON-NEXT: fstp %st(1) ; ATHLON-NEXT: flds 4(%eax) -; ATHLON-NEXT: fmul %st(0), %st(0) +; ATHLON-NEXT: fmul %st, %st(0) ; ATHLON-NEXT: fxch %st(2) -; ATHLON-NEXT: fcmove %st(2), %st(0) +; ATHLON-NEXT: fcmove %st(2), %st ; ATHLON-NEXT: fstp %st(2) ; ATHLON-NEXT: flds 8(%eax) -; ATHLON-NEXT: fmul %st(0), %st(0) +; ATHLON-NEXT: fmul %st, %st(0) ; ATHLON-NEXT: fxch %st(3) -; ATHLON-NEXT: fcmove %st(3), %st(0) +; ATHLON-NEXT: fcmove %st(3), %st ; ATHLON-NEXT: fstp %st(3) ; ATHLON-NEXT: flds 12(%eax) -; ATHLON-NEXT: fmul %st(0), %st(0) +; ATHLON-NEXT: fmul %st, %st(0) ; ATHLON-NEXT: fxch %st(4) -; ATHLON-NEXT: fcmove %st(4), %st(0) +; ATHLON-NEXT: fcmove %st(4), %st ; ATHLON-NEXT: fstp %st(4) ; ATHLON-NEXT: fxch %st(3) ; ATHLON-NEXT: fstps 12(%ecx) @@ -332,13 +332,13 @@ define void @test6(i32 %C, <4 x float>* %A, <4 x float>* %B) nounwind { ; MCU-NEXT: flds 4(%ecx) ; MCU-NEXT: flds 8(%ecx) ; MCU-NEXT: flds 12(%ecx) -; MCU-NEXT: fmul %st(0), %st(0) +; MCU-NEXT: fmul %st, %st(0) ; MCU-NEXT: fxch %st(1) -; MCU-NEXT: fmul %st(0), %st(0) +; MCU-NEXT: fmul %st, %st(0) ; MCU-NEXT: fxch %st(2) -; MCU-NEXT: fmul %st(0), %st(0) +; MCU-NEXT: fmul %st, %st(0) ; MCU-NEXT: fxch %st(3) -; MCU-NEXT: fmul %st(0), %st(0) +; MCU-NEXT: fmul %st, %st(0) ; MCU-NEXT: testl %eax, %eax ; MCU-NEXT: flds (%edx) ; MCU-NEXT: je .LBB5_2 diff --git a/llvm/test/CodeGen/X86/sincos-opt.ll b/llvm/test/CodeGen/X86/sincos-opt.ll index b4330ea58ea5a..b64450863427b 100644 --- a/llvm/test/CodeGen/X86/sincos-opt.ll +++ b/llvm/test/CodeGen/X86/sincos-opt.ll @@ -115,13 +115,13 @@ entry: ; GNU_SINCOS: callq sincosl ; GNU_SINCOS: fldt 16(%rsp) ; GNU_SINCOS: fldt 32(%rsp) -; GNU_SINCOS: faddp %st(1) +; GNU_SINCOS: faddp %st, %st(1) ; GNU_SINCOS_FASTMATH-LABEL: test3: ; GNU_SINCOS_FASTMATH: callq sincosl ; GNU_SINCOS_FASTMATH: fldt 16(%{{[re]}}sp) ; GNU_SINCOS_FASTMATH: fldt 32(%{{[re]}}sp) -; GNU_SINCOS_FASTMATH: faddp %st(1) +; GNU_SINCOS_FASTMATH: faddp %st, %st(1) %call = tail call x86_fp80 @sinl(x86_fp80 %x) readnone %call1 = tail call x86_fp80 @cosl(x86_fp80 %x) readnone %add = fadd x86_fp80 %call, %call1 diff --git a/llvm/test/CodeGen/X86/x87-schedule.ll b/llvm/test/CodeGen/X86/x87-schedule.ll index 1921f8c75a3d1..599f313b13025 100644 --- a/llvm/test/CodeGen/X86/x87-schedule.ll +++ b/llvm/test/CodeGen/X86/x87-schedule.ll @@ -180,8 +180,8 @@ define void @test_fadd(float *%a0, double *%a1) optsize { ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %ecx ; GENERIC-NEXT: #APP -; GENERIC-NEXT: fadd %st(0), %st(1) -; GENERIC-NEXT: fadd %st(2) +; GENERIC-NEXT: fadd %st, %st(1) +; GENERIC-NEXT: fadd %st(2), %st ; GENERIC-NEXT: fadds (%ecx) ; GENERIC-NEXT: faddl (%eax) ; GENERIC-NEXT: #NO_APP @@ -192,8 +192,8 @@ define void @test_fadd(float *%a0, double *%a1) optsize { ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [1:1.00] ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [1:1.00] ; ATOM-NEXT: #APP -; ATOM-NEXT: fadd %st(0), %st(1) # sched: [5:5.00] -; ATOM-NEXT: fadd %st(2) # sched: [5:5.00] +; ATOM-NEXT: fadd %st, %st(1) # sched: [5:5.00] +; ATOM-NEXT: fadd %st(2), %st # sched: [5:5.00] ; ATOM-NEXT: fadds (%ecx) # sched: [5:5.00] ; ATOM-NEXT: faddl (%eax) # sched: [5:5.00] ; ATOM-NEXT: #NO_APP @@ -204,8 +204,8 @@ define void @test_fadd(float *%a0, double *%a1) optsize { ; SLM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [3:1.00] ; SLM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [3:1.00] ; SLM-NEXT: #APP -; SLM-NEXT: fadd %st(0), %st(1) # sched: [3:1.00] -; SLM-NEXT: fadd %st(2) # sched: [3:1.00] +; SLM-NEXT: fadd %st, %st(1) # sched: [3:1.00] +; SLM-NEXT: fadd %st(2), %st # sched: [3:1.00] ; SLM-NEXT: fadds (%ecx) # sched: [6:1.00] ; SLM-NEXT: faddl (%eax) # sched: [6:1.00] ; SLM-NEXT: #NO_APP @@ -216,8 +216,8 @@ define void @test_fadd(float *%a0, double *%a1) optsize { ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SANDY-NEXT: #APP -; SANDY-NEXT: fadd %st(0), %st(1) # sched: [3:1.00] -; SANDY-NEXT: fadd %st(2) # sched: [3:1.00] +; SANDY-NEXT: fadd %st, %st(1) # sched: [3:1.00] +; SANDY-NEXT: fadd %st(2), %st # sched: [3:1.00] ; SANDY-NEXT: fadds (%ecx) # sched: [10:1.00] ; SANDY-NEXT: faddl (%eax) # sched: [10:1.00] ; SANDY-NEXT: #NO_APP @@ -228,8 +228,8 @@ define void @test_fadd(float *%a0, double *%a1) optsize { ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; HASWELL-NEXT: #APP -; HASWELL-NEXT: fadd %st(0), %st(1) # sched: [3:1.00] -; HASWELL-NEXT: fadd %st(2) # sched: [3:1.00] +; HASWELL-NEXT: fadd %st, %st(1) # sched: [3:1.00] +; HASWELL-NEXT: fadd %st(2), %st # sched: [3:1.00] ; HASWELL-NEXT: fadds (%ecx) # sched: [10:1.00] ; HASWELL-NEXT: faddl (%eax) # sched: [10:1.00] ; HASWELL-NEXT: #NO_APP @@ -240,8 +240,8 @@ define void @test_fadd(float *%a0, double *%a1) optsize { ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: fadd %st(0), %st(1) # sched: [3:1.00] -; BROADWELL-NEXT: fadd %st(2) # sched: [3:1.00] +; BROADWELL-NEXT: fadd %st, %st(1) # sched: [3:1.00] +; BROADWELL-NEXT: fadd %st(2), %st # sched: [3:1.00] ; BROADWELL-NEXT: fadds (%ecx) # sched: [9:1.00] ; BROADWELL-NEXT: faddl (%eax) # sched: [9:1.00] ; BROADWELL-NEXT: #NO_APP @@ -252,8 +252,8 @@ define void @test_fadd(float *%a0, double *%a1) optsize { ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: fadd %st(0), %st(1) # sched: [3:1.00] -; SKYLAKE-NEXT: fadd %st(2) # sched: [3:1.00] +; SKYLAKE-NEXT: fadd %st, %st(1) # sched: [3:1.00] +; SKYLAKE-NEXT: fadd %st(2), %st # sched: [3:1.00] ; SKYLAKE-NEXT: fadds (%ecx) # sched: [10:1.00] ; SKYLAKE-NEXT: faddl (%eax) # sched: [10:1.00] ; SKYLAKE-NEXT: #NO_APP @@ -264,8 +264,8 @@ define void @test_fadd(float *%a0, double *%a1) optsize { ; SKX-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKX-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKX-NEXT: #APP -; SKX-NEXT: fadd %st(0), %st(1) # sched: [3:1.00] -; SKX-NEXT: fadd %st(2) # sched: [3:1.00] +; SKX-NEXT: fadd %st, %st(1) # sched: [3:1.00] +; SKX-NEXT: fadd %st(2), %st # sched: [3:1.00] ; SKX-NEXT: fadds (%ecx) # sched: [10:1.00] ; SKX-NEXT: faddl (%eax) # sched: [10:1.00] ; SKX-NEXT: #NO_APP @@ -276,8 +276,8 @@ define void @test_fadd(float *%a0, double *%a1) optsize { ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BDVER2-NEXT: #APP -; BDVER2-NEXT: fadd %st(0), %st(1) # sched: [5:1.00] -; BDVER2-NEXT: fadd %st(2) # sched: [5:1.00] +; BDVER2-NEXT: fadd %st, %st(1) # sched: [5:1.00] +; BDVER2-NEXT: fadd %st(2), %st # sched: [5:1.00] ; BDVER2-NEXT: fadds (%ecx) # sched: [10:1.00] ; BDVER2-NEXT: faddl (%eax) # sched: [10:1.00] ; BDVER2-NEXT: #NO_APP @@ -288,8 +288,8 @@ define void @test_fadd(float *%a0, double *%a1) optsize { ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:1.00] ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:1.00] ; BTVER2-NEXT: #APP -; BTVER2-NEXT: fadd %st(0), %st(1) # sched: [3:1.00] -; BTVER2-NEXT: fadd %st(2) # sched: [3:1.00] +; BTVER2-NEXT: fadd %st, %st(1) # sched: [3:1.00] +; BTVER2-NEXT: fadd %st(2), %st # sched: [3:1.00] ; BTVER2-NEXT: fadds (%ecx) # sched: [8:1.00] ; BTVER2-NEXT: faddl (%eax) # sched: [8:1.00] ; BTVER2-NEXT: #NO_APP @@ -300,8 +300,8 @@ define void @test_fadd(float *%a0, double *%a1) optsize { ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [8:0.50] ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [8:0.50] ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: fadd %st(0), %st(1) # sched: [3:1.00] -; ZNVER1-NEXT: fadd %st(2) # sched: [3:1.00] +; ZNVER1-NEXT: fadd %st, %st(1) # sched: [3:1.00] +; ZNVER1-NEXT: fadd %st(2), %st # sched: [3:1.00] ; ZNVER1-NEXT: fadds (%ecx) # sched: [10:1.00] ; ZNVER1-NEXT: faddl (%eax) # sched: [10:1.00] ; ZNVER1-NEXT: #NO_APP @@ -316,8 +316,8 @@ define void @test_faddp_fiadd(i16 *%a0, i32 *%a1) optsize { ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %ecx ; GENERIC-NEXT: #APP -; GENERIC-NEXT: faddp %st(1) -; GENERIC-NEXT: faddp %st(2) +; GENERIC-NEXT: faddp %st, %st(1) +; GENERIC-NEXT: faddp %st, %st(2) ; GENERIC-NEXT: fiadds (%ecx) ; GENERIC-NEXT: fiaddl (%eax) ; GENERIC-NEXT: #NO_APP @@ -328,8 +328,8 @@ define void @test_faddp_fiadd(i16 *%a0, i32 *%a1) optsize { ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [1:1.00] ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [1:1.00] ; ATOM-NEXT: #APP -; ATOM-NEXT: faddp %st(1) # sched: [5:5.00] -; ATOM-NEXT: faddp %st(2) # sched: [5:5.00] +; ATOM-NEXT: faddp %st, %st(1) # sched: [5:5.00] +; ATOM-NEXT: faddp %st, %st(2) # sched: [5:5.00] ; ATOM-NEXT: fiadds (%ecx) # sched: [5:5.00] ; ATOM-NEXT: fiaddl (%eax) # sched: [5:5.00] ; ATOM-NEXT: #NO_APP @@ -340,8 +340,8 @@ define void @test_faddp_fiadd(i16 *%a0, i32 *%a1) optsize { ; SLM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [3:1.00] ; SLM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [3:1.00] ; SLM-NEXT: #APP -; SLM-NEXT: faddp %st(1) # sched: [3:1.00] -; SLM-NEXT: faddp %st(2) # sched: [3:1.00] +; SLM-NEXT: faddp %st, %st(1) # sched: [3:1.00] +; SLM-NEXT: faddp %st, %st(2) # sched: [3:1.00] ; SLM-NEXT: fiadds (%ecx) # sched: [6:1.00] ; SLM-NEXT: fiaddl (%eax) # sched: [6:1.00] ; SLM-NEXT: #NO_APP @@ -352,8 +352,8 @@ define void @test_faddp_fiadd(i16 *%a0, i32 *%a1) optsize { ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SANDY-NEXT: #APP -; SANDY-NEXT: faddp %st(1) # sched: [3:1.00] -; SANDY-NEXT: faddp %st(2) # sched: [3:1.00] +; SANDY-NEXT: faddp %st, %st(1) # sched: [3:1.00] +; SANDY-NEXT: faddp %st, %st(2) # sched: [3:1.00] ; SANDY-NEXT: fiadds (%ecx) # sched: [13:2.00] ; SANDY-NEXT: fiaddl (%eax) # sched: [13:2.00] ; SANDY-NEXT: #NO_APP @@ -364,8 +364,8 @@ define void @test_faddp_fiadd(i16 *%a0, i32 *%a1) optsize { ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; HASWELL-NEXT: #APP -; HASWELL-NEXT: faddp %st(1) # sched: [3:1.00] -; HASWELL-NEXT: faddp %st(2) # sched: [3:1.00] +; HASWELL-NEXT: faddp %st, %st(1) # sched: [3:1.00] +; HASWELL-NEXT: faddp %st, %st(2) # sched: [3:1.00] ; HASWELL-NEXT: fiadds (%ecx) # sched: [13:2.00] ; HASWELL-NEXT: fiaddl (%eax) # sched: [13:2.00] ; HASWELL-NEXT: #NO_APP @@ -376,8 +376,8 @@ define void @test_faddp_fiadd(i16 *%a0, i32 *%a1) optsize { ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: faddp %st(1) # sched: [3:1.00] -; BROADWELL-NEXT: faddp %st(2) # sched: [3:1.00] +; BROADWELL-NEXT: faddp %st, %st(1) # sched: [3:1.00] +; BROADWELL-NEXT: faddp %st, %st(2) # sched: [3:1.00] ; BROADWELL-NEXT: fiadds (%ecx) # sched: [12:2.00] ; BROADWELL-NEXT: fiaddl (%eax) # sched: [12:2.00] ; BROADWELL-NEXT: #NO_APP @@ -388,8 +388,8 @@ define void @test_faddp_fiadd(i16 *%a0, i32 *%a1) optsize { ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: faddp %st(1) # sched: [3:1.00] -; SKYLAKE-NEXT: faddp %st(2) # sched: [3:1.00] +; SKYLAKE-NEXT: faddp %st, %st(1) # sched: [3:1.00] +; SKYLAKE-NEXT: faddp %st, %st(2) # sched: [3:1.00] ; SKYLAKE-NEXT: fiadds (%ecx) # sched: [13:2.00] ; SKYLAKE-NEXT: fiaddl (%eax) # sched: [13:2.00] ; SKYLAKE-NEXT: #NO_APP @@ -400,8 +400,8 @@ define void @test_faddp_fiadd(i16 *%a0, i32 *%a1) optsize { ; SKX-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKX-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKX-NEXT: #APP -; SKX-NEXT: faddp %st(1) # sched: [3:1.00] -; SKX-NEXT: faddp %st(2) # sched: [3:1.00] +; SKX-NEXT: faddp %st, %st(1) # sched: [3:1.00] +; SKX-NEXT: faddp %st, %st(2) # sched: [3:1.00] ; SKX-NEXT: fiadds (%ecx) # sched: [13:2.00] ; SKX-NEXT: fiaddl (%eax) # sched: [13:2.00] ; SKX-NEXT: #NO_APP @@ -412,8 +412,8 @@ define void @test_faddp_fiadd(i16 *%a0, i32 *%a1) optsize { ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BDVER2-NEXT: #APP -; BDVER2-NEXT: faddp %st(1) # sched: [5:1.00] -; BDVER2-NEXT: faddp %st(2) # sched: [5:1.00] +; BDVER2-NEXT: faddp %st, %st(1) # sched: [5:1.00] +; BDVER2-NEXT: faddp %st, %st(2) # sched: [5:1.00] ; BDVER2-NEXT: fiadds (%ecx) # sched: [10:1.00] ; BDVER2-NEXT: fiaddl (%eax) # sched: [10:1.00] ; BDVER2-NEXT: #NO_APP @@ -424,8 +424,8 @@ define void @test_faddp_fiadd(i16 *%a0, i32 *%a1) optsize { ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:1.00] ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:1.00] ; BTVER2-NEXT: #APP -; BTVER2-NEXT: faddp %st(1) # sched: [3:1.00] -; BTVER2-NEXT: faddp %st(2) # sched: [3:1.00] +; BTVER2-NEXT: faddp %st, %st(1) # sched: [3:1.00] +; BTVER2-NEXT: faddp %st, %st(2) # sched: [3:1.00] ; BTVER2-NEXT: fiadds (%ecx) # sched: [8:1.00] ; BTVER2-NEXT: fiaddl (%eax) # sched: [8:1.00] ; BTVER2-NEXT: #NO_APP @@ -436,8 +436,8 @@ define void @test_faddp_fiadd(i16 *%a0, i32 *%a1) optsize { ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [8:0.50] ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [8:0.50] ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: faddp %st(1) # sched: [3:1.00] -; ZNVER1-NEXT: faddp %st(2) # sched: [3:1.00] +; ZNVER1-NEXT: faddp %st, %st(1) # sched: [3:1.00] +; ZNVER1-NEXT: faddp %st, %st(2) # sched: [3:1.00] ; ZNVER1-NEXT: fiadds (%ecx) # sched: [10:1.00] ; ZNVER1-NEXT: fiaddl (%eax) # sched: [10:1.00] ; ZNVER1-NEXT: #NO_APP @@ -807,154 +807,154 @@ define void @test_fcmov() optsize { ; GENERIC-LABEL: test_fcmov: ; GENERIC: # %bb.0: ; GENERIC-NEXT: #APP -; GENERIC-NEXT: fcmovb %st(1), %st(0) -; GENERIC-NEXT: fcmovbe %st(1), %st(0) -; GENERIC-NEXT: fcmove %st(1), %st(0) -; GENERIC-NEXT: fcmovnb %st(1), %st(0) -; GENERIC-NEXT: fcmovnbe %st(1), %st(0) -; GENERIC-NEXT: fcmovne %st(1), %st(0) -; GENERIC-NEXT: fcmovnu %st(1), %st(0) -; GENERIC-NEXT: fcmovu %st(1), %st(0) +; GENERIC-NEXT: fcmovb %st(1), %st +; GENERIC-NEXT: fcmovbe %st(1), %st +; GENERIC-NEXT: fcmove %st(1), %st +; GENERIC-NEXT: fcmovnb %st(1), %st +; GENERIC-NEXT: fcmovnbe %st(1), %st +; GENERIC-NEXT: fcmovne %st(1), %st +; GENERIC-NEXT: fcmovnu %st(1), %st +; GENERIC-NEXT: fcmovu %st(1), %st ; GENERIC-NEXT: #NO_APP ; GENERIC-NEXT: retl ; ; ATOM-LABEL: test_fcmov: ; ATOM: # %bb.0: ; ATOM-NEXT: #APP -; ATOM-NEXT: fcmovb %st(1), %st(0) # sched: [9:4.50] -; ATOM-NEXT: fcmovbe %st(1), %st(0) # sched: [9:4.50] -; ATOM-NEXT: fcmove %st(1), %st(0) # sched: [9:4.50] -; ATOM-NEXT: fcmovnb %st(1), %st(0) # sched: [9:4.50] -; ATOM-NEXT: fcmovnbe %st(1), %st(0) # sched: [9:4.50] -; ATOM-NEXT: fcmovne %st(1), %st(0) # sched: [9:4.50] -; ATOM-NEXT: fcmovnu %st(1), %st(0) # sched: [9:4.50] -; ATOM-NEXT: fcmovu %st(1), %st(0) # sched: [9:4.50] +; ATOM-NEXT: fcmovb %st(1), %st # sched: [9:4.50] +; ATOM-NEXT: fcmovbe %st(1), %st # sched: [9:4.50] +; ATOM-NEXT: fcmove %st(1), %st # sched: [9:4.50] +; ATOM-NEXT: fcmovnb %st(1), %st # sched: [9:4.50] +; ATOM-NEXT: fcmovnbe %st(1), %st # sched: [9:4.50] +; ATOM-NEXT: fcmovne %st(1), %st # sched: [9:4.50] +; ATOM-NEXT: fcmovnu %st(1), %st # sched: [9:4.50] +; ATOM-NEXT: fcmovu %st(1), %st # sched: [9:4.50] ; ATOM-NEXT: #NO_APP ; ATOM-NEXT: retl # sched: [79:39.50] ; ; SLM-LABEL: test_fcmov: ; SLM: # %bb.0: ; SLM-NEXT: #APP -; SLM-NEXT: fcmovb %st(1), %st(0) # sched: [3:1.00] -; SLM-NEXT: fcmovbe %st(1), %st(0) # sched: [3:1.00] -; SLM-NEXT: fcmove %st(1), %st(0) # sched: [3:1.00] -; SLM-NEXT: fcmovnb %st(1), %st(0) # sched: [3:1.00] -; SLM-NEXT: fcmovnbe %st(1), %st(0) # sched: [3:1.00] -; SLM-NEXT: fcmovne %st(1), %st(0) # sched: [3:1.00] -; SLM-NEXT: fcmovnu %st(1), %st(0) # sched: [3:1.00] -; SLM-NEXT: fcmovu %st(1), %st(0) # sched: [3:1.00] +; SLM-NEXT: fcmovb %st(1), %st # sched: [3:1.00] +; SLM-NEXT: fcmovbe %st(1), %st # sched: [3:1.00] +; SLM-NEXT: fcmove %st(1), %st # sched: [3:1.00] +; SLM-NEXT: fcmovnb %st(1), %st # sched: [3:1.00] +; SLM-NEXT: fcmovnbe %st(1), %st # sched: [3:1.00] +; SLM-NEXT: fcmovne %st(1), %st # sched: [3:1.00] +; SLM-NEXT: fcmovnu %st(1), %st # sched: [3:1.00] +; SLM-NEXT: fcmovu %st(1), %st # sched: [3:1.00] ; SLM-NEXT: #NO_APP ; SLM-NEXT: retl # sched: [4:1.00] ; ; SANDY-LABEL: test_fcmov: ; SANDY: # %bb.0: ; SANDY-NEXT: #APP -; SANDY-NEXT: fcmovb %st(1), %st(0) # sched: [3:2.00] -; SANDY-NEXT: fcmovbe %st(1), %st(0) # sched: [3:2.00] -; SANDY-NEXT: fcmove %st(1), %st(0) # sched: [3:2.00] -; SANDY-NEXT: fcmovnb %st(1), %st(0) # sched: [3:2.00] -; SANDY-NEXT: fcmovnbe %st(1), %st(0) # sched: [3:2.00] -; SANDY-NEXT: fcmovne %st(1), %st(0) # sched: [3:2.00] -; SANDY-NEXT: fcmovnu %st(1), %st(0) # sched: [3:2.00] -; SANDY-NEXT: fcmovu %st(1), %st(0) # sched: [3:2.00] +; SANDY-NEXT: fcmovb %st(1), %st # sched: [3:2.00] +; SANDY-NEXT: fcmovbe %st(1), %st # sched: [3:2.00] +; SANDY-NEXT: fcmove %st(1), %st # sched: [3:2.00] +; SANDY-NEXT: fcmovnb %st(1), %st # sched: [3:2.00] +; SANDY-NEXT: fcmovnbe %st(1), %st # sched: [3:2.00] +; SANDY-NEXT: fcmovne %st(1), %st # sched: [3:2.00] +; SANDY-NEXT: fcmovnu %st(1), %st # sched: [3:2.00] +; SANDY-NEXT: fcmovu %st(1), %st # sched: [3:2.00] ; SANDY-NEXT: #NO_APP ; SANDY-NEXT: retl # sched: [6:1.00] ; ; HASWELL-LABEL: test_fcmov: ; HASWELL: # %bb.0: ; HASWELL-NEXT: #APP -; HASWELL-NEXT: fcmovb %st(1), %st(0) # sched: [3:1.00] -; HASWELL-NEXT: fcmovbe %st(1), %st(0) # sched: [3:1.00] -; HASWELL-NEXT: fcmove %st(1), %st(0) # sched: [3:1.00] -; HASWELL-NEXT: fcmovnb %st(1), %st(0) # sched: [3:1.00] -; HASWELL-NEXT: fcmovnbe %st(1), %st(0) # sched: [3:1.00] -; HASWELL-NEXT: fcmovne %st(1), %st(0) # sched: [3:1.00] -; HASWELL-NEXT: fcmovnu %st(1), %st(0) # sched: [3:1.00] -; HASWELL-NEXT: fcmovu %st(1), %st(0) # sched: [3:1.00] +; HASWELL-NEXT: fcmovb %st(1), %st # sched: [3:1.00] +; HASWELL-NEXT: fcmovbe %st(1), %st # sched: [3:1.00] +; HASWELL-NEXT: fcmove %st(1), %st # sched: [3:1.00] +; HASWELL-NEXT: fcmovnb %st(1), %st # sched: [3:1.00] +; HASWELL-NEXT: fcmovnbe %st(1), %st # sched: [3:1.00] +; HASWELL-NEXT: fcmovne %st(1), %st # sched: [3:1.00] +; HASWELL-NEXT: fcmovnu %st(1), %st # sched: [3:1.00] +; HASWELL-NEXT: fcmovu %st(1), %st # sched: [3:1.00] ; HASWELL-NEXT: #NO_APP ; HASWELL-NEXT: retl # sched: [7:1.00] ; ; BROADWELL-LABEL: test_fcmov: ; BROADWELL: # %bb.0: ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: fcmovb %st(1), %st(0) # sched: [3:1.00] -; BROADWELL-NEXT: fcmovbe %st(1), %st(0) # sched: [3:1.00] -; BROADWELL-NEXT: fcmove %st(1), %st(0) # sched: [3:1.00] -; BROADWELL-NEXT: fcmovnb %st(1), %st(0) # sched: [3:1.00] -; BROADWELL-NEXT: fcmovnbe %st(1), %st(0) # sched: [3:1.00] -; BROADWELL-NEXT: fcmovne %st(1), %st(0) # sched: [3:1.00] -; BROADWELL-NEXT: fcmovnu %st(1), %st(0) # sched: [3:1.00] -; BROADWELL-NEXT: fcmovu %st(1), %st(0) # sched: [3:1.00] +; BROADWELL-NEXT: fcmovb %st(1), %st # sched: [3:1.00] +; BROADWELL-NEXT: fcmovbe %st(1), %st # sched: [3:1.00] +; BROADWELL-NEXT: fcmove %st(1), %st # sched: [3:1.00] +; BROADWELL-NEXT: fcmovnb %st(1), %st # sched: [3:1.00] +; BROADWELL-NEXT: fcmovnbe %st(1), %st # sched: [3:1.00] +; BROADWELL-NEXT: fcmovne %st(1), %st # sched: [3:1.00] +; BROADWELL-NEXT: fcmovnu %st(1), %st # sched: [3:1.00] +; BROADWELL-NEXT: fcmovu %st(1), %st # sched: [3:1.00] ; BROADWELL-NEXT: #NO_APP ; BROADWELL-NEXT: retl # sched: [6:0.50] ; ; SKYLAKE-LABEL: test_fcmov: ; SKYLAKE: # %bb.0: ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: fcmovb %st(1), %st(0) # sched: [3:1.00] -; SKYLAKE-NEXT: fcmovbe %st(1), %st(0) # sched: [3:1.00] -; SKYLAKE-NEXT: fcmove %st(1), %st(0) # sched: [3:1.00] -; SKYLAKE-NEXT: fcmovnb %st(1), %st(0) # sched: [3:1.00] -; SKYLAKE-NEXT: fcmovnbe %st(1), %st(0) # sched: [3:1.00] -; SKYLAKE-NEXT: fcmovne %st(1), %st(0) # sched: [3:1.00] -; SKYLAKE-NEXT: fcmovnu %st(1), %st(0) # sched: [3:1.00] -; SKYLAKE-NEXT: fcmovu %st(1), %st(0) # sched: [3:1.00] +; SKYLAKE-NEXT: fcmovb %st(1), %st # sched: [3:1.00] +; SKYLAKE-NEXT: fcmovbe %st(1), %st # sched: [3:1.00] +; SKYLAKE-NEXT: fcmove %st(1), %st # sched: [3:1.00] +; SKYLAKE-NEXT: fcmovnb %st(1), %st # sched: [3:1.00] +; SKYLAKE-NEXT: fcmovnbe %st(1), %st # sched: [3:1.00] +; SKYLAKE-NEXT: fcmovne %st(1), %st # sched: [3:1.00] +; SKYLAKE-NEXT: fcmovnu %st(1), %st # sched: [3:1.00] +; SKYLAKE-NEXT: fcmovu %st(1), %st # sched: [3:1.00] ; SKYLAKE-NEXT: #NO_APP ; SKYLAKE-NEXT: retl # sched: [6:0.50] ; ; SKX-LABEL: test_fcmov: ; SKX: # %bb.0: ; SKX-NEXT: #APP -; SKX-NEXT: fcmovb %st(1), %st(0) # sched: [3:1.00] -; SKX-NEXT: fcmovbe %st(1), %st(0) # sched: [3:1.00] -; SKX-NEXT: fcmove %st(1), %st(0) # sched: [3:1.00] -; SKX-NEXT: fcmovnb %st(1), %st(0) # sched: [3:1.00] -; SKX-NEXT: fcmovnbe %st(1), %st(0) # sched: [3:1.00] -; SKX-NEXT: fcmovne %st(1), %st(0) # sched: [3:1.00] -; SKX-NEXT: fcmovnu %st(1), %st(0) # sched: [3:1.00] -; SKX-NEXT: fcmovu %st(1), %st(0) # sched: [3:1.00] +; SKX-NEXT: fcmovb %st(1), %st # sched: [3:1.00] +; SKX-NEXT: fcmovbe %st(1), %st # sched: [3:1.00] +; SKX-NEXT: fcmove %st(1), %st # sched: [3:1.00] +; SKX-NEXT: fcmovnb %st(1), %st # sched: [3:1.00] +; SKX-NEXT: fcmovnbe %st(1), %st # sched: [3:1.00] +; SKX-NEXT: fcmovne %st(1), %st # sched: [3:1.00] +; SKX-NEXT: fcmovnu %st(1), %st # sched: [3:1.00] +; SKX-NEXT: fcmovu %st(1), %st # sched: [3:1.00] ; SKX-NEXT: #NO_APP ; SKX-NEXT: retl # sched: [6:0.50] ; ; BDVER2-LABEL: test_fcmov: ; BDVER2: # %bb.0: ; BDVER2-NEXT: #APP -; BDVER2-NEXT: fcmovb %st(1), %st(0) # sched: [1:1.00] -; BDVER2-NEXT: fcmovbe %st(1), %st(0) # sched: [1:1.00] -; BDVER2-NEXT: fcmove %st(1), %st(0) # sched: [1:1.00] -; BDVER2-NEXT: fcmovnb %st(1), %st(0) # sched: [1:1.00] -; BDVER2-NEXT: fcmovnbe %st(1), %st(0) # sched: [1:1.00] -; BDVER2-NEXT: fcmovne %st(1), %st(0) # sched: [1:1.00] -; BDVER2-NEXT: fcmovnu %st(1), %st(0) # sched: [1:1.00] -; BDVER2-NEXT: fcmovu %st(1), %st(0) # sched: [1:1.00] +; BDVER2-NEXT: fcmovb %st(1), %st # sched: [1:1.00] +; BDVER2-NEXT: fcmovbe %st(1), %st # sched: [1:1.00] +; BDVER2-NEXT: fcmove %st(1), %st # sched: [1:1.00] +; BDVER2-NEXT: fcmovnb %st(1), %st # sched: [1:1.00] +; BDVER2-NEXT: fcmovnbe %st(1), %st # sched: [1:1.00] +; BDVER2-NEXT: fcmovne %st(1), %st # sched: [1:1.00] +; BDVER2-NEXT: fcmovnu %st(1), %st # sched: [1:1.00] +; BDVER2-NEXT: fcmovu %st(1), %st # sched: [1:1.00] ; BDVER2-NEXT: #NO_APP ; BDVER2-NEXT: retl # sched: [5:1.00] ; ; BTVER2-LABEL: test_fcmov: ; BTVER2: # %bb.0: ; BTVER2-NEXT: #APP -; BTVER2-NEXT: fcmovb %st(1), %st(0) # sched: [3:1.00] -; BTVER2-NEXT: fcmovbe %st(1), %st(0) # sched: [3:1.00] -; BTVER2-NEXT: fcmove %st(1), %st(0) # sched: [3:1.00] -; BTVER2-NEXT: fcmovnb %st(1), %st(0) # sched: [3:1.00] -; BTVER2-NEXT: fcmovnbe %st(1), %st(0) # sched: [3:1.00] -; BTVER2-NEXT: fcmovne %st(1), %st(0) # sched: [3:1.00] -; BTVER2-NEXT: fcmovnu %st(1), %st(0) # sched: [3:1.00] -; BTVER2-NEXT: fcmovu %st(1), %st(0) # sched: [3:1.00] +; BTVER2-NEXT: fcmovb %st(1), %st # sched: [3:1.00] +; BTVER2-NEXT: fcmovbe %st(1), %st # sched: [3:1.00] +; BTVER2-NEXT: fcmove %st(1), %st # sched: [3:1.00] +; BTVER2-NEXT: fcmovnb %st(1), %st # sched: [3:1.00] +; BTVER2-NEXT: fcmovnbe %st(1), %st # sched: [3:1.00] +; BTVER2-NEXT: fcmovne %st(1), %st # sched: [3:1.00] +; BTVER2-NEXT: fcmovnu %st(1), %st # sched: [3:1.00] +; BTVER2-NEXT: fcmovu %st(1), %st # sched: [3:1.00] ; BTVER2-NEXT: #NO_APP ; BTVER2-NEXT: retl # sched: [4:1.00] ; ; ZNVER1-LABEL: test_fcmov: ; ZNVER1: # %bb.0: ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: fcmovb %st(1), %st(0) # sched: [100:0.25] -; ZNVER1-NEXT: fcmovbe %st(1), %st(0) # sched: [100:0.25] -; ZNVER1-NEXT: fcmove %st(1), %st(0) # sched: [100:0.25] -; ZNVER1-NEXT: fcmovnb %st(1), %st(0) # sched: [100:0.25] -; ZNVER1-NEXT: fcmovnbe %st(1), %st(0) # sched: [100:0.25] -; ZNVER1-NEXT: fcmovne %st(1), %st(0) # sched: [100:0.25] -; ZNVER1-NEXT: fcmovnu %st(1), %st(0) # sched: [100:0.25] -; ZNVER1-NEXT: fcmovu %st(1), %st(0) # sched: [100:0.25] +; ZNVER1-NEXT: fcmovb %st(1), %st # sched: [100:0.25] +; ZNVER1-NEXT: fcmovbe %st(1), %st # sched: [100:0.25] +; ZNVER1-NEXT: fcmove %st(1), %st # sched: [100:0.25] +; ZNVER1-NEXT: fcmovnb %st(1), %st # sched: [100:0.25] +; ZNVER1-NEXT: fcmovnbe %st(1), %st # sched: [100:0.25] +; ZNVER1-NEXT: fcmovne %st(1), %st # sched: [100:0.25] +; ZNVER1-NEXT: fcmovnu %st(1), %st # sched: [100:0.25] +; ZNVER1-NEXT: fcmovu %st(1), %st # sched: [100:0.25] ; ZNVER1-NEXT: #NO_APP ; ZNVER1-NEXT: retl # sched: [1:0.50] tail call void asm sideeffect "fcmovb %st(1), %st(0) \0A\09 fcmovbe %st(1), %st(0) \0A\09 fcmove %st(1), %st(0) \0A\09 fcmovnb %st(1), %st(0) \0A\09 fcmovnbe %st(1), %st(0) \0A\09 fcmovne %st(1), %st(0) \0A\09 fcmovnu %st(1), %st(0) \0A\09 fcmovu %st(1), %st(0)", ""() nounwind @@ -1248,88 +1248,88 @@ define void @test_fcomi_fcomip() optsize { ; GENERIC-LABEL: test_fcomi_fcomip: ; GENERIC: # %bb.0: ; GENERIC-NEXT: #APP -; GENERIC-NEXT: fcomi %st(3) -; GENERIC-NEXT: fcompi %st(3) +; GENERIC-NEXT: fcomi %st(3), %st +; GENERIC-NEXT: fcompi %st(3), %st ; GENERIC-NEXT: #NO_APP ; GENERIC-NEXT: retl ; ; ATOM-LABEL: test_fcomi_fcomip: ; ATOM: # %bb.0: ; ATOM-NEXT: #APP -; ATOM-NEXT: fcomi %st(3) # sched: [9:4.50] -; ATOM-NEXT: fcompi %st(3) # sched: [9:4.50] +; ATOM-NEXT: fcomi %st(3), %st # sched: [9:4.50] +; ATOM-NEXT: fcompi %st(3), %st # sched: [9:4.50] ; ATOM-NEXT: #NO_APP ; ATOM-NEXT: retl # sched: [79:39.50] ; ; SLM-LABEL: test_fcomi_fcomip: ; SLM: # %bb.0: ; SLM-NEXT: #APP -; SLM-NEXT: fcomi %st(3) # sched: [3:1.00] -; SLM-NEXT: fcompi %st(3) # sched: [3:1.00] +; SLM-NEXT: fcomi %st(3), %st # sched: [3:1.00] +; SLM-NEXT: fcompi %st(3), %st # sched: [3:1.00] ; SLM-NEXT: #NO_APP ; SLM-NEXT: retl # sched: [4:1.00] ; ; SANDY-LABEL: test_fcomi_fcomip: ; SANDY: # %bb.0: ; SANDY-NEXT: #APP -; SANDY-NEXT: fcomi %st(3) # sched: [3:1.00] -; SANDY-NEXT: fcompi %st(3) # sched: [3:1.00] +; SANDY-NEXT: fcomi %st(3), %st # sched: [3:1.00] +; SANDY-NEXT: fcompi %st(3), %st # sched: [3:1.00] ; SANDY-NEXT: #NO_APP ; SANDY-NEXT: retl # sched: [6:1.00] ; ; HASWELL-LABEL: test_fcomi_fcomip: ; HASWELL: # %bb.0: ; HASWELL-NEXT: #APP -; HASWELL-NEXT: fcomi %st(3) # sched: [1:0.50] -; HASWELL-NEXT: fcompi %st(3) # sched: [1:0.50] +; HASWELL-NEXT: fcomi %st(3), %st # sched: [1:0.50] +; HASWELL-NEXT: fcompi %st(3), %st # sched: [1:0.50] ; HASWELL-NEXT: #NO_APP ; HASWELL-NEXT: retl # sched: [7:1.00] ; ; BROADWELL-LABEL: test_fcomi_fcomip: ; BROADWELL: # %bb.0: ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: fcomi %st(3) # sched: [3:1.00] -; BROADWELL-NEXT: fcompi %st(3) # sched: [3:1.00] +; BROADWELL-NEXT: fcomi %st(3), %st # sched: [3:1.00] +; BROADWELL-NEXT: fcompi %st(3), %st # sched: [3:1.00] ; BROADWELL-NEXT: #NO_APP ; BROADWELL-NEXT: retl # sched: [6:0.50] ; ; SKYLAKE-LABEL: test_fcomi_fcomip: ; SKYLAKE: # %bb.0: ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: fcomi %st(3) # sched: [2:1.00] -; SKYLAKE-NEXT: fcompi %st(3) # sched: [2:1.00] +; SKYLAKE-NEXT: fcomi %st(3), %st # sched: [2:1.00] +; SKYLAKE-NEXT: fcompi %st(3), %st # sched: [2:1.00] ; SKYLAKE-NEXT: #NO_APP ; SKYLAKE-NEXT: retl # sched: [6:0.50] ; ; SKX-LABEL: test_fcomi_fcomip: ; SKX: # %bb.0: ; SKX-NEXT: #APP -; SKX-NEXT: fcomi %st(3) # sched: [2:1.00] -; SKX-NEXT: fcompi %st(3) # sched: [2:1.00] +; SKX-NEXT: fcomi %st(3), %st # sched: [2:1.00] +; SKX-NEXT: fcompi %st(3), %st # sched: [2:1.00] ; SKX-NEXT: #NO_APP ; SKX-NEXT: retl # sched: [6:0.50] ; ; BDVER2-LABEL: test_fcomi_fcomip: ; BDVER2: # %bb.0: ; BDVER2-NEXT: #APP -; BDVER2-NEXT: fcomi %st(3) # sched: [1:1.00] -; BDVER2-NEXT: fcompi %st(3) # sched: [1:1.00] +; BDVER2-NEXT: fcomi %st(3), %st # sched: [1:1.00] +; BDVER2-NEXT: fcompi %st(3), %st # sched: [1:1.00] ; BDVER2-NEXT: #NO_APP ; BDVER2-NEXT: retl # sched: [5:1.00] ; ; BTVER2-LABEL: test_fcomi_fcomip: ; BTVER2: # %bb.0: ; BTVER2-NEXT: #APP -; BTVER2-NEXT: fcomi %st(3) # sched: [3:1.00] -; BTVER2-NEXT: fcompi %st(3) # sched: [3:1.00] +; BTVER2-NEXT: fcomi %st(3), %st # sched: [3:1.00] +; BTVER2-NEXT: fcompi %st(3), %st # sched: [3:1.00] ; BTVER2-NEXT: #NO_APP ; BTVER2-NEXT: retl # sched: [4:1.00] ; ; ZNVER1-LABEL: test_fcomi_fcomip: ; ZNVER1: # %bb.0: ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: fcomi %st(3) # sched: [9:0.50] -; ZNVER1-NEXT: fcompi %st(3) # sched: [9:0.50] +; ZNVER1-NEXT: fcomi %st(3), %st # sched: [9:0.50] +; ZNVER1-NEXT: fcompi %st(3), %st # sched: [9:0.50] ; ZNVER1-NEXT: #NO_APP ; ZNVER1-NEXT: retl # sched: [1:0.50] tail call void asm sideeffect "fcomi %st(3) \0A\09 fcomip %st(3)", ""() nounwind @@ -1504,8 +1504,8 @@ define void @test_fdiv(float *%a0, double *%a1) optsize { ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %ecx ; GENERIC-NEXT: #APP -; GENERIC-NEXT: fdiv %st(0), %st(1) -; GENERIC-NEXT: fdiv %st(2) +; GENERIC-NEXT: fdiv %st, %st(1) +; GENERIC-NEXT: fdiv %st(2), %st ; GENERIC-NEXT: fdivs (%ecx) ; GENERIC-NEXT: fdivl (%eax) ; GENERIC-NEXT: #NO_APP @@ -1516,8 +1516,8 @@ define void @test_fdiv(float *%a0, double *%a1) optsize { ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [1:1.00] ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [1:1.00] ; ATOM-NEXT: #APP -; ATOM-NEXT: fdiv %st(0), %st(1) # sched: [34:17.00] -; ATOM-NEXT: fdiv %st(2) # sched: [34:17.00] +; ATOM-NEXT: fdiv %st, %st(1) # sched: [34:17.00] +; ATOM-NEXT: fdiv %st(2), %st # sched: [34:17.00] ; ATOM-NEXT: fdivs (%ecx) # sched: [34:17.00] ; ATOM-NEXT: fdivl (%eax) # sched: [34:17.00] ; ATOM-NEXT: #NO_APP @@ -1528,8 +1528,8 @@ define void @test_fdiv(float *%a0, double *%a1) optsize { ; SLM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [3:1.00] ; SLM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [3:1.00] ; SLM-NEXT: #APP -; SLM-NEXT: fdiv %st(0), %st(1) # sched: [19:17.00] -; SLM-NEXT: fdiv %st(2) # sched: [19:17.00] +; SLM-NEXT: fdiv %st, %st(1) # sched: [19:17.00] +; SLM-NEXT: fdiv %st(2), %st # sched: [19:17.00] ; SLM-NEXT: fdivs (%ecx) # sched: [22:17.00] ; SLM-NEXT: fdivl (%eax) # sched: [22:17.00] ; SLM-NEXT: #NO_APP @@ -1540,8 +1540,8 @@ define void @test_fdiv(float *%a0, double *%a1) optsize { ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SANDY-NEXT: #APP -; SANDY-NEXT: fdiv %st(0), %st(1) # sched: [14:14.00] -; SANDY-NEXT: fdiv %st(2) # sched: [14:14.00] +; SANDY-NEXT: fdiv %st, %st(1) # sched: [14:14.00] +; SANDY-NEXT: fdiv %st(2), %st # sched: [14:14.00] ; SANDY-NEXT: fdivs (%ecx) # sched: [31:1.00] ; SANDY-NEXT: fdivl (%eax) # sched: [31:1.00] ; SANDY-NEXT: #NO_APP @@ -1552,8 +1552,8 @@ define void @test_fdiv(float *%a0, double *%a1) optsize { ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; HASWELL-NEXT: #APP -; HASWELL-NEXT: fdiv %st(0), %st(1) # sched: [24:1.00] -; HASWELL-NEXT: fdiv %st(2) # sched: [20:1.00] +; HASWELL-NEXT: fdiv %st, %st(1) # sched: [24:1.00] +; HASWELL-NEXT: fdiv %st(2), %st # sched: [20:1.00] ; HASWELL-NEXT: fdivs (%ecx) # sched: [31:1.00] ; HASWELL-NEXT: fdivl (%eax) # sched: [31:1.00] ; HASWELL-NEXT: #NO_APP @@ -1564,8 +1564,8 @@ define void @test_fdiv(float *%a0, double *%a1) optsize { ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: fdiv %st(0), %st(1) # sched: [15:1.00] -; BROADWELL-NEXT: fdiv %st(2) # sched: [20:1.00] +; BROADWELL-NEXT: fdiv %st, %st(1) # sched: [15:1.00] +; BROADWELL-NEXT: fdiv %st(2), %st # sched: [20:1.00] ; BROADWELL-NEXT: fdivs (%ecx) # sched: [21:1.00] ; BROADWELL-NEXT: fdivl (%eax) # sched: [21:1.00] ; BROADWELL-NEXT: #NO_APP @@ -1576,8 +1576,8 @@ define void @test_fdiv(float *%a0, double *%a1) optsize { ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: fdiv %st(0), %st(1) # sched: [15:1.00] -; SKYLAKE-NEXT: fdiv %st(2) # sched: [20:1.00] +; SKYLAKE-NEXT: fdiv %st, %st(1) # sched: [15:1.00] +; SKYLAKE-NEXT: fdiv %st(2), %st # sched: [20:1.00] ; SKYLAKE-NEXT: fdivs (%ecx) # sched: [22:1.00] ; SKYLAKE-NEXT: fdivl (%eax) # sched: [22:1.00] ; SKYLAKE-NEXT: #NO_APP @@ -1588,8 +1588,8 @@ define void @test_fdiv(float *%a0, double *%a1) optsize { ; SKX-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKX-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKX-NEXT: #APP -; SKX-NEXT: fdiv %st(0), %st(1) # sched: [15:1.00] -; SKX-NEXT: fdiv %st(2) # sched: [20:1.00] +; SKX-NEXT: fdiv %st, %st(1) # sched: [15:1.00] +; SKX-NEXT: fdiv %st(2), %st # sched: [20:1.00] ; SKX-NEXT: fdivs (%ecx) # sched: [22:1.00] ; SKX-NEXT: fdivl (%eax) # sched: [22:1.00] ; SKX-NEXT: #NO_APP @@ -1600,8 +1600,8 @@ define void @test_fdiv(float *%a0, double *%a1) optsize { ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BDVER2-NEXT: #APP -; BDVER2-NEXT: fdiv %st(0), %st(1) # sched: [9:9.50] -; BDVER2-NEXT: fdiv %st(2) # sched: [9:9.50] +; BDVER2-NEXT: fdiv %st, %st(1) # sched: [9:9.50] +; BDVER2-NEXT: fdiv %st(2), %st # sched: [9:9.50] ; BDVER2-NEXT: fdivs (%ecx) # sched: [14:9.50] ; BDVER2-NEXT: fdivl (%eax) # sched: [14:9.50] ; BDVER2-NEXT: #NO_APP @@ -1612,8 +1612,8 @@ define void @test_fdiv(float *%a0, double *%a1) optsize { ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:1.00] ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:1.00] ; BTVER2-NEXT: #APP -; BTVER2-NEXT: fdiv %st(0), %st(1) # sched: [19:19.00] -; BTVER2-NEXT: fdiv %st(2) # sched: [19:19.00] +; BTVER2-NEXT: fdiv %st, %st(1) # sched: [19:19.00] +; BTVER2-NEXT: fdiv %st(2), %st # sched: [19:19.00] ; BTVER2-NEXT: fdivs (%ecx) # sched: [24:19.00] ; BTVER2-NEXT: fdivl (%eax) # sched: [24:19.00] ; BTVER2-NEXT: #NO_APP @@ -1624,8 +1624,8 @@ define void @test_fdiv(float *%a0, double *%a1) optsize { ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [8:0.50] ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [8:0.50] ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: fdiv %st(0), %st(1) # sched: [15:1.00] -; ZNVER1-NEXT: fdiv %st(2) # sched: [15:1.00] +; ZNVER1-NEXT: fdiv %st, %st(1) # sched: [15:1.00] +; ZNVER1-NEXT: fdiv %st(2), %st # sched: [15:1.00] ; ZNVER1-NEXT: fdivs (%ecx) # sched: [22:1.00] ; ZNVER1-NEXT: fdivl (%eax) # sched: [22:1.00] ; ZNVER1-NEXT: #NO_APP @@ -1640,8 +1640,8 @@ define void @test_fdivp_fidiv(i16 *%a0, i32 *%a1) optsize { ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %ecx ; GENERIC-NEXT: #APP -; GENERIC-NEXT: fdivp %st(1) -; GENERIC-NEXT: fdivp %st(2) +; GENERIC-NEXT: fdivp %st, %st(1) +; GENERIC-NEXT: fdivp %st, %st(2) ; GENERIC-NEXT: fidivs (%ecx) ; GENERIC-NEXT: fidivl (%eax) ; GENERIC-NEXT: #NO_APP @@ -1652,8 +1652,8 @@ define void @test_fdivp_fidiv(i16 *%a0, i32 *%a1) optsize { ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [1:1.00] ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [1:1.00] ; ATOM-NEXT: #APP -; ATOM-NEXT: fdivp %st(1) # sched: [34:17.00] -; ATOM-NEXT: fdivp %st(2) # sched: [34:17.00] +; ATOM-NEXT: fdivp %st, %st(1) # sched: [34:17.00] +; ATOM-NEXT: fdivp %st, %st(2) # sched: [34:17.00] ; ATOM-NEXT: fidivs (%ecx) # sched: [34:17.00] ; ATOM-NEXT: fidivl (%eax) # sched: [34:17.00] ; ATOM-NEXT: #NO_APP @@ -1664,8 +1664,8 @@ define void @test_fdivp_fidiv(i16 *%a0, i32 *%a1) optsize { ; SLM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [3:1.00] ; SLM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [3:1.00] ; SLM-NEXT: #APP -; SLM-NEXT: fdivp %st(1) # sched: [19:17.00] -; SLM-NEXT: fdivp %st(2) # sched: [19:17.00] +; SLM-NEXT: fdivp %st, %st(1) # sched: [19:17.00] +; SLM-NEXT: fdivp %st, %st(2) # sched: [19:17.00] ; SLM-NEXT: fidivs (%ecx) # sched: [22:17.00] ; SLM-NEXT: fidivl (%eax) # sched: [22:17.00] ; SLM-NEXT: #NO_APP @@ -1676,8 +1676,8 @@ define void @test_fdivp_fidiv(i16 *%a0, i32 *%a1) optsize { ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SANDY-NEXT: #APP -; SANDY-NEXT: fdivp %st(1) # sched: [14:14.00] -; SANDY-NEXT: fdivp %st(2) # sched: [14:14.00] +; SANDY-NEXT: fdivp %st, %st(1) # sched: [14:14.00] +; SANDY-NEXT: fdivp %st, %st(2) # sched: [14:14.00] ; SANDY-NEXT: fidivs (%ecx) # sched: [34:1.00] ; SANDY-NEXT: fidivl (%eax) # sched: [34:1.00] ; SANDY-NEXT: #NO_APP @@ -1688,8 +1688,8 @@ define void @test_fdivp_fidiv(i16 *%a0, i32 *%a1) optsize { ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; HASWELL-NEXT: #APP -; HASWELL-NEXT: fdivp %st(1) # sched: [24:1.00] -; HASWELL-NEXT: fdivp %st(2) # sched: [24:1.00] +; HASWELL-NEXT: fdivp %st, %st(1) # sched: [24:1.00] +; HASWELL-NEXT: fdivp %st, %st(2) # sched: [24:1.00] ; HASWELL-NEXT: fidivs (%ecx) # sched: [34:1.00] ; HASWELL-NEXT: fidivl (%eax) # sched: [34:1.00] ; HASWELL-NEXT: #NO_APP @@ -1700,8 +1700,8 @@ define void @test_fdivp_fidiv(i16 *%a0, i32 *%a1) optsize { ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: fdivp %st(1) # sched: [15:1.00] -; BROADWELL-NEXT: fdivp %st(2) # sched: [15:1.00] +; BROADWELL-NEXT: fdivp %st, %st(1) # sched: [15:1.00] +; BROADWELL-NEXT: fdivp %st, %st(2) # sched: [15:1.00] ; BROADWELL-NEXT: fidivs (%ecx) # sched: [24:1.00] ; BROADWELL-NEXT: fidivl (%eax) # sched: [24:1.00] ; BROADWELL-NEXT: #NO_APP @@ -1712,8 +1712,8 @@ define void @test_fdivp_fidiv(i16 *%a0, i32 *%a1) optsize { ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: fdivp %st(1) # sched: [15:1.00] -; SKYLAKE-NEXT: fdivp %st(2) # sched: [15:1.00] +; SKYLAKE-NEXT: fdivp %st, %st(1) # sched: [15:1.00] +; SKYLAKE-NEXT: fdivp %st, %st(2) # sched: [15:1.00] ; SKYLAKE-NEXT: fidivs (%ecx) # sched: [25:1.00] ; SKYLAKE-NEXT: fidivl (%eax) # sched: [25:1.00] ; SKYLAKE-NEXT: #NO_APP @@ -1724,8 +1724,8 @@ define void @test_fdivp_fidiv(i16 *%a0, i32 *%a1) optsize { ; SKX-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKX-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKX-NEXT: #APP -; SKX-NEXT: fdivp %st(1) # sched: [15:1.00] -; SKX-NEXT: fdivp %st(2) # sched: [15:1.00] +; SKX-NEXT: fdivp %st, %st(1) # sched: [15:1.00] +; SKX-NEXT: fdivp %st, %st(2) # sched: [15:1.00] ; SKX-NEXT: fidivs (%ecx) # sched: [25:1.00] ; SKX-NEXT: fidivl (%eax) # sched: [25:1.00] ; SKX-NEXT: #NO_APP @@ -1736,8 +1736,8 @@ define void @test_fdivp_fidiv(i16 *%a0, i32 *%a1) optsize { ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BDVER2-NEXT: #APP -; BDVER2-NEXT: fdivp %st(1) # sched: [9:9.50] -; BDVER2-NEXT: fdivp %st(2) # sched: [9:9.50] +; BDVER2-NEXT: fdivp %st, %st(1) # sched: [9:9.50] +; BDVER2-NEXT: fdivp %st, %st(2) # sched: [9:9.50] ; BDVER2-NEXT: fidivs (%ecx) # sched: [14:9.50] ; BDVER2-NEXT: fidivl (%eax) # sched: [14:9.50] ; BDVER2-NEXT: #NO_APP @@ -1748,8 +1748,8 @@ define void @test_fdivp_fidiv(i16 *%a0, i32 *%a1) optsize { ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:1.00] ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:1.00] ; BTVER2-NEXT: #APP -; BTVER2-NEXT: fdivp %st(1) # sched: [19:19.00] -; BTVER2-NEXT: fdivp %st(2) # sched: [19:19.00] +; BTVER2-NEXT: fdivp %st, %st(1) # sched: [19:19.00] +; BTVER2-NEXT: fdivp %st, %st(2) # sched: [19:19.00] ; BTVER2-NEXT: fidivs (%ecx) # sched: [24:19.00] ; BTVER2-NEXT: fidivl (%eax) # sched: [24:19.00] ; BTVER2-NEXT: #NO_APP @@ -1760,8 +1760,8 @@ define void @test_fdivp_fidiv(i16 *%a0, i32 *%a1) optsize { ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [8:0.50] ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [8:0.50] ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: fdivp %st(1) # sched: [15:1.00] -; ZNVER1-NEXT: fdivp %st(2) # sched: [15:1.00] +; ZNVER1-NEXT: fdivp %st, %st(1) # sched: [15:1.00] +; ZNVER1-NEXT: fdivp %st, %st(2) # sched: [15:1.00] ; ZNVER1-NEXT: fidivs (%ecx) # sched: [22:1.00] ; ZNVER1-NEXT: fidivl (%eax) # sched: [22:1.00] ; ZNVER1-NEXT: #NO_APP @@ -1776,8 +1776,8 @@ define void @test_fdivr(float *%a0, double *%a1) optsize { ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %ecx ; GENERIC-NEXT: #APP -; GENERIC-NEXT: fdivr %st(0), %st(1) -; GENERIC-NEXT: fdivr %st(2) +; GENERIC-NEXT: fdivr %st, %st(1) +; GENERIC-NEXT: fdivr %st(2), %st ; GENERIC-NEXT: fdivrs (%ecx) ; GENERIC-NEXT: fdivrl (%eax) ; GENERIC-NEXT: #NO_APP @@ -1788,8 +1788,8 @@ define void @test_fdivr(float *%a0, double *%a1) optsize { ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [1:1.00] ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [1:1.00] ; ATOM-NEXT: #APP -; ATOM-NEXT: fdivr %st(0), %st(1) # sched: [34:17.00] -; ATOM-NEXT: fdivr %st(2) # sched: [34:17.00] +; ATOM-NEXT: fdivr %st, %st(1) # sched: [34:17.00] +; ATOM-NEXT: fdivr %st(2), %st # sched: [34:17.00] ; ATOM-NEXT: fdivrs (%ecx) # sched: [34:17.00] ; ATOM-NEXT: fdivrl (%eax) # sched: [34:17.00] ; ATOM-NEXT: #NO_APP @@ -1800,8 +1800,8 @@ define void @test_fdivr(float *%a0, double *%a1) optsize { ; SLM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [3:1.00] ; SLM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [3:1.00] ; SLM-NEXT: #APP -; SLM-NEXT: fdivr %st(0), %st(1) # sched: [19:17.00] -; SLM-NEXT: fdivr %st(2) # sched: [19:17.00] +; SLM-NEXT: fdivr %st, %st(1) # sched: [19:17.00] +; SLM-NEXT: fdivr %st(2), %st # sched: [19:17.00] ; SLM-NEXT: fdivrs (%ecx) # sched: [22:17.00] ; SLM-NEXT: fdivrl (%eax) # sched: [22:17.00] ; SLM-NEXT: #NO_APP @@ -1812,8 +1812,8 @@ define void @test_fdivr(float *%a0, double *%a1) optsize { ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SANDY-NEXT: #APP -; SANDY-NEXT: fdivr %st(0), %st(1) # sched: [14:14.00] -; SANDY-NEXT: fdivr %st(2) # sched: [14:14.00] +; SANDY-NEXT: fdivr %st, %st(1) # sched: [14:14.00] +; SANDY-NEXT: fdivr %st(2), %st # sched: [14:14.00] ; SANDY-NEXT: fdivrs (%ecx) # sched: [31:1.00] ; SANDY-NEXT: fdivrl (%eax) # sched: [31:1.00] ; SANDY-NEXT: #NO_APP @@ -1824,8 +1824,8 @@ define void @test_fdivr(float *%a0, double *%a1) optsize { ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; HASWELL-NEXT: #APP -; HASWELL-NEXT: fdivr %st(0), %st(1) # sched: [20:1.00] -; HASWELL-NEXT: fdivr %st(2) # sched: [24:1.00] +; HASWELL-NEXT: fdivr %st, %st(1) # sched: [20:1.00] +; HASWELL-NEXT: fdivr %st(2), %st # sched: [24:1.00] ; HASWELL-NEXT: fdivrs (%ecx) # sched: [27:1.00] ; HASWELL-NEXT: fdivrl (%eax) # sched: [27:1.00] ; HASWELL-NEXT: #NO_APP @@ -1836,8 +1836,8 @@ define void @test_fdivr(float *%a0, double *%a1) optsize { ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: fdivr %st(0), %st(1) # sched: [20:1.00] -; BROADWELL-NEXT: fdivr %st(2) # sched: [15:1.00] +; BROADWELL-NEXT: fdivr %st, %st(1) # sched: [20:1.00] +; BROADWELL-NEXT: fdivr %st(2), %st # sched: [15:1.00] ; BROADWELL-NEXT: fdivrs (%ecx) # sched: [26:1.00] ; BROADWELL-NEXT: fdivrl (%eax) # sched: [26:1.00] ; BROADWELL-NEXT: #NO_APP @@ -1848,8 +1848,8 @@ define void @test_fdivr(float *%a0, double *%a1) optsize { ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: fdivr %st(0), %st(1) # sched: [20:1.00] -; SKYLAKE-NEXT: fdivr %st(2) # sched: [15:1.00] +; SKYLAKE-NEXT: fdivr %st, %st(1) # sched: [20:1.00] +; SKYLAKE-NEXT: fdivr %st(2), %st # sched: [15:1.00] ; SKYLAKE-NEXT: fdivrs (%ecx) # sched: [27:1.00] ; SKYLAKE-NEXT: fdivrl (%eax) # sched: [27:1.00] ; SKYLAKE-NEXT: #NO_APP @@ -1860,8 +1860,8 @@ define void @test_fdivr(float *%a0, double *%a1) optsize { ; SKX-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKX-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKX-NEXT: #APP -; SKX-NEXT: fdivr %st(0), %st(1) # sched: [20:1.00] -; SKX-NEXT: fdivr %st(2) # sched: [15:1.00] +; SKX-NEXT: fdivr %st, %st(1) # sched: [20:1.00] +; SKX-NEXT: fdivr %st(2), %st # sched: [15:1.00] ; SKX-NEXT: fdivrs (%ecx) # sched: [27:1.00] ; SKX-NEXT: fdivrl (%eax) # sched: [27:1.00] ; SKX-NEXT: #NO_APP @@ -1872,8 +1872,8 @@ define void @test_fdivr(float *%a0, double *%a1) optsize { ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BDVER2-NEXT: #APP -; BDVER2-NEXT: fdivr %st(0), %st(1) # sched: [9:9.50] -; BDVER2-NEXT: fdivr %st(2) # sched: [9:9.50] +; BDVER2-NEXT: fdivr %st, %st(1) # sched: [9:9.50] +; BDVER2-NEXT: fdivr %st(2), %st # sched: [9:9.50] ; BDVER2-NEXT: fdivrs (%ecx) # sched: [14:9.50] ; BDVER2-NEXT: fdivrl (%eax) # sched: [14:9.50] ; BDVER2-NEXT: #NO_APP @@ -1884,8 +1884,8 @@ define void @test_fdivr(float *%a0, double *%a1) optsize { ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:1.00] ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:1.00] ; BTVER2-NEXT: #APP -; BTVER2-NEXT: fdivr %st(0), %st(1) # sched: [19:19.00] -; BTVER2-NEXT: fdivr %st(2) # sched: [19:19.00] +; BTVER2-NEXT: fdivr %st, %st(1) # sched: [19:19.00] +; BTVER2-NEXT: fdivr %st(2), %st # sched: [19:19.00] ; BTVER2-NEXT: fdivrs (%ecx) # sched: [24:19.00] ; BTVER2-NEXT: fdivrl (%eax) # sched: [24:19.00] ; BTVER2-NEXT: #NO_APP @@ -1896,8 +1896,8 @@ define void @test_fdivr(float *%a0, double *%a1) optsize { ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [8:0.50] ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [8:0.50] ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: fdivr %st(0), %st(1) # sched: [15:1.00] -; ZNVER1-NEXT: fdivr %st(2) # sched: [15:1.00] +; ZNVER1-NEXT: fdivr %st, %st(1) # sched: [15:1.00] +; ZNVER1-NEXT: fdivr %st(2), %st # sched: [15:1.00] ; ZNVER1-NEXT: fdivrs (%ecx) # sched: [22:1.00] ; ZNVER1-NEXT: fdivrl (%eax) # sched: [22:1.00] ; ZNVER1-NEXT: #NO_APP @@ -1912,8 +1912,8 @@ define void @test_fdivrp_fidivr(i16 *%a0, i32 *%a1) optsize { ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %ecx ; GENERIC-NEXT: #APP -; GENERIC-NEXT: fdivrp %st(1) -; GENERIC-NEXT: fdivrp %st(2) +; GENERIC-NEXT: fdivrp %st, %st(1) +; GENERIC-NEXT: fdivrp %st, %st(2) ; GENERIC-NEXT: fidivrs (%ecx) ; GENERIC-NEXT: fidivrl (%eax) ; GENERIC-NEXT: #NO_APP @@ -1924,8 +1924,8 @@ define void @test_fdivrp_fidivr(i16 *%a0, i32 *%a1) optsize { ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [1:1.00] ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [1:1.00] ; ATOM-NEXT: #APP -; ATOM-NEXT: fdivrp %st(1) # sched: [34:17.00] -; ATOM-NEXT: fdivrp %st(2) # sched: [34:17.00] +; ATOM-NEXT: fdivrp %st, %st(1) # sched: [34:17.00] +; ATOM-NEXT: fdivrp %st, %st(2) # sched: [34:17.00] ; ATOM-NEXT: fidivrs (%ecx) # sched: [34:17.00] ; ATOM-NEXT: fidivrl (%eax) # sched: [34:17.00] ; ATOM-NEXT: #NO_APP @@ -1936,8 +1936,8 @@ define void @test_fdivrp_fidivr(i16 *%a0, i32 *%a1) optsize { ; SLM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [3:1.00] ; SLM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [3:1.00] ; SLM-NEXT: #APP -; SLM-NEXT: fdivrp %st(1) # sched: [19:17.00] -; SLM-NEXT: fdivrp %st(2) # sched: [19:17.00] +; SLM-NEXT: fdivrp %st, %st(1) # sched: [19:17.00] +; SLM-NEXT: fdivrp %st, %st(2) # sched: [19:17.00] ; SLM-NEXT: fidivrs (%ecx) # sched: [22:17.00] ; SLM-NEXT: fidivrl (%eax) # sched: [22:17.00] ; SLM-NEXT: #NO_APP @@ -1948,8 +1948,8 @@ define void @test_fdivrp_fidivr(i16 *%a0, i32 *%a1) optsize { ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SANDY-NEXT: #APP -; SANDY-NEXT: fdivrp %st(1) # sched: [14:14.00] -; SANDY-NEXT: fdivrp %st(2) # sched: [14:14.00] +; SANDY-NEXT: fdivrp %st, %st(1) # sched: [14:14.00] +; SANDY-NEXT: fdivrp %st, %st(2) # sched: [14:14.00] ; SANDY-NEXT: fidivrs (%ecx) # sched: [34:1.00] ; SANDY-NEXT: fidivrl (%eax) # sched: [34:1.00] ; SANDY-NEXT: #NO_APP @@ -1960,8 +1960,8 @@ define void @test_fdivrp_fidivr(i16 *%a0, i32 *%a1) optsize { ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; HASWELL-NEXT: #APP -; HASWELL-NEXT: fdivrp %st(1) # sched: [20:1.00] -; HASWELL-NEXT: fdivrp %st(2) # sched: [20:1.00] +; HASWELL-NEXT: fdivrp %st, %st(1) # sched: [20:1.00] +; HASWELL-NEXT: fdivrp %st, %st(2) # sched: [20:1.00] ; HASWELL-NEXT: fidivrs (%ecx) # sched: [30:1.00] ; HASWELL-NEXT: fidivrl (%eax) # sched: [30:1.00] ; HASWELL-NEXT: #NO_APP @@ -1972,8 +1972,8 @@ define void @test_fdivrp_fidivr(i16 *%a0, i32 *%a1) optsize { ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: fdivrp %st(1) # sched: [20:1.00] -; BROADWELL-NEXT: fdivrp %st(2) # sched: [20:1.00] +; BROADWELL-NEXT: fdivrp %st, %st(1) # sched: [20:1.00] +; BROADWELL-NEXT: fdivrp %st, %st(2) # sched: [20:1.00] ; BROADWELL-NEXT: fidivrs (%ecx) # sched: [29:1.00] ; BROADWELL-NEXT: fidivrl (%eax) # sched: [29:1.00] ; BROADWELL-NEXT: #NO_APP @@ -1984,8 +1984,8 @@ define void @test_fdivrp_fidivr(i16 *%a0, i32 *%a1) optsize { ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: fdivrp %st(1) # sched: [20:1.00] -; SKYLAKE-NEXT: fdivrp %st(2) # sched: [20:1.00] +; SKYLAKE-NEXT: fdivrp %st, %st(1) # sched: [20:1.00] +; SKYLAKE-NEXT: fdivrp %st, %st(2) # sched: [20:1.00] ; SKYLAKE-NEXT: fidivrs (%ecx) # sched: [30:1.00] ; SKYLAKE-NEXT: fidivrl (%eax) # sched: [30:1.00] ; SKYLAKE-NEXT: #NO_APP @@ -1996,8 +1996,8 @@ define void @test_fdivrp_fidivr(i16 *%a0, i32 *%a1) optsize { ; SKX-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKX-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKX-NEXT: #APP -; SKX-NEXT: fdivrp %st(1) # sched: [20:1.00] -; SKX-NEXT: fdivrp %st(2) # sched: [20:1.00] +; SKX-NEXT: fdivrp %st, %st(1) # sched: [20:1.00] +; SKX-NEXT: fdivrp %st, %st(2) # sched: [20:1.00] ; SKX-NEXT: fidivrs (%ecx) # sched: [30:1.00] ; SKX-NEXT: fidivrl (%eax) # sched: [30:1.00] ; SKX-NEXT: #NO_APP @@ -2008,8 +2008,8 @@ define void @test_fdivrp_fidivr(i16 *%a0, i32 *%a1) optsize { ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BDVER2-NEXT: #APP -; BDVER2-NEXT: fdivrp %st(1) # sched: [9:9.50] -; BDVER2-NEXT: fdivrp %st(2) # sched: [9:9.50] +; BDVER2-NEXT: fdivrp %st, %st(1) # sched: [9:9.50] +; BDVER2-NEXT: fdivrp %st, %st(2) # sched: [9:9.50] ; BDVER2-NEXT: fidivrs (%ecx) # sched: [14:9.50] ; BDVER2-NEXT: fidivrl (%eax) # sched: [14:9.50] ; BDVER2-NEXT: #NO_APP @@ -2020,8 +2020,8 @@ define void @test_fdivrp_fidivr(i16 *%a0, i32 *%a1) optsize { ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:1.00] ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:1.00] ; BTVER2-NEXT: #APP -; BTVER2-NEXT: fdivrp %st(1) # sched: [19:19.00] -; BTVER2-NEXT: fdivrp %st(2) # sched: [19:19.00] +; BTVER2-NEXT: fdivrp %st, %st(1) # sched: [19:19.00] +; BTVER2-NEXT: fdivrp %st, %st(2) # sched: [19:19.00] ; BTVER2-NEXT: fidivrs (%ecx) # sched: [24:19.00] ; BTVER2-NEXT: fidivrl (%eax) # sched: [24:19.00] ; BTVER2-NEXT: #NO_APP @@ -2032,8 +2032,8 @@ define void @test_fdivrp_fidivr(i16 *%a0, i32 *%a1) optsize { ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [8:0.50] ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [8:0.50] ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: fdivrp %st(1) # sched: [15:1.00] -; ZNVER1-NEXT: fdivrp %st(2) # sched: [15:1.00] +; ZNVER1-NEXT: fdivrp %st, %st(1) # sched: [15:1.00] +; ZNVER1-NEXT: fdivrp %st, %st(2) # sched: [15:1.00] ; ZNVER1-NEXT: fidivrs (%ecx) # sched: [22:1.00] ; ZNVER1-NEXT: fidivrl (%eax) # sched: [22:1.00] ; ZNVER1-NEXT: #NO_APP @@ -3243,8 +3243,8 @@ define void @test_fmul(float *%a0, double *%a1) optsize { ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %ecx ; GENERIC-NEXT: #APP -; GENERIC-NEXT: fmul %st(0), %st(1) -; GENERIC-NEXT: fmul %st(2) +; GENERIC-NEXT: fmul %st, %st(1) +; GENERIC-NEXT: fmul %st(2), %st ; GENERIC-NEXT: fmuls (%ecx) ; GENERIC-NEXT: fmull (%eax) ; GENERIC-NEXT: #NO_APP @@ -3255,8 +3255,8 @@ define void @test_fmul(float *%a0, double *%a1) optsize { ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [1:1.00] ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [1:1.00] ; ATOM-NEXT: #APP -; ATOM-NEXT: fmul %st(0), %st(1) # sched: [4:4.00] -; ATOM-NEXT: fmul %st(2) # sched: [4:4.00] +; ATOM-NEXT: fmul %st, %st(1) # sched: [4:4.00] +; ATOM-NEXT: fmul %st(2), %st # sched: [4:4.00] ; ATOM-NEXT: fmuls (%ecx) # sched: [4:4.00] ; ATOM-NEXT: fmull (%eax) # sched: [4:4.00] ; ATOM-NEXT: #NO_APP @@ -3267,8 +3267,8 @@ define void @test_fmul(float *%a0, double *%a1) optsize { ; SLM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [3:1.00] ; SLM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [3:1.00] ; SLM-NEXT: #APP -; SLM-NEXT: fmul %st(0), %st(1) # sched: [5:2.00] -; SLM-NEXT: fmul %st(2) # sched: [5:2.00] +; SLM-NEXT: fmul %st, %st(1) # sched: [5:2.00] +; SLM-NEXT: fmul %st(2), %st # sched: [5:2.00] ; SLM-NEXT: fmuls (%ecx) # sched: [8:2.00] ; SLM-NEXT: fmull (%eax) # sched: [8:2.00] ; SLM-NEXT: #NO_APP @@ -3279,8 +3279,8 @@ define void @test_fmul(float *%a0, double *%a1) optsize { ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SANDY-NEXT: #APP -; SANDY-NEXT: fmul %st(0), %st(1) # sched: [5:1.00] -; SANDY-NEXT: fmul %st(2) # sched: [5:1.00] +; SANDY-NEXT: fmul %st, %st(1) # sched: [5:1.00] +; SANDY-NEXT: fmul %st(2), %st # sched: [5:1.00] ; SANDY-NEXT: fmuls (%ecx) # sched: [12:1.00] ; SANDY-NEXT: fmull (%eax) # sched: [12:1.00] ; SANDY-NEXT: #NO_APP @@ -3291,8 +3291,8 @@ define void @test_fmul(float *%a0, double *%a1) optsize { ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; HASWELL-NEXT: #APP -; HASWELL-NEXT: fmul %st(0), %st(1) # sched: [5:1.00] -; HASWELL-NEXT: fmul %st(2) # sched: [5:1.00] +; HASWELL-NEXT: fmul %st, %st(1) # sched: [5:1.00] +; HASWELL-NEXT: fmul %st(2), %st # sched: [5:1.00] ; HASWELL-NEXT: fmuls (%ecx) # sched: [12:1.00] ; HASWELL-NEXT: fmull (%eax) # sched: [12:1.00] ; HASWELL-NEXT: #NO_APP @@ -3303,8 +3303,8 @@ define void @test_fmul(float *%a0, double *%a1) optsize { ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: fmul %st(0), %st(1) # sched: [5:1.00] -; BROADWELL-NEXT: fmul %st(2) # sched: [5:1.00] +; BROADWELL-NEXT: fmul %st, %st(1) # sched: [5:1.00] +; BROADWELL-NEXT: fmul %st(2), %st # sched: [5:1.00] ; BROADWELL-NEXT: fmuls (%ecx) # sched: [11:1.00] ; BROADWELL-NEXT: fmull (%eax) # sched: [11:1.00] ; BROADWELL-NEXT: #NO_APP @@ -3315,8 +3315,8 @@ define void @test_fmul(float *%a0, double *%a1) optsize { ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: fmul %st(0), %st(1) # sched: [4:1.00] -; SKYLAKE-NEXT: fmul %st(2) # sched: [4:1.00] +; SKYLAKE-NEXT: fmul %st, %st(1) # sched: [4:1.00] +; SKYLAKE-NEXT: fmul %st(2), %st # sched: [4:1.00] ; SKYLAKE-NEXT: fmuls (%ecx) # sched: [11:1.00] ; SKYLAKE-NEXT: fmull (%eax) # sched: [11:1.00] ; SKYLAKE-NEXT: #NO_APP @@ -3327,8 +3327,8 @@ define void @test_fmul(float *%a0, double *%a1) optsize { ; SKX-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKX-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKX-NEXT: #APP -; SKX-NEXT: fmul %st(0), %st(1) # sched: [4:1.00] -; SKX-NEXT: fmul %st(2) # sched: [4:1.00] +; SKX-NEXT: fmul %st, %st(1) # sched: [4:1.00] +; SKX-NEXT: fmul %st(2), %st # sched: [4:1.00] ; SKX-NEXT: fmuls (%ecx) # sched: [11:1.00] ; SKX-NEXT: fmull (%eax) # sched: [11:1.00] ; SKX-NEXT: #NO_APP @@ -3339,8 +3339,8 @@ define void @test_fmul(float *%a0, double *%a1) optsize { ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BDVER2-NEXT: #APP -; BDVER2-NEXT: fmul %st(0), %st(1) # sched: [5:1.00] -; BDVER2-NEXT: fmul %st(2) # sched: [5:1.00] +; BDVER2-NEXT: fmul %st, %st(1) # sched: [5:1.00] +; BDVER2-NEXT: fmul %st(2), %st # sched: [5:1.00] ; BDVER2-NEXT: fmuls (%ecx) # sched: [10:1.00] ; BDVER2-NEXT: fmull (%eax) # sched: [10:1.00] ; BDVER2-NEXT: #NO_APP @@ -3351,8 +3351,8 @@ define void @test_fmul(float *%a0, double *%a1) optsize { ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:1.00] ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:1.00] ; BTVER2-NEXT: #APP -; BTVER2-NEXT: fmul %st(0), %st(1) # sched: [2:1.00] -; BTVER2-NEXT: fmul %st(2) # sched: [2:1.00] +; BTVER2-NEXT: fmul %st, %st(1) # sched: [2:1.00] +; BTVER2-NEXT: fmul %st(2), %st # sched: [2:1.00] ; BTVER2-NEXT: fmuls (%ecx) # sched: [7:1.00] ; BTVER2-NEXT: fmull (%eax) # sched: [7:1.00] ; BTVER2-NEXT: #NO_APP @@ -3363,8 +3363,8 @@ define void @test_fmul(float *%a0, double *%a1) optsize { ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [8:0.50] ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [8:0.50] ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: fmul %st(0), %st(1) # sched: [3:0.50] -; ZNVER1-NEXT: fmul %st(2) # sched: [3:0.50] +; ZNVER1-NEXT: fmul %st, %st(1) # sched: [3:0.50] +; ZNVER1-NEXT: fmul %st(2), %st # sched: [3:0.50] ; ZNVER1-NEXT: fmuls (%ecx) # sched: [10:0.50] ; ZNVER1-NEXT: fmull (%eax) # sched: [10:0.50] ; ZNVER1-NEXT: #NO_APP @@ -3379,8 +3379,8 @@ define void @test_fmulp_fimul(i16 *%a0, i32 *%a1) optsize { ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %ecx ; GENERIC-NEXT: #APP -; GENERIC-NEXT: fmulp %st(1) -; GENERIC-NEXT: fmulp %st(2) +; GENERIC-NEXT: fmulp %st, %st(1) +; GENERIC-NEXT: fmulp %st, %st(2) ; GENERIC-NEXT: fimuls (%ecx) ; GENERIC-NEXT: fimull (%eax) ; GENERIC-NEXT: #NO_APP @@ -3391,8 +3391,8 @@ define void @test_fmulp_fimul(i16 *%a0, i32 *%a1) optsize { ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [1:1.00] ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [1:1.00] ; ATOM-NEXT: #APP -; ATOM-NEXT: fmulp %st(1) # sched: [4:4.00] -; ATOM-NEXT: fmulp %st(2) # sched: [4:4.00] +; ATOM-NEXT: fmulp %st, %st(1) # sched: [4:4.00] +; ATOM-NEXT: fmulp %st, %st(2) # sched: [4:4.00] ; ATOM-NEXT: fimuls (%ecx) # sched: [4:4.00] ; ATOM-NEXT: fimull (%eax) # sched: [4:4.00] ; ATOM-NEXT: #NO_APP @@ -3403,8 +3403,8 @@ define void @test_fmulp_fimul(i16 *%a0, i32 *%a1) optsize { ; SLM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [3:1.00] ; SLM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [3:1.00] ; SLM-NEXT: #APP -; SLM-NEXT: fmulp %st(1) # sched: [5:2.00] -; SLM-NEXT: fmulp %st(2) # sched: [5:2.00] +; SLM-NEXT: fmulp %st, %st(1) # sched: [5:2.00] +; SLM-NEXT: fmulp %st, %st(2) # sched: [5:2.00] ; SLM-NEXT: fimuls (%ecx) # sched: [8:2.00] ; SLM-NEXT: fimull (%eax) # sched: [8:2.00] ; SLM-NEXT: #NO_APP @@ -3415,8 +3415,8 @@ define void @test_fmulp_fimul(i16 *%a0, i32 *%a1) optsize { ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SANDY-NEXT: #APP -; SANDY-NEXT: fmulp %st(1) # sched: [5:1.00] -; SANDY-NEXT: fmulp %st(2) # sched: [5:1.00] +; SANDY-NEXT: fmulp %st, %st(1) # sched: [5:1.00] +; SANDY-NEXT: fmulp %st, %st(2) # sched: [5:1.00] ; SANDY-NEXT: fimuls (%ecx) # sched: [15:1.00] ; SANDY-NEXT: fimull (%eax) # sched: [15:1.00] ; SANDY-NEXT: #NO_APP @@ -3427,8 +3427,8 @@ define void @test_fmulp_fimul(i16 *%a0, i32 *%a1) optsize { ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; HASWELL-NEXT: #APP -; HASWELL-NEXT: fmulp %st(1) # sched: [5:1.00] -; HASWELL-NEXT: fmulp %st(2) # sched: [5:1.00] +; HASWELL-NEXT: fmulp %st, %st(1) # sched: [5:1.00] +; HASWELL-NEXT: fmulp %st, %st(2) # sched: [5:1.00] ; HASWELL-NEXT: fimuls (%ecx) # sched: [15:1.00] ; HASWELL-NEXT: fimull (%eax) # sched: [15:1.00] ; HASWELL-NEXT: #NO_APP @@ -3439,8 +3439,8 @@ define void @test_fmulp_fimul(i16 *%a0, i32 *%a1) optsize { ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: fmulp %st(1) # sched: [5:1.00] -; BROADWELL-NEXT: fmulp %st(2) # sched: [5:1.00] +; BROADWELL-NEXT: fmulp %st, %st(1) # sched: [5:1.00] +; BROADWELL-NEXT: fmulp %st, %st(2) # sched: [5:1.00] ; BROADWELL-NEXT: fimuls (%ecx) # sched: [14:1.00] ; BROADWELL-NEXT: fimull (%eax) # sched: [14:1.00] ; BROADWELL-NEXT: #NO_APP @@ -3451,8 +3451,8 @@ define void @test_fmulp_fimul(i16 *%a0, i32 *%a1) optsize { ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: fmulp %st(1) # sched: [4:1.00] -; SKYLAKE-NEXT: fmulp %st(2) # sched: [4:1.00] +; SKYLAKE-NEXT: fmulp %st, %st(1) # sched: [4:1.00] +; SKYLAKE-NEXT: fmulp %st, %st(2) # sched: [4:1.00] ; SKYLAKE-NEXT: fimuls (%ecx) # sched: [14:1.00] ; SKYLAKE-NEXT: fimull (%eax) # sched: [14:1.00] ; SKYLAKE-NEXT: #NO_APP @@ -3463,8 +3463,8 @@ define void @test_fmulp_fimul(i16 *%a0, i32 *%a1) optsize { ; SKX-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKX-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKX-NEXT: #APP -; SKX-NEXT: fmulp %st(1) # sched: [4:1.00] -; SKX-NEXT: fmulp %st(2) # sched: [4:1.00] +; SKX-NEXT: fmulp %st, %st(1) # sched: [4:1.00] +; SKX-NEXT: fmulp %st, %st(2) # sched: [4:1.00] ; SKX-NEXT: fimuls (%ecx) # sched: [14:1.00] ; SKX-NEXT: fimull (%eax) # sched: [14:1.00] ; SKX-NEXT: #NO_APP @@ -3475,8 +3475,8 @@ define void @test_fmulp_fimul(i16 *%a0, i32 *%a1) optsize { ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BDVER2-NEXT: #APP -; BDVER2-NEXT: fmulp %st(1) # sched: [5:1.00] -; BDVER2-NEXT: fmulp %st(2) # sched: [5:1.00] +; BDVER2-NEXT: fmulp %st, %st(1) # sched: [5:1.00] +; BDVER2-NEXT: fmulp %st, %st(2) # sched: [5:1.00] ; BDVER2-NEXT: fimuls (%ecx) # sched: [10:1.00] ; BDVER2-NEXT: fimull (%eax) # sched: [10:1.00] ; BDVER2-NEXT: #NO_APP @@ -3487,8 +3487,8 @@ define void @test_fmulp_fimul(i16 *%a0, i32 *%a1) optsize { ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:1.00] ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:1.00] ; BTVER2-NEXT: #APP -; BTVER2-NEXT: fmulp %st(1) # sched: [2:1.00] -; BTVER2-NEXT: fmulp %st(2) # sched: [2:1.00] +; BTVER2-NEXT: fmulp %st, %st(1) # sched: [2:1.00] +; BTVER2-NEXT: fmulp %st, %st(2) # sched: [2:1.00] ; BTVER2-NEXT: fimuls (%ecx) # sched: [7:1.00] ; BTVER2-NEXT: fimull (%eax) # sched: [7:1.00] ; BTVER2-NEXT: #NO_APP @@ -3499,8 +3499,8 @@ define void @test_fmulp_fimul(i16 *%a0, i32 *%a1) optsize { ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [8:0.50] ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [8:0.50] ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: fmulp %st(1) # sched: [3:0.50] -; ZNVER1-NEXT: fmulp %st(2) # sched: [3:0.50] +; ZNVER1-NEXT: fmulp %st, %st(1) # sched: [3:0.50] +; ZNVER1-NEXT: fmulp %st, %st(2) # sched: [3:0.50] ; ZNVER1-NEXT: fimuls (%ecx) # sched: [10:0.50] ; ZNVER1-NEXT: fimull (%eax) # sched: [10:0.50] ; ZNVER1-NEXT: #NO_APP @@ -4983,8 +4983,8 @@ define void @test_fsub(float *%a0, double *%a1) optsize { ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %ecx ; GENERIC-NEXT: #APP -; GENERIC-NEXT: fsub %st(0), %st(1) -; GENERIC-NEXT: fsub %st(2) +; GENERIC-NEXT: fsub %st, %st(1) +; GENERIC-NEXT: fsub %st(2), %st ; GENERIC-NEXT: fsubs (%ecx) ; GENERIC-NEXT: fsubl (%eax) ; GENERIC-NEXT: #NO_APP @@ -4995,8 +4995,8 @@ define void @test_fsub(float *%a0, double *%a1) optsize { ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [1:1.00] ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [1:1.00] ; ATOM-NEXT: #APP -; ATOM-NEXT: fsub %st(0), %st(1) # sched: [5:5.00] -; ATOM-NEXT: fsub %st(2) # sched: [5:5.00] +; ATOM-NEXT: fsub %st, %st(1) # sched: [5:5.00] +; ATOM-NEXT: fsub %st(2), %st # sched: [5:5.00] ; ATOM-NEXT: fsubs (%ecx) # sched: [5:5.00] ; ATOM-NEXT: fsubl (%eax) # sched: [5:5.00] ; ATOM-NEXT: #NO_APP @@ -5007,8 +5007,8 @@ define void @test_fsub(float *%a0, double *%a1) optsize { ; SLM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [3:1.00] ; SLM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [3:1.00] ; SLM-NEXT: #APP -; SLM-NEXT: fsub %st(0), %st(1) # sched: [3:1.00] -; SLM-NEXT: fsub %st(2) # sched: [3:1.00] +; SLM-NEXT: fsub %st, %st(1) # sched: [3:1.00] +; SLM-NEXT: fsub %st(2), %st # sched: [3:1.00] ; SLM-NEXT: fsubs (%ecx) # sched: [6:1.00] ; SLM-NEXT: fsubl (%eax) # sched: [6:1.00] ; SLM-NEXT: #NO_APP @@ -5019,8 +5019,8 @@ define void @test_fsub(float *%a0, double *%a1) optsize { ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SANDY-NEXT: #APP -; SANDY-NEXT: fsub %st(0), %st(1) # sched: [3:1.00] -; SANDY-NEXT: fsub %st(2) # sched: [3:1.00] +; SANDY-NEXT: fsub %st, %st(1) # sched: [3:1.00] +; SANDY-NEXT: fsub %st(2), %st # sched: [3:1.00] ; SANDY-NEXT: fsubs (%ecx) # sched: [10:1.00] ; SANDY-NEXT: fsubl (%eax) # sched: [10:1.00] ; SANDY-NEXT: #NO_APP @@ -5031,8 +5031,8 @@ define void @test_fsub(float *%a0, double *%a1) optsize { ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; HASWELL-NEXT: #APP -; HASWELL-NEXT: fsub %st(0), %st(1) # sched: [3:1.00] -; HASWELL-NEXT: fsub %st(2) # sched: [3:1.00] +; HASWELL-NEXT: fsub %st, %st(1) # sched: [3:1.00] +; HASWELL-NEXT: fsub %st(2), %st # sched: [3:1.00] ; HASWELL-NEXT: fsubs (%ecx) # sched: [10:1.00] ; HASWELL-NEXT: fsubl (%eax) # sched: [10:1.00] ; HASWELL-NEXT: #NO_APP @@ -5043,8 +5043,8 @@ define void @test_fsub(float *%a0, double *%a1) optsize { ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: fsub %st(0), %st(1) # sched: [3:1.00] -; BROADWELL-NEXT: fsub %st(2) # sched: [3:1.00] +; BROADWELL-NEXT: fsub %st, %st(1) # sched: [3:1.00] +; BROADWELL-NEXT: fsub %st(2), %st # sched: [3:1.00] ; BROADWELL-NEXT: fsubs (%ecx) # sched: [9:1.00] ; BROADWELL-NEXT: fsubl (%eax) # sched: [9:1.00] ; BROADWELL-NEXT: #NO_APP @@ -5055,8 +5055,8 @@ define void @test_fsub(float *%a0, double *%a1) optsize { ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: fsub %st(0), %st(1) # sched: [3:1.00] -; SKYLAKE-NEXT: fsub %st(2) # sched: [3:1.00] +; SKYLAKE-NEXT: fsub %st, %st(1) # sched: [3:1.00] +; SKYLAKE-NEXT: fsub %st(2), %st # sched: [3:1.00] ; SKYLAKE-NEXT: fsubs (%ecx) # sched: [10:1.00] ; SKYLAKE-NEXT: fsubl (%eax) # sched: [10:1.00] ; SKYLAKE-NEXT: #NO_APP @@ -5067,8 +5067,8 @@ define void @test_fsub(float *%a0, double *%a1) optsize { ; SKX-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKX-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKX-NEXT: #APP -; SKX-NEXT: fsub %st(0), %st(1) # sched: [3:1.00] -; SKX-NEXT: fsub %st(2) # sched: [3:1.00] +; SKX-NEXT: fsub %st, %st(1) # sched: [3:1.00] +; SKX-NEXT: fsub %st(2), %st # sched: [3:1.00] ; SKX-NEXT: fsubs (%ecx) # sched: [10:1.00] ; SKX-NEXT: fsubl (%eax) # sched: [10:1.00] ; SKX-NEXT: #NO_APP @@ -5079,8 +5079,8 @@ define void @test_fsub(float *%a0, double *%a1) optsize { ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BDVER2-NEXT: #APP -; BDVER2-NEXT: fsub %st(0), %st(1) # sched: [5:1.00] -; BDVER2-NEXT: fsub %st(2) # sched: [5:1.00] +; BDVER2-NEXT: fsub %st, %st(1) # sched: [5:1.00] +; BDVER2-NEXT: fsub %st(2), %st # sched: [5:1.00] ; BDVER2-NEXT: fsubs (%ecx) # sched: [10:1.00] ; BDVER2-NEXT: fsubl (%eax) # sched: [10:1.00] ; BDVER2-NEXT: #NO_APP @@ -5091,8 +5091,8 @@ define void @test_fsub(float *%a0, double *%a1) optsize { ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:1.00] ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:1.00] ; BTVER2-NEXT: #APP -; BTVER2-NEXT: fsub %st(0), %st(1) # sched: [3:1.00] -; BTVER2-NEXT: fsub %st(2) # sched: [3:1.00] +; BTVER2-NEXT: fsub %st, %st(1) # sched: [3:1.00] +; BTVER2-NEXT: fsub %st(2), %st # sched: [3:1.00] ; BTVER2-NEXT: fsubs (%ecx) # sched: [8:1.00] ; BTVER2-NEXT: fsubl (%eax) # sched: [8:1.00] ; BTVER2-NEXT: #NO_APP @@ -5103,8 +5103,8 @@ define void @test_fsub(float *%a0, double *%a1) optsize { ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [8:0.50] ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [8:0.50] ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: fsub %st(0), %st(1) # sched: [3:1.00] -; ZNVER1-NEXT: fsub %st(2) # sched: [3:1.00] +; ZNVER1-NEXT: fsub %st, %st(1) # sched: [3:1.00] +; ZNVER1-NEXT: fsub %st(2), %st # sched: [3:1.00] ; ZNVER1-NEXT: fsubs (%ecx) # sched: [10:1.00] ; ZNVER1-NEXT: fsubl (%eax) # sched: [10:1.00] ; ZNVER1-NEXT: #NO_APP @@ -5119,8 +5119,8 @@ define void @test_fsubp_fisub(i16 *%a0, i32 *%a1) optsize { ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %ecx ; GENERIC-NEXT: #APP -; GENERIC-NEXT: fsubp %st(1) -; GENERIC-NEXT: fsubp %st(2) +; GENERIC-NEXT: fsubp %st, %st(1) +; GENERIC-NEXT: fsubp %st, %st(2) ; GENERIC-NEXT: fisubs (%ecx) ; GENERIC-NEXT: fisubl (%eax) ; GENERIC-NEXT: #NO_APP @@ -5131,8 +5131,8 @@ define void @test_fsubp_fisub(i16 *%a0, i32 *%a1) optsize { ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [1:1.00] ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [1:1.00] ; ATOM-NEXT: #APP -; ATOM-NEXT: fsubp %st(1) # sched: [5:5.00] -; ATOM-NEXT: fsubp %st(2) # sched: [5:5.00] +; ATOM-NEXT: fsubp %st, %st(1) # sched: [5:5.00] +; ATOM-NEXT: fsubp %st, %st(2) # sched: [5:5.00] ; ATOM-NEXT: fisubs (%ecx) # sched: [5:5.00] ; ATOM-NEXT: fisubl (%eax) # sched: [5:5.00] ; ATOM-NEXT: #NO_APP @@ -5143,8 +5143,8 @@ define void @test_fsubp_fisub(i16 *%a0, i32 *%a1) optsize { ; SLM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [3:1.00] ; SLM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [3:1.00] ; SLM-NEXT: #APP -; SLM-NEXT: fsubp %st(1) # sched: [3:1.00] -; SLM-NEXT: fsubp %st(2) # sched: [3:1.00] +; SLM-NEXT: fsubp %st, %st(1) # sched: [3:1.00] +; SLM-NEXT: fsubp %st, %st(2) # sched: [3:1.00] ; SLM-NEXT: fisubs (%ecx) # sched: [6:1.00] ; SLM-NEXT: fisubl (%eax) # sched: [6:1.00] ; SLM-NEXT: #NO_APP @@ -5155,8 +5155,8 @@ define void @test_fsubp_fisub(i16 *%a0, i32 *%a1) optsize { ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SANDY-NEXT: #APP -; SANDY-NEXT: fsubp %st(1) # sched: [3:1.00] -; SANDY-NEXT: fsubp %st(2) # sched: [3:1.00] +; SANDY-NEXT: fsubp %st, %st(1) # sched: [3:1.00] +; SANDY-NEXT: fsubp %st, %st(2) # sched: [3:1.00] ; SANDY-NEXT: fisubs (%ecx) # sched: [13:2.00] ; SANDY-NEXT: fisubl (%eax) # sched: [13:2.00] ; SANDY-NEXT: #NO_APP @@ -5167,8 +5167,8 @@ define void @test_fsubp_fisub(i16 *%a0, i32 *%a1) optsize { ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; HASWELL-NEXT: #APP -; HASWELL-NEXT: fsubp %st(1) # sched: [3:1.00] -; HASWELL-NEXT: fsubp %st(2) # sched: [3:1.00] +; HASWELL-NEXT: fsubp %st, %st(1) # sched: [3:1.00] +; HASWELL-NEXT: fsubp %st, %st(2) # sched: [3:1.00] ; HASWELL-NEXT: fisubs (%ecx) # sched: [13:2.00] ; HASWELL-NEXT: fisubl (%eax) # sched: [13:2.00] ; HASWELL-NEXT: #NO_APP @@ -5179,8 +5179,8 @@ define void @test_fsubp_fisub(i16 *%a0, i32 *%a1) optsize { ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: fsubp %st(1) # sched: [3:1.00] -; BROADWELL-NEXT: fsubp %st(2) # sched: [3:1.00] +; BROADWELL-NEXT: fsubp %st, %st(1) # sched: [3:1.00] +; BROADWELL-NEXT: fsubp %st, %st(2) # sched: [3:1.00] ; BROADWELL-NEXT: fisubs (%ecx) # sched: [12:2.00] ; BROADWELL-NEXT: fisubl (%eax) # sched: [12:2.00] ; BROADWELL-NEXT: #NO_APP @@ -5191,8 +5191,8 @@ define void @test_fsubp_fisub(i16 *%a0, i32 *%a1) optsize { ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: fsubp %st(1) # sched: [3:1.00] -; SKYLAKE-NEXT: fsubp %st(2) # sched: [3:1.00] +; SKYLAKE-NEXT: fsubp %st, %st(1) # sched: [3:1.00] +; SKYLAKE-NEXT: fsubp %st, %st(2) # sched: [3:1.00] ; SKYLAKE-NEXT: fisubs (%ecx) # sched: [13:2.00] ; SKYLAKE-NEXT: fisubl (%eax) # sched: [13:2.00] ; SKYLAKE-NEXT: #NO_APP @@ -5203,8 +5203,8 @@ define void @test_fsubp_fisub(i16 *%a0, i32 *%a1) optsize { ; SKX-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKX-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKX-NEXT: #APP -; SKX-NEXT: fsubp %st(1) # sched: [3:1.00] -; SKX-NEXT: fsubp %st(2) # sched: [3:1.00] +; SKX-NEXT: fsubp %st, %st(1) # sched: [3:1.00] +; SKX-NEXT: fsubp %st, %st(2) # sched: [3:1.00] ; SKX-NEXT: fisubs (%ecx) # sched: [13:2.00] ; SKX-NEXT: fisubl (%eax) # sched: [13:2.00] ; SKX-NEXT: #NO_APP @@ -5215,8 +5215,8 @@ define void @test_fsubp_fisub(i16 *%a0, i32 *%a1) optsize { ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BDVER2-NEXT: #APP -; BDVER2-NEXT: fsubp %st(1) # sched: [5:1.00] -; BDVER2-NEXT: fsubp %st(2) # sched: [5:1.00] +; BDVER2-NEXT: fsubp %st, %st(1) # sched: [5:1.00] +; BDVER2-NEXT: fsubp %st, %st(2) # sched: [5:1.00] ; BDVER2-NEXT: fisubs (%ecx) # sched: [10:1.00] ; BDVER2-NEXT: fisubl (%eax) # sched: [10:1.00] ; BDVER2-NEXT: #NO_APP @@ -5227,8 +5227,8 @@ define void @test_fsubp_fisub(i16 *%a0, i32 *%a1) optsize { ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:1.00] ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:1.00] ; BTVER2-NEXT: #APP -; BTVER2-NEXT: fsubp %st(1) # sched: [3:1.00] -; BTVER2-NEXT: fsubp %st(2) # sched: [3:1.00] +; BTVER2-NEXT: fsubp %st, %st(1) # sched: [3:1.00] +; BTVER2-NEXT: fsubp %st, %st(2) # sched: [3:1.00] ; BTVER2-NEXT: fisubs (%ecx) # sched: [8:1.00] ; BTVER2-NEXT: fisubl (%eax) # sched: [8:1.00] ; BTVER2-NEXT: #NO_APP @@ -5239,8 +5239,8 @@ define void @test_fsubp_fisub(i16 *%a0, i32 *%a1) optsize { ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [8:0.50] ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [8:0.50] ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: fsubp %st(1) # sched: [3:1.00] -; ZNVER1-NEXT: fsubp %st(2) # sched: [3:1.00] +; ZNVER1-NEXT: fsubp %st, %st(1) # sched: [3:1.00] +; ZNVER1-NEXT: fsubp %st, %st(2) # sched: [3:1.00] ; ZNVER1-NEXT: fisubs (%ecx) # sched: [10:1.00] ; ZNVER1-NEXT: fisubl (%eax) # sched: [10:1.00] ; ZNVER1-NEXT: #NO_APP @@ -5255,8 +5255,8 @@ define void @test_fsubr(float *%a0, double *%a1) optsize { ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %ecx ; GENERIC-NEXT: #APP -; GENERIC-NEXT: fsubr %st(0), %st(1) -; GENERIC-NEXT: fsubr %st(2) +; GENERIC-NEXT: fsubr %st, %st(1) +; GENERIC-NEXT: fsubr %st(2), %st ; GENERIC-NEXT: fsubrs (%ecx) ; GENERIC-NEXT: fsubrl (%eax) ; GENERIC-NEXT: #NO_APP @@ -5267,8 +5267,8 @@ define void @test_fsubr(float *%a0, double *%a1) optsize { ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [1:1.00] ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [1:1.00] ; ATOM-NEXT: #APP -; ATOM-NEXT: fsubr %st(0), %st(1) # sched: [5:5.00] -; ATOM-NEXT: fsubr %st(2) # sched: [5:5.00] +; ATOM-NEXT: fsubr %st, %st(1) # sched: [5:5.00] +; ATOM-NEXT: fsubr %st(2), %st # sched: [5:5.00] ; ATOM-NEXT: fsubrs (%ecx) # sched: [5:5.00] ; ATOM-NEXT: fsubrl (%eax) # sched: [5:5.00] ; ATOM-NEXT: #NO_APP @@ -5279,8 +5279,8 @@ define void @test_fsubr(float *%a0, double *%a1) optsize { ; SLM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [3:1.00] ; SLM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [3:1.00] ; SLM-NEXT: #APP -; SLM-NEXT: fsubr %st(0), %st(1) # sched: [3:1.00] -; SLM-NEXT: fsubr %st(2) # sched: [3:1.00] +; SLM-NEXT: fsubr %st, %st(1) # sched: [3:1.00] +; SLM-NEXT: fsubr %st(2), %st # sched: [3:1.00] ; SLM-NEXT: fsubrs (%ecx) # sched: [6:1.00] ; SLM-NEXT: fsubrl (%eax) # sched: [6:1.00] ; SLM-NEXT: #NO_APP @@ -5291,8 +5291,8 @@ define void @test_fsubr(float *%a0, double *%a1) optsize { ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SANDY-NEXT: #APP -; SANDY-NEXT: fsubr %st(0), %st(1) # sched: [3:1.00] -; SANDY-NEXT: fsubr %st(2) # sched: [3:1.00] +; SANDY-NEXT: fsubr %st, %st(1) # sched: [3:1.00] +; SANDY-NEXT: fsubr %st(2), %st # sched: [3:1.00] ; SANDY-NEXT: fsubrs (%ecx) # sched: [10:1.00] ; SANDY-NEXT: fsubrl (%eax) # sched: [10:1.00] ; SANDY-NEXT: #NO_APP @@ -5303,8 +5303,8 @@ define void @test_fsubr(float *%a0, double *%a1) optsize { ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; HASWELL-NEXT: #APP -; HASWELL-NEXT: fsubr %st(0), %st(1) # sched: [3:1.00] -; HASWELL-NEXT: fsubr %st(2) # sched: [3:1.00] +; HASWELL-NEXT: fsubr %st, %st(1) # sched: [3:1.00] +; HASWELL-NEXT: fsubr %st(2), %st # sched: [3:1.00] ; HASWELL-NEXT: fsubrs (%ecx) # sched: [10:1.00] ; HASWELL-NEXT: fsubrl (%eax) # sched: [10:1.00] ; HASWELL-NEXT: #NO_APP @@ -5315,8 +5315,8 @@ define void @test_fsubr(float *%a0, double *%a1) optsize { ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: fsubr %st(0), %st(1) # sched: [3:1.00] -; BROADWELL-NEXT: fsubr %st(2) # sched: [3:1.00] +; BROADWELL-NEXT: fsubr %st, %st(1) # sched: [3:1.00] +; BROADWELL-NEXT: fsubr %st(2), %st # sched: [3:1.00] ; BROADWELL-NEXT: fsubrs (%ecx) # sched: [9:1.00] ; BROADWELL-NEXT: fsubrl (%eax) # sched: [9:1.00] ; BROADWELL-NEXT: #NO_APP @@ -5327,8 +5327,8 @@ define void @test_fsubr(float *%a0, double *%a1) optsize { ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: fsubr %st(0), %st(1) # sched: [3:1.00] -; SKYLAKE-NEXT: fsubr %st(2) # sched: [3:1.00] +; SKYLAKE-NEXT: fsubr %st, %st(1) # sched: [3:1.00] +; SKYLAKE-NEXT: fsubr %st(2), %st # sched: [3:1.00] ; SKYLAKE-NEXT: fsubrs (%ecx) # sched: [10:1.00] ; SKYLAKE-NEXT: fsubrl (%eax) # sched: [10:1.00] ; SKYLAKE-NEXT: #NO_APP @@ -5339,8 +5339,8 @@ define void @test_fsubr(float *%a0, double *%a1) optsize { ; SKX-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKX-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKX-NEXT: #APP -; SKX-NEXT: fsubr %st(0), %st(1) # sched: [3:1.00] -; SKX-NEXT: fsubr %st(2) # sched: [3:1.00] +; SKX-NEXT: fsubr %st, %st(1) # sched: [3:1.00] +; SKX-NEXT: fsubr %st(2), %st # sched: [3:1.00] ; SKX-NEXT: fsubrs (%ecx) # sched: [10:1.00] ; SKX-NEXT: fsubrl (%eax) # sched: [10:1.00] ; SKX-NEXT: #NO_APP @@ -5351,8 +5351,8 @@ define void @test_fsubr(float *%a0, double *%a1) optsize { ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BDVER2-NEXT: #APP -; BDVER2-NEXT: fsubr %st(0), %st(1) # sched: [5:1.00] -; BDVER2-NEXT: fsubr %st(2) # sched: [5:1.00] +; BDVER2-NEXT: fsubr %st, %st(1) # sched: [5:1.00] +; BDVER2-NEXT: fsubr %st(2), %st # sched: [5:1.00] ; BDVER2-NEXT: fsubrs (%ecx) # sched: [10:1.00] ; BDVER2-NEXT: fsubrl (%eax) # sched: [10:1.00] ; BDVER2-NEXT: #NO_APP @@ -5363,8 +5363,8 @@ define void @test_fsubr(float *%a0, double *%a1) optsize { ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:1.00] ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:1.00] ; BTVER2-NEXT: #APP -; BTVER2-NEXT: fsubr %st(0), %st(1) # sched: [3:1.00] -; BTVER2-NEXT: fsubr %st(2) # sched: [3:1.00] +; BTVER2-NEXT: fsubr %st, %st(1) # sched: [3:1.00] +; BTVER2-NEXT: fsubr %st(2), %st # sched: [3:1.00] ; BTVER2-NEXT: fsubrs (%ecx) # sched: [8:1.00] ; BTVER2-NEXT: fsubrl (%eax) # sched: [8:1.00] ; BTVER2-NEXT: #NO_APP @@ -5375,8 +5375,8 @@ define void @test_fsubr(float *%a0, double *%a1) optsize { ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [8:0.50] ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [8:0.50] ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: fsubr %st(0), %st(1) # sched: [3:1.00] -; ZNVER1-NEXT: fsubr %st(2) # sched: [3:1.00] +; ZNVER1-NEXT: fsubr %st, %st(1) # sched: [3:1.00] +; ZNVER1-NEXT: fsubr %st(2), %st # sched: [3:1.00] ; ZNVER1-NEXT: fsubrs (%ecx) # sched: [10:1.00] ; ZNVER1-NEXT: fsubrl (%eax) # sched: [10:1.00] ; ZNVER1-NEXT: #NO_APP @@ -5391,8 +5391,8 @@ define void @test_fsubrp_fisubr(i16 *%a0, i32 *%a1) optsize { ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %eax ; GENERIC-NEXT: movl {{[0-9]+}}(%esp), %ecx ; GENERIC-NEXT: #APP -; GENERIC-NEXT: fsubrp %st(1) -; GENERIC-NEXT: fsubrp %st(2) +; GENERIC-NEXT: fsubrp %st, %st(1) +; GENERIC-NEXT: fsubrp %st, %st(2) ; GENERIC-NEXT: fisubrs (%ecx) ; GENERIC-NEXT: fisubrl (%eax) ; GENERIC-NEXT: #NO_APP @@ -5403,8 +5403,8 @@ define void @test_fsubrp_fisubr(i16 *%a0, i32 *%a1) optsize { ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [1:1.00] ; ATOM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [1:1.00] ; ATOM-NEXT: #APP -; ATOM-NEXT: fsubrp %st(1) # sched: [5:5.00] -; ATOM-NEXT: fsubrp %st(2) # sched: [5:5.00] +; ATOM-NEXT: fsubrp %st, %st(1) # sched: [5:5.00] +; ATOM-NEXT: fsubrp %st, %st(2) # sched: [5:5.00] ; ATOM-NEXT: fisubrs (%ecx) # sched: [5:5.00] ; ATOM-NEXT: fisubrl (%eax) # sched: [5:5.00] ; ATOM-NEXT: #NO_APP @@ -5415,8 +5415,8 @@ define void @test_fsubrp_fisubr(i16 *%a0, i32 *%a1) optsize { ; SLM-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [3:1.00] ; SLM-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [3:1.00] ; SLM-NEXT: #APP -; SLM-NEXT: fsubrp %st(1) # sched: [3:1.00] -; SLM-NEXT: fsubrp %st(2) # sched: [3:1.00] +; SLM-NEXT: fsubrp %st, %st(1) # sched: [3:1.00] +; SLM-NEXT: fsubrp %st, %st(2) # sched: [3:1.00] ; SLM-NEXT: fisubrs (%ecx) # sched: [6:1.00] ; SLM-NEXT: fisubrl (%eax) # sched: [6:1.00] ; SLM-NEXT: #NO_APP @@ -5427,8 +5427,8 @@ define void @test_fsubrp_fisubr(i16 *%a0, i32 *%a1) optsize { ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SANDY-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SANDY-NEXT: #APP -; SANDY-NEXT: fsubrp %st(1) # sched: [3:1.00] -; SANDY-NEXT: fsubrp %st(2) # sched: [3:1.00] +; SANDY-NEXT: fsubrp %st, %st(1) # sched: [3:1.00] +; SANDY-NEXT: fsubrp %st, %st(2) # sched: [3:1.00] ; SANDY-NEXT: fisubrs (%ecx) # sched: [13:2.00] ; SANDY-NEXT: fisubrl (%eax) # sched: [13:2.00] ; SANDY-NEXT: #NO_APP @@ -5439,8 +5439,8 @@ define void @test_fsubrp_fisubr(i16 *%a0, i32 *%a1) optsize { ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; HASWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; HASWELL-NEXT: #APP -; HASWELL-NEXT: fsubrp %st(1) # sched: [3:1.00] -; HASWELL-NEXT: fsubrp %st(2) # sched: [3:1.00] +; HASWELL-NEXT: fsubrp %st, %st(1) # sched: [3:1.00] +; HASWELL-NEXT: fsubrp %st, %st(2) # sched: [3:1.00] ; HASWELL-NEXT: fisubrs (%ecx) # sched: [13:2.00] ; HASWELL-NEXT: fisubrl (%eax) # sched: [13:2.00] ; HASWELL-NEXT: #NO_APP @@ -5451,8 +5451,8 @@ define void @test_fsubrp_fisubr(i16 *%a0, i32 *%a1) optsize { ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BROADWELL-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: fsubrp %st(1) # sched: [3:1.00] -; BROADWELL-NEXT: fsubrp %st(2) # sched: [3:1.00] +; BROADWELL-NEXT: fsubrp %st, %st(1) # sched: [3:1.00] +; BROADWELL-NEXT: fsubrp %st, %st(2) # sched: [3:1.00] ; BROADWELL-NEXT: fisubrs (%ecx) # sched: [12:2.00] ; BROADWELL-NEXT: fisubrl (%eax) # sched: [12:2.00] ; BROADWELL-NEXT: #NO_APP @@ -5463,8 +5463,8 @@ define void @test_fsubrp_fisubr(i16 *%a0, i32 *%a1) optsize { ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKYLAKE-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: fsubrp %st(1) # sched: [3:1.00] -; SKYLAKE-NEXT: fsubrp %st(2) # sched: [3:1.00] +; SKYLAKE-NEXT: fsubrp %st, %st(1) # sched: [3:1.00] +; SKYLAKE-NEXT: fsubrp %st, %st(2) # sched: [3:1.00] ; SKYLAKE-NEXT: fisubrs (%ecx) # sched: [13:2.00] ; SKYLAKE-NEXT: fisubrl (%eax) # sched: [13:2.00] ; SKYLAKE-NEXT: #NO_APP @@ -5475,8 +5475,8 @@ define void @test_fsubrp_fisubr(i16 *%a0, i32 *%a1) optsize { ; SKX-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; SKX-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; SKX-NEXT: #APP -; SKX-NEXT: fsubrp %st(1) # sched: [3:1.00] -; SKX-NEXT: fsubrp %st(2) # sched: [3:1.00] +; SKX-NEXT: fsubrp %st, %st(1) # sched: [3:1.00] +; SKX-NEXT: fsubrp %st, %st(2) # sched: [3:1.00] ; SKX-NEXT: fisubrs (%ecx) # sched: [13:2.00] ; SKX-NEXT: fisubrl (%eax) # sched: [13:2.00] ; SKX-NEXT: #NO_APP @@ -5487,8 +5487,8 @@ define void @test_fsubrp_fisubr(i16 *%a0, i32 *%a1) optsize { ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:0.50] ; BDVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:0.50] ; BDVER2-NEXT: #APP -; BDVER2-NEXT: fsubrp %st(1) # sched: [5:1.00] -; BDVER2-NEXT: fsubrp %st(2) # sched: [5:1.00] +; BDVER2-NEXT: fsubrp %st, %st(1) # sched: [5:1.00] +; BDVER2-NEXT: fsubrp %st, %st(2) # sched: [5:1.00] ; BDVER2-NEXT: fisubrs (%ecx) # sched: [10:1.00] ; BDVER2-NEXT: fisubrl (%eax) # sched: [10:1.00] ; BDVER2-NEXT: #NO_APP @@ -5499,8 +5499,8 @@ define void @test_fsubrp_fisubr(i16 *%a0, i32 *%a1) optsize { ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [5:1.00] ; BTVER2-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [5:1.00] ; BTVER2-NEXT: #APP -; BTVER2-NEXT: fsubrp %st(1) # sched: [3:1.00] -; BTVER2-NEXT: fsubrp %st(2) # sched: [3:1.00] +; BTVER2-NEXT: fsubrp %st, %st(1) # sched: [3:1.00] +; BTVER2-NEXT: fsubrp %st, %st(2) # sched: [3:1.00] ; BTVER2-NEXT: fisubrs (%ecx) # sched: [8:1.00] ; BTVER2-NEXT: fisubrl (%eax) # sched: [8:1.00] ; BTVER2-NEXT: #NO_APP @@ -5511,8 +5511,8 @@ define void @test_fsubrp_fisubr(i16 *%a0, i32 *%a1) optsize { ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %eax # sched: [8:0.50] ; ZNVER1-NEXT: movl {{[0-9]+}}(%esp), %ecx # sched: [8:0.50] ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: fsubrp %st(1) # sched: [3:1.00] -; ZNVER1-NEXT: fsubrp %st(2) # sched: [3:1.00] +; ZNVER1-NEXT: fsubrp %st, %st(1) # sched: [3:1.00] +; ZNVER1-NEXT: fsubrp %st, %st(2) # sched: [3:1.00] ; ZNVER1-NEXT: fisubrs (%ecx) # sched: [10:1.00] ; ZNVER1-NEXT: fisubrl (%eax) # sched: [10:1.00] ; ZNVER1-NEXT: #NO_APP @@ -5731,88 +5731,88 @@ define void @test_fucomi_fucomip() optsize { ; GENERIC-LABEL: test_fucomi_fucomip: ; GENERIC: # %bb.0: ; GENERIC-NEXT: #APP -; GENERIC-NEXT: fucomi %st(3) -; GENERIC-NEXT: fucompi %st(3) +; GENERIC-NEXT: fucomi %st(3), %st +; GENERIC-NEXT: fucompi %st(3), %st ; GENERIC-NEXT: #NO_APP ; GENERIC-NEXT: retl ; ; ATOM-LABEL: test_fucomi_fucomip: ; ATOM: # %bb.0: ; ATOM-NEXT: #APP -; ATOM-NEXT: fucomi %st(3) # sched: [9:4.50] -; ATOM-NEXT: fucompi %st(3) # sched: [9:4.50] +; ATOM-NEXT: fucomi %st(3), %st # sched: [9:4.50] +; ATOM-NEXT: fucompi %st(3), %st # sched: [9:4.50] ; ATOM-NEXT: #NO_APP ; ATOM-NEXT: retl # sched: [79:39.50] ; ; SLM-LABEL: test_fucomi_fucomip: ; SLM: # %bb.0: ; SLM-NEXT: #APP -; SLM-NEXT: fucomi %st(3) # sched: [3:1.00] -; SLM-NEXT: fucompi %st(3) # sched: [3:1.00] +; SLM-NEXT: fucomi %st(3), %st # sched: [3:1.00] +; SLM-NEXT: fucompi %st(3), %st # sched: [3:1.00] ; SLM-NEXT: #NO_APP ; SLM-NEXT: retl # sched: [4:1.00] ; ; SANDY-LABEL: test_fucomi_fucomip: ; SANDY: # %bb.0: ; SANDY-NEXT: #APP -; SANDY-NEXT: fucomi %st(3) # sched: [3:1.00] -; SANDY-NEXT: fucompi %st(3) # sched: [3:1.00] +; SANDY-NEXT: fucomi %st(3), %st # sched: [3:1.00] +; SANDY-NEXT: fucompi %st(3), %st # sched: [3:1.00] ; SANDY-NEXT: #NO_APP ; SANDY-NEXT: retl # sched: [6:1.00] ; ; HASWELL-LABEL: test_fucomi_fucomip: ; HASWELL: # %bb.0: ; HASWELL-NEXT: #APP -; HASWELL-NEXT: fucomi %st(3) # sched: [1:0.50] -; HASWELL-NEXT: fucompi %st(3) # sched: [1:0.50] +; HASWELL-NEXT: fucomi %st(3), %st # sched: [1:0.50] +; HASWELL-NEXT: fucompi %st(3), %st # sched: [1:0.50] ; HASWELL-NEXT: #NO_APP ; HASWELL-NEXT: retl # sched: [7:1.00] ; ; BROADWELL-LABEL: test_fucomi_fucomip: ; BROADWELL: # %bb.0: ; BROADWELL-NEXT: #APP -; BROADWELL-NEXT: fucomi %st(3) # sched: [3:1.00] -; BROADWELL-NEXT: fucompi %st(3) # sched: [3:1.00] +; BROADWELL-NEXT: fucomi %st(3), %st # sched: [3:1.00] +; BROADWELL-NEXT: fucompi %st(3), %st # sched: [3:1.00] ; BROADWELL-NEXT: #NO_APP ; BROADWELL-NEXT: retl # sched: [6:0.50] ; ; SKYLAKE-LABEL: test_fucomi_fucomip: ; SKYLAKE: # %bb.0: ; SKYLAKE-NEXT: #APP -; SKYLAKE-NEXT: fucomi %st(3) # sched: [2:1.00] -; SKYLAKE-NEXT: fucompi %st(3) # sched: [2:1.00] +; SKYLAKE-NEXT: fucomi %st(3), %st # sched: [2:1.00] +; SKYLAKE-NEXT: fucompi %st(3), %st # sched: [2:1.00] ; SKYLAKE-NEXT: #NO_APP ; SKYLAKE-NEXT: retl # sched: [6:0.50] ; ; SKX-LABEL: test_fucomi_fucomip: ; SKX: # %bb.0: ; SKX-NEXT: #APP -; SKX-NEXT: fucomi %st(3) # sched: [2:1.00] -; SKX-NEXT: fucompi %st(3) # sched: [2:1.00] +; SKX-NEXT: fucomi %st(3), %st # sched: [2:1.00] +; SKX-NEXT: fucompi %st(3), %st # sched: [2:1.00] ; SKX-NEXT: #NO_APP ; SKX-NEXT: retl # sched: [6:0.50] ; ; BDVER2-LABEL: test_fucomi_fucomip: ; BDVER2: # %bb.0: ; BDVER2-NEXT: #APP -; BDVER2-NEXT: fucomi %st(3) # sched: [1:1.00] -; BDVER2-NEXT: fucompi %st(3) # sched: [1:1.00] +; BDVER2-NEXT: fucomi %st(3), %st # sched: [1:1.00] +; BDVER2-NEXT: fucompi %st(3), %st # sched: [1:1.00] ; BDVER2-NEXT: #NO_APP ; BDVER2-NEXT: retl # sched: [5:1.00] ; ; BTVER2-LABEL: test_fucomi_fucomip: ; BTVER2: # %bb.0: ; BTVER2-NEXT: #APP -; BTVER2-NEXT: fucomi %st(3) # sched: [3:1.00] -; BTVER2-NEXT: fucompi %st(3) # sched: [3:1.00] +; BTVER2-NEXT: fucomi %st(3), %st # sched: [3:1.00] +; BTVER2-NEXT: fucompi %st(3), %st # sched: [3:1.00] ; BTVER2-NEXT: #NO_APP ; BTVER2-NEXT: retl # sched: [4:1.00] ; ; ZNVER1-LABEL: test_fucomi_fucomip: ; ZNVER1: # %bb.0: ; ZNVER1-NEXT: #APP -; ZNVER1-NEXT: fucomi %st(3) # sched: [9:0.50] -; ZNVER1-NEXT: fucompi %st(3) # sched: [9:0.50] +; ZNVER1-NEXT: fucomi %st(3), %st # sched: [9:0.50] +; ZNVER1-NEXT: fucompi %st(3), %st # sched: [9:0.50] ; ZNVER1-NEXT: #NO_APP ; ZNVER1-NEXT: retl # sched: [1:0.50] tail call void asm sideeffect "fucomi %st(3) \0A\09 fucomip %st(3)", ""() nounwind diff --git a/llvm/test/DebugInfo/COFF/types-empty-member-fn.ll b/llvm/test/DebugInfo/COFF/types-empty-member-fn.ll new file mode 100644 index 0000000000000..87cba9d62099e --- /dev/null +++ b/llvm/test/DebugInfo/COFF/types-empty-member-fn.ll @@ -0,0 +1,72 @@ +; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s + +; ModuleID = 'foo.3a1fbbbh-cgu.0' +source_filename = "foo.3a1fbbbh-cgu.0" +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +; Rust source to regenerate: +; $ cat foo.rs +; pub struct Foo; +; impl Foo { +; pub fn foo() {} +; } +; $ rustc foo.rs --crate-type lib -Cdebuginfo=1 --emit=llvm-ir + +; CHECK: CodeViewTypes [ +; CHECK: MemberFunction (0x1006) { +; CHECK-NEXT: TypeLeafKind: LF_MFUNCTION (0x1009) +; CHECK-NEXT: ReturnType: void (0x3) +; CHECK-NEXT: ClassType: foo::Foo (0x1000) +; CHECK-NEXT: ThisType: 0x0 +; CHECK-NEXT: CallingConvention: NearC (0x0) +; CHECK-NEXT: FunctionOptions [ (0x0) +; CHECK-NEXT: ] +; CHECK-NEXT: NumParameters: 0 +; CHECK-NEXT: ArgListType: () (0x1005) +; CHECK-NEXT: ThisAdjustment: 0 +; CHECK-NEXT: } +; CHECK-NEXT: MemberFuncId (0x1007) { +; CHECK-NEXT: TypeLeafKind: LF_MFUNC_ID (0x1602) +; CHECK-NEXT: ClassType: foo::Foo (0x1000) +; CHECK-NEXT: FunctionType: void foo::Foo::() (0x1006) +; CHECK-NEXT: Name: foo +; CHECK-NEXT: } +; CHECK: CodeViewDebugInfo [ +; CHECK: FunctionLineTable [ +; CHECK-NEXT: LinkageName: _ZN3foo3Foo3foo17hc557c2121772885bE +; CHECK-NEXT: Flags: 0x0 +; CHECK-NEXT: CodeSize: 0x1 +; CHECK-NEXT: FilenameSegment [ +; CHECK-NEXT: Filename: D:\rust\foo.rs (0x0) +; CHECK-NEXT: +0x0 [ +; CHECK-NEXT: LineNumberStart: 3 +; CHECK-NEXT: LineNumberEndDelta: 0 +; CHECK-NEXT: IsStatement: No +; CHECK-NEXT: ] +; CHECK-NEXT: ] +; CHECK-NEXT: ] + +; foo::Foo::foo +; Function Attrs: uwtable +define void @_ZN3foo3Foo3foo17hc557c2121772885bE() unnamed_addr #0 !dbg !5 { +start: + ret void, !dbg !10 +} + +attributes #0 = { uwtable "target-cpu"="x86-64" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} + +!0 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !1, producer: "clang LLVM (rustc version 1.33.0-nightly (8b0f0156e 2019-01-22))", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2) +!1 = !DIFile(filename: "foo.rs", directory: "D:\5Crust") +!2 = !{} +!3 = !{i32 2, !"CodeView", i32 1} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = distinct !DISubprogram(name: "foo", linkageName: "_ZN3foo3Foo3foo17hc557c2121772885bE", scope: !6, file: !1, line: 3, type: !9, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, templateParams: !2, retainedNodes: !2) +!6 = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", scope: !8, file: !7, align: 8, elements: !2, templateParams: !2, identifier: "5105d9fe1a2a3c68518268151b672274") +!7 = !DIFile(filename: "", directory: "") +!8 = !DINamespace(name: "foo", scope: null) +!9 = !DISubroutineType(types: !2) +!10 = !DILocation(line: 3, scope: !5) diff --git a/llvm/test/DebugInfo/Mips/dwarfdump-tls.ll b/llvm/test/DebugInfo/Mips/dwarfdump-tls.ll index 6aa429adb417b..8d8af8c5124a9 100644 --- a/llvm/test/DebugInfo/Mips/dwarfdump-tls.ll +++ b/llvm/test/DebugInfo/Mips/dwarfdump-tls.ll @@ -1,12 +1,34 @@ -; RUN: llc -O0 -march=mips -mcpu=mips32r2 -filetype=obj -o=%t-32.o < %s +; RUN: llc -O0 -march=mips -mcpu=mips32r2 -filetype=obj \ +; RUN: -split-dwarf-file=foo.dwo -o=%t-32.o < %s ; RUN: llvm-dwarfdump %t-32.o 2>&1 | FileCheck %s -; RUN: llc -O0 -march=mips64 -mcpu=mips64r2 -filetype=obj -o=%t-64.o < %s +; RUN: llc -O0 -march=mips64 -mcpu=mips64r2 -filetype=obj \ +; RUN: -split-dwarf-file=foo.dwo -o=%t-64.o < %s ; RUN: llvm-dwarfdump %t-64.o 2>&1 | FileCheck %s +; RUN: llc -O0 -march=mips -mcpu=mips32r2 -filetype=asm \ +; RUN: -split-dwarf-file=foo.dwo < %s | FileCheck -check-prefix=ASM32 %s +; RUN: llc -O0 -march=mips64 -mcpu=mips64r2 -filetype=asm \ +; RUN: -split-dwarf-file=foo.dwo < %s | FileCheck -check-prefix=ASM64 %s + @x = thread_local global i32 5, align 4, !dbg !0 ; CHECK-NOT: error: failed to compute relocation: R_MIPS_TLS_DTPREL +; CHECK: DW_AT_name ("x") +; CHECK-NEXT: DW_AT_type (0x00000025 "int") +; CHECK-NEXT: DW_AT_external (true) +; CHECK-NEXT: DW_AT_decl_file (0x01) +; CHECK-NEXT: DW_AT_decl_line (1) +; CHECK-NEXT: DW_AT_location (DW_OP_GNU_const_index 0x0, {{DW_OP_GNU_push_tls_address|DW_OP_form_tls_address}}) + +; ASM32: .section .debug_addr +; ASM32-NEXT: $addr_table_base0: +; ASM32-NEXT: .4byte x+32768 + +; ASM64: .section .debug_addr +; ASM64-NEXT: .Laddr_table_base0: +; ASM64-NEXT: .8byte x+32768 + !llvm.dbg.cu = !{!2} !llvm.module.flags = !{!7, !8} diff --git a/llvm/test/DebugInfo/Mips/eh_frame.ll b/llvm/test/DebugInfo/Mips/eh_frame.ll index 4687443cb1cff..122d0a7f6ab2a 100644 --- a/llvm/test/DebugInfo/Mips/eh_frame.ll +++ b/llvm/test/DebugInfo/Mips/eh_frame.ll @@ -1,9 +1,21 @@ -; RUN: llc -mtriple mips-unknown-linux-gnu -mattr=+micromips -O3 -filetype=obj -o - %s | llvm-readelf -r | FileCheck %s - -; CHECK: .rel.eh_frame -; CHECK: DW.ref.__gxx_personality_v0 -; CHECK-NEXT: .text -; CHECK-NEXT: .gcc_except_table +; RUN: llc -mtriple mips-unknown-linux-gnu -mattr=+micromips -relocation-model=static -O3 -filetype=obj -o - %s | \ +; RUN: llvm-readelf -r | FileCheck %s --check-prefix=CHECK-READELF +; RUN: llc -mtriple mips-unknown-linux-gnu -mattr=+micromips -relocation-model=pic -O3 -filetype=obj -o - %s | \ +; RUN: llvm-readelf -r | FileCheck %s --check-prefix=CHECK-READELF +; RUN: llc -mtriple mips-unknown-linux-gnu -mattr=+micromips -relocation-model=static -O3 -filetype=obj -o - %s | \ +; RUN: llvm-objdump -s -j .gcc_except_table - | FileCheck %s --check-prefix=CHECK-EXCEPT-TABLE-STATIC +; RUN: llc -mtriple mips-unknown-linux-gnu -mattr=+micromips -relocation-model=pic -O3 -filetype=obj -o - %s | \ +; RUN: llvm-objdump -s -j .gcc_except_table - | FileCheck %s --check-prefix=CHECK-EXCEPT-TABLE-PIC + +; CHECK-READELF: .rel.eh_frame +; CHECK-READELF: DW.ref.__gxx_personality_v0 +; CHECK-READELF-NEXT: .text +; CHECK-READELF-NEXT: .gcc_except_table + +; CHECK-EXCEPT-TABLE-STATIC: 0000 ff9b1501 0c011500 00150e23 01231e00 ...........#.#.. +; CHECK-EXCEPT-TABLE-STATIC: 0010 00010000 00000000 +; CHECK-EXCEPT-TABLE-PIC: 0000 ff9b1501 0c012d00 002d133f 013f2a00 ......-..-.?.?*. +; CHECK-EXCEPT-TABLE-PIC: 0010 00010000 00000000 ........ @_ZTIi = external constant i8* diff --git a/llvm/test/DebugInfo/X86/dwarfdump-debug-loclists.test b/llvm/test/DebugInfo/X86/dwarfdump-debug-loclists.test index 669607fe557a3..32f2482b5117c 100644 --- a/llvm/test/DebugInfo/X86/dwarfdump-debug-loclists.test +++ b/llvm/test/DebugInfo/X86/dwarfdump-debug-loclists.test @@ -9,7 +9,7 @@ # CHECK-NEXT: [0x0000000000000700, 0x0000000000000710): DW_OP_breg5 RDI+0 # CHECK: .debug_loclists contents: -# CHECK-NEXT: 0x00000000: locations list header: length = 0x0000002f, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 +# CHECK-NEXT: 0x00000000: locations list header: length = 0x0000002c, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 # CHECK-NEXT: 0x00000000: # CHECK-NEXT: [0x0000000000000000, 0x0000000000000010): DW_OP_breg5 RDI+0 # CHECK-NEXT: [0x0000000000000530, 0x0000000000000540): DW_OP_breg6 RBP-8, DW_OP_deref @@ -37,7 +37,7 @@ .byte 4 # DW_LLE_offset_pair .uleb128 0x0 # starting offset .uleb128 0x10 # ending offset - .short 2 # Loc expr size + .byte 2 # Loc expr size .byte 117 # DW_OP_breg5 .byte 0 # 0 @@ -47,7 +47,7 @@ .byte 4 # DW_LLE_offset_pair .uleb128 0x30 # starting offset .uleb128 0x40 # ending offset - .short 3 # Loc expr size + .byte 3 # Loc expr size .byte 118 # DW_OP_breg6 .byte 120 # -8 .byte 6 # DW_OP_deref @@ -55,7 +55,7 @@ .byte 8 # DW_LLE_start_length .quad 0x700 # Some address .uleb128 0x10 # length - .short 2 # Loc expr size + .byte 2 # Loc expr size .byte 117 # DW_OP_breg5 .byte 0 # 0 diff --git a/llvm/test/Instrumentation/MemorySanitizer/global_ctors_2to3.ll b/llvm/test/Instrumentation/MemorySanitizer/global_ctors_2to3.ll new file mode 100644 index 0000000000000..d841c6c05c9b7 --- /dev/null +++ b/llvm/test/Instrumentation/MemorySanitizer/global_ctors_2to3.ll @@ -0,0 +1,18 @@ +; MSan converts 2-element global_ctors to 3-element when adding the new entry. +; RUN: opt < %s -msan-with-comdat -S -passes=msan 2>&1 | FileCheck %s +; RUN: opt < %s -msan -msan-with-comdat -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; CHECK: $msan.module_ctor = comdat any +; CHECK: @llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @f, i8* null }, { i32, void ()*, i8* } { i32 0, void ()* @msan.module_ctor, i8* bitcast (void ()* @msan.module_ctor to i8*) }] + +@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @f }] + +define internal void @f() { +entry: + ret void +} + +; CHECK: define internal void @msan.module_ctor() comdat { diff --git a/llvm/test/Instrumentation/MemorySanitizer/msan_basic.ll b/llvm/test/Instrumentation/MemorySanitizer/msan_basic.ll index f4cbc637ef1aa..569c2320c5c91 100644 --- a/llvm/test/Instrumentation/MemorySanitizer/msan_basic.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/msan_basic.ll @@ -9,7 +9,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" -; CHECK: @llvm.global_ctors {{.*}} { i32 0, void ()* @__msan_init, i8* null } +; CHECK: @llvm.global_ctors {{.*}} { i32 0, void ()* @msan.module_ctor, i8* null } ; Check the presence and the linkage type of __msan_track_origins and ; other interface symbols. @@ -991,4 +991,5 @@ define i8* @MismatchingCallMustTailCall(i32 %a) sanitize_memory { ; CHECK-NEXT: ret i8* -; CHECK: declare void @__msan_init() +; CHECK-LABEL: define internal void @msan.module_ctor() { +; CHECK: call void @__msan_init() diff --git a/llvm/test/Instrumentation/MemorySanitizer/msan_llvm_is_constant.ll b/llvm/test/Instrumentation/MemorySanitizer/msan_llvm_is_constant.ll index b7847db06ac27..4f316be235798 100644 --- a/llvm/test/Instrumentation/MemorySanitizer/msan_llvm_is_constant.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/msan_llvm_is_constant.ll @@ -1,6 +1,9 @@ ; Make sure MSan doesn't insert shadow checks for @llvm.is.constant.* arguments. +; RUN: opt < %s -msan-kernel=1 -S -passes=msan 2>&1 | FileCheck \ +; RUN: -check-prefixes=CHECK %s ; RUN: opt < %s -msan -msan-kernel=1 -S | FileCheck -check-prefixes=CHECK %s +; RUN: opt < %s -S -passes=msan 2>&1 | FileCheck -check-prefixes=CHECK %s ; RUN: opt < %s -msan -S | FileCheck -check-prefixes=CHECK %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/test/MC/Disassembler/X86/fp-stack.txt b/llvm/test/MC/Disassembler/X86/fp-stack.txt index 8c4ad47eb8732..1b1687b2a204b 100644 --- a/llvm/test/MC/Disassembler/X86/fp-stack.txt +++ b/llvm/test/MC/Disassembler/X86/fp-stack.txt @@ -1,52 +1,52 @@ # RUN: llvm-mc --disassemble %s -triple=x86_64 | FileCheck %s # RUN: llvm-mc --disassemble %s -triple=i686-apple-darwin9 | FileCheck %s -# CHECK: fadd %st(0) +# CHECK: fadd %st(0), %st 0xd8,0xc0 -# CHECK: fadd %st(1) +# CHECK: fadd %st(1), %st 0xd8,0xc1 -# CHECK: fadd %st(2) +# CHECK: fadd %st(2), %st 0xd8,0xc2 -# CHECK: fadd %st(3) +# CHECK: fadd %st(3), %st 0xd8,0xc3 -# CHECK: fadd %st(4) +# CHECK: fadd %st(4), %st 0xd8,0xc4 -# CHECK: fadd %st(5) +# CHECK: fadd %st(5), %st 0xd8,0xc5 -# CHECK: fadd %st(6) +# CHECK: fadd %st(6), %st 0xd8,0xc6 -# CHECK: fadd %st(7) +# CHECK: fadd %st(7), %st 0xd8,0xc7 -# CHECK: fmul %st(0) +# CHECK: fmul %st(0), %st 0xd8,0xc8 -# CHECK: fmul %st(1) +# CHECK: fmul %st(1), %st 0xd8,0xc9 -# CHECK: fmul %st(2) +# CHECK: fmul %st(2), %st 0xd8,0xca -# CHECK: fmul %st(3) +# CHECK: fmul %st(3), %st 0xd8,0xcb -# CHECK: fmul %st(4) +# CHECK: fmul %st(4), %st 0xd8,0xcc -# CHECK: fmul %st(5) +# CHECK: fmul %st(5), %st 0xd8,0xcd -# CHECK: fmul %st(6) +# CHECK: fmul %st(6), %st 0xd8,0xce -# CHECK: fmul %st(7) +# CHECK: fmul %st(7), %st 0xd8,0xcf # CHECK: fcom %st(0) @@ -97,100 +97,100 @@ # CHECK: fcomp %st(7) 0xd8,0xdf -# CHECK: fsub %st(0) +# CHECK: fsub %st(0), %st 0xd8,0xe0 -# CHECK: fsub %st(1) +# CHECK: fsub %st(1), %st 0xd8,0xe1 -# CHECK: fsub %st(2) +# CHECK: fsub %st(2), %st 0xd8,0xe2 -# CHECK: fsub %st(3) +# CHECK: fsub %st(3), %st 0xd8,0xe3 -# CHECK: fsub %st(4) +# CHECK: fsub %st(4), %st 0xd8,0xe4 -# CHECK: fsub %st(5) +# CHECK: fsub %st(5), %st 0xd8,0xe5 -# CHECK: fsub %st(6) +# CHECK: fsub %st(6), %st 0xd8,0xe6 -# CHECK: fsub %st(7) +# CHECK: fsub %st(7), %st 0xd8,0xe7 -# CHECK: fsubr %st(0) +# CHECK: fsubr %st(0), %st 0xd8,0xe8 -# CHECK: fsubr %st(1) +# CHECK: fsubr %st(1), %st 0xd8,0xe9 -# CHECK: fsubr %st(2) +# CHECK: fsubr %st(2), %st 0xd8,0xea -# CHECK: fsubr %st(3) +# CHECK: fsubr %st(3), %st 0xd8,0xeb -# CHECK: fsubr %st(4) +# CHECK: fsubr %st(4), %st 0xd8,0xec -# CHECK: fsubr %st(5) +# CHECK: fsubr %st(5), %st 0xd8,0xed -# CHECK: fsubr %st(6) +# CHECK: fsubr %st(6), %st 0xd8,0xee -# CHECK: fsubr %st(7) +# CHECK: fsubr %st(7), %st 0xd8,0xef -# CHECK: fdiv %st(0) +# CHECK: fdiv %st(0), %st 0xd8,0xf0 -# CHECK: fdiv %st(1) +# CHECK: fdiv %st(1), %st 0xd8,0xf1 -# CHECK: fdiv %st(2) +# CHECK: fdiv %st(2), %st 0xd8,0xf2 -# CHECK: fdiv %st(3) +# CHECK: fdiv %st(3), %st 0xd8,0xf3 -# CHECK: fdiv %st(4) +# CHECK: fdiv %st(4), %st 0xd8,0xf4 -# CHECK: fdiv %st(5) +# CHECK: fdiv %st(5), %st 0xd8,0xf5 -# CHECK: fdiv %st(6) +# CHECK: fdiv %st(6), %st 0xd8,0xf6 -# CHECK: fdiv %st(7) +# CHECK: fdiv %st(7), %st 0xd8,0xf7 -# CHECK: fdivr %st(0) +# CHECK: fdivr %st(0), %st 0xd8,0xf8 -# CHECK: fdivr %st(1) +# CHECK: fdivr %st(1), %st 0xd8,0xf9 -# CHECK: fdivr %st(2) +# CHECK: fdivr %st(2), %st 0xd8,0xfa -# CHECK: fdivr %st(3) +# CHECK: fdivr %st(3), %st 0xd8,0xfb -# CHECK: fdivr %st(4) +# CHECK: fdivr %st(4), %st 0xd8,0xfc -# CHECK: fdivr %st(5) +# CHECK: fdivr %st(5), %st 0xd8,0xfd -# CHECK: fdivr %st(6) +# CHECK: fdivr %st(6), %st 0xd8,0xfe -# CHECK: fdivr %st(7) +# CHECK: fdivr %st(7), %st 0xd8,0xff # CHECK: fld %st(0) @@ -325,199 +325,199 @@ # CHECK: fcos 0xd9,0xff -# CHECK: fcmovb %st(0), %st(0) +# CHECK: fcmovb %st(0), %st 0xda,0xc0 -# CHECK: fcmovb %st(1), %st(0) +# CHECK: fcmovb %st(1), %st 0xda,0xc1 -# CHECK: fcmovb %st(2), %st(0) +# CHECK: fcmovb %st(2), %st 0xda,0xc2 -# CHECK: fcmovb %st(3), %st(0) +# CHECK: fcmovb %st(3), %st 0xda,0xc3 -# CHECK: fcmovb %st(4), %st(0) +# CHECK: fcmovb %st(4), %st 0xda,0xc4 -# CHECK: fcmovb %st(5), %st(0) +# CHECK: fcmovb %st(5), %st 0xda,0xc5 -# CHECK: fcmovb %st(6), %st(0) +# CHECK: fcmovb %st(6), %st 0xda,0xc6 -# CHECK: fcmovb %st(7), %st(0) +# CHECK: fcmovb %st(7), %st 0xda,0xc7 -# CHECK: fcmove %st(0), %st(0) +# CHECK: fcmove %st(0), %st 0xda,0xc8 -# CHECK: fcmove %st(1), %st(0) +# CHECK: fcmove %st(1), %st 0xda,0xc9 -# CHECK: fcmove %st(2), %st(0) +# CHECK: fcmove %st(2), %st 0xda,0xca -# CHECK: fcmove %st(3), %st(0) +# CHECK: fcmove %st(3), %st 0xda,0xcb -# CHECK: fcmove %st(4), %st(0) +# CHECK: fcmove %st(4), %st 0xda,0xcc -# CHECK: fcmove %st(5), %st(0) +# CHECK: fcmove %st(5), %st 0xda,0xcd -# CHECK: fcmove %st(6), %st(0) +# CHECK: fcmove %st(6), %st 0xda,0xce -# CHECK: fcmove %st(7), %st(0) +# CHECK: fcmove %st(7), %st 0xda,0xcf -# CHECK: fcmovbe %st(0), %st(0) +# CHECK: fcmovbe %st(0), %st 0xda,0xd0 -# CHECK: fcmovbe %st(1), %st(0) +# CHECK: fcmovbe %st(1), %st 0xda,0xd1 -# CHECK: fcmovbe %st(2), %st(0) +# CHECK: fcmovbe %st(2), %st 0xda,0xd2 -# CHECK: fcmovbe %st(3), %st(0) +# CHECK: fcmovbe %st(3), %st 0xda,0xd3 -# CHECK: fcmovbe %st(4), %st(0) +# CHECK: fcmovbe %st(4), %st 0xda,0xd4 -# CHECK: fcmovbe %st(5), %st(0) +# CHECK: fcmovbe %st(5), %st 0xda,0xd5 -# CHECK: fcmovbe %st(6), %st(0) +# CHECK: fcmovbe %st(6), %st 0xda,0xd6 -# CHECK: fcmovbe %st(7), %st(0) +# CHECK: fcmovbe %st(7), %st 0xda,0xd7 -# CHECK: fcmovu %st(0), %st(0) +# CHECK: fcmovu %st(0), %st 0xda,0xd8 -# CHECK: fcmovu %st(1), %st(0) +# CHECK: fcmovu %st(1), %st 0xda,0xd9 -# CHECK: fcmovu %st(2), %st(0) +# CHECK: fcmovu %st(2), %st 0xda,0xda -# CHECK: fcmovu %st(3), %st(0) +# CHECK: fcmovu %st(3), %st 0xda,0xdb -# CHECK: fcmovu %st(4), %st(0) +# CHECK: fcmovu %st(4), %st 0xda,0xdc -# CHECK: fcmovu %st(5), %st(0) +# CHECK: fcmovu %st(5), %st 0xda,0xdd -# CHECK: fcmovu %st(6), %st(0) +# CHECK: fcmovu %st(6), %st 0xda,0xde -# CHECK: fcmovu %st(7), %st(0) +# CHECK: fcmovu %st(7), %st 0xda,0xdf # CHECK: fucompp 0xda,0xe9 -# CHECK: fcmovnb %st(0), %st(0) +# CHECK: fcmovnb %st(0), %st 0xdb,0xc0 -# CHECK: fcmovnb %st(1), %st(0) +# CHECK: fcmovnb %st(1), %st 0xdb,0xc1 -# CHECK: fcmovnb %st(2), %st(0) +# CHECK: fcmovnb %st(2), %st 0xdb,0xc2 -# CHECK: fcmovnb %st(3), %st(0) +# CHECK: fcmovnb %st(3), %st 0xdb,0xc3 -# CHECK: fcmovnb %st(4), %st(0) +# CHECK: fcmovnb %st(4), %st 0xdb,0xc4 -# CHECK: fcmovnb %st(5), %st(0) +# CHECK: fcmovnb %st(5), %st 0xdb,0xc5 -# CHECK: fcmovnb %st(6), %st(0) +# CHECK: fcmovnb %st(6), %st 0xdb,0xc6 -# CHECK: fcmovnb %st(7), %st(0) +# CHECK: fcmovnb %st(7), %st 0xdb,0xc7 -# CHECK: fcmovne %st(0), %st(0) +# CHECK: fcmovne %st(0), %st 0xdb,0xc8 -# CHECK: fcmovne %st(1), %st(0) +# CHECK: fcmovne %st(1), %st 0xdb,0xc9 -# CHECK: fcmovne %st(2), %st(0) +# CHECK: fcmovne %st(2), %st 0xdb,0xca -# CHECK: fcmovne %st(3), %st(0) +# CHECK: fcmovne %st(3), %st 0xdb,0xcb -# CHECK: fcmovne %st(4), %st(0) +# CHECK: fcmovne %st(4), %st 0xdb,0xcc -# CHECK: fcmovne %st(5), %st(0) +# CHECK: fcmovne %st(5), %st 0xdb,0xcd -# CHECK: fcmovne %st(6), %st(0) +# CHECK: fcmovne %st(6), %st 0xdb,0xce -# CHECK: fcmovne %st(7), %st(0) +# CHECK: fcmovne %st(7), %st 0xdb,0xcf -# CHECK: fcmovnbe %st(0), %st(0) +# CHECK: fcmovnbe %st(0), %st 0xdb,0xd0 -# CHECK: fcmovnbe %st(1), %st(0) +# CHECK: fcmovnbe %st(1), %st 0xdb,0xd1 -# CHECK: fcmovnbe %st(2), %st(0) +# CHECK: fcmovnbe %st(2), %st 0xdb,0xd2 -# CHECK: fcmovnbe %st(3), %st(0) +# CHECK: fcmovnbe %st(3), %st 0xdb,0xd3 -# CHECK: fcmovnbe %st(4), %st(0) +# CHECK: fcmovnbe %st(4), %st 0xdb,0xd4 -# CHECK: fcmovnbe %st(5), %st(0) +# CHECK: fcmovnbe %st(5), %st 0xdb,0xd5 -# CHECK: fcmovnbe %st(6), %st(0) +# CHECK: fcmovnbe %st(6), %st 0xdb,0xd6 -# CHECK: fcmovnbe %st(7), %st(0) +# CHECK: fcmovnbe %st(7), %st 0xdb,0xd7 -# CHECK: fcmovnu %st(0), %st(0) +# CHECK: fcmovnu %st(0), %st 0xdb,0xd8 -# CHECK: fcmovnu %st(1), %st(0) +# CHECK: fcmovnu %st(1), %st 0xdb,0xd9 -# CHECK: fcmovnu %st(2), %st(0) +# CHECK: fcmovnu %st(2), %st 0xdb,0xda -# CHECK: fcmovnu %st(3), %st(0) +# CHECK: fcmovnu %st(3), %st 0xdb,0xdb -# CHECK: fcmovnu %st(4), %st(0) +# CHECK: fcmovnu %st(4), %st 0xdb,0xdc -# CHECK: fcmovnu %st(5), %st(0) +# CHECK: fcmovnu %st(5), %st 0xdb,0xdd -# CHECK: fcmovnu %st(6), %st(0) +# CHECK: fcmovnu %st(6), %st 0xdb,0xde -# CHECK: fcmovnu %st(7), %st(0) +# CHECK: fcmovnu %st(7), %st 0xdb,0xdf # CHECK: fnclex @@ -574,148 +574,148 @@ # CHECK: fcomi %st(7) 0xdb,0xf7 -# CHECK: fadd %st(0), %st(0) +# CHECK: fadd %st, %st(0) 0xdc,0xc0 -# CHECK: fadd %st(0), %st(1) +# CHECK: fadd %st, %st(1) 0xdc,0xc1 -# CHECK: fadd %st(0), %st(2) +# CHECK: fadd %st, %st(2) 0xdc,0xc2 -# CHECK: fadd %st(0), %st(3) +# CHECK: fadd %st, %st(3) 0xdc,0xc3 -# CHECK: fadd %st(0), %st(4) +# CHECK: fadd %st, %st(4) 0xdc,0xc4 -# CHECK: fadd %st(0), %st(5) +# CHECK: fadd %st, %st(5) 0xdc,0xc5 -# CHECK: fadd %st(0), %st(6) +# CHECK: fadd %st, %st(6) 0xdc,0xc6 -# CHECK: fadd %st(0), %st(7) +# CHECK: fadd %st, %st(7) 0xdc,0xc7 -# CHECK: fmul %st(0), %st(0) +# CHECK: fmul %st, %st(0) 0xdc,0xc8 -# CHECK: fmul %st(0), %st(1) +# CHECK: fmul %st, %st(1) 0xdc,0xc9 -# CHECK: fmul %st(0), %st(2) +# CHECK: fmul %st, %st(2) 0xdc,0xca -# CHECK: fmul %st(0), %st(3) +# CHECK: fmul %st, %st(3) 0xdc,0xcb -# CHECK: fmul %st(0), %st(4) +# CHECK: fmul %st, %st(4) 0xdc,0xcc -# CHECK: fmul %st(0), %st(5) +# CHECK: fmul %st, %st(5) 0xdc,0xcd -# CHECK: fmul %st(0), %st(6) +# CHECK: fmul %st, %st(6) 0xdc,0xce -# CHECK: fmul %st(0), %st(7) +# CHECK: fmul %st, %st(7) 0xdc,0xcf -# CHECK: fsub %st(0), %st(0) +# CHECK: fsub %st, %st(0) 0xdc,0xe0 -# CHECK: fsub %st(0), %st(1) +# CHECK: fsub %st, %st(1) 0xdc,0xe1 -# CHECK: fsub %st(0), %st(2) +# CHECK: fsub %st, %st(2) 0xdc,0xe2 -# CHECK: fsub %st(0), %st(3) +# CHECK: fsub %st, %st(3) 0xdc,0xe3 -# CHECK: fsub %st(0), %st(4) +# CHECK: fsub %st, %st(4) 0xdc,0xe4 -# CHECK: fsub %st(0), %st(5) +# CHECK: fsub %st, %st(5) 0xdc,0xe5 -# CHECK: fsub %st(0), %st(6) +# CHECK: fsub %st, %st(6) 0xdc,0xe6 -# CHECK: fsub %st(0), %st(7) +# CHECK: fsub %st, %st(7) 0xdc,0xe7 -# CHECK: fsubr %st(0), %st(0) +# CHECK: fsubr %st, %st(0) 0xdc,0xe8 -# CHECK: fsubr %st(0), %st(1) +# CHECK: fsubr %st, %st(1) 0xdc,0xe9 -# CHECK: fsubr %st(0), %st(2) +# CHECK: fsubr %st, %st(2) 0xdc,0xea -# CHECK: fsubr %st(0), %st(3) +# CHECK: fsubr %st, %st(3) 0xdc,0xeb -# CHECK: fsubr %st(0), %st(4) +# CHECK: fsubr %st, %st(4) 0xdc,0xec -# CHECK: fsubr %st(0), %st(5) +# CHECK: fsubr %st, %st(5) 0xdc,0xed -# CHECK: fsubr %st(0), %st(6) +# CHECK: fsubr %st, %st(6) 0xdc,0xee -# CHECK: fsubr %st(0), %st(7) +# CHECK: fsubr %st, %st(7) 0xdc,0xef -# CHECK: fdiv %st(0), %st(0) +# CHECK: fdiv %st, %st(0) 0xdc,0xf0 -# CHECK: fdiv %st(0), %st(1) +# CHECK: fdiv %st, %st(1) 0xdc,0xf1 -# CHECK: fdiv %st(0), %st(2) +# CHECK: fdiv %st, %st(2) 0xdc,0xf2 -# CHECK: fdiv %st(0), %st(3) +# CHECK: fdiv %st, %st(3) 0xdc,0xf3 -# CHECK: fdiv %st(0), %st(4) +# CHECK: fdiv %st, %st(4) 0xdc,0xf4 -# CHECK: fdiv %st(0), %st(5) +# CHECK: fdiv %st, %st(5) 0xdc,0xf5 -# CHECK: fdiv %st(0), %st(6) +# CHECK: fdiv %st, %st(6) 0xdc,0xf6 -# CHECK: fdiv %st(0), %st(7) +# CHECK: fdiv %st, %st(7) 0xdc,0xf7 -# CHECK: fdivr %st(0), %st(0) +# CHECK: fdivr %st, %st(0) 0xdc,0xf8 -# CHECK: fdivr %st(0), %st(1) +# CHECK: fdivr %st, %st(1) 0xdc,0xf9 -# CHECK: fdivr %st(0), %st(2) +# CHECK: fdivr %st, %st(2) 0xdc,0xfa -# CHECK: fdivr %st(0), %st(3) +# CHECK: fdivr %st, %st(3) 0xdc,0xfb -# CHECK: fdivr %st(0), %st(4) +# CHECK: fdivr %st, %st(4) 0xdc,0xfc -# CHECK: fdivr %st(0), %st(5) +# CHECK: fdivr %st, %st(5) 0xdc,0xfd -# CHECK: fdivr %st(0), %st(6) +# CHECK: fdivr %st, %st(6) 0xdc,0xfe -# CHECK: fdivr %st(0), %st(7) +# CHECK: fdivr %st, %st(7) 0xdc,0xff # CHECK: ffree %st(0) @@ -838,151 +838,151 @@ # CHECK: fucomp %st(7) 0xdd,0xef -# CHECK: faddp %st(0) +# CHECK: faddp %st, %st(0) 0xde,0xc0 -# CHECK: faddp %st(1) +# CHECK: faddp %st, %st(1) 0xde,0xc1 -# CHECK: faddp %st(2) +# CHECK: faddp %st, %st(2) 0xde,0xc2 -# CHECK: faddp %st(3) +# CHECK: faddp %st, %st(3) 0xde,0xc3 -# CHECK: faddp %st(4) +# CHECK: faddp %st, %st(4) 0xde,0xc4 -# CHECK: faddp %st(5) +# CHECK: faddp %st, %st(5) 0xde,0xc5 -# CHECK: faddp %st(6) +# CHECK: faddp %st, %st(6) 0xde,0xc6 -# CHECK: faddp %st(7) +# CHECK: faddp %st, %st(7) 0xde,0xc7 -# CHECK: fmulp %st(0) +# CHECK: fmulp %st, %st(0) 0xde,0xc8 -# CHECK: fmulp %st(1) +# CHECK: fmulp %st, %st(1) 0xde,0xc9 -# CHECK: fmulp %st(2) +# CHECK: fmulp %st, %st(2) 0xde,0xca -# CHECK: fmulp %st(3) +# CHECK: fmulp %st, %st(3) 0xde,0xcb -# CHECK: fmulp %st(4) +# CHECK: fmulp %st, %st(4) 0xde,0xcc -# CHECK: fmulp %st(5) +# CHECK: fmulp %st, %st(5) 0xde,0xcd -# CHECK: fmulp %st(6) +# CHECK: fmulp %st, %st(6) 0xde,0xce -# CHECK: fmulp %st(7) +# CHECK: fmulp %st, %st(7) 0xde,0xcf # CHECK: fcompp 0xde,0xd9 -# CHECK: fsubp %st(0) +# CHECK: fsubp %st, %st(0) 0xde,0xe0 -# CHECK: fsubp %st(1) +# CHECK: fsubp %st, %st(1) 0xde,0xe1 -# CHECK: fsubp %st(2) +# CHECK: fsubp %st, %st(2) 0xde,0xe2 -# CHECK: fsubp %st(3) +# CHECK: fsubp %st, %st(3) 0xde,0xe3 -# CHECK: fsubp %st(4) +# CHECK: fsubp %st, %st(4) 0xde,0xe4 -# CHECK: fsubp %st(5) +# CHECK: fsubp %st, %st(5) 0xde,0xe5 -# CHECK: fsubp %st(6) +# CHECK: fsubp %st, %st(6) 0xde,0xe6 -# CHECK: fsubp %st(7) +# CHECK: fsubp %st, %st(7) 0xde,0xe7 -# CHECK: fsubrp %st(0) +# CHECK: fsubrp %st, %st(0) 0xde,0xe8 -# CHECK: fsubrp %st(1) +# CHECK: fsubrp %st, %st(1) 0xde,0xe9 -# CHECK: fsubrp %st(2) +# CHECK: fsubrp %st, %st(2) 0xde,0xea -# CHECK: fsubrp %st(3) +# CHECK: fsubrp %st, %st(3) 0xde,0xeb -# CHECK: fsubrp %st(4) +# CHECK: fsubrp %st, %st(4) 0xde,0xec -# CHECK: fsubrp %st(5) +# CHECK: fsubrp %st, %st(5) 0xde,0xed -# CHECK: fsubrp %st(6) +# CHECK: fsubrp %st, %st(6) 0xde,0xee -# CHECK: fsubrp %st(7) +# CHECK: fsubrp %st, %st(7) 0xde,0xef -# CHECK: fdivp %st(0) +# CHECK: fdivp %st, %st(0) 0xde,0xf0 -# CHECK: fdivp %st(1) +# CHECK: fdivp %st, %st(1) 0xde,0xf1 -# CHECK: fdivp %st(2) +# CHECK: fdivp %st, %st(2) 0xde,0xf2 -# CHECK: fdivp %st(3) +# CHECK: fdivp %st, %st(3) 0xde,0xf3 -# CHECK: fdivp %st(4) +# CHECK: fdivp %st, %st(4) 0xde,0xf4 -# CHECK: fdivp %st(5) +# CHECK: fdivp %st, %st(5) 0xde,0xf5 -# CHECK: fdivp %st(6) +# CHECK: fdivp %st, %st(6) 0xde,0xf6 -# CHECK: fdivp %st(7) +# CHECK: fdivp %st, %st(7) 0xde,0xf7 -# CHECK: fdivrp %st(0) +# CHECK: fdivrp %st, %st(0) 0xde,0xf8 -# CHECK: fdivrp %st(1) +# CHECK: fdivrp %st, %st(1) 0xde,0xf9 -# CHECK: fdivrp %st(2) +# CHECK: fdivrp %st, %st(2) 0xde,0xfa -# CHECK: fdivrp %st(3) +# CHECK: fdivrp %st, %st(3) 0xde,0xfb -# CHECK: fdivrp %st(4) +# CHECK: fdivrp %st, %st(4) 0xde,0xfc -# CHECK: fdivrp %st(5) +# CHECK: fdivrp %st, %st(5) 0xde,0xfd -# CHECK: fdivrp %st(6) +# CHECK: fdivrp %st, %st(6) 0xde,0xfe -# CHECK: fdivrp %st(7) +# CHECK: fdivrp %st, %st(7) 0xde,0xff # CHECK: ffreep %st(0) diff --git a/llvm/test/MC/Disassembler/X86/x86-16.txt b/llvm/test/MC/Disassembler/X86/x86-16.txt index 43cd09516c3b1..286aa88489cb4 100644 --- a/llvm/test/MC/Disassembler/X86/x86-16.txt +++ b/llvm/test/MC/Disassembler/X86/x86-16.txt @@ -759,10 +759,10 @@ # CHECK: strl %eax 0x66 0x0f 0x00 0xc8 -# CHECK: fsubp %st(1) +# CHECK: fsubp %st, %st(1) 0xde 0xe1 -# CHECK: fsubp %st(2) +# CHECK: fsubp %st, %st(2) 0xde 0xe2 # CHECKX: nop diff --git a/llvm/test/MC/ELF/invalid-symver.s b/llvm/test/MC/ELF/invalid-symver.s index 3c4f8c084b94b..d9f97b102b579 100644 --- a/llvm/test/MC/ELF/invalid-symver.s +++ b/llvm/test/MC/ELF/invalid-symver.s @@ -1,7 +1,7 @@ // RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t 2> %t.out // RUN: FileCheck --input-file=%t.out %s -// CHECK: A @@ version cannot be undefined +// CHECK: error: versioned symbol foo@@bar must be defined .symver undefined, foo@@bar .long undefined diff --git a/llvm/test/MC/ELF/multiple-different-symver.s b/llvm/test/MC/ELF/multiple-different-symver.s index d7706f89f4198..c34626c08173c 100644 --- a/llvm/test/MC/ELF/multiple-different-symver.s +++ b/llvm/test/MC/ELF/multiple-different-symver.s @@ -1,6 +1,6 @@ // RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t 2>&1 | FileCheck %s -// CHECK: Multiple symbol versions defined for foo +// CHECK: error: multiple symbol versions defined for foo .symver foo, foo@1 .symver foo, foo@2 diff --git a/llvm/test/MC/MachO/file-single.s b/llvm/test/MC/MachO/file-single.s deleted file mode 100644 index 747af22750af7..0000000000000 --- a/llvm/test/MC/MachO/file-single.s +++ /dev/null @@ -1,8 +0,0 @@ -// RUN: not llvm-mc -triple i386-apple-darwin9 %s -o /dev/null 2>&1 | FileCheck %s - -// Previously this crashed MC. - -// CHECK: error: target does not support '.file' without a number - - .file "dir/foo" - nop diff --git a/llvm/test/MC/MachO/file.s b/llvm/test/MC/MachO/file.s index 3ddfb2efe2246..eddbb599d97a2 100644 --- a/llvm/test/MC/MachO/file.s +++ b/llvm/test/MC/MachO/file.s @@ -1,5 +1,8 @@ // RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | llvm-readobj -s -section-data | FileCheck %s +// This number-less file directive is ignored on MachO. + .file "bar/baz.s" + .file 1 "dir/foo" nop diff --git a/llvm/test/MC/PowerPC/ppc64-localentry-symbols.s b/llvm/test/MC/PowerPC/ppc64-localentry-symbols.s new file mode 100644 index 0000000000000..f1d5c5d0ab1ac --- /dev/null +++ b/llvm/test/MC/PowerPC/ppc64-localentry-symbols.s @@ -0,0 +1,34 @@ +# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-freebsd13.0 %s -o %t +# RUN: llvm-objdump -t %t | FileCheck %s + +# CHECK: 0000000000000000 gw F .text 00000000 0x60 __impl_foo +# CHECK: 0000000000000000 g F .text 00000000 0x60 foo +# CHECK: 0000000000000000 gw F .text 00000000 0x60 foo@FBSD_1.1 +# CHECK: 0000000000000008 g F .text 00000000 0x60 func +# CHECK: 0000000000000008 gw F .text 00000000 0x60 weak_func + +.text +.abiversion 2 + +.globl foo +.type foo,@function +foo: + nop + nop + .localentry foo, 8 + +.symver __impl_foo, foo@FBSD_1.1 +.weak __impl_foo +.set __impl_foo, foo + +.globl func +# Mimick FreeBSD weak function/reference +.weak weak_func +.equ weak_func, func + +.p2align 2 +.type func,@function +func: + nop + nop + .localentry func, 8 diff --git a/llvm/test/MC/WebAssembly/external-func-address.ll b/llvm/test/MC/WebAssembly/external-func-address.ll index 60ec23a1a8ed3..8e36c76e84f3b 100644 --- a/llvm/test/MC/WebAssembly/external-func-address.ll +++ b/llvm/test/MC/WebAssembly/external-func-address.ll @@ -8,7 +8,7 @@ target triple = "wasm32-unknown-unknown" declare void @f0(i32) #0 @ptr_to_f0 = hidden global void (i32)* @f0, align 4 -attributes #0 = { "wasm-import-module"="somewhere" } +attributes #0 = { "wasm-import-module"="somewhere" "wasm-import-name"="something" } declare void @f1(i32) #1 @ptr_to_f1 = hidden global void (i32)* @f1, align 4 @@ -47,7 +47,7 @@ define void @call(i32) { ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: SigIndex: 1 ; CHECK: - Module: somewhere -; CHECK-NEXT: Field: f0 +; CHECK-NEXT: Field: something ; CHECK: - Module: env ; CHECK-NEXT: Field: f1 ; CHECK-NEXT: Kind: FUNCTION diff --git a/llvm/test/MC/WebAssembly/import-module.ll b/llvm/test/MC/WebAssembly/import-module.ll new file mode 100644 index 0000000000000..461d5c20ae9b7 --- /dev/null +++ b/llvm/test/MC/WebAssembly/import-module.ll @@ -0,0 +1,31 @@ +; RUN: llc -filetype=obj %s -o - | obj2yaml | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +define void @test() { + call void @foo() + call void @plain() + ret void +} + +declare void @foo() #0 +declare void @plain() + +attributes #0 = { "wasm-import-module"="bar" "wasm-import-name"="qux" } + +; CHECK: - Type: IMPORT +; CHECK-NEXT: Imports: +; CHECK: - Module: bar +; CHECK-NEXT: Field: qux +; CHECK-NEXT: Kind: FUNCTION + +; CHECK: - Module: env +; CHECK-NEXT: Field: plain +; CHECK-NEXT: Kind: FUNCTION + +; CHECK: - Type: CUSTOM +; CHECK: Name: foo +; CHECK-NEXT: Flags: [ UNDEFINED ] + +; CHECK: Name: plain +; CHECK-NEXT: Flags: [ UNDEFINED ] diff --git a/llvm/test/MC/WebAssembly/null-output.s b/llvm/test/MC/WebAssembly/null-output.s new file mode 100644 index 0000000000000..a25d095e0cbef --- /dev/null +++ b/llvm/test/MC/WebAssembly/null-output.s @@ -0,0 +1,10 @@ +# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -o /dev/null < %s + + .text + .section .text.main,"",@ + .type main,@function +main: + .functype main (i32, i32) -> (i32) + end_function +.Lfunc_end0: + .size main, .Lfunc_end0-main diff --git a/llvm/test/MC/X86/PPRO-32.s b/llvm/test/MC/X86/PPRO-32.s index bbd933e58af09..6deea6de9c449 100644 --- a/llvm/test/MC/X86/PPRO-32.s +++ b/llvm/test/MC/X86/PPRO-32.s @@ -64,37 +64,37 @@ cmovpl %eax, %eax // CHECK: encoding: [0x0f,0x48,0xc0] cmovsl %eax, %eax -// CHECK: fcmovbe %st(4), %st(0) +// CHECK: fcmovbe %st(4), %st // CHECK: encoding: [0xda,0xd4] -fcmovbe %st(4), %st(0) +fcmovbe %st(4), %st -// CHECK: fcmovb %st(4), %st(0) +// CHECK: fcmovb %st(4), %st // CHECK: encoding: [0xda,0xc4] -fcmovb %st(4), %st(0) +fcmovb %st(4), %st -// CHECK: fcmove %st(4), %st(0) +// CHECK: fcmove %st(4), %st // CHECK: encoding: [0xda,0xcc] -fcmove %st(4), %st(0) +fcmove %st(4), %st -// CHECK: fcmovnbe %st(4), %st(0) +// CHECK: fcmovnbe %st(4), %st // CHECK: encoding: [0xdb,0xd4] -fcmovnbe %st(4), %st(0) +fcmovnbe %st(4), %st -// CHECK: fcmovnb %st(4), %st(0) +// CHECK: fcmovnb %st(4), %st // CHECK: encoding: [0xdb,0xc4] -fcmovnb %st(4), %st(0) +fcmovnb %st(4), %st -// CHECK: fcmovne %st(4), %st(0) +// CHECK: fcmovne %st(4), %st // CHECK: encoding: [0xdb,0xcc] -fcmovne %st(4), %st(0) +fcmovne %st(4), %st -// CHECK: fcmovnu %st(4), %st(0) +// CHECK: fcmovnu %st(4), %st // CHECK: encoding: [0xdb,0xdc] -fcmovnu %st(4), %st(0) +fcmovnu %st(4), %st -// CHECK: fcmovu %st(4), %st(0) +// CHECK: fcmovu %st(4), %st // CHECK: encoding: [0xda,0xdc] -fcmovu %st(4), %st(0) +fcmovu %st(4), %st // CHECK: fcomi %st(4) // CHECK: encoding: [0xdb,0xf4] diff --git a/llvm/test/MC/X86/PPRO-64.s b/llvm/test/MC/X86/PPRO-64.s index a41d4a0f93cc9..8004772e8f3de 100644 --- a/llvm/test/MC/X86/PPRO-64.s +++ b/llvm/test/MC/X86/PPRO-64.s @@ -64,37 +64,37 @@ cmovpl %r13d, %r13d // CHECK: encoding: [0x45,0x0f,0x48,0xed] cmovsl %r13d, %r13d -// CHECK: fcmovbe %st(4), %st(0) +// CHECK: fcmovbe %st(4), %st // CHECK: encoding: [0xda,0xd4] -fcmovbe %st(4), %st(0) +fcmovbe %st(4), %st -// CHECK: fcmovb %st(4), %st(0) +// CHECK: fcmovb %st(4), %st // CHECK: encoding: [0xda,0xc4] -fcmovb %st(4), %st(0) +fcmovb %st(4), %st -// CHECK: fcmove %st(4), %st(0) +// CHECK: fcmove %st(4), %st // CHECK: encoding: [0xda,0xcc] -fcmove %st(4), %st(0) +fcmove %st(4), %st -// CHECK: fcmovnbe %st(4), %st(0) +// CHECK: fcmovnbe %st(4), %st // CHECK: encoding: [0xdb,0xd4] -fcmovnbe %st(4), %st(0) +fcmovnbe %st(4), %st -// CHECK: fcmovnb %st(4), %st(0) +// CHECK: fcmovnb %st(4), %st // CHECK: encoding: [0xdb,0xc4] -fcmovnb %st(4), %st(0) +fcmovnb %st(4), %st -// CHECK: fcmovne %st(4), %st(0) +// CHECK: fcmovne %st(4), %st // CHECK: encoding: [0xdb,0xcc] -fcmovne %st(4), %st(0) +fcmovne %st(4), %st -// CHECK: fcmovnu %st(4), %st(0) +// CHECK: fcmovnu %st(4), %st // CHECK: encoding: [0xdb,0xdc] -fcmovnu %st(4), %st(0) +fcmovnu %st(4), %st -// CHECK: fcmovu %st(4), %st(0) +// CHECK: fcmovu %st(4), %st // CHECK: encoding: [0xda,0xdc] -fcmovu %st(4), %st(0) +fcmovu %st(4), %st // CHECK: fcomi %st(4) // CHECK: encoding: [0xdb,0xf4] diff --git a/llvm/test/MC/X86/X87-32.s b/llvm/test/MC/X86/X87-32.s index 967763de93e05..d414ab65b7dc4 100755 --- a/llvm/test/MC/X86/X87-32.s +++ b/llvm/test/MC/X86/X87-32.s @@ -31,7 +31,7 @@ faddl 64(%edx,%eax) // CHECK: encoding: [0xdc,0x02] faddl (%edx) -// CHECK: faddp %st(4) +// CHECK: faddp %st, %st(4) // CHECK: encoding: [0xde,0xc4] faddp %st(4) @@ -59,11 +59,11 @@ fadds 64(%edx,%eax) // CHECK: encoding: [0xd8,0x02] fadds (%edx) -// CHECK: fadd %st(0), %st(4) +// CHECK: fadd %st, %st(4) // CHECK: encoding: [0xdc,0xc4] -fadd %st(0), %st(4) +fadd %st, %st(4) -// CHECK: fadd %st(4) +// CHECK: fadd %st(4), %st // CHECK: encoding: [0xd8,0xc4] fadd %st(4) @@ -259,7 +259,7 @@ fdivl 64(%edx,%eax) // CHECK: encoding: [0xdc,0x32] fdivl (%edx) -// CHECK: fdivp %st(4) +// CHECK: fdivp %st, %st(4) // CHECK: encoding: [0xde,0xf4] fdivp %st(4) @@ -287,7 +287,7 @@ fdivrl 64(%edx,%eax) // CHECK: encoding: [0xdc,0x3a] fdivrl (%edx) -// CHECK: fdivrp %st(4) +// CHECK: fdivrp %st, %st(4) // CHECK: encoding: [0xde,0xfc] fdivrp %st(4) @@ -315,11 +315,11 @@ fdivrs 64(%edx,%eax) // CHECK: encoding: [0xd8,0x3a] fdivrs (%edx) -// CHECK: fdivr %st(0), %st(4) +// CHECK: fdivr %st, %st(4) // CHECK: encoding: [0xdc,0xfc] -fdivr %st(0), %st(4) +fdivr %st, %st(4) -// CHECK: fdivr %st(4) +// CHECK: fdivr %st(4), %st // CHECK: encoding: [0xd8,0xfc] fdivr %st(4) @@ -347,11 +347,11 @@ fdivs 64(%edx,%eax) // CHECK: encoding: [0xd8,0x32] fdivs (%edx) -// CHECK: fdiv %st(0), %st(4) +// CHECK: fdiv %st, %st(4) // CHECK: encoding: [0xdc,0xf4] -fdiv %st(0), %st(4) +fdiv %st, %st(4) -// CHECK: fdiv %st(4) +// CHECK: fdiv %st(4), %st // CHECK: encoding: [0xd8,0xf4] fdiv %st(4) @@ -1119,7 +1119,7 @@ fmull 64(%edx,%eax) // CHECK: encoding: [0xdc,0x0a] fmull (%edx) -// CHECK: fmulp %st(4) +// CHECK: fmulp %st, %st(4) // CHECK: encoding: [0xde,0xcc] fmulp %st(4) @@ -1147,11 +1147,11 @@ fmuls 64(%edx,%eax) // CHECK: encoding: [0xd8,0x0a] fmuls (%edx) -// CHECK: fmul %st(0), %st(4) +// CHECK: fmul %st, %st(4) // CHECK: encoding: [0xdc,0xcc] -fmul %st(0), %st(4) +fmul %st, %st(4) -// CHECK: fmul %st(4) +// CHECK: fmul %st(4), %st // CHECK: encoding: [0xd8,0xcc] fmul %st(4) @@ -1479,7 +1479,7 @@ fsubl 64(%edx,%eax) // CHECK: encoding: [0xdc,0x22] fsubl (%edx) -// CHECK: fsubp %st(4) +// CHECK: fsubp %st, %st(4) // CHECK: encoding: [0xde,0xe4] fsubp %st(4) @@ -1507,7 +1507,7 @@ fsubrl 64(%edx,%eax) // CHECK: encoding: [0xdc,0x2a] fsubrl (%edx) -// CHECK: fsubrp %st(4) +// CHECK: fsubrp %st, %st(4) // CHECK: encoding: [0xde,0xec] fsubrp %st(4) @@ -1535,11 +1535,11 @@ fsubrs 64(%edx,%eax) // CHECK: encoding: [0xd8,0x2a] fsubrs (%edx) -// CHECK: fsubr %st(0), %st(4) +// CHECK: fsubr %st, %st(4) // CHECK: encoding: [0xdc,0xec] -fsubr %st(0), %st(4) +fsubr %st, %st(4) -// CHECK: fsubr %st(4) +// CHECK: fsubr %st(4), %st // CHECK: encoding: [0xd8,0xec] fsubr %st(4) @@ -1567,11 +1567,11 @@ fsubs 64(%edx,%eax) // CHECK: encoding: [0xd8,0x22] fsubs (%edx) -// CHECK: fsub %st(0), %st(4) +// CHECK: fsub %st, %st(4) // CHECK: encoding: [0xdc,0xe4] -fsub %st(0), %st(4) +fsub %st, %st(4) -// CHECK: fsub %st(4) +// CHECK: fsub %st(4), %st // CHECK: encoding: [0xd8,0xe4] fsub %st(4) diff --git a/llvm/test/MC/X86/X87-64.s b/llvm/test/MC/X86/X87-64.s index a3b76b4e4b0ad..1103f326ea047 100755 --- a/llvm/test/MC/X86/X87-64.s +++ b/llvm/test/MC/X86/X87-64.s @@ -31,7 +31,7 @@ faddl 64(%rdx,%rax) // CHECK: encoding: [0xdc,0x02] faddl (%rdx) -// CHECK: faddp %st(4) +// CHECK: faddp %st, %st(4) // CHECK: encoding: [0xde,0xc4] faddp %st(4) @@ -59,11 +59,11 @@ fadds 64(%rdx,%rax) // CHECK: encoding: [0xd8,0x02] fadds (%rdx) -// CHECK: fadd %st(0), %st(4) +// CHECK: fadd %st, %st(4) // CHECK: encoding: [0xdc,0xc4] -fadd %st(0), %st(4) +fadd %st, %st(4) -// CHECK: fadd %st(4) +// CHECK: fadd %st(4), %st // CHECK: encoding: [0xd8,0xc4] fadd %st(4) @@ -259,7 +259,7 @@ fdivl 64(%rdx,%rax) // CHECK: encoding: [0xdc,0x32] fdivl (%rdx) -// CHECK: fdivp %st(4) +// CHECK: fdivp %st, %st(4) // CHECK: encoding: [0xde,0xf4] fdivp %st(4) @@ -287,7 +287,7 @@ fdivrl 64(%rdx,%rax) // CHECK: encoding: [0xdc,0x3a] fdivrl (%rdx) -// CHECK: fdivrp %st(4) +// CHECK: fdivrp %st, %st(4) // CHECK: encoding: [0xde,0xfc] fdivrp %st(4) @@ -315,11 +315,11 @@ fdivrs 64(%rdx,%rax) // CHECK: encoding: [0xd8,0x3a] fdivrs (%rdx) -// CHECK: fdivr %st(0), %st(4) +// CHECK: fdivr %st, %st(4) // CHECK: encoding: [0xdc,0xfc] -fdivr %st(0), %st(4) +fdivr %st, %st(4) -// CHECK: fdivr %st(4) +// CHECK: fdivr %st(4), %st // CHECK: encoding: [0xd8,0xfc] fdivr %st(4) @@ -347,11 +347,11 @@ fdivs 64(%rdx,%rax) // CHECK: encoding: [0xd8,0x32] fdivs (%rdx) -// CHECK: fdiv %st(0), %st(4) +// CHECK: fdiv %st, %st(4) // CHECK: encoding: [0xdc,0xf4] -fdiv %st(0), %st(4) +fdiv %st, %st(4) -// CHECK: fdiv %st(4) +// CHECK: fdiv %st(4), %st // CHECK: encoding: [0xd8,0xf4] fdiv %st(4) @@ -1119,7 +1119,7 @@ fmull 64(%rdx,%rax) // CHECK: encoding: [0xdc,0x0a] fmull (%rdx) -// CHECK: fmulp %st(4) +// CHECK: fmulp %st, %st(4) // CHECK: encoding: [0xde,0xcc] fmulp %st(4) @@ -1147,9 +1147,9 @@ fmuls 64(%rdx,%rax) // CHECK: encoding: [0xd8,0x0a] fmuls (%rdx) -// CHECK: fmul %st(0), %st(4) +// CHECK: fmul %st, %st(4) // CHECK: encoding: [0xdc,0xcc] -fmul %st(0), %st(4) +fmul %st, %st(4) // CHECK: fmul %st(4) // CHECK: encoding: [0xd8,0xcc] @@ -1479,7 +1479,7 @@ fsubl 64(%rdx,%rax) // CHECK: encoding: [0xdc,0x22] fsubl (%rdx) -// CHECK: fsubp %st(4) +// CHECK: fsubp %st, %st(4) // CHECK: encoding: [0xde,0xe4] fsubp %st(4) @@ -1507,7 +1507,7 @@ fsubrl 64(%rdx,%rax) // CHECK: encoding: [0xdc,0x2a] fsubrl (%rdx) -// CHECK: fsubrp %st(4) +// CHECK: fsubrp %st, %st(4) // CHECK: encoding: [0xde,0xec] fsubrp %st(4) @@ -1535,11 +1535,11 @@ fsubrs 64(%rdx,%rax) // CHECK: encoding: [0xd8,0x2a] fsubrs (%rdx) -// CHECK: fsubr %st(0), %st(4) +// CHECK: fsubr %st, %st(4) // CHECK: encoding: [0xdc,0xec] -fsubr %st(0), %st(4) +fsubr %st, %st(4) -// CHECK: fsubr %st(4) +// CHECK: fsubr %st(4), %st // CHECK: encoding: [0xd8,0xec] fsubr %st(4) @@ -1567,11 +1567,11 @@ fsubs 64(%rdx,%rax) // CHECK: encoding: [0xd8,0x22] fsubs (%rdx) -// CHECK: fsub %st(0), %st(4) +// CHECK: fsub %st, %st(4) // CHECK: encoding: [0xdc,0xe4] -fsub %st(0), %st(4) +fsub %st, %st(4) -// CHECK: fsub %st(4) +// CHECK: fsub %st(4), %st // CHECK: encoding: [0xd8,0xe4] fsub %st(4) diff --git a/llvm/test/MC/X86/intel-syntax-2.s b/llvm/test/MC/X86/intel-syntax-2.s index aead5766db4d5..b23965ae52e88 100644 --- a/llvm/test/MC/X86/intel-syntax-2.s +++ b/llvm/test/MC/X86/intel-syntax-2.s @@ -18,14 +18,14 @@ _test2: _test3: fadd -// CHECK: faddp %st(1) +// CHECK: faddp %st, %st(1) fmul -// CHECK: fmulp %st(1) +// CHECK: fmulp %st, %st(1) fsub -// CHECK: fsubp %st(1) +// CHECK: fsubp %st, %st(1) fsubr -// CHECK: fsubrp %st(1) +// CHECK: fsubrp %st, %st(1) fdiv -// CHECK: fdivp %st(1) +// CHECK: fdivp %st, %st(1) fdivr -// CHECK: fdivrp %st(1) +// CHECK: fdivrp %st, %st(1) diff --git a/llvm/test/MC/X86/intel-syntax.s b/llvm/test/MC/X86/intel-syntax.s index 428a7e4ec41f1..171357e1f5212 100644 --- a/llvm/test/MC/X86/intel-syntax.s +++ b/llvm/test/MC/X86/intel-syntax.s @@ -556,12 +556,12 @@ fnstsw fnstsw AX fnstsw WORD PTR [EAX] -// CHECK: faddp %st(1) -// CHECK: fmulp %st(1) -// CHECK: fsubrp %st(1) -// CHECK: fsubp %st(1) -// CHECK: fdivrp %st(1) -// CHECK: fdivp %st(1) +// CHECK: faddp %st, %st(1) +// CHECK: fmulp %st, %st(1) +// CHECK: fsubrp %st, %st(1) +// CHECK: fsubp %st, %st(1) +// CHECK: fdivrp %st, %st(1) +// CHECK: fdivp %st, %st(1) faddp ST(1), ST(0) fmulp ST(1), ST(0) fsubp ST(1), ST(0) @@ -569,12 +569,12 @@ fsubrp ST(1), ST(0) fdivp ST(1), ST(0) fdivrp ST(1), ST(0) -// CHECK: faddp %st(1) -// CHECK: fmulp %st(1) -// CHECK: fsubrp %st(1) -// CHECK: fsubp %st(1) -// CHECK: fdivrp %st(1) -// CHECK: fdivp %st(1) +// CHECK: faddp %st, %st(1) +// CHECK: fmulp %st, %st(1) +// CHECK: fsubrp %st, %st(1) +// CHECK: fsubp %st, %st(1) +// CHECK: fdivrp %st, %st(1) +// CHECK: fdivp %st, %st(1) faddp ST(0), ST(1) fmulp ST(0), ST(1) fsubp ST(0), ST(1) @@ -582,12 +582,12 @@ fsubrp ST(0), ST(1) fdivp ST(0), ST(1) fdivrp ST(0), ST(1) -// CHECK: faddp %st(1) -// CHECK: fmulp %st(1) -// CHECK: fsubrp %st(1) -// CHECK: fsubp %st(1) -// CHECK: fdivrp %st(1) -// CHECK: fdivp %st(1) +// CHECK: faddp %st, %st(1) +// CHECK: fmulp %st, %st(1) +// CHECK: fsubrp %st, %st(1) +// CHECK: fsubp %st, %st(1) +// CHECK: fdivrp %st, %st(1) +// CHECK: fdivp %st, %st(1) faddp ST(1) fmulp ST(1) fsubp ST(1) @@ -596,12 +596,12 @@ fdivp ST(1) fdivrp ST(1) -// CHECK: faddp %st(1) -// CHECK: fmulp %st(1) -// CHECK: fsubrp %st(1) -// CHECK: fsubp %st(1) -// CHECK: fdivrp %st(1) -// CHECK: fdivp %st(1) +// CHECK: faddp %st, %st(1) +// CHECK: fmulp %st, %st(1) +// CHECK: fsubrp %st, %st(1) +// CHECK: fsubp %st, %st(1) +// CHECK: fdivrp %st, %st(1) +// CHECK: fdivp %st, %st(1) fadd fmul fsub @@ -609,12 +609,12 @@ fsubr fdiv fdivr -// CHECK: faddp %st(1) -// CHECK: fmulp %st(1) -// CHECK: fsubrp %st(1) -// CHECK: fsubp %st(1) -// CHECK: fdivrp %st(1) -// CHECK: fdivp %st(1) +// CHECK: faddp %st, %st(1) +// CHECK: fmulp %st, %st(1) +// CHECK: fsubrp %st, %st(1) +// CHECK: fsubp %st, %st(1) +// CHECK: fdivrp %st, %st(1) +// CHECK: fdivp %st, %st(1) faddp fmulp fsubp @@ -622,12 +622,12 @@ fsubrp fdivp fdivrp -// CHECK: fadd %st(1) -// CHECK: fmul %st(1) -// CHECK: fsub %st(1) -// CHECK: fsubr %st(1) -// CHECK: fdiv %st(1) -// CHECK: fdivr %st(1) +// CHECK: fadd %st(1), %st +// CHECK: fmul %st(1), %st +// CHECK: fsub %st(1), %st +// CHECK: fsubr %st(1), %st +// CHECK: fdiv %st(1), %st +// CHECK: fdivr %st(1), %st fadd ST(0), ST(1) fmul ST(0), ST(1) fsub ST(0), ST(1) @@ -635,12 +635,12 @@ fsubr ST(0), ST(1) fdiv ST(0), ST(1) fdivr ST(0), ST(1) -// CHECK: fadd %st(0), %st(1) -// CHECK: fmul %st(0), %st(1) -// CHECK: fsubr %st(0), %st(1) -// CHECK: fsub %st(0), %st(1) -// CHECK: fdivr %st(0), %st(1) -// CHECK: fdiv %st(0), %st(1) +// CHECK: fadd %st, %st(1) +// CHECK: fmul %st, %st(1) +// CHECK: fsubr %st, %st(1) +// CHECK: fsub %st, %st(1) +// CHECK: fdivr %st, %st(1) +// CHECK: fdiv %st, %st(1) fadd ST(1), ST(0) fmul ST(1), ST(0) fsub ST(1), ST(0) @@ -648,12 +648,12 @@ fsubr ST(1), ST(0) fdiv ST(1), ST(0) fdivr ST(1), ST(0) -// CHECK: fadd %st(1) -// CHECK: fmul %st(1) -// CHECK: fsub %st(1) -// CHECK: fsubr %st(1) -// CHECK: fdiv %st(1) -// CHECK: fdivr %st(1) +// CHECK: fadd %st(1), %st +// CHECK: fmul %st(1), %st +// CHECK: fsub %st(1), %st +// CHECK: fsubr %st(1), %st +// CHECK: fdiv %st(1), %st +// CHECK: fdivr %st(1), %st fadd ST(1) fmul ST(1) fsub ST(1) diff --git a/llvm/test/MC/X86/x86-16.s b/llvm/test/MC/X86/x86-16.s index 50263beaa6756..88ee77a6d4143 100644 --- a/llvm/test/MC/X86/x86-16.s +++ b/llvm/test/MC/X86/x86-16.s @@ -920,11 +920,11 @@ pshufw $90, %mm4, %mm0 str %eax -// CHECK: fsubp +// CHECK: fsubp %st, %st(1) // CHECK: encoding: [0xde,0xe1] fsubp %st,%st(1) -// CHECK: fsubp %st(2) +// CHECK: fsubp %st, %st(2) // CHECK: encoding: [0xde,0xe2] fsubp %st, %st(2) diff --git a/llvm/test/MC/X86/x86-32-coverage.s b/llvm/test/MC/X86/x86-32-coverage.s index 32281f4121644..ba59fb357b974 100644 --- a/llvm/test/MC/X86/x86-32-coverage.s +++ b/llvm/test/MC/X86/x86-32-coverage.s @@ -2472,11 +2472,11 @@ // CHECK: encoding: [0xda,0x05,0x78,0x56,0x34,0x12] fiaddl 0x12345678 -// CHECK: faddp %st(2) +// CHECK: faddp %st, %st(2) // CHECK: encoding: [0xde,0xc2] faddp %st(2) -// CHECK: fsub %st(2) +// CHECK: fsub %st(2), %st // CHECK: encoding: [0xd8,0xe2] fsub %st(2) @@ -2504,11 +2504,11 @@ // CHECK: encoding: [0xda,0x25,0x78,0x56,0x34,0x12] fisubl 0x12345678 -// CHECK: fsubp %st(2) +// CHECK: fsubp %st, %st(2) // CHECK: encoding: [0xde,0xe2] fsubp %st(2) -// CHECK: fsubr %st(2) +// CHECK: fsubr %st(2), %st // CHECK: encoding: [0xd8,0xea] fsubr %st(2) @@ -2536,11 +2536,11 @@ // CHECK: encoding: [0xda,0x2d,0x78,0x56,0x34,0x12] fisubrl 0x12345678 -// CHECK: fsubrp %st(2) +// CHECK: fsubrp %st, %st(2) // CHECK: encoding: [0xde,0xea] fsubrp %st(2) -// CHECK: fmul %st(2) +// CHECK: fmul %st(2), %st // CHECK: encoding: [0xd8,0xca] fmul %st(2) @@ -2568,11 +2568,11 @@ // CHECK: encoding: [0xda,0x0d,0x78,0x56,0x34,0x12] fimull 0x12345678 -// CHECK: fmulp %st(2) +// CHECK: fmulp %st, %st(2) // CHECK: encoding: [0xde,0xca] fmulp %st(2) -// CHECK: fdiv %st(2) +// CHECK: fdiv %st(2), %st // CHECK: encoding: [0xd8,0xf2] fdiv %st(2) @@ -2600,11 +2600,11 @@ // CHECK: encoding: [0xda,0x35,0x78,0x56,0x34,0x12] fidivl 0x12345678 -// CHECK: fdivp %st(2) +// CHECK: fdivp %st, %st(2) // CHECK: encoding: [0xde,0xf2] fdivp %st(2) -// CHECK: fdivr %st(2) +// CHECK: fdivr %st(2), %st // CHECK: encoding: [0xd8,0xfa] fdivr %st(2) @@ -2632,7 +2632,7 @@ // CHECK: encoding: [0xda,0x3d,0x78,0x56,0x34,0x12] fidivrl 0x12345678 -// CHECK: fdivrp %st(2) +// CHECK: fdivrp %st, %st(2) // CHECK: encoding: [0xde,0xfa] fdivrp %st(2) @@ -2876,35 +2876,35 @@ // CHECK: encoding: [0x0f,0x0b] ud2 -// CHECK: fcmovb %st(2), %st(0) +// CHECK: fcmovb %st(2), %st // CHECK: encoding: [0xda,0xc2] fcmovb %st(2),%st -// CHECK: fcmove %st(2), %st(0) +// CHECK: fcmove %st(2), %st // CHECK: encoding: [0xda,0xca] fcmove %st(2),%st -// CHECK: fcmovbe %st(2), %st(0) +// CHECK: fcmovbe %st(2), %st // CHECK: encoding: [0xda,0xd2] fcmovbe %st(2),%st -// CHECK: fcmovu %st(2), %st(0) +// CHECK: fcmovu %st(2), %st // CHECK: encoding: [0xda,0xda] fcmovu %st(2),%st -// CHECK: fcmovnb %st(2), %st(0) +// CHECK: fcmovnb %st(2), %st // CHECK: encoding: [0xdb,0xc2] fcmovnb %st(2),%st -// CHECK: fcmovne %st(2), %st(0) +// CHECK: fcmovne %st(2), %st // CHECK: encoding: [0xdb,0xca] fcmovne %st(2),%st -// CHECK: fcmovnbe %st(2), %st(0) +// CHECK: fcmovnbe %st(2), %st // CHECK: encoding: [0xdb,0xd2] fcmovnbe %st(2),%st -// CHECK: fcmovnu %st(2), %st(0) +// CHECK: fcmovnu %st(2), %st // CHECK: encoding: [0xdb,0xda] fcmovnu %st(2),%st diff --git a/llvm/test/MC/X86/x86-32.s b/llvm/test/MC/X86/x86-32.s index 69d3603259345..1593c26b9d029 100644 --- a/llvm/test/MC/X86/x86-32.s +++ b/llvm/test/MC/X86/x86-32.s @@ -1055,7 +1055,7 @@ pshufw $90, %mm4, %mm0 fsubp %st,%st(1) // PR9164 -// CHECK: fsubp %st(2) +// CHECK: fsubp %st, %st(2) // CHECK: encoding: [0xde,0xe2] fsubp %st, %st(2) diff --git a/llvm/test/MC/X86/x86-64.s b/llvm/test/MC/X86/x86-64.s index df811a6c4cf2e..e35ba19fc4f2e 100644 --- a/llvm/test/MC/X86/x86-64.s +++ b/llvm/test/MC/X86/x86-64.s @@ -307,13 +307,13 @@ insl (%dx), %es:(%rdi) // CHECK: fxch %st(1) // CHECK: fucom %st(1) // CHECK: fucomp %st(1) -// CHECK: faddp %st(1) -// CHECK: faddp %st(0) -// CHECK: fsubp %st(1) -// CHECK: fsubrp %st(1) -// CHECK: fmulp %st(1) -// CHECK: fdivp %st(1) -// CHECK: fdivrp %st(1) +// CHECK: faddp %st, %st(1) +// CHECK: faddp %st, %st(0) +// CHECK: fsubp %st, %st(1) +// CHECK: fsubrp %st, %st(1) +// CHECK: fmulp %st, %st(1) +// CHECK: fdivp %st, %st(1) +// CHECK: fdivrp %st, %st(1) fxch fucom @@ -416,21 +416,21 @@ enter $0x7ace,$0x7f mov %cs, %ax // rdar://8456391 -fcmovb %st(1), %st(0) // CHECK: fcmovb %st(1), %st(0) -fcmove %st(1), %st(0) // CHECK: fcmove %st(1), %st(0) -fcmovbe %st(1), %st(0) // CHECK: fcmovbe %st(1), %st(0) -fcmovu %st(1), %st(0) // CHECK: fcmovu %st(1), %st(0) +fcmovb %st(1), %st // CHECK: fcmovb %st(1), %st +fcmove %st(1), %st // CHECK: fcmove %st(1), %st +fcmovbe %st(1), %st // CHECK: fcmovbe %st(1), %st +fcmovu %st(1), %st // CHECK: fcmovu %st(1), %st -fcmovnb %st(1), %st(0) // CHECK: fcmovnb %st(1), %st(0) -fcmovne %st(1), %st(0) // CHECK: fcmovne %st(1), %st(0) -fcmovnbe %st(1), %st(0) // CHECK: fcmovnbe %st(1), %st(0) -fcmovnu %st(1), %st(0) // CHECK: fcmovnu %st(1), %st(0) +fcmovnb %st(1), %st // CHECK: fcmovnb %st(1), %st +fcmovne %st(1), %st // CHECK: fcmovne %st(1), %st +fcmovnbe %st(1), %st // CHECK: fcmovnbe %st(1), %st +fcmovnu %st(1), %st // CHECK: fcmovnu %st(1), %st -fcmovnae %st(1), %st(0) // CHECK: fcmovb %st(1), %st(0) -fcmovna %st(1), %st(0) // CHECK: fcmovbe %st(1), %st(0) +fcmovnae %st(1), %st // CHECK: fcmovb %st(1), %st +fcmovna %st(1), %st // CHECK: fcmovbe %st(1), %st -fcmovae %st(1), %st(0) // CHECK: fcmovnb %st(1), %st(0) -fcmova %st(1), %st(0) // CHECK: fcmovnbe %st(1), %st(0) +fcmovae %st(1), %st // CHECK: fcmovnb %st(1), %st +fcmova %st(1), %st // CHECK: fcmovnbe %st(1), %st // rdar://8456417 .byte (88 + 1) & 15 // CHECK: .byte 9 @@ -456,20 +456,20 @@ mov %rdx, %db15 // CHECK: encoding: [0x44,0x0f,0x23,0xfa] // rdar://8456371 - Handle commutable instructions written backward. -// CHECK: faddp %st(1) -// CHECK: fmulp %st(2) +// CHECK: faddp %st, %st(1) +// CHECK: fmulp %st, %st(2) faddp %st, %st(1) fmulp %st, %st(2) // rdar://8468087 - Encode these accurately, they are not synonyms. -// CHECK: fmul %st(0), %st(1) +// CHECK: fmul %st, %st(1) // CHECK: encoding: [0xdc,0xc9] // CHECK: fmul %st(1) // CHECK: encoding: [0xd8,0xc9] fmul %st, %st(1) fmul %st(1), %st -// CHECK: fadd %st(0), %st(1) +// CHECK: fadd %st, %st(1) // CHECK: encoding: [0xdc,0xc1] // CHECK: fadd %st(1) // CHECK: encoding: [0xd8,0xc1] @@ -582,15 +582,15 @@ movmskpd %xmm6, %eax // CHECK: encoding: [0x66,0x0f,0x50,0xc6] // rdar://8491845 - Gas supports commuted forms of non-commutable instructions. -fdivrp %st(0), %st(1) // CHECK: encoding: [0xde,0xf9] -fdivrp %st(1), %st(0) // CHECK: encoding: [0xde,0xf9] +fdivrp %st, %st(1) // CHECK: encoding: [0xde,0xf9] +fdivrp %st(1), %st // CHECK: encoding: [0xde,0xf9] -fsubrp %st(0), %st(1) // CHECK: encoding: [0xde,0xe9] -fsubrp %st(1), %st(0) // CHECK: encoding: [0xde,0xe9] +fsubrp %st, %st(1) // CHECK: encoding: [0xde,0xe9] +fsubrp %st(1), %st // CHECK: encoding: [0xde,0xe9] // also PR8861 -fdivp %st(0), %st(1) // CHECK: encoding: [0xde,0xf1] -fdivp %st(1), %st(0) // CHECK: encoding: [0xde,0xf1] +fdivp %st, %st(1) // CHECK: encoding: [0xde,0xf1] +fdivp %st(1), %st // CHECK: encoding: [0xde,0xf1] movl foo(%rip), %eax @@ -1391,38 +1391,38 @@ clac // CHECK: encoding: [0x0f,0x01,0xcb] stac -// CHECK: faddp %st(1) -// CHECK: fmulp %st(1) -// CHECK: fsubp %st(1) -// CHECK: fsubrp %st(1) -// CHECK: fdivp %st(1) -// CHECK: fdivrp %st(1) -faddp %st(0), %st(1) -fmulp %st(0), %st(1) -fsubp %st(0), %st(1) -fsubrp %st(0), %st(1) -fdivp %st(0), %st(1) -fdivrp %st(0), %st(1) - -// CHECK: faddp %st(1) -// CHECK: fmulp %st(1) -// CHECK: fsubp %st(1) -// CHECK: fsubrp %st(1) -// CHECK: fdivp %st(1) -// CHECK: fdivrp %st(1) -faddp %st(1), %st(0) -fmulp %st(1), %st(0) -fsubp %st(1), %st(0) -fsubrp %st(1), %st(0) -fdivp %st(1), %st(0) -fdivrp %st(1), %st(0) - -// CHECK: faddp %st(1) -// CHECK: fmulp %st(1) -// CHECK: fsubp %st(1) -// CHECK: fsubrp %st(1) -// CHECK: fdivp %st(1) -// CHECK: fdivrp %st(1) +// CHECK: faddp %st, %st(1) +// CHECK: fmulp %st, %st(1) +// CHECK: fsubp %st, %st(1) +// CHECK: fsubrp %st, %st(1) +// CHECK: fdivp %st, %st(1) +// CHECK: fdivrp %st, %st(1) +faddp %st, %st(1) +fmulp %st, %st(1) +fsubp %st, %st(1) +fsubrp %st, %st(1) +fdivp %st, %st(1) +fdivrp %st, %st(1) + +// CHECK: faddp %st, %st(1) +// CHECK: fmulp %st, %st(1) +// CHECK: fsubp %st, %st(1) +// CHECK: fsubrp %st, %st(1) +// CHECK: fdivp %st, %st(1) +// CHECK: fdivrp %st, %st(1) +faddp %st(1), %st +fmulp %st(1), %st +fsubp %st(1), %st +fsubrp %st(1), %st +fdivp %st(1), %st +fdivrp %st(1), %st + +// CHECK: faddp %st, %st(1) +// CHECK: fmulp %st, %st(1) +// CHECK: fsubp %st, %st(1) +// CHECK: fsubrp %st, %st(1) +// CHECK: fdivp %st, %st(1) +// CHECK: fdivrp %st, %st(1) faddp %st(1) fmulp %st(1) fsubp %st(1) @@ -1430,12 +1430,12 @@ fsubrp %st(1) fdivp %st(1) fdivrp %st(1) -// CHECK: faddp %st(1) -// CHECK: fmulp %st(1) -// CHECK: fsubp %st(1) -// CHECK: fsubrp %st(1) -// CHECK: fdivp %st(1) -// CHECK: fdivrp %st(1) +// CHECK: faddp %st, %st(1) +// CHECK: fmulp %st, %st(1) +// CHECK: fsubp %st, %st(1) +// CHECK: fsubrp %st, %st(1) +// CHECK: fdivp %st, %st(1) +// CHECK: fdivrp %st, %st(1) faddp fmulp fsubp @@ -1449,25 +1449,25 @@ fdivrp // CHECK: fsubr %st(1) // CHECK: fdiv %st(1) // CHECK: fdivr %st(1) -fadd %st(1), %st(0) -fmul %st(1), %st(0) -fsub %st(1), %st(0) -fsubr %st(1), %st(0) -fdiv %st(1), %st(0) -fdivr %st(1), %st(0) - -// CHECK: fadd %st(0), %st(1) -// CHECK: fmul %st(0), %st(1) -// CHECK: fsub %st(0), %st(1) -// CHECK: fsubr %st(0), %st(1) -// CHECK: fdiv %st(0), %st(1) -// CHECK: fdivr %st(0), %st(1) -fadd %st(0), %st(1) -fmul %st(0), %st(1) -fsub %st(0), %st(1) -fsubr %st(0), %st(1) -fdiv %st(0), %st(1) -fdivr %st(0), %st(1) +fadd %st(1), %st +fmul %st(1), %st +fsub %st(1), %st +fsubr %st(1), %st +fdiv %st(1), %st +fdivr %st(1), %st + +// CHECK: fadd %st, %st(1) +// CHECK: fmul %st, %st(1) +// CHECK: fsub %st, %st(1) +// CHECK: fsubr %st, %st(1) +// CHECK: fdiv %st, %st(1) +// CHECK: fdivr %st, %st(1) +fadd %st, %st(1) +fmul %st, %st(1) +fsub %st, %st(1) +fsubr %st, %st(1) +fdiv %st, %st(1) +fdivr %st, %st(1) // CHECK: fadd %st(1) // CHECK: fmul %st(1) diff --git a/llvm/test/Transforms/DeadStoreElimination/X86/gather-null-pointer.ll b/llvm/test/Transforms/DeadStoreElimination/X86/gather-null-pointer.ll new file mode 100644 index 0000000000000..6a5f4bb9eb25c --- /dev/null +++ b/llvm/test/Transforms/DeadStoreElimination/X86/gather-null-pointer.ll @@ -0,0 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -dse -S | FileCheck %s + +; Both stores should be emitted because we can't tell if the gather aliases. + +define <4 x i32> @bar(<4 x i32> %arg, i32* %arg1) { +; CHECK-LABEL: @bar( +; CHECK-NEXT: bb: +; CHECK-NEXT: store i32 5, i32* [[ARG1:%.*]] +; CHECK-NEXT: [[TMP:%.*]] = tail call <4 x i32> @llvm.x86.avx2.gather.d.d(<4 x i32> zeroinitializer, i8* null, <4 x i32> [[ARG:%.*]], <4 x i32> , i8 1) +; CHECK-NEXT: store i32 10, i32* [[ARG1]] +; CHECK-NEXT: ret <4 x i32> [[TMP]] +; +bb: + store i32 5, i32* %arg1 + %tmp = tail call <4 x i32> @llvm.x86.avx2.gather.d.d(<4 x i32> zeroinitializer, i8* null, <4 x i32> %arg, <4 x i32> , i8 1) + store i32 10, i32* %arg1 + ret <4 x i32> %tmp +} + +declare <4 x i32> @llvm.x86.avx2.gather.d.d(<4 x i32>, i8*, <4 x i32>, <4 x i32>, i8) diff --git a/llvm/test/Transforms/FunctionImport/Inputs/comdat.ll b/llvm/test/Transforms/FunctionImport/Inputs/comdat.ll new file mode 100644 index 0000000000000..1df6f25351e58 --- /dev/null +++ b/llvm/test/Transforms/FunctionImport/Inputs/comdat.ll @@ -0,0 +1,10 @@ +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc19.0.24215" + +define void @main() { +entry: + call i8* @lwt_fun() + ret void +} + +declare i8* @lwt_fun() diff --git a/llvm/test/Transforms/FunctionImport/comdat.ll b/llvm/test/Transforms/FunctionImport/comdat.ll new file mode 100644 index 0000000000000..29e8cb538ab66 --- /dev/null +++ b/llvm/test/Transforms/FunctionImport/comdat.ll @@ -0,0 +1,32 @@ +; Test to ensure that comdat is renamed consistently when comdat leader is +; promoted and renamed due to an import. Required by COFF. + +; REQUIRES: x86-registered-target + +; RUN: opt -thinlto-bc -o %t1.bc %s +; RUN: opt -thinlto-bc -o %t2.bc %S/Inputs/comdat.ll +; RUN: llvm-lto2 run -save-temps -o %t3 %t1.bc %t2.bc \ +; RUN: -r %t1.bc,lwt_fun,plx \ +; RUN: -r %t2.bc,main,plx \ +; RUN: -r %t2.bc,lwt_fun, +; RUN: llvm-dis -o - %t3.1.3.import.bc | FileCheck %s + +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc19.0.24215" + +; CHECK: $lwt.llvm.[[HASH:[0-9]+]] = comdat any +$lwt = comdat any + +; CHECK: @lwt_aliasee = private unnamed_addr global {{.*}}, comdat($lwt.llvm.[[HASH]]) +@lwt_aliasee = private unnamed_addr global [1 x i8*] [i8* null], comdat($lwt) + +; CHECK: @lwt.llvm.[[HASH]] = hidden unnamed_addr alias +@lwt = internal unnamed_addr alias [1 x i8*], [1 x i8*]* @lwt_aliasee + +; Below function should get imported into other module, resulting in @lwt being +; promoted and renamed. +define i8* @lwt_fun() { + %1 = getelementptr inbounds [1 x i8*], [1 x i8*]* @lwt, i32 0, i32 0 + %2 = load i8*, i8** %1 + ret i8* %2 +} diff --git a/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll b/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll index c170f2ca74ba6..e8f7f720b1527 100644 --- a/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll +++ b/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll @@ -1,8 +1,8 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -instcombine -S | FileCheck %s - -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" +; RUN: opt < %s -instcombine -S -mtriple x86_64-unknown-linux-gnu | FileCheck %s --check-prefixes=CHECK,LINUX,ISC99 +; RUN: opt < %s -instcombine -S -mtriple x86_64-pc-win32 | FileCheck %s --check-prefixes=CHECK,ISC99 +; RUN: opt < %s -instcombine -S -mtriple x86_64-pc-windows-msvc16 | FileCheck %s --check-prefixes=CHECK,MS64,ISC89 +; RUN: opt < %s -instcombine -S -mtriple i386-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK,ISC99 +; RUN: opt < %s -instcombine -S -mtriple i686-pc-windows-msvc17 | FileCheck %s --check-prefixes=CHECK,MS32,ISC89 ; Check for and against shrinkage when using the ; unsafe-fp-math function attribute on a math lib @@ -12,8 +12,10 @@ target triple = "x86_64-unknown-linux-gnu" define float @acos_test1(float %f) { ; CHECK-LABEL: @acos_test1( -; CHECK-NEXT: [[ACOSF:%.*]] = call fast float @acosf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ACOSF]] +; LINUX-NEXT: [[ACOSF:%.*]] = call fast float @acosf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[ACOSF]] +; MS32: [[ACOSF:%.*]] = call fast double @acos(double [[F:%.*]]) +; MS64-NEXT: [[ACOSF:%.*]] = call fast float @acosf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @acos(double %conv) @@ -34,8 +36,9 @@ define double @acos_test2(float %f) { define float @acosh_test1(float %f) { ; CHECK-LABEL: @acosh_test1( -; CHECK-NEXT: [[ACOSHF:%.*]] = call fast float @acoshf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ACOSHF]] +; ISC99-NEXT: [[ACOSHF:%.*]] = call fast float @acoshf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[ACOSHF]] +; ISC89: [[ACOSHF:%.*]] = call fast double @acosh(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @acosh(double %conv) @@ -56,8 +59,10 @@ define double @acosh_test2(float %f) { define float @asin_test1(float %f) { ; CHECK-LABEL: @asin_test1( -; CHECK-NEXT: [[ASINF:%.*]] = call fast float @asinf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ASINF]] +; LINUX-NEXT: [[ASINF:%.*]] = call fast float @asinf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[ASINF]] +; MS32: [[ASINF:%.*]] = call fast double @asin(double [[F:%.*]]) +; MS64-NEXT: [[ASINF:%.*]] = call fast float @asinf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @asin(double %conv) @@ -78,8 +83,9 @@ define double @asin_test2(float %f) { define float @asinh_test1(float %f) { ; CHECK-LABEL: @asinh_test1( -; CHECK-NEXT: [[ASINHF:%.*]] = call fast float @asinhf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ASINHF]] +; ISC99-NEXT: [[ASINHF:%.*]] = call fast float @asinhf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[ASINHF]] +; ISC89: [[ASINHF:%.*]] = call fast double @asinh(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @asinh(double %conv) @@ -100,8 +106,10 @@ define double @asinh_test2(float %f) { define float @atan_test1(float %f) { ; CHECK-LABEL: @atan_test1( -; CHECK-NEXT: [[ATANF:%.*]] = call fast float @atanf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ATANF]] +; LINUX-NEXT: [[ATANF:%.*]] = call fast float @atanf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[ATANF]] +; MS32: [[ATANF:%.*]] = call fast double @atan(double [[F:%.*]]) +; MS64-NEXT: [[ATANF:%.*]] = call fast float @atanf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @atan(double %conv) @@ -122,8 +130,9 @@ define double @atan_test2(float %f) { define float @atanh_test1(float %f) { ; CHECK-LABEL: @atanh_test1( -; CHECK-NEXT: [[ATANHF:%.*]] = call fast float @atanhf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ATANHF]] +; ISC99-NEXT: [[ATANHF:%.*]] = call fast float @atanhf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[ATANHF]] +; ISC89: [[ATANHF:%.*]] = call fast double @atanh(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @atanh(double %conv) @@ -144,8 +153,9 @@ define double @atanh_test2(float %f) { define float @cbrt_test1(float %f) { ; CHECK-LABEL: @cbrt_test1( -; CHECK-NEXT: [[CBRTF:%.*]] = call fast float @cbrtf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[CBRTF]] +; ISC99-NEXT: [[CBRTF:%.*]] = call fast float @cbrtf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[CBRTF]] +; ISC89: [[CBRTF:%.*]] = call fast double @cbrt(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @cbrt(double %conv) @@ -166,8 +176,10 @@ define double @cbrt_test2(float %f) { define float @exp_test1(float %f) { ; CHECK-LABEL: @exp_test1( -; CHECK-NEXT: [[EXPF:%.*]] = call fast float @expf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[EXPF]] +; LINUX-NEXT: [[EXPF:%.*]] = call fast float @expf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[EXPF]] +; MS32: [[EXPF:%.*]] = call fast double @exp(double [[F:%.*]]) +; MS64-NEXT: [[EXPF:%.*]] = call fast float @expf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @exp(double %conv) @@ -188,8 +200,9 @@ define double @exp_test2(float %f) { define float @expm1_test1(float %f) { ; CHECK-LABEL: @expm1_test1( -; CHECK-NEXT: [[EXPM1F:%.*]] = call fast float @expm1f(float [[F:%.*]]) -; CHECK-NEXT: ret float [[EXPM1F]] +; ISC99-NEXT: [[EXPM1F:%.*]] = call fast float @expm1f(float [[F:%.*]]) +; ISC99-NEXT: ret float [[EXPM1F]] +; ISC89: [[EXPM1F:%.*]] = call fast double @expm1(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @expm1(double %conv) @@ -236,8 +249,10 @@ define double @exp10_test2(float %f) { define float @log_test1(float %f) { ; CHECK-LABEL: @log_test1( -; CHECK-NEXT: [[LOGF:%.*]] = call fast float @logf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOGF]] +; LINUX-NEXT: [[LOGF:%.*]] = call fast float @logf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[LOGF]] +; MS32: [[LOGF:%.*]] = call fast double @log(double [[F:%.*]]) +; MS64-NEXT: [[LOGF:%.*]] = call fast float @logf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @log(double %conv) @@ -258,8 +273,10 @@ define double @log_test2(float %f) { define float @log10_test1(float %f) { ; CHECK-LABEL: @log10_test1( -; CHECK-NEXT: [[LOG10F:%.*]] = call fast float @log10f(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOG10F]] +; LINUX-NEXT: [[LOG10F:%.*]] = call fast float @log10f(float [[F:%.*]]) +; LINUX-NEXT: ret float [[LOG10F]] +; MS32: [[LOG10F:%.*]] = call fast double @log10(double [[F:%.*]]) +; MS64-NEXT: [[LOG10F:%.*]] = call fast float @log10f(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @log10(double %conv) @@ -280,8 +297,9 @@ define double @log10_test2(float %f) { define float @log1p_test1(float %f) { ; CHECK-LABEL: @log1p_test1( -; CHECK-NEXT: [[LOG1PF:%.*]] = call fast float @log1pf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOG1PF]] +; ISC99-NEXT: [[LOG1PF:%.*]] = call fast float @log1pf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[LOG1PF]] +; ISC89: [[LOG1PF:%.*]] = call fast double @log1p(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @log1p(double %conv) @@ -302,8 +320,9 @@ define double @log1p_test2(float %f) { define float @log2_test1(float %f) { ; CHECK-LABEL: @log2_test1( -; CHECK-NEXT: [[LOG2F:%.*]] = call fast float @log2f(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOG2F]] +; ISC99-NEXT: [[LOG2F:%.*]] = call fast float @log2f(float [[F:%.*]]) +; ISC99-NEXT: ret float [[LOG2F]] +; ISC89: [[LOG2F:%.*]] = call fast double @log2(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @log2(double %conv) @@ -324,8 +343,10 @@ define double @log2_test2(float %f) { define float @logb_test1(float %f) { ; CHECK-LABEL: @logb_test1( -; CHECK-NEXT: [[LOGBF:%.*]] = call fast float @logbf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOGBF]] +; LINUX-NEXT: [[LOGBF:%.*]] = call fast float @logbf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[LOGBF]] +; MS32: [[POWF:%.*]] = call fast double @logb(double [[F:%.*]]) +; MS64-NEXT: [[LOGBF:%.*]] = call fast float @logbf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @logb(double %conv) @@ -346,8 +367,10 @@ define double @logb_test2(float %f) { define float @pow_test1(float %f, float %g) { ; CHECK-LABEL: @pow_test1( -; CHECK-NEXT: [[POWF:%.*]] = call fast float @powf(float %f, float %g) -; CHECK-NEXT: ret float [[POWF]] +; LINUX-NEXT: [[POWF:%.*]] = call fast float @powf(float %f, float %g) +; LINUX-NEXT: ret float [[POWF]] +; MS32: [[POWF:%.*]] = call fast double @pow(double %df, double %dg) +; MS64-NEXT: [[POWF:%.*]] = call fast float @powf(float %f, float %g) ; %df = fpext float %f to double %dg = fpext float %g to double @@ -369,8 +392,10 @@ define double @pow_test2(float %f, float %g) { define float @sin_test1(float %f) { ; CHECK-LABEL: @sin_test1( -; CHECK-NEXT: [[SINF:%.*]] = call fast float @sinf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[SINF]] +; LINUX-NEXT: [[SINF:%.*]] = call fast float @sinf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[SINF]] +; MS32: [[SINF:%.*]] = call fast double @sin(double [[F:%.*]]) +; MS64-NEXT: [[SINF:%.*]] = call fast float @sinf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @sin(double %conv) @@ -391,8 +416,10 @@ define double @sin_test2(float %f) { define float @sqrt_test1(float %f) { ; CHECK-LABEL: @sqrt_test1( -; CHECK-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[SQRTF]] +; LINUX-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[SQRTF]] +; MS32: [[SQRTF:%.*]] = call double @sqrt(double [[F:%.*]]) +; MS64-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call double @sqrt(double %conv) @@ -413,8 +440,10 @@ define double @sqrt_test2(float %f) { define float @sqrt_int_test1(float %f) { ; CHECK-LABEL: @sqrt_int_test1( -; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.sqrt.f32(float [[F:%.*]]) -; CHECK-NEXT: ret float [[TMP1]] +; LINUX-NEXT: [[TMP1:%.*]] = call float @llvm.sqrt.f32(float [[F:%.*]]) +; LINUX-NEXT: ret float [[TMP1]] +; MS32: [[TMP1:%.*]] = call double @llvm.sqrt.f64(double [[F:%.*]]) +; MS64-NEXT: [[TMP1:%.*]] = call float @llvm.sqrt.f32(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call double @llvm.sqrt.f64(double %conv) @@ -435,8 +464,10 @@ define double @sqrt_int_test2(float %f) { define float @tan_test1(float %f) { ; CHECK-LABEL: @tan_test1( -; CHECK-NEXT: [[TANF:%.*]] = call fast float @tanf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[TANF]] +; LINUX-NEXT: [[TANF:%.*]] = call fast float @tanf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[TANF]] +; MS32: [[TANF:%.*]] = call fast double @tan(double [[F:%.*]]) +; MS64-NEXT: [[TANF:%.*]] = call fast float @tanf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @tan(double %conv) @@ -456,8 +487,10 @@ define double @tan_test2(float %f) { } define float @tanh_test1(float %f) { ; CHECK-LABEL: @tanh_test1( -; CHECK-NEXT: [[TANHF:%.*]] = call fast float @tanhf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[TANHF]] +; LINUX-NEXT: [[TANHF:%.*]] = call fast float @tanhf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[TANHF]] +; MS32: [[TANHF:%.*]] = call fast double @tanh(double [[F:%.*]]) +; MS64-NEXT: [[TANHF:%.*]] = call fast float @tanhf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @tanh(double %conv) @@ -480,8 +513,9 @@ define double @tanh_test2(float %f) { ; flags are propagated for shrunken *binary* double FP calls. define float @max1(float %a, float %b) { ; CHECK-LABEL: @max1( -; CHECK-NEXT: [[FMAXF:%.*]] = call arcp float @fmaxf(float [[A:%.*]], float [[B:%.*]]) -; CHECK-NEXT: ret float [[FMAXF]] +; ISC99-NEXT: [[FMAXF:%.*]] = call arcp float @fmaxf(float [[A:%.*]], float [[B:%.*]]) +; ISC99-NEXT: ret float [[FMAXF]] +; ISC89: [[FMAXF:%.*]] = call arcp double @fmax(double [[A:%.*]], double [[B:%.*]]) ; %c = fpext float %a to double %d = fpext float %b to double diff --git a/llvm/test/Transforms/InstCombine/double-float-shrink-2.ll b/llvm/test/Transforms/InstCombine/double-float-shrink-2.ll index 5bdeaf7d9d7e0..76e497bd68fc7 100644 --- a/llvm/test/Transforms/InstCombine/double-float-shrink-2.ll +++ b/llvm/test/Transforms/InstCombine/double-float-shrink-2.ll @@ -1,11 +1,11 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -instcombine -S -mtriple "i386-pc-linux" | FileCheck -check-prefix=ALL -check-prefix=DO-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "i386-pc-win32" | FileCheck -check-prefix=ALL -check-prefix=DONT-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-win32" | FileCheck -check-prefix=ALL -check-prefix=C89-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "i386-pc-mingw32" | FileCheck -check-prefix=ALL -check-prefix=DO-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-mingw32" | FileCheck -check-prefix=ALL -check-prefix=DO-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "sparc-sun-solaris" | FileCheck -check-prefix=ALL -check-prefix=DO-SIMPLIFY %s -; RUN: opt < %s -enable-debugify -instcombine -S -mtriple "x86_64-pc-win32" 2>&1 | FileCheck -check-prefix=DBG-VALID %s +; RUN: opt < %s -instcombine -S -mtriple "i386-pc-linux" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "i386-pc-win32" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-win32" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "i386-pc-mingw32" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-mingw32" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "sparc-sun-solaris" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-win32" -enable-debugify 2>&1 | FileCheck --check-prefix=DBG-VALID %s declare double @floor(double) declare double @ceil(double) @@ -36,9 +36,9 @@ declare double @llvm.trunc.f64(double) declare <2 x double> @llvm.trunc.v2f64(<2 x double>) define float @test_shrink_libcall_floor(float %C) { -; ALL-LABEL: @test_shrink_libcall_floor( -; ALL-NEXT: [[F:%.*]] = call float @llvm.floor.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_floor( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.floor.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> floorf @@ -48,9 +48,9 @@ define float @test_shrink_libcall_floor(float %C) { } define float @test_shrink_libcall_ceil(float %C) { -; ALL-LABEL: @test_shrink_libcall_ceil( -; ALL-NEXT: [[F:%.*]] = call float @llvm.ceil.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_ceil( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.ceil.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> ceilf @@ -60,21 +60,9 @@ define float @test_shrink_libcall_ceil(float %C) { } define float @test_shrink_libcall_round(float %C) { -; DO-SIMPLIFY-LABEL: @test_shrink_libcall_round( -; DO-SIMPLIFY-NEXT: [[F:%.*]] = call float @llvm.round.f32(float [[C:%.*]]) -; DO-SIMPLIFY-NEXT: ret float [[F]] -; -; DONT-SIMPLIFY-LABEL: @test_shrink_libcall_round( -; DONT-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; DONT-SIMPLIFY-NEXT: [[E:%.*]] = call double @round(double [[D]]) -; DONT-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; DONT-SIMPLIFY-NEXT: ret float [[F]] -; -; C89-SIMPLIFY-LABEL: @test_shrink_libcall_round( -; C89-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; C89-SIMPLIFY-NEXT: [[E:%.*]] = call double @round(double [[D]]) -; C89-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; C89-SIMPLIFY-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_round( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.round.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> roundf @@ -84,21 +72,9 @@ define float @test_shrink_libcall_round(float %C) { } define float @test_shrink_libcall_nearbyint(float %C) { -; DO-SIMPLIFY-LABEL: @test_shrink_libcall_nearbyint( -; DO-SIMPLIFY-NEXT: [[F:%.*]] = call float @llvm.nearbyint.f32(float [[C:%.*]]) -; DO-SIMPLIFY-NEXT: ret float [[F]] -; -; DONT-SIMPLIFY-LABEL: @test_shrink_libcall_nearbyint( -; DONT-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; DONT-SIMPLIFY-NEXT: [[E:%.*]] = call double @nearbyint(double [[D]]) -; DONT-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; DONT-SIMPLIFY-NEXT: ret float [[F]] -; -; C89-SIMPLIFY-LABEL: @test_shrink_libcall_nearbyint( -; C89-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; C89-SIMPLIFY-NEXT: [[E:%.*]] = call double @nearbyint(double [[D]]) -; C89-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; C89-SIMPLIFY-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_nearbyint( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.nearbyint.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> nearbyintf @@ -108,21 +84,9 @@ define float @test_shrink_libcall_nearbyint(float %C) { } define float @test_shrink_libcall_trunc(float %C) { -; DO-SIMPLIFY-LABEL: @test_shrink_libcall_trunc( -; DO-SIMPLIFY-NEXT: [[F:%.*]] = call float @llvm.trunc.f32(float [[C:%.*]]) -; DO-SIMPLIFY-NEXT: ret float [[F]] -; -; DONT-SIMPLIFY-LABEL: @test_shrink_libcall_trunc( -; DONT-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; DONT-SIMPLIFY-NEXT: [[E:%.*]] = call double @trunc(double [[D]]) -; DONT-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; DONT-SIMPLIFY-NEXT: ret float [[F]] -; -; C89-SIMPLIFY-LABEL: @test_shrink_libcall_trunc( -; C89-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; C89-SIMPLIFY-NEXT: [[E:%.*]] = call double @trunc(double [[D]]) -; C89-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; C89-SIMPLIFY-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_trunc( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.trunc.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> truncf @@ -132,11 +96,11 @@ define float @test_shrink_libcall_trunc(float %C) { } ; This is replaced with the intrinsic, which does the right thing on -; all platforms. +; CHECK platforms. define float @test_shrink_libcall_fabs(float %C) { -; ALL-LABEL: @test_shrink_libcall_fabs( -; ALL-NEXT: [[F:%.*]] = call float @llvm.fabs.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_fabs( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.fabs.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double %E = call double @fabs(double %D) @@ -146,9 +110,9 @@ define float @test_shrink_libcall_fabs(float %C) { ; Make sure fast math flags are preserved define float @test_shrink_libcall_fabs_fast(float %C) { -; ALL-LABEL: @test_shrink_libcall_fabs_fast( -; ALL-NEXT: [[F:%.*]] = call fast float @llvm.fabs.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_fabs_fast( +; CHECK-NEXT: [[F:%.*]] = call fast float @llvm.fabs.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double %E = call fast double @fabs(double %D) @@ -157,9 +121,9 @@ define float @test_shrink_libcall_fabs_fast(float %C) { } define float @test_shrink_intrin_ceil(float %C) { -; ALL-LABEL: @test_shrink_intrin_ceil( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.ceil.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_ceil( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.ceil.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.ceil.f64(double %D) @@ -168,9 +132,9 @@ define float @test_shrink_intrin_ceil(float %C) { } define float @test_shrink_intrin_fabs(float %C) { -; ALL-LABEL: @test_shrink_intrin_fabs( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_fabs( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.fabs.f64(double %D) @@ -179,9 +143,9 @@ define float @test_shrink_intrin_fabs(float %C) { } define float @test_shrink_intrin_floor(float %C) { -; ALL-LABEL: @test_shrink_intrin_floor( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.floor.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_floor( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.floor.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.floor.f64(double %D) @@ -190,9 +154,9 @@ define float @test_shrink_intrin_floor(float %C) { } define float @test_shrink_intrin_nearbyint(float %C) { -; ALL-LABEL: @test_shrink_intrin_nearbyint( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.nearbyint.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_nearbyint( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.nearbyint.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.nearbyint.f64(double %D) @@ -201,9 +165,9 @@ define float @test_shrink_intrin_nearbyint(float %C) { } define half @test_shrink_intrin_rint(half %C) { -; ALL-LABEL: @test_shrink_intrin_rint( -; ALL-NEXT: [[TMP1:%.*]] = call half @llvm.rint.f16(half [[C:%.*]]) -; ALL-NEXT: ret half [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_rint( +; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.rint.f16(half [[C:%.*]]) +; CHECK-NEXT: ret half [[TMP1]] ; %D = fpext half %C to float %E = call float @llvm.rint.f32(float %D) @@ -212,9 +176,9 @@ define half @test_shrink_intrin_rint(half %C) { } define float @test_shrink_intrin_round(float %C) { -; ALL-LABEL: @test_shrink_intrin_round( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.round.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_round( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.round.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.round.f64(double %D) @@ -223,9 +187,9 @@ define float @test_shrink_intrin_round(float %C) { } define float @test_shrink_intrin_trunc(float %C) { -; ALL-LABEL: @test_shrink_intrin_trunc( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.trunc.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_trunc( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.trunc.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.trunc.f64(double %D) @@ -237,12 +201,12 @@ declare void @use_v2f64(<2 x double>) declare void @use_v2f32(<2 x float>) define <2 x float> @test_shrink_intrin_ceil_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_ceil_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.ceil.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_ceil_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.ceil.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.ceil.v2f64(<2 x double> %D) @@ -252,11 +216,11 @@ define <2 x float> @test_shrink_intrin_ceil_multi_use(<2 x float> %C) { } define <2 x float> @test_shrink_intrin_fabs_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_fabs_multi_use( -; ALL-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x float> [[TMP1]] to <2 x double> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[E]]) -; ALL-NEXT: ret <2 x float> [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_fabs_multi_use( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x float> [[TMP1]] to <2 x double> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[E]]) +; CHECK-NEXT: ret <2 x float> [[TMP1]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.fabs.v2f64(<2 x double> %D) @@ -266,13 +230,13 @@ define <2 x float> @test_shrink_intrin_fabs_multi_use(<2 x float> %C) { } define <2 x float> @test_shrink_intrin_floor_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_floor_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.floor.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: call void @use_v2f64(<2 x double> [[E]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_floor_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.floor.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[E]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.floor.v2f64(<2 x double> %D) @@ -283,12 +247,12 @@ define <2 x float> @test_shrink_intrin_floor_multi_use(<2 x float> %C) { } define <2 x float> @test_shrink_intrin_nearbyint_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_nearbyint_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.nearbyint.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_nearbyint_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.nearbyint.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.nearbyint.v2f64(<2 x double> %D) @@ -298,11 +262,11 @@ define <2 x float> @test_shrink_intrin_nearbyint_multi_use(<2 x float> %C) { } define <2 x half> @test_shrink_intrin_rint_multi_use(<2 x half> %C) { -; ALL-LABEL: @test_shrink_intrin_rint_multi_use( -; ALL-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.rint.v2f16(<2 x half> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x float> -; ALL-NEXT: call void @use_v2f32(<2 x float> [[E]]) -; ALL-NEXT: ret <2 x half> [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_rint_multi_use( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.rint.v2f16(<2 x half> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x float> +; CHECK-NEXT: call void @use_v2f32(<2 x float> [[E]]) +; CHECK-NEXT: ret <2 x half> [[TMP1]] ; %D = fpext <2 x half> %C to <2 x float> %E = call <2 x float> @llvm.rint.v2f32(<2 x float> %D) @@ -312,13 +276,13 @@ define <2 x half> @test_shrink_intrin_rint_multi_use(<2 x half> %C) { } define <2 x float> @test_shrink_intrin_round_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_round_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.round.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: call void @use_v2f64(<2 x double> [[E]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_round_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.round.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[E]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.round.v2f64(<2 x double> %D) @@ -329,12 +293,12 @@ define <2 x float> @test_shrink_intrin_round_multi_use(<2 x float> %C) { } define <2 x float> @test_shrink_intrin_trunc_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_trunc_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.trunc.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_trunc_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.trunc.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.trunc.v2f64(<2 x double> %D) @@ -345,9 +309,9 @@ define <2 x float> @test_shrink_intrin_trunc_multi_use(<2 x float> %C) { ; Make sure fast math flags are preserved define float @test_shrink_intrin_fabs_fast(float %C) { -; ALL-LABEL: @test_shrink_intrin_fabs_fast( -; ALL-NEXT: [[TMP1:%.*]] = call fast float @llvm.fabs.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_fabs_fast( +; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.fabs.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call fast double @llvm.fabs.f64(double %D) @@ -356,10 +320,10 @@ define float @test_shrink_intrin_fabs_fast(float %C) { } define float @test_no_shrink_intrin_floor(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_floor( -; ALL-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_floor( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.floor.f64(double %D) %F = fptrunc double %E to float @@ -367,10 +331,10 @@ define float @test_no_shrink_intrin_floor(double %D) { } define float @test_no_shrink_intrin_ceil(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_ceil( -; ALL-NEXT: [[E:%.*]] = call double @llvm.ceil.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_ceil( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.ceil.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.ceil.f64(double %D) %F = fptrunc double %E to float @@ -378,10 +342,10 @@ define float @test_no_shrink_intrin_ceil(double %D) { } define float @test_no_shrink_intrin_round(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_round( -; ALL-NEXT: [[E:%.*]] = call double @llvm.round.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_round( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.round.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.round.f64(double %D) %F = fptrunc double %E to float @@ -389,10 +353,10 @@ define float @test_no_shrink_intrin_round(double %D) { } define float @test_no_shrink_intrin_nearbyint(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_nearbyint( -; ALL-NEXT: [[E:%.*]] = call double @llvm.nearbyint.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_nearbyint( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.nearbyint.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.nearbyint.f64(double %D) %F = fptrunc double %E to float @@ -400,10 +364,10 @@ define float @test_no_shrink_intrin_nearbyint(double %D) { } define float @test_no_shrink_intrin_trunc(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_trunc( -; ALL-NEXT: [[E:%.*]] = call double @llvm.trunc.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_trunc( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.trunc.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.trunc.f64(double %D) %F = fptrunc double %E to float @@ -411,10 +375,10 @@ define float @test_no_shrink_intrin_trunc(double %D) { } define float @test_shrink_intrin_fabs_double_src(double %D) { -; ALL-LABEL: @test_shrink_intrin_fabs_double_src( -; ALL-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to float -; ALL-NEXT: [[F:%.*]] = call float @llvm.fabs.f32(float [[TMP1]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_fabs_double_src( +; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to float +; CHECK-NEXT: [[F:%.*]] = call float @llvm.fabs.f32(float [[TMP1]]) +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.fabs.f64(double %D) %F = fptrunc double %E to float @@ -423,10 +387,10 @@ define float @test_shrink_intrin_fabs_double_src(double %D) { ; Make sure fast math flags are preserved define float @test_shrink_intrin_fabs_fast_double_src(double %D) { -; ALL-LABEL: @test_shrink_intrin_fabs_fast_double_src( -; ALL-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to float -; ALL-NEXT: [[F:%.*]] = call fast float @llvm.fabs.f32(float [[TMP1]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_fabs_fast_double_src( +; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to float +; CHECK-NEXT: [[F:%.*]] = call fast float @llvm.fabs.f32(float [[TMP1]]) +; CHECK-NEXT: ret float [[F]] ; %E = call fast double @llvm.fabs.f64(double %D) %F = fptrunc double %E to float @@ -434,8 +398,8 @@ define float @test_shrink_intrin_fabs_fast_double_src(double %D) { } define float @test_shrink_float_convertible_constant_intrin_floor() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_floor( -; ALL-NEXT: ret float 2.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_floor( +; CHECK-NEXT: ret float 2.000000e+00 ; %E = call double @llvm.floor.f64(double 2.1) %F = fptrunc double %E to float @@ -443,8 +407,8 @@ define float @test_shrink_float_convertible_constant_intrin_floor() { } define float @test_shrink_float_convertible_constant_intrin_ceil() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_ceil( -; ALL-NEXT: ret float 3.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_ceil( +; CHECK-NEXT: ret float 3.000000e+00 ; %E = call double @llvm.ceil.f64(double 2.1) %F = fptrunc double %E to float @@ -452,8 +416,8 @@ define float @test_shrink_float_convertible_constant_intrin_ceil() { } define float @test_shrink_float_convertible_constant_intrin_round() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_round( -; ALL-NEXT: ret float 2.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_round( +; CHECK-NEXT: ret float 2.000000e+00 ; %E = call double @llvm.round.f64(double 2.1) %F = fptrunc double %E to float @@ -461,8 +425,8 @@ define float @test_shrink_float_convertible_constant_intrin_round() { } define float @test_shrink_float_convertible_constant_intrin_nearbyint() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_nearbyint( -; ALL-NEXT: ret float 2.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_nearbyint( +; CHECK-NEXT: ret float 2.000000e+00 ; %E = call double @llvm.nearbyint.f64(double 2.1) %F = fptrunc double %E to float @@ -470,8 +434,8 @@ define float @test_shrink_float_convertible_constant_intrin_nearbyint() { } define float @test_shrink_float_convertible_constant_intrin_trunc() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_trunc( -; ALL-NEXT: ret float 2.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_trunc( +; CHECK-NEXT: ret float 2.000000e+00 ; %E = call double @llvm.trunc.f64(double 2.1) %F = fptrunc double %E to float @@ -479,8 +443,8 @@ define float @test_shrink_float_convertible_constant_intrin_trunc() { } define float @test_shrink_float_convertible_constant_intrin_fabs() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_fabs( -; ALL-NEXT: ret float 0x4000CCCCC0000000 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_fabs( +; CHECK-NEXT: ret float 0x4000CCCCC0000000 ; %E = call double @llvm.fabs.f64(double 2.1) %F = fptrunc double %E to float @@ -489,8 +453,8 @@ define float @test_shrink_float_convertible_constant_intrin_fabs() { ; Make sure fast math flags are preserved define float @test_shrink_float_convertible_constant_intrin_fabs_fast() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_fabs_fast( -; ALL-NEXT: ret float 0x4000CCCCC0000000 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_fabs_fast( +; CHECK-NEXT: ret float 0x4000CCCCC0000000 ; %E = call fast double @llvm.fabs.f64(double 2.1) %F = fptrunc double %E to float @@ -498,10 +462,10 @@ define float @test_shrink_float_convertible_constant_intrin_fabs_fast() { } define half @test_no_shrink_mismatched_type_intrin_floor(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_floor( -; ALL-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_floor( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.floor.f64(double %D) %F = fptrunc double %E to half @@ -509,10 +473,10 @@ define half @test_no_shrink_mismatched_type_intrin_floor(double %D) { } define half @test_no_shrink_mismatched_type_intrin_ceil(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_ceil( -; ALL-NEXT: [[E:%.*]] = call double @llvm.ceil.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_ceil( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.ceil.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.ceil.f64(double %D) %F = fptrunc double %E to half @@ -520,10 +484,10 @@ define half @test_no_shrink_mismatched_type_intrin_ceil(double %D) { } define half @test_no_shrink_mismatched_type_intrin_round(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_round( -; ALL-NEXT: [[E:%.*]] = call double @llvm.round.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_round( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.round.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.round.f64(double %D) %F = fptrunc double %E to half @@ -531,10 +495,10 @@ define half @test_no_shrink_mismatched_type_intrin_round(double %D) { } define half @test_no_shrink_mismatched_type_intrin_nearbyint(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_nearbyint( -; ALL-NEXT: [[E:%.*]] = call double @llvm.nearbyint.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_nearbyint( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.nearbyint.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.nearbyint.f64(double %D) %F = fptrunc double %E to half @@ -542,10 +506,10 @@ define half @test_no_shrink_mismatched_type_intrin_nearbyint(double %D) { } define half @test_no_shrink_mismatched_type_intrin_trunc(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_trunc( -; ALL-NEXT: [[E:%.*]] = call double @llvm.trunc.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_trunc( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.trunc.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.trunc.f64(double %D) %F = fptrunc double %E to half @@ -553,10 +517,10 @@ define half @test_no_shrink_mismatched_type_intrin_trunc(double %D) { } define half @test_shrink_mismatched_type_intrin_fabs_double_src(double %D) { -; ALL-LABEL: @test_shrink_mismatched_type_intrin_fabs_double_src( -; ALL-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to half -; ALL-NEXT: [[F:%.*]] = call half @llvm.fabs.f16(half [[TMP1]]) -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_shrink_mismatched_type_intrin_fabs_double_src( +; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to half +; CHECK-NEXT: [[F:%.*]] = call half @llvm.fabs.f16(half [[TMP1]]) +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.fabs.f64(double %D) %F = fptrunc double %E to half @@ -565,10 +529,10 @@ define half @test_shrink_mismatched_type_intrin_fabs_double_src(double %D) { ; Make sure fast math flags are preserved define half @test_mismatched_type_intrin_fabs_fast_double_src(double %D) { -; ALL-LABEL: @test_mismatched_type_intrin_fabs_fast_double_src( -; ALL-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to half -; ALL-NEXT: [[F:%.*]] = call fast half @llvm.fabs.f16(half [[TMP1]]) -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_mismatched_type_intrin_fabs_fast_double_src( +; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to half +; CHECK-NEXT: [[F:%.*]] = call fast half @llvm.fabs.f16(half [[TMP1]]) +; CHECK-NEXT: ret half [[F]] ; %E = call fast double @llvm.fabs.f64(double %D) %F = fptrunc double %E to half @@ -576,10 +540,10 @@ define half @test_mismatched_type_intrin_fabs_fast_double_src(double %D) { } define <2 x double> @test_shrink_intrin_floor_fp16_vec(<2 x half> %C) { -; ALL-LABEL: @test_shrink_intrin_floor_fp16_vec( -; ALL-NEXT: [[TMP1:%.*]] = call arcp <2 x half> @llvm.floor.v2f16(<2 x half> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> -; ALL-NEXT: ret <2 x double> [[E]] +; CHECK-LABEL: @test_shrink_intrin_floor_fp16_vec( +; CHECK-NEXT: [[TMP1:%.*]] = call arcp <2 x half> @llvm.floor.v2f16(<2 x half> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> +; CHECK-NEXT: ret <2 x double> [[E]] ; %D = fpext <2 x half> %C to <2 x double> %E = call arcp <2 x double> @llvm.floor.v2f64(<2 x double> %D) @@ -587,10 +551,10 @@ define <2 x double> @test_shrink_intrin_floor_fp16_vec(<2 x half> %C) { } define float @test_shrink_intrin_ceil_fp16_src(half %C) { -; ALL-LABEL: @test_shrink_intrin_ceil_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call half @llvm.ceil.f16(half [[C:%.*]]) -; ALL-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_ceil_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.ceil.f16(half [[C:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double %E = call double @llvm.ceil.f64(double %D) @@ -599,10 +563,10 @@ define float @test_shrink_intrin_ceil_fp16_src(half %C) { } define <2 x double> @test_shrink_intrin_round_fp16_vec(<2 x half> %C) { -; ALL-LABEL: @test_shrink_intrin_round_fp16_vec( -; ALL-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.round.v2f16(<2 x half> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> -; ALL-NEXT: ret <2 x double> [[E]] +; CHECK-LABEL: @test_shrink_intrin_round_fp16_vec( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.round.v2f16(<2 x half> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> +; CHECK-NEXT: ret <2 x double> [[E]] ; %D = fpext <2 x half> %C to <2 x double> %E = call <2 x double> @llvm.round.v2f64(<2 x double> %D) @@ -610,10 +574,10 @@ define <2 x double> @test_shrink_intrin_round_fp16_vec(<2 x half> %C) { } define float @test_shrink_intrin_nearbyint_fp16_src(half %C) { -; ALL-LABEL: @test_shrink_intrin_nearbyint_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call half @llvm.nearbyint.f16(half [[C:%.*]]) -; ALL-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_nearbyint_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.nearbyint.f16(half [[C:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double %E = call double @llvm.nearbyint.f64(double %D) @@ -622,10 +586,10 @@ define float @test_shrink_intrin_nearbyint_fp16_src(half %C) { } define <2 x double> @test_shrink_intrin_trunc_fp16_src(<2 x half> %C) { -; ALL-LABEL: @test_shrink_intrin_trunc_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.trunc.v2f16(<2 x half> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> -; ALL-NEXT: ret <2 x double> [[E]] +; CHECK-LABEL: @test_shrink_intrin_trunc_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.trunc.v2f16(<2 x half> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> +; CHECK-NEXT: ret <2 x double> [[E]] ; %D = fpext <2 x half> %C to <2 x double> %E = call <2 x double> @llvm.trunc.v2f64(<2 x double> %D) @@ -633,10 +597,10 @@ define <2 x double> @test_shrink_intrin_trunc_fp16_src(<2 x half> %C) { } define float @test_shrink_intrin_fabs_fp16_src(half %C) { -; ALL-LABEL: @test_shrink_intrin_fabs_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[C:%.*]]) -; ALL-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_fabs_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[C:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double %E = call double @llvm.fabs.f64(double %D) @@ -646,10 +610,10 @@ define float @test_shrink_intrin_fabs_fp16_src(half %C) { ; Make sure fast math flags are preserved define float @test_shrink_intrin_fabs_fast_fp16_src(half %C) { -; ALL-LABEL: @test_shrink_intrin_fabs_fast_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call fast half @llvm.fabs.f16(half [[C:%.*]]) -; ALL-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_fabs_fast_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call fast half @llvm.fabs.f16(half [[C:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double %E = call fast double @llvm.fabs.f64(double %D) @@ -658,12 +622,12 @@ define float @test_shrink_intrin_fabs_fast_fp16_src(half %C) { } define float @test_no_shrink_intrin_floor_multi_use_fpext(half %C) { -; ALL-LABEL: @test_no_shrink_intrin_floor_multi_use_fpext( -; ALL-NEXT: [[D:%.*]] = fpext half [[C:%.*]] to double -; ALL-NEXT: store volatile double [[D]], double* undef, align 8 -; ALL-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_floor_multi_use_fpext( +; CHECK-NEXT: [[D:%.*]] = fpext half [[C:%.*]] to double +; CHECK-NEXT: store volatile double [[D]], double* undef, align 8 +; CHECK-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double store volatile double %D, double* undef @@ -673,12 +637,12 @@ define float @test_no_shrink_intrin_floor_multi_use_fpext(half %C) { } define float @test_no_shrink_intrin_fabs_multi_use_fpext(half %C) { -; ALL-LABEL: @test_no_shrink_intrin_fabs_multi_use_fpext( -; ALL-NEXT: [[D:%.*]] = fpext half [[C:%.*]] to double -; ALL-NEXT: store volatile double [[D]], double* undef, align 8 -; ALL-NEXT: [[E:%.*]] = call double @llvm.fabs.f64(double [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_fabs_multi_use_fpext( +; CHECK-NEXT: [[D:%.*]] = fpext half [[C:%.*]] to double +; CHECK-NEXT: store volatile double [[D]], double* undef, align 8 +; CHECK-NEXT: [[E:%.*]] = call double @llvm.fabs.f64(double [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double store volatile double %D, double* undef diff --git a/llvm/test/Transforms/InstCombine/pow-1.ll b/llvm/test/Transforms/InstCombine/pow-1.ll index 672ec70e71ec2..957e2488b721b 100644 --- a/llvm/test/Transforms/InstCombine/pow-1.ll +++ b/llvm/test/Transforms/InstCombine/pow-1.ll @@ -1,15 +1,18 @@ ; Test that the pow library call simplifier works correctly. ; -; RUN: opt -instcombine -S < %s | FileCheck %s --check-prefixes=ANY -; RUN: opt -instcombine -S < %s -mtriple=x86_64-apple-macosx10.9 | FileCheck %s --check-prefixes=ANY,CHECK-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=arm-apple-ios7.0 | FileCheck %s --check-prefixes=ANY,CHECK-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=x86_64-apple-macosx10.8 | FileCheck %s --check-prefixes=ANY,CHECK-NO-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=arm-apple-ios6.0 | FileCheck %s --check-prefixes=ANY,CHECK-NO-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=x86_64-netbsd | FileCheck %s --check-prefixes=ANY,CHECK-NO-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=arm-apple-tvos9.0 | FileCheck %s --check-prefixes=ANY,CHECK-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=arm-apple-watchos2.0 | FileCheck %s --check-prefixes=ANY,CHECK-EXP10 +; RUN: opt -instcombine -S < %s | FileCheck %s --check-prefixes=CHECK,ANY +; RUN: opt -instcombine -S < %s -mtriple=x86_64-apple-macosx10.9 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=arm-apple-ios7.0 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=x86_64-apple-macosx10.8 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=arm-apple-ios6.0 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=x86_64-netbsd | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=arm-apple-tvos9.0 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=arm-apple-watchos2.0 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-EXP10 ; rdar://7251832 -; RUN: opt -instcombine -S < %s -mtriple=x86_64-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK-WIN +; RUN: opt -instcombine -S < %s -mtriple=i386-pc-windows-msvc18 | FileCheck %s --check-prefixes=CHECK,MSVC,VC32,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=i386-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK,MSVC,VC51,VC19,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=x86_64-pc-windows-msvc18 | FileCheck %s --check-prefixes=CHECK,MSVC,VC64,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=x86_64-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK,MSVC,VC83,VC19,CHECK-NO-EXP10 ; NOTE: The readonly attribute on the pow call should be preserved ; in the cases below where pow is transformed into another function call. @@ -23,32 +26,39 @@ declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>) nounwind readon ; Check pow(1.0, x) -> 1.0. define float @test_simplify1(float %x) { -; ANY-LABEL: @test_simplify1( +; CHECK-LABEL: @test_simplify1( ; ANY-NEXT: ret float 1.000000e+00 +; VC32-NEXT: [[POW:%.*]] = call float @powf(float 1.000000e+00, float [[X:%.*]]) +; VC32-NEXT: ret float [[POW]] +; VC64-NEXT: ret float 1.000000e+00 ; %retval = call float @powf(float 1.0, float %x) ret float %retval } define <2 x float> @test_simplify1v(<2 x float> %x) { -; ANY-LABEL: @test_simplify1v( +; CHECK-LABEL: @test_simplify1v( ; ANY-NEXT: ret <2 x float> +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> %x) ret <2 x float> %retval } define double @test_simplify2(double %x) { -; ANY-LABEL: @test_simplify2( -; ANY-NEXT: ret double 1.000000e+00 +; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: ret double 1.000000e+00 ; %retval = call double @pow(double 1.0, double %x) ret double %retval } define <2 x double> @test_simplify2v(<2 x double> %x) { -; ANY-LABEL: @test_simplify2v( +; CHECK-LABEL: @test_simplify2v( ; ANY-NEXT: ret <2 x double> +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[X:%.*]]) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> %x) ret <2 x double> %retval @@ -57,104 +67,114 @@ define <2 x double> @test_simplify2v(<2 x double> %x) { ; Check pow(2.0 ** n, x) -> exp2(n * x). define float @test_simplify3(float %x) { -; ANY-LABEL: @test_simplify3( -; ANY-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[X:%.*]]) [[NUW_RO:#[0-9]+]] +; CHECK-LABEL: @test_simplify3( +; ANY-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[X:%.*]]) ; ANY-NEXT: ret float [[EXP2F]] -; -; CHECK-WIN-LABEL: @test_simplify3( -; CHECK-WIN-NEXT: [[POW:%.*]] = call float @powf(float 2.000000e+00, float [[X:%.*]]) -; CHECK-WIN-NEXT: ret float [[POW]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float 2.000000e+00, float [[X:%.*]]) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float 2.000000e+00, float [[X:%.*]]) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[POW:%.*]] = call float @powf(float 2.000000e+00, float [[X:%.*]]) +; VC64-NEXT: ret float [[POW]] +; VC83-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[X:%.*]]) +; VC83-NEXT: ret float [[EXP2F]] ; %retval = call float @powf(float 2.0, float %x) ret float %retval } define double @test_simplify3n(double %x) { -; ANY-LABEL: @test_simplify3n( +; CHECK-LABEL: @test_simplify3n( ; ANY-NEXT: [[MUL:%.*]] = fmul double [[X:%.*]], -2.000000e+00 -; ANY-NEXT: [[EXP2:%.*]] = call double @exp2(double [[MUL]]) [[NUW_RO]] +; ANY-NEXT: [[EXP2:%.*]] = call double @exp2(double [[MUL]]) ; ANY-NEXT: ret double [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify3n( -; CHECK-WIN-NEXT: [[POW:%.*]] = call double @pow(double 2.500000e-01, double [[X:%.*]]) -; CHECK-WIN-NEXT: ret double [[POW]] +; VC19-NEXT: [[MUL:%.*]] = fmul double [[X:%.*]], -2.000000e+00 +; VC19-NEXT: [[EXP2:%.*]] = call double @exp2(double [[MUL]]) +; VC19-NEXT: ret double [[EXP2]] +; VC32-NEXT: [[POW:%.*]] = call double @pow(double 2.500000e-01, double [[X:%.*]]) +; VC32-NEXT: ret double [[POW]] +; VC64-NEXT: [[POW:%.*]] = call double @pow(double 2.500000e-01, double [[X:%.*]]) +; VC64-NEXT: ret double [[POW]] ; %retval = call double @pow(double 0.25, double %x) ret double %retval } define <2 x float> @test_simplify3v(<2 x float> %x) { -; ANY-LABEL: @test_simplify3v( +; CHECK-LABEL: @test_simplify3v( ; ANY-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[X:%.*]]) ; ANY-NEXT: ret <2 x float> [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify3v( -; CHECK-WIN-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) -; CHECK-WIN-NEXT: ret <2 x float> [[POW]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> %x) ret <2 x float> %retval } define <2 x double> @test_simplify3vn(<2 x double> %x) { -; ANY-LABEL: @test_simplify3vn( +; CHECK-LABEL: @test_simplify3vn( ; ANY-NEXT: [[MUL:%.*]] = fmul <2 x double> [[X:%.*]], ; ANY-NEXT: [[EXP2:%.*]] = call <2 x double> @llvm.exp2.v2f64(<2 x double> [[MUL]]) ; ANY-NEXT: ret <2 x double> [[EXP2]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[X:%.*]]) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> %x) ret <2 x double> %retval } define double @test_simplify4(double %x) { -; ANY-LABEL: @test_simplify4( -; ANY-NEXT: [[EXP2:%.*]] = call double @exp2(double [[X:%.*]]) [[NUW_RO]] +; CHECK-LABEL: @test_simplify4( +; ANY-NEXT: [[EXP2:%.*]] = call double @exp2(double [[X:%.*]]) ; ANY-NEXT: ret double [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify4( -; CHECK-WIN-NEXT: [[POW:%.*]] = call double @pow(double 2.000000e+00, double [[X:%.*]]) -; CHECK-WIN-NEXT: ret double [[POW]] +; VC19-NEXT: [[EXP2:%.*]] = call double @exp2(double [[X:%.*]]) +; VC19-NEXT: ret double [[EXP2]] +; VC32-NEXT: [[POW:%.*]] = call double @pow(double 2.000000e+00, double [[X:%.*]]) +; VC32-NEXT: ret double [[POW]] +; VC64-NEXT: [[POW:%.*]] = call double @pow(double 2.000000e+00, double [[X:%.*]]) +; VC64-NEXT: ret double [[POW]] ; %retval = call double @pow(double 2.0, double %x) ret double %retval } define float @test_simplify4n(float %x) { -; ANY-LABEL: @test_simplify4n( +; CHECK-LABEL: @test_simplify4n( ; ANY-NEXT: [[MUL:%.*]] = fmul float [[X:%.*]], 3.000000e+00 -; ANY-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[MUL]]) [[NUW_RO]] +; ANY-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[MUL]]) ; ANY-NEXT: ret float [[EXP2F]] -; -; CHECK-WIN-LABEL: @test_simplify4n( -; CHECK-WIN-NEXT: [[POW:%.*]] = call float @powf(float 8.000000e+00, float [[X:%.*]]) -; CHECK-WIN-NEXT: ret float [[POW]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float 8.000000e+00, float [[X:%.*]]) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float 8.000000e+00, float [[X:%.*]]) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[POW:%.*]] = call float @powf(float 8.000000e+00, float [[X:%.*]]) +; VC64-NEXT: ret float [[POW]] +; VC83-NEXT: [[MUL:%.*]] = fmul float [[X:%.*]], 3.000000e+00 +; VC83-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[MUL]]) +; VC83-NEXT: ret float [[EXP2F]] ; %retval = call float @powf(float 8.0, float %x) ret float %retval } define <2 x double> @test_simplify4v(<2 x double> %x) { -; ANY-LABEL: @test_simplify4v( +; CHECK-LABEL: @test_simplify4v( ; ANY-NEXT: [[EXP2:%.*]] = call <2 x double> @llvm.exp2.v2f64(<2 x double> [[X:%.*]]) ; ANY-NEXT: ret <2 x double> [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify4v( -; CHECK-WIN-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[X:%.*]]) -; CHECK-WIN-NEXT: ret <2 x double> [[POW]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[X:%.*]]) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> %x) ret <2 x double> %retval } define <2 x float> @test_simplify4vn(<2 x float> %x) { -; ANY-LABEL: @test_simplify4vn( +; CHECK-LABEL: @test_simplify4vn( ; ANY-NEXT: [[MUL:%.*]] = fsub <2 x float> , [[X:%.*]] ; ANY-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[MUL]]) ; ANY-NEXT: ret <2 x float> [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify4vn( -; CHECK-WIN-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) -; CHECK-WIN-NEXT: ret <2 x float> [[POW]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> %x) ret <2 x float> %retval @@ -163,32 +183,42 @@ define <2 x float> @test_simplify4vn(<2 x float> %x) { ; Check pow(x, 0.0) -> 1.0. define float @test_simplify5(float %x) { -; ANY-LABEL: @test_simplify5( +; CHECK-LABEL: @test_simplify5( ; ANY-NEXT: ret float 1.000000e+00 +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 0.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 0.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: ret float 1.000000e+00 +; VC83-NEXT: ret float 1.000000e+00 ; %retval = call float @powf(float %x, float 0.0) ret float %retval } define <2 x float> @test_simplify5v(<2 x float> %x) { -; ANY-LABEL: @test_simplify5v( +; CHECK-LABEL: @test_simplify5v( ; ANY-NEXT: ret <2 x float> +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> zeroinitializer) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %retval } define double @test_simplify6(double %x) { -; ANY-LABEL: @test_simplify6( -; ANY-NEXT: ret double 1.000000e+00 +; CHECK-LABEL: @test_simplify6( +; CHECK-NEXT: ret double 1.000000e+00 ; %retval = call double @pow(double %x, double 0.0) ret double %retval } define <2 x double> @test_simplify6v(<2 x double> %x) { -; ANY-LABEL: @test_simplify6v( +; CHECK-LABEL: @test_simplify6v( ; ANY-NEXT: ret <2 x double> +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> zeroinitializer) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %retval @@ -197,24 +227,38 @@ define <2 x double> @test_simplify6v(<2 x double> %x) { ; Check pow(x, 0.5) -> fabs(sqrt(x)), where x != -infinity. define float @test_simplify7(float %x) { -; ANY-LABEL: @test_simplify7( -; ANY-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[X:%.*]]) [[NUW_RO]] +; CHECK-LABEL: @test_simplify7( +; ANY-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[X:%.*]]) ; ANY-NEXT: [[ABS:%.*]] = call float @llvm.fabs.f32(float [[SQRTF]]) ; ANY-NEXT: [[ISINF:%.*]] = fcmp oeq float [[X]], 0xFFF0000000000000 ; ANY-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], float 0x7FF0000000000000, float [[ABS]] ; ANY-NEXT: ret float [[TMP1]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 5.000000e-01) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 5.000000e-01) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[X:%.*]]) +; VC64-NEXT: [[ABS:%.*]] = call float @llvm.fabs.f32(float [[SQRTF]]) +; VC64-NEXT: [[ISINF:%.*]] = fcmp oeq float [[X]], 0xFFF0000000000000 +; VC64-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], float 0x7FF0000000000000, float [[ABS]] +; VC64-NEXT: ret float [[TMP1]] +; VC83-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[X:%.*]]) +; VC83-NEXT: [[ABS:%.*]] = call float @llvm.fabs.f32(float [[SQRTF]]) +; VC83-NEXT: [[ISINF:%.*]] = fcmp oeq float [[X]], 0xFFF0000000000000 +; VC83-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], float 0x7FF0000000000000, float [[ABS]] +; VC83-NEXT: ret float [[TMP1]] ; %retval = call float @powf(float %x, float 0.5) ret float %retval } define double @test_simplify8(double %x) { -; ANY-LABEL: @test_simplify8( -; ANY-NEXT: [[SQRT:%.*]] = call double @sqrt(double [[X:%.*]]) [[NUW_RO]] -; ANY-NEXT: [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SQRT]]) -; ANY-NEXT: [[ISINF:%.*]] = fcmp oeq double [[X]], 0xFFF0000000000000 -; ANY-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]] -; ANY-NEXT: ret double [[TMP1]] +; CHECK-LABEL: @test_simplify8( +; CHECK-NEXT: [[SQRT:%.*]] = call double @sqrt(double [[X:%.*]]) +; CHECK-NEXT: [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SQRT]]) +; CHECK-NEXT: [[ISINF:%.*]] = fcmp oeq double [[X]], 0xFFF0000000000000 +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]] +; CHECK-NEXT: ret double [[TMP1]] ; %retval = call double @pow(double %x, double 0.5) ret double %retval @@ -223,16 +267,22 @@ define double @test_simplify8(double %x) { ; Check pow(-infinity, 0.5) -> +infinity. define float @test_simplify9(float %x) { -; ANY-LABEL: @test_simplify9( +; CHECK-LABEL: @test_simplify9( ; ANY-NEXT: ret float 0x7FF0000000000000 +; VC32-NEXT: [[POW:%.*]] = call float @powf(float 0xFFF0000000000000, float 5.000000e-01) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float 0xFFF0000000000000, float 5.000000e-01) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: ret float 0x7FF0000000000000 +; VC83-NEXT: ret float 0x7FF0000000000000 ; %retval = call float @powf(float 0xFFF0000000000000, float 0.5) ret float %retval } define double @test_simplify10(double %x) { -; ANY-LABEL: @test_simplify10( -; ANY-NEXT: ret double 0x7FF0000000000000 +; CHECK-LABEL: @test_simplify10( +; CHECK-NEXT: ret double 0x7FF0000000000000 ; %retval = call double @pow(double 0xFFF0000000000000, double 0.5) ret double %retval @@ -241,32 +291,42 @@ define double @test_simplify10(double %x) { ; Check pow(x, 1.0) -> x. define float @test_simplify11(float %x) { -; ANY-LABEL: @test_simplify11( +; CHECK-LABEL: @test_simplify11( ; ANY-NEXT: ret float [[X:%.*]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 1.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 1.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: ret float [[X:%.*]] +; VC83-NEXT: ret float [[X:%.*]] ; %retval = call float @powf(float %x, float 1.0) ret float %retval } define <2 x float> @test_simplify11v(<2 x float> %x) { -; ANY-LABEL: @test_simplify11v( +; CHECK-LABEL: @test_simplify11v( ; ANY-NEXT: ret <2 x float> [[X:%.*]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> ) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %retval } define double @test_simplify12(double %x) { -; ANY-LABEL: @test_simplify12( -; ANY-NEXT: ret double [[X:%.*]] +; CHECK-LABEL: @test_simplify12( +; CHECK-NEXT: ret double [[X:%.*]] ; %retval = call double @pow(double %x, double 1.0) ret double %retval } define <2 x double> @test_simplify12v(<2 x double> %x) { -; ANY-LABEL: @test_simplify12v( +; CHECK-LABEL: @test_simplify12v( ; ANY-NEXT: ret <2 x double> [[X:%.*]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> ) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %retval @@ -275,36 +335,48 @@ define <2 x double> @test_simplify12v(<2 x double> %x) { ; Check pow(x, 2.0) -> x*x. define float @pow2_strict(float %x) { -; ANY-LABEL: @pow2_strict( +; CHECK-LABEL: @pow2_strict( ; ANY-NEXT: [[SQUARE:%.*]] = fmul float [[X:%.*]], [[X]] ; ANY-NEXT: ret float [[SQUARE]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 2.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 2.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[SQUARE:%.*]] = fmul float [[X:%.*]], [[X]] +; VC64-NEXT: ret float [[SQUARE]] +; VC83-NEXT: [[SQUARE:%.*]] = fmul float [[X:%.*]], [[X]] +; VC83-NEXT: ret float [[SQUARE]] ; %r = call float @powf(float %x, float 2.0) ret float %r } define <2 x float> @pow2_strictv(<2 x float> %x) { -; ANY-LABEL: @pow2_strictv( +; CHECK-LABEL: @pow2_strictv( ; ANY-NEXT: [[SQUARE:%.*]] = fmul <2 x float> [[X:%.*]], [[X]] ; ANY-NEXT: ret <2 x float> [[SQUARE]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> ) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %r = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %r } define double @pow2_double_strict(double %x) { -; ANY-LABEL: @pow2_double_strict( -; ANY-NEXT: [[SQUARE:%.*]] = fmul double [[X:%.*]], [[X]] -; ANY-NEXT: ret double [[SQUARE]] +; CHECK-LABEL: @pow2_double_strict( +; CHECK-NEXT: [[SQUARE:%.*]] = fmul double [[X:%.*]], [[X]] +; CHECK-NEXT: ret double [[SQUARE]] ; %r = call double @pow(double %x, double 2.0) ret double %r } define <2 x double> @pow2_double_strictv(<2 x double> %x) { -; ANY-LABEL: @pow2_double_strictv( +; CHECK-LABEL: @pow2_double_strictv( ; ANY-NEXT: [[SQUARE:%.*]] = fmul <2 x double> [[X:%.*]], [[X]] ; ANY-NEXT: ret <2 x double> [[SQUARE]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> ) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %r = call <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %r @@ -313,9 +385,17 @@ define <2 x double> @pow2_double_strictv(<2 x double> %x) { ; Don't drop the FMF - PR35601 ( https://bugs.llvm.org/show_bug.cgi?id=35601 ) define float @pow2_fast(float %x) { -; ANY-LABEL: @pow2_fast( +; CHECK-LABEL: @pow2_fast( ; ANY-NEXT: [[SQUARE:%.*]] = fmul fast float [[X:%.*]], [[X]] ; ANY-NEXT: ret float [[SQUARE]] +; VC32-NEXT: [[POW:%.*]] = call fast float @powf(float [[X:%.*]], float 2.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call fast float @powf(float [[X:%.*]], float 2.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[SQUARE:%.*]] = fmul fast float [[X:%.*]], [[X]] +; VC64-NEXT: ret float [[SQUARE]] +; VC83-NEXT: [[SQUARE:%.*]] = fmul fast float [[X:%.*]], [[X]] +; VC83-NEXT: ret float [[SQUARE]] ; %r = call fast float @powf(float %x, float 2.0) ret float %r @@ -324,48 +404,60 @@ define float @pow2_fast(float %x) { ; Check pow(x, -1.0) -> 1.0/x. define float @pow_neg1_strict(float %x) { -; ANY-LABEL: @pow_neg1_strict( +; CHECK-LABEL: @pow_neg1_strict( ; ANY-NEXT: [[RECIPROCAL:%.*]] = fdiv float 1.000000e+00, [[X:%.*]] ; ANY-NEXT: ret float [[RECIPROCAL]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float -1.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float -1.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[RECIPROCAL:%.*]] = fdiv float 1.000000e+00, [[X:%.*]] +; VC64-NEXT: ret float [[RECIPROCAL]] +; VC83-NEXT: [[RECIPROCAL:%.*]] = fdiv float 1.000000e+00, [[X:%.*]] +; VC83-NEXT: ret float [[RECIPROCAL]] ; %r = call float @powf(float %x, float -1.0) ret float %r } define <2 x float> @pow_neg1_strictv(<2 x float> %x) { -; ANY-LABEL: @pow_neg1_strictv( +; CHECK-LABEL: @pow_neg1_strictv( ; ANY-NEXT: [[RECIPROCAL:%.*]] = fdiv <2 x float> , [[X:%.*]] ; ANY-NEXT: ret <2 x float> [[RECIPROCAL]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> ) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %r = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %r } define double @pow_neg1_double_fast(double %x) { -; ANY-LABEL: @pow_neg1_double_fast( -; ANY-NEXT: [[RECIPROCAL:%.*]] = fdiv fast double 1.000000e+00, [[X:%.*]] -; ANY-NEXT: ret double [[RECIPROCAL]] +; CHECK-LABEL: @pow_neg1_double_fast( +; CHECK-NEXT: [[RECIPROCAL:%.*]] = fdiv fast double 1.000000e+00, [[X:%.*]] +; CHECK-NEXT: ret double [[RECIPROCAL]] ; %r = call fast double @pow(double %x, double -1.0) ret double %r } define <2 x double> @pow_neg1_double_fastv(<2 x double> %x) { -; ANY-LABEL: @pow_neg1_double_fastv( +; CHECK-LABEL: @pow_neg1_double_fastv( ; ANY-NEXT: [[RECIPROCAL:%.*]] = fdiv fast <2 x double> , [[X:%.*]] ; ANY-NEXT: ret <2 x double> [[RECIPROCAL]] +; MSVC-NEXT: [[POW:%.*]] = call fast <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> ) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %r = call fast <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %r } define double @test_simplify17(double %x) { -; ANY-LABEL: @test_simplify17( -; ANY-NEXT: [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[X:%.*]]) -; ANY-NEXT: [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SQRT]]) -; ANY-NEXT: [[ISINF:%.*]] = fcmp oeq double [[X]], 0xFFF0000000000000 -; ANY-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]] -; ANY-NEXT: ret double [[TMP1]] +; CHECK-LABEL: @test_simplify17( +; CHECK-NEXT: [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[X:%.*]]) +; CHECK-NEXT: [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SQRT]]) +; CHECK-NEXT: [[ISINF:%.*]] = fcmp oeq double [[X]], 0xFFF0000000000000 +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]] +; CHECK-NEXT: ret double [[TMP1]] ; %retval = call double @llvm.pow.f64(double %x, double 0.5) ret double %retval @@ -374,29 +466,23 @@ define double @test_simplify17(double %x) { ; Check pow(10.0, x) -> __exp10(x) on OS X 10.9+ and iOS 7.0+. define float @test_simplify18(float %x) { -; CHECK-EXP10-LABEL: @test_simplify18( -; CHECK-EXP10-NEXT: [[__EXP10F:%.*]] = call float @__exp10f(float [[X:%.*]]) [[NUW_RO]] -; CHECK-EXP10-NEXT: ret float [[__EXP10F]] -; -; CHECK-NO-EXP10-LABEL: @test_simplify18( -; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call float @powf(float 1.000000e+01, float [[X:%.*]]) -; CHECK-NO-EXP10-NEXT: ret float [[RETVAL]] +; CHECK-LABEL: @test_simplify18( +; CHECK-EXP10-NEXT: [[__EXP10F:%.*]] = call float @__exp10f(float [[X:%.*]]) +; CHECK-EXP10-NEXT: ret float [[__EXP10F]] +; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call float @powf(float 1.000000e+01, float [[X:%.*]]) +; CHECK-NO-EXP10-NEXT: ret float [[RETVAL]] ; %retval = call float @powf(float 10.0, float %x) ret float %retval } define double @test_simplify19(double %x) { -; CHECK-EXP10-LABEL: @test_simplify19( -; CHECK-EXP10-NEXT: [[__EXP10:%.*]] = call double @__exp10(double [[X:%.*]]) [[NUW_RO]] -; CHECK-EXP10-NEXT: ret double [[__EXP10]] -; -; CHECK-NO-EXP10-LABEL: @test_simplify19( -; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call double @pow(double 1.000000e+01, double [[X:%.*]]) -; CHECK-NO-EXP10-NEXT: ret double [[RETVAL]] +; CHECK-LABEL: @test_simplify19( +; CHECK-EXP10-NEXT: [[__EXP10:%.*]] = call double @__exp10(double [[X:%.*]]) +; CHECK-EXP10-NEXT: ret double [[__EXP10]] +; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call double @pow(double 1.000000e+01, double [[X:%.*]]) +; CHECK-NO-EXP10-NEXT: ret double [[RETVAL]] ; %retval = call double @pow(double 10.0, double %x) ret double %retval } - -; CHECK-EXP10: attributes [[NUW_RO]] = { nounwind readonly } diff --git a/llvm/test/Transforms/InstCombine/sink-alloca.ll b/llvm/test/Transforms/InstCombine/sink-alloca.ll new file mode 100644 index 0000000000000..f2de74ff533ba --- /dev/null +++ b/llvm/test/Transforms/InstCombine/sink-alloca.ll @@ -0,0 +1,52 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128" +target triple = "i686-unknown-linux-gnu" + +; Check that instcombine doesn't sink dynamic allocas across llvm.stacksave. + +; Helper to generate branch conditions. +declare i1 @cond() + +declare i32* @use_and_return(i32*) + +declare i8* @llvm.stacksave() #0 + +declare void @llvm.stackrestore(i8*) #0 + +define void @foo(i32 %x) { +entry: + %c1 = call i1 @cond() + br i1 %c1, label %ret, label %nonentry + +nonentry: ; preds = %entry + %argmem = alloca i32, i32 %x, align 4 + %sp = call i8* @llvm.stacksave() + %c2 = call i1 @cond() + br i1 %c2, label %ret, label %sinktarget + +sinktarget: ; preds = %nonentry + ; Arrange for there to be a single use of %argmem by returning it. + %p = call i32* @use_and_return(i32* nonnull %argmem) + store i32 13, i32* %p, align 4 + call void @llvm.stackrestore(i8* %sp) + %0 = call i32* @use_and_return(i32* %p) + br label %ret + +ret: ; preds = %sinktarget, %nonentry, %entry + ret void +} + +; CHECK-LABEL: define void @foo(i32 %x) +; CHECK: nonentry: +; CHECK: %argmem = alloca i32, i32 %x +; CHECK: %sp = call i8* @llvm.stacksave() +; CHECK: %c2 = call i1 @cond() +; CHECK: br i1 %c2, label %ret, label %sinktarget +; CHECK: sinktarget: +; CHECK: %p = call i32* @use_and_return(i32* nonnull %argmem) +; CHECK: store i32 13, i32* %p +; CHECK: call void @llvm.stackrestore(i8* %sp) +; CHECK: %0 = call i32* @use_and_return(i32* %p) + +attributes #0 = { nounwind } diff --git a/llvm/test/Transforms/InstCombine/vec_shuffle.ll b/llvm/test/Transforms/InstCombine/vec_shuffle.ll index b82c8117eebf5..8f6818f4eb79d 100644 --- a/llvm/test/Transforms/InstCombine/vec_shuffle.ll +++ b/llvm/test/Transforms/InstCombine/vec_shuffle.ll @@ -1114,3 +1114,18 @@ define <2 x float> @frem_splat_constant1(<2 x float> %x) { ret <2 x float> %r } +; Equivalent shuffle masks, but only one is a narrowing op. + +define <2 x i1> @PR40734(<1 x i1> %x, <4 x i1> %y) { +; CHECK-LABEL: @PR40734( +; CHECK-NEXT: [[WIDEN:%.*]] = shufflevector <1 x i1> zeroinitializer, <1 x i1> [[X:%.*]], <2 x i32> +; CHECK-NEXT: [[NARROW:%.*]] = shufflevector <4 x i1> [[Y:%.*]], <4 x i1> undef, <2 x i32> +; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[WIDEN]], [[NARROW]] +; CHECK-NEXT: ret <2 x i1> [[R]] +; + %widen = shufflevector <1 x i1> zeroinitializer, <1 x i1> %x, <2 x i32> + %narrow = shufflevector <4 x i1> %y, <4 x i1> undef, <2 x i32> + %r = and <2 x i1> %widen, %narrow + ret <2 x i1> %r +} + diff --git a/llvm/test/Transforms/InstCombine/win-math.ll b/llvm/test/Transforms/InstCombine/win-math.ll index 36947791393d9..38ed949e949dc 100644 --- a/llvm/test/Transforms/InstCombine/win-math.ll +++ b/llvm/test/Transforms/InstCombine/win-math.ll @@ -1,17 +1,21 @@ -; RUN: opt -O2 -S -mtriple=i386-pc-win32 < %s | FileCheck %s -check-prefix=WIN32 -; RUN: opt -O2 -S -mtriple=x86_64-pc-win32 < %s | FileCheck %s -check-prefix=WIN64 -; RUN: opt -O2 -S -mtriple=i386-pc-mingw32 < %s | FileCheck %s -check-prefix=MINGW32 -; RUN: opt -O2 -S -mtriple=x86_64-pc-mingw32 < %s | FileCheck %s -check-prefix=MINGW64 +; RUN: opt < %s -O2 -S -mtriple=i386-pc-windows-msvc18 | FileCheck %s --check-prefixes=CHECK,MSVCXX,MSVC32 +; RUN: opt < %s -O2 -S -mtriple=i386-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK,MSVC19,MSVC51 +; RUN: opt < %s -O2 -S -mtriple=x86_64-pc-windows-msvc17 | FileCheck %s --check-prefixes=CHECK,MSVCXX,MSVC64 +; RUN: opt < %s -O2 -S -mtriple=x86_64-pc-win32 | FileCheck %s --check-prefixes=CHECK,MSVC19,MSVC83 +; RUN: opt < %s -O2 -S -mtriple=i386-pc-mingw32 | FileCheck %s --check-prefixes=CHECK,MINGW32 +; RUN: opt < %s -O2 -S -mtriple=x86_64-pc-mingw32 | FileCheck %s --check-prefixes=CHECK,MINGW64 ; x86 win32 msvcrt does not provide entry points for single-precision libm. -; x86-64 win32 msvcrt does (except for fabsf) -; msvcrt does not provide C99 math, but mingw32 does. +; x86-64 win32 msvcrt does, but with exceptions +; msvcrt does not provide all of C99 math, but mingw32 does. declare double @acos(double %x) define float @float_acos(float %x) nounwind readnone { -; WIN32-LABEL: @float_acos( -; WIN32-NOT: float @acosf -; WIN32: double @acos +; CHECK-LABEL: @float_acos( +; MSVCXX-NOT: float @acosf +; MSVCXX: double @acos +; MSVC19-NOT: float @acosf +; MSVC19: double @acos %1 = fpext float %x to double %2 = call double @acos(double %1) %3 = fptrunc double %2 to float @@ -20,9 +24,11 @@ define float @float_acos(float %x) nounwind readnone { declare double @asin(double %x) define float @float_asin(float %x) nounwind readnone { -; WIN32-LABEL: @float_asin( -; WIN32-NOT: float @asinf -; WIN32: double @asin +; CHECK-LABEL: @float_asin( +; MSVCXX-NOT: float @asinf +; MSVCXX: double @asin +; MSVC19-NOT: float @asinf +; MSVC19: double @asin %1 = fpext float %x to double %2 = call double @asin(double %1) %3 = fptrunc double %2 to float @@ -31,9 +37,11 @@ define float @float_asin(float %x) nounwind readnone { declare double @atan(double %x) define float @float_atan(float %x) nounwind readnone { -; WIN32-LABEL: @float_atan( -; WIN32-NOT: float @atanf -; WIN32: double @atan +; CHECK-LABEL: @float_atan( +; MSVCXX-NOT: float @atanf +; MSVCXX: double @atan +; MSVC19-NOT: float @atanf +; MSVC19: double @atan %1 = fpext float %x to double %2 = call double @atan(double %1) %3 = fptrunc double %2 to float @@ -42,9 +50,11 @@ define float @float_atan(float %x) nounwind readnone { declare double @atan2(double %x, double %y) define float @float_atan2(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_atan2( -; WIN32-NOT: float @atan2f -; WIN32: double @atan2 +; CHECK-LABEL: @float_atan2( +; MSVCXX-NOT: float @atan2f +; MSVCXX: double @atan2 +; MSVC19-NOT: float @atan2f +; MSVC19: double @atan2 %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @atan2(double %1, double %2) @@ -54,18 +64,15 @@ define float @float_atan2(float %x, float %y) nounwind readnone { declare double @ceil(double %x) define float @float_ceil(float %x) nounwind readnone { -; WIN32-LABEL: @float_ceil( -; WIN32-NOT: float @ceilf -; WIN32: float @llvm.ceil.f32 -; WIN64-LABEL: @float_ceil( -; WIN64: float @llvm.ceil.f32 -; WIN64-NOT: double @ceil -; MINGW32-LABEL: @float_ceil( -; MINGW32: float @llvm.ceil.f32 +; CHECK-LABEL: @float_ceil( +; MSVCXX-NOT: float @ceilf +; MSVCXX: float @llvm.ceil.f32 +; MSVC19-NOT: double @ceil +; MSVC19: float @llvm.ceil.f32 ; MINGW32-NOT: double @ceil -; MINGW64-LABEL: @float_ceil( -; MINGW64: float @llvm.ceil.f32 +; MINGW32: float @llvm.ceil.f32 ; MINGW64-NOT: double @ceil +; MINGW64: float @llvm.ceil.f32 %1 = fpext float %x to double %2 = call double @ceil(double %1) %3 = fptrunc double %2 to float @@ -74,10 +81,11 @@ define float @float_ceil(float %x) nounwind readnone { declare double @_copysign(double %x) define float @float_copysign(float %x) nounwind readnone { -; WIN32-LABEL: @float_copysign( -; WIN32-NOT: float @copysignf -; WIN32-NOT: float @_copysignf -; WIN32: double @_copysign +; CHECK-LABEL: @float_copysign( +; MSVCXX-NOT: float @_copysignf +; MSVCXX: double @_copysign +; MSVC19-NOT: float @_copysignf +; MSVC19: double @_copysign %1 = fpext float %x to double %2 = call double @_copysign(double %1) %3 = fptrunc double %2 to float @@ -86,9 +94,11 @@ define float @float_copysign(float %x) nounwind readnone { declare double @cos(double %x) define float @float_cos(float %x) nounwind readnone { -; WIN32-LABEL: @float_cos( -; WIN32-NOT: float @cosf -; WIN32: double @cos +; CHECK-LABEL: @float_cos( +; MSVCXX-NOT: float @cosf +; MSVCXX: double @cos +; MSVC19-NOT: float @cosf +; MSVC19: double @cos %1 = fpext float %x to double %2 = call double @cos(double %1) %3 = fptrunc double %2 to float @@ -97,9 +107,11 @@ define float @float_cos(float %x) nounwind readnone { declare double @cosh(double %x) define float @float_cosh(float %x) nounwind readnone { -; WIN32-LABEL: @float_cosh( -; WIN32-NOT: float @coshf -; WIN32: double @cosh +; CHECK-LABEL: @float_cosh( +; MSVCXX-NOT: float @coshf +; MSVCXX: double @cosh +; MSVC19-NOT: float @coshf +; MSVC19: double @cosh %1 = fpext float %x to double %2 = call double @cosh(double %1) %3 = fptrunc double %2 to float @@ -108,9 +120,11 @@ define float @float_cosh(float %x) nounwind readnone { declare double @exp(double %x, double %y) define float @float_exp(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_exp( -; WIN32-NOT: float @expf -; WIN32: double @exp +; CHECK-LABEL: @float_exp( +; MSVCXX-NOT: float @expf +; MSVCXX: double @exp +; MSVC19-NOT: float @expf +; MSVC19: double @exp %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @exp(double %1, double %2) @@ -120,12 +134,11 @@ define float @float_exp(float %x, float %y) nounwind readnone { declare double @fabs(double %x, double %y) define float @float_fabs(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_fabs( -; WIN32-NOT: float @fabsf -; WIN32: double @fabs -; WIN64-LABEL: @float_fabs( -; WIN64-NOT: float @fabsf -; WIN64: double @fabs +; CHECK-LABEL: @float_fabs( +; MSVCXX-NOT: float @fabsf +; MSVCXX: double @fabs +; MSVC19-NOT: float @fabsf +; MSVC19: double @fabs %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @fabs(double %1, double %2) @@ -135,18 +148,15 @@ define float @float_fabs(float %x, float %y) nounwind readnone { declare double @floor(double %x) define float @float_floor(float %x) nounwind readnone { -; WIN32-LABEL: @float_floor( -; WIN32-NOT: float @floorf -; WIN32: float @llvm.floor.f32 -; WIN64-LABEL: @float_floor( -; WIN64: float @llvm.floor.f32 -; WIN64-NOT: double @floor -; MINGW32-LABEL: @float_floor( -; MINGW32: float @llvm.floor.f32 +; CHECK-LABEL: @float_floor( +; MSVCXX-NOT: float @floorf +; MSVCXX: float @llvm.floor.f32 +; MSVC19-NOT: double @floor +; MSVC19: float @llvm.floor.f32 ; MINGW32-NOT: double @floor -; MINGW64-LABEL: @float_floor( -; MINGW64: float @llvm.floor.f32 +; MINGW32: float @llvm.floor.f32 ; MINGW64-NOT: double @floor +; MINGW64: float @llvm.floor.f32 %1 = fpext float %x to double %2 = call double @floor(double %1) %3 = fptrunc double %2 to float @@ -155,9 +165,11 @@ define float @float_floor(float %x) nounwind readnone { declare double @fmod(double %x, double %y) define float @float_fmod(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_fmod( -; WIN32-NOT: float @fmodf -; WIN32: double @fmod +; MSVCXX-LABEL: @float_fmod( +; MSVCXX-NOT: float @fmodf +; MSVCXX: double @fmod +; MSVC19-NOT: float @fmodf +; MSVC19: double @fmod %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @fmod(double %1, double %2) @@ -167,20 +179,37 @@ define float @float_fmod(float %x, float %y) nounwind readnone { declare double @log(double %x) define float @float_log(float %x) nounwind readnone { -; WIN32-LABEL: @float_log( -; WIN32-NOT: float @logf -; WIN32: double @log +; CHECK-LABEL: @float_log( +; MSVCXX-NOT: float @logf +; MSVCXX: double @log +; MSVC19-NOT: float @logf +; MSVC19: double @log %1 = fpext float %x to double %2 = call double @log(double %1) %3 = fptrunc double %2 to float ret float %3 } +declare double @logb(double %x) +define float @float_logb(float %x) nounwind readnone { +; CHECK-LABEL: @float_logb( +; MSVCXX-NOT: float @logbf +; MSVCXX: double @logb +; MSVC19-NOT: float @logbf +; MSVC19: double @logb + %1 = fpext float %x to double + %2 = call double @logb(double %1) + %3 = fptrunc double %2 to float + ret float %3 +} + declare double @pow(double %x, double %y) define float @float_pow(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_pow( -; WIN32-NOT: float @powf -; WIN32: double @pow +; CHECK-LABEL: @float_pow( +; MSVCXX-NOT: float @powf +; MSVCXX: double @pow +; MSVC19-NOT: float @powf +; MSVC19: double @pow %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @pow(double %1, double %2) @@ -190,9 +219,11 @@ define float @float_pow(float %x, float %y) nounwind readnone { declare double @sin(double %x) define float @float_sin(float %x) nounwind readnone { -; WIN32-LABEL: @float_sin( -; WIN32-NOT: float @sinf -; WIN32: double @sin +; CHECK-LABEL: @float_sin( +; MSVCXX-NOT: float @sinf +; MSVCXX: double @sin +; MSVC19-NOT: float @sinf +; MSVC19: double @sin %1 = fpext float %x to double %2 = call double @sin(double %1) %3 = fptrunc double %2 to float @@ -201,9 +232,11 @@ define float @float_sin(float %x) nounwind readnone { declare double @sinh(double %x) define float @float_sinh(float %x) nounwind readnone { -; WIN32-LABEL: @float_sinh( -; WIN32-NOT: float @sinhf -; WIN32: double @sinh +; CHECK-LABEL: @float_sinh( +; MSVCXX-NOT: float @sinhf +; MSVCXX: double @sinh +; MSVC19-NOT: float @sinhf +; MSVC19: double @sinh %1 = fpext float %x to double %2 = call double @sinh(double %1) %3 = fptrunc double %2 to float @@ -212,18 +245,19 @@ define float @float_sinh(float %x) nounwind readnone { declare double @sqrt(double %x) define float @float_sqrt(float %x) nounwind readnone { -; WIN32-LABEL: @float_sqrt( -; WIN32-NOT: float @sqrtf -; WIN32: double @sqrt -; WIN64-LABEL: @float_sqrt( -; WIN64: float @sqrtf -; WIN64-NOT: double @sqrt -; MINGW32-LABEL: @float_sqrt( -; MINGW32: float @sqrtf +; CHECK-LABEL: @float_sqrt( +; MSVC32-NOT: float @sqrtf +; MSVC32: double @sqrt +; MSVC51-NOT: float @sqrtf +; MSVC51: double @sqrt +; MSVC64-NOT: double @sqrt +; MSVC64: float @sqrtf +; MSVC83-NOT: double @sqrt +; MSVC83: float @sqrtf ; MINGW32-NOT: double @sqrt -; MINGW64-LABEL: @float_sqrt( -; MINGW64: float @sqrtf +; MINGW32: float @sqrtf ; MINGW64-NOT: double @sqrt +; MINGW64: float @sqrtf %1 = fpext float %x to double %2 = call double @sqrt(double %1) %3 = fptrunc double %2 to float @@ -232,9 +266,11 @@ define float @float_sqrt(float %x) nounwind readnone { declare double @tan(double %x) define float @float_tan(float %x) nounwind readnone { -; WIN32-LABEL: @float_tan( -; WIN32-NOT: float @tanf -; WIN32: double @tan +; CHECK-LABEL: @float_tan( +; MSVCXX-NOT: float @tanf +; MSVCXX: double @tan +; MSVC19-NOT: float @tanf +; MSVC19: double @tan %1 = fpext float %x to double %2 = call double @tan(double %1) %3 = fptrunc double %2 to float @@ -243,30 +279,29 @@ define float @float_tan(float %x) nounwind readnone { declare double @tanh(double %x) define float @float_tanh(float %x) nounwind readnone { -; WIN32-LABEL: @float_tanh( -; WIN32-NOT: float @tanhf -; WIN32: double @tanh +; CHECK-LABEL: @float_tanh( +; MSVCXX-NOT: float @tanhf +; MSVCXX: double @tanh +; MSVC19-NOT: float @tanhf +; MSVC19: double @tanh %1 = fpext float %x to double %2 = call double @tanh(double %1) %3 = fptrunc double %2 to float ret float %3 } -; win32 does not have round; mingw32 does +; win32 does not have roundf; mingw32 does declare double @round(double %x) define float @float_round(float %x) nounwind readnone { -; WIN32-LABEL: @float_round( -; WIN32-NOT: float @roundf -; WIN32: double @round -; WIN64-LABEL: @float_round( -; WIN64-NOT: float @roundf -; WIN64: double @round -; MINGW32-LABEL: @float_round( -; MINGW32: float @llvm.round.f32 +; CHECK-LABEL: @float_round( +; MSVCXX-NOT: double @roundf +; MSVCXX: double @round +; MSVC19-NOT: double @round +; MSVC19: float @llvm.round.f32 ; MINGW32-NOT: double @round -; MINGW64-LABEL: @float_round( -; MINGW64: float @llvm.round.f32 +; MINGW32: float @llvm.round.f32 ; MINGW64-NOT: double @round +; MINGW64: float @llvm.round.f32 %1 = fpext float %x to double %2 = call double @round(double %1) %3 = fptrunc double %2 to float @@ -275,26 +310,26 @@ define float @float_round(float %x) nounwind readnone { declare float @powf(float, float) -; win32 lacks sqrtf&fabsf, win64 lacks fabsf, but +; win32 lacks sqrtf & fabsf, win64 lacks fabsf, but ; calls to the intrinsics can be emitted instead. define float @float_powsqrt(float %x) nounwind readnone { -; WIN32-LABEL: @float_powsqrt( -; WIN32-NOT: float @sqrtf -; WIN32: float @powf - -; WIN64-LABEL: @float_powsqrt( -; WIN64: float @sqrtf -; WIN64: float @llvm.fabs.f32( -; WIN64-NOT: float @powf - -; MINGW32-LABEL: @float_powsqrt( +; CHECK-LABEL: @float_powsqrt( +; MSVC32-NOT: float @sqrtf +; MSVC32: float @powf +; MSVC51-NOT: float @sqrtf +; MSVC51: float @powf +; MSVC64-NOT: float @powf +; MSVC64: float @sqrtf +; MSVC64: float @llvm.fabs.f32( +; MSVC83-NOT: float @powf +; MSVC83: float @sqrtf +; MSVC83: float @llvm.fabs.f32( +; MINGW32-NOT: float @powf ; MINGW32: float @sqrtf ; MINGW32: float @llvm.fabs.f32 -; MINGW32-NOT: float @powf -; MINGW64-LABEL: @float_powsqrt( +; MINGW64-NOT: float @powf ; MINGW64: float @sqrtf ; MINGW64: float @llvm.fabs.f32( -; MINGW64-NOT: float @powf %1 = call float @powf(float %x, float 0.5) ret float %1 } diff --git a/llvm/test/Transforms/LoopTransformWarning/enable_and_isvectorized.ll b/llvm/test/Transforms/LoopTransformWarning/enable_and_isvectorized.ll new file mode 100644 index 0000000000000..77d09ad53f788 --- /dev/null +++ b/llvm/test/Transforms/LoopTransformWarning/enable_and_isvectorized.ll @@ -0,0 +1,33 @@ +; RUN: opt -transform-warning -disable-output < %s 2>&1 | FileCheck -allow-empty %s +; +; llvm.org/PR40546 +; Do not warn about about leftover llvm.loop.vectorize.enable for already +; vectorized loops. + +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" + +define void @test(i32 %n) { +entry: + %cmp = icmp eq i32 %n, 0 + br i1 %cmp, label %simd.if.end, label %omp.inner.for.body.preheader + +omp.inner.for.body.preheader: + %wide.trip.count = zext i32 %n to i64 + br label %omp.inner.for.body + +omp.inner.for.body: + %indvars.iv = phi i64 [ 0, %omp.inner.for.body.preheader ], [ %indvars.iv.next, %omp.inner.for.body ] + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count + br i1 %exitcond, label %simd.if.end, label %omp.inner.for.body, !llvm.loop !0 + +simd.if.end: + ret void +} + +!0 = distinct !{!0, !1, !2} +!1 = !{!"llvm.loop.vectorize.enable", i1 true} +!2 = !{!"llvm.loop.isvectorized"} + + +; CHECK-NOT: loop not vectorized diff --git a/llvm/test/Transforms/LoopVectorize/no_switch_disable_vectorization.ll b/llvm/test/Transforms/LoopVectorize/no_switch_disable_vectorization.ll new file mode 100644 index 0000000000000..424ef3846224a --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/no_switch_disable_vectorization.ll @@ -0,0 +1,95 @@ +; RUN: opt < %s -loop-vectorize -force-vector-width=4 -transform-warning -S 2>&1 | FileCheck %s +; RUN: opt < %s -loop-vectorize -force-vector-width=1 -transform-warning -S 2>&1 | FileCheck %s -check-prefix=NOANALYSIS +; RUN: opt < %s -loop-vectorize -force-vector-width=4 -transform-warning -pass-remarks-missed='loop-vectorize' -S 2>&1 | FileCheck %s -check-prefix=MOREINFO + +; This test is a copy of no_switch.ll, with the "llvm.loop.vectorize.enable" metadata set to false. +; It tests that vectorization is explicitly disabled and no warnings are emitted. + +; CHECK-NOT: remark: source.cpp:4:5: loop not vectorized: loop contains a switch statement +; CHECK-NOT: warning: source.cpp:4:5: loop not vectorized: the optimizer was unable to perform the requested transformation; the transformation might be disabled or specified as part of an unsupported transformation ordering + +; NOANALYSIS-NOT: remark: {{.*}} +; NOANALYSIS-NOT: warning: source.cpp:4:5: loop not vectorized: the optimizer was unable to perform the requested transformation; the transformation might be disabled or specified as part of an unsupported transformation ordering + +; MOREINFO: remark: source.cpp:4:5: loop not vectorized: vectorization is explicitly disabled +; MOREINFO-NOT: warning: source.cpp:4:5: loop not vectorized: the optimizer was unable to perform the requested transformation; the transformation might be disabled or specified as part of an unsupported transformation ordering + +; CHECK: _Z11test_switchPii +; CHECK-NOT: x i32> +; CHECK: ret + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + +; Function Attrs: nounwind optsize ssp uwtable +define void @_Z11test_switchPii(i32* nocapture %A, i32 %Length) #0 !dbg !4 { +entry: + %cmp18 = icmp sgt i32 %Length, 0, !dbg !10 + br i1 %cmp18, label %for.body.preheader, label %for.end, !dbg !10, !llvm.loop !12 + +for.body.preheader: ; preds = %entry + br label %for.body, !dbg !14 + +for.body: ; preds = %for.body.preheader, %for.inc + %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %for.body.preheader ] + %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv, !dbg !14 + %0 = load i32, i32* %arrayidx, align 4, !dbg !14, !tbaa !16 + switch i32 %0, label %for.inc [ + i32 0, label %sw.bb + i32 1, label %sw.bb3 + ], !dbg !14 + +sw.bb: ; preds = %for.body + %1 = trunc i64 %indvars.iv to i32, !dbg !20 + %mul = shl nsw i32 %1, 1, !dbg !20 + br label %for.inc, !dbg !22 + +sw.bb3: ; preds = %for.body + %2 = trunc i64 %indvars.iv to i32, !dbg !23 + store i32 %2, i32* %arrayidx, align 4, !dbg !23, !tbaa !16 + br label %for.inc, !dbg !23 + +for.inc: ; preds = %sw.bb3, %for.body, %sw.bb + %storemerge = phi i32 [ %mul, %sw.bb ], [ 0, %for.body ], [ 0, %sw.bb3 ] + store i32 %storemerge, i32* %arrayidx, align 4, !dbg !20, !tbaa !16 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !10 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !10 + %exitcond = icmp eq i32 %lftr.wideiv, %Length, !dbg !10 + br i1 %exitcond, label %for.end.loopexit, label %for.body, !dbg !10, !llvm.loop !12 + +for.end.loopexit: ; preds = %for.inc + br label %for.end + +for.end: ; preds = %for.end.loopexit, %entry + ret void, !dbg !24 +} + +attributes #0 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!7, !8} +!llvm.ident = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0", isOptimized: true, runtimeVersion: 6, emissionKind: LineTablesOnly, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2) +!1 = !DIFile(filename: "source.cpp", directory: ".") +!2 = !{} +!4 = distinct !DISubprogram(name: "test_switch", line: 1, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, retainedNodes: !2) +!5 = !DIFile(filename: "source.cpp", directory: ".") +!6 = !DISubroutineType(types: !2) +!7 = !{i32 2, !"Dwarf Version", i32 2} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{!"clang version 3.5.0"} +!10 = !DILocation(line: 3, column: 8, scope: !11) +!11 = distinct !DILexicalBlock(line: 3, column: 3, file: !1, scope: !4) +!12 = !{!12, !13, !13} +!13 = !{!"llvm.loop.vectorize.enable", i1 false} +!14 = !DILocation(line: 4, column: 5, scope: !15) +!15 = distinct !DILexicalBlock(line: 3, column: 36, file: !1, scope: !11) +!16 = !{!17, !17, i64 0} +!17 = !{!"int", !18, i64 0} +!18 = !{!"omnipotent char", !19, i64 0} +!19 = !{!"Simple C/C++ TBAA"} +!20 = !DILocation(line: 6, column: 7, scope: !21) +!21 = distinct !DILexicalBlock(line: 4, column: 18, file: !1, scope: !15) +!22 = !DILocation(line: 7, column: 5, scope: !21) +!23 = !DILocation(line: 9, column: 7, scope: !21) +!24 = !DILocation(line: 14, column: 1, scope: !4) diff --git a/llvm/test/Transforms/SLPVectorizer/X86/PR39774.ll b/llvm/test/Transforms/SLPVectorizer/X86/PR39774.ll index 8405117090b46..67717a54659c3 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/PR39774.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/PR39774.ll @@ -3,93 +3,185 @@ ; RUN: opt -slp-vectorizer -S < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=skylake -slp-threshold=-8 -slp-min-tree-size=6 | FileCheck %s --check-prefixes=ALL,FORCE_REDUCTION define void @Test(i32) { -; ALL-LABEL: @Test( -; ALL-NEXT: entry: -; ALL-NEXT: br label [[LOOP:%.*]] -; ALL: loop: -; ALL-NEXT: [[TMP1:%.*]] = phi <2 x i32> [ [[TMP11:%.*]], [[LOOP]] ], [ zeroinitializer, [[ENTRY:%.*]] ] -; ALL-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <8 x i32> -; ALL-NEXT: [[TMP2:%.*]] = extractelement <8 x i32> [[SHUFFLE]], i32 1 -; ALL-NEXT: [[TMP3:%.*]] = add <8 x i32> , [[SHUFFLE]] -; ALL-NEXT: [[VAL_1:%.*]] = and i32 [[TMP2]], undef -; ALL-NEXT: [[VAL_2:%.*]] = and i32 [[VAL_1]], [[TMP0:%.*]] -; ALL-NEXT: [[VAL_3:%.*]] = and i32 [[VAL_2]], [[TMP0]] -; ALL-NEXT: [[VAL_4:%.*]] = and i32 [[VAL_3]], [[TMP0]] -; ALL-NEXT: [[VAL_5:%.*]] = and i32 [[VAL_4]], [[TMP0]] -; ALL-NEXT: [[VAL_7:%.*]] = and i32 [[VAL_5]], undef -; ALL-NEXT: [[VAL_8:%.*]] = and i32 [[VAL_7]], [[TMP0]] -; ALL-NEXT: [[VAL_9:%.*]] = and i32 [[VAL_8]], [[TMP0]] -; ALL-NEXT: [[VAL_10:%.*]] = and i32 [[VAL_9]], [[TMP0]] -; ALL-NEXT: [[VAL_12:%.*]] = and i32 [[VAL_10]], undef -; ALL-NEXT: [[VAL_13:%.*]] = and i32 [[VAL_12]], [[TMP0]] -; ALL-NEXT: [[VAL_14:%.*]] = and i32 [[VAL_13]], [[TMP0]] -; ALL-NEXT: [[VAL_15:%.*]] = and i32 [[VAL_14]], [[TMP0]] -; ALL-NEXT: [[VAL_16:%.*]] = and i32 [[VAL_15]], [[TMP0]] -; ALL-NEXT: [[VAL_17:%.*]] = and i32 [[VAL_16]], [[TMP0]] -; ALL-NEXT: [[VAL_19:%.*]] = and i32 [[VAL_17]], undef -; ALL-NEXT: [[VAL_21:%.*]] = and i32 [[VAL_19]], undef -; ALL-NEXT: [[VAL_22:%.*]] = and i32 [[VAL_21]], [[TMP0]] -; ALL-NEXT: [[VAL_23:%.*]] = and i32 [[VAL_22]], [[TMP0]] -; ALL-NEXT: [[VAL_24:%.*]] = and i32 [[VAL_23]], [[TMP0]] -; ALL-NEXT: [[VAL_25:%.*]] = and i32 [[VAL_24]], [[TMP0]] -; ALL-NEXT: [[VAL_26:%.*]] = and i32 [[VAL_25]], [[TMP0]] -; ALL-NEXT: [[VAL_27:%.*]] = and i32 [[VAL_26]], [[TMP0]] -; ALL-NEXT: [[VAL_28:%.*]] = and i32 [[VAL_27]], [[TMP0]] -; ALL-NEXT: [[VAL_29:%.*]] = and i32 [[VAL_28]], [[TMP0]] -; ALL-NEXT: [[VAL_30:%.*]] = and i32 [[VAL_29]], [[TMP0]] -; ALL-NEXT: [[VAL_31:%.*]] = and i32 [[VAL_30]], [[TMP0]] -; ALL-NEXT: [[VAL_32:%.*]] = and i32 [[VAL_31]], [[TMP0]] -; ALL-NEXT: [[VAL_33:%.*]] = and i32 [[VAL_32]], [[TMP0]] -; ALL-NEXT: [[VAL_35:%.*]] = and i32 [[VAL_33]], undef -; ALL-NEXT: [[VAL_36:%.*]] = and i32 [[VAL_35]], [[TMP0]] -; ALL-NEXT: [[VAL_37:%.*]] = and i32 [[VAL_36]], [[TMP0]] -; ALL-NEXT: [[VAL_38:%.*]] = and i32 [[VAL_37]], [[TMP0]] -; ALL-NEXT: [[VAL_40:%.*]] = and i32 [[VAL_38]], undef -; ALL-NEXT: [[TMP4:%.*]] = insertelement <2 x i32> undef, i32 [[VAL_40]], i32 0 -; ALL-NEXT: [[TMP5:%.*]] = insertelement <2 x i32> [[TMP4]], i32 [[TMP2]], i32 1 -; ALL-NEXT: [[TMP6:%.*]] = extractelement <8 x i32> [[TMP3]], i32 7 -; ALL-NEXT: [[TMP7:%.*]] = insertelement <2 x i32> undef, i32 [[TMP6]], i32 0 -; ALL-NEXT: [[TMP8:%.*]] = insertelement <2 x i32> [[TMP7]], i32 14910, i32 1 -; ALL-NEXT: [[TMP9:%.*]] = and <2 x i32> [[TMP5]], [[TMP8]] -; ALL-NEXT: [[TMP10:%.*]] = add <2 x i32> [[TMP5]], [[TMP8]] -; ALL-NEXT: [[TMP11]] = shufflevector <2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> -; ALL-NEXT: [[RDX_SHUF:%.*]] = shufflevector <8 x i32> [[TMP3]], <8 x i32> undef, <8 x i32> -; ALL-NEXT: [[BIN_RDX:%.*]] = and <8 x i32> [[TMP3]], [[RDX_SHUF]] -; ALL-NEXT: [[RDX_SHUF1:%.*]] = shufflevector <8 x i32> [[BIN_RDX]], <8 x i32> undef, <8 x i32> -; ALL-NEXT: [[BIN_RDX2:%.*]] = and <8 x i32> [[BIN_RDX]], [[RDX_SHUF1]] -; ALL-NEXT: [[RDX_SHUF3:%.*]] = shufflevector <8 x i32> [[BIN_RDX2]], <8 x i32> undef, <8 x i32> -; ALL-NEXT: [[BIN_RDX4:%.*]] = and <8 x i32> [[BIN_RDX2]], [[RDX_SHUF3]] -; ALL-NEXT: [[TMP12:%.*]] = extractelement <8 x i32> [[BIN_RDX4]], i32 0 -; ALL-NEXT: [[OP_EXTRA:%.*]] = and i32 [[TMP12]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA5:%.*]] = and i32 [[OP_EXTRA]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA6:%.*]] = and i32 [[OP_EXTRA5]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA7:%.*]] = and i32 [[OP_EXTRA6]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA8:%.*]] = and i32 [[OP_EXTRA7]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA9:%.*]] = and i32 [[OP_EXTRA8]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA10:%.*]] = and i32 [[OP_EXTRA9]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA11:%.*]] = and i32 [[OP_EXTRA10]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA12:%.*]] = and i32 [[OP_EXTRA11]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA13:%.*]] = and i32 [[OP_EXTRA12]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA14:%.*]] = and i32 [[OP_EXTRA13]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA15:%.*]] = and i32 [[OP_EXTRA14]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA16:%.*]] = and i32 [[OP_EXTRA15]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA17:%.*]] = and i32 [[OP_EXTRA16]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA18:%.*]] = and i32 [[OP_EXTRA17]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA19:%.*]] = and i32 [[OP_EXTRA18]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA20:%.*]] = and i32 [[OP_EXTRA19]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA21:%.*]] = and i32 [[OP_EXTRA20]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA22:%.*]] = and i32 [[OP_EXTRA21]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA23:%.*]] = and i32 [[OP_EXTRA22]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA24:%.*]] = and i32 [[OP_EXTRA23]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA25:%.*]] = and i32 [[OP_EXTRA24]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA26:%.*]] = and i32 [[OP_EXTRA25]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA27:%.*]] = and i32 [[OP_EXTRA26]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA28:%.*]] = and i32 [[OP_EXTRA27]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA29:%.*]] = and i32 [[OP_EXTRA28]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA30:%.*]] = and i32 [[OP_EXTRA29]], [[TMP0]] -; ALL-NEXT: [[OP_EXTRA31:%.*]] = and i32 [[OP_EXTRA30]], [[TMP2]] -; ALL-NEXT: [[TMP13:%.*]] = extractelement <2 x i32> [[TMP11]], i32 0 -; ALL-NEXT: br label [[LOOP]] +; CHECK-LABEL: @Test( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[TMP1:%.*]] = phi <2 x i32> [ [[TMP15:%.*]], [[LOOP]] ], [ zeroinitializer, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <8 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <8 x i32> [[SHUFFLE]], i32 1 +; CHECK-NEXT: [[TMP3:%.*]] = add <8 x i32> , [[SHUFFLE]] +; CHECK-NEXT: [[VAL_1:%.*]] = and i32 [[TMP2]], undef +; CHECK-NEXT: [[VAL_2:%.*]] = and i32 [[VAL_1]], [[TMP0:%.*]] +; CHECK-NEXT: [[VAL_3:%.*]] = and i32 [[VAL_2]], [[TMP0]] +; CHECK-NEXT: [[VAL_4:%.*]] = and i32 [[VAL_3]], [[TMP0]] +; CHECK-NEXT: [[VAL_5:%.*]] = and i32 [[VAL_4]], [[TMP0]] +; CHECK-NEXT: [[VAL_7:%.*]] = and i32 [[VAL_5]], undef +; CHECK-NEXT: [[VAL_8:%.*]] = and i32 [[VAL_7]], [[TMP0]] +; CHECK-NEXT: [[VAL_9:%.*]] = and i32 [[VAL_8]], [[TMP0]] +; CHECK-NEXT: [[VAL_10:%.*]] = and i32 [[VAL_9]], [[TMP0]] +; CHECK-NEXT: [[VAL_12:%.*]] = and i32 [[VAL_10]], undef +; CHECK-NEXT: [[VAL_13:%.*]] = and i32 [[VAL_12]], [[TMP0]] +; CHECK-NEXT: [[VAL_14:%.*]] = and i32 [[VAL_13]], [[TMP0]] +; CHECK-NEXT: [[VAL_15:%.*]] = and i32 [[VAL_14]], [[TMP0]] +; CHECK-NEXT: [[VAL_16:%.*]] = and i32 [[VAL_15]], [[TMP0]] +; CHECK-NEXT: [[VAL_17:%.*]] = and i32 [[VAL_16]], [[TMP0]] +; CHECK-NEXT: [[VAL_19:%.*]] = and i32 [[VAL_17]], undef +; CHECK-NEXT: [[VAL_21:%.*]] = and i32 [[VAL_19]], undef +; CHECK-NEXT: [[VAL_22:%.*]] = and i32 [[VAL_21]], [[TMP0]] +; CHECK-NEXT: [[VAL_23:%.*]] = and i32 [[VAL_22]], [[TMP0]] +; CHECK-NEXT: [[VAL_24:%.*]] = and i32 [[VAL_23]], [[TMP0]] +; CHECK-NEXT: [[VAL_25:%.*]] = and i32 [[VAL_24]], [[TMP0]] +; CHECK-NEXT: [[VAL_26:%.*]] = and i32 [[VAL_25]], [[TMP0]] +; CHECK-NEXT: [[VAL_27:%.*]] = and i32 [[VAL_26]], [[TMP0]] +; CHECK-NEXT: [[VAL_28:%.*]] = and i32 [[VAL_27]], [[TMP0]] +; CHECK-NEXT: [[VAL_29:%.*]] = and i32 [[VAL_28]], [[TMP0]] +; CHECK-NEXT: [[VAL_30:%.*]] = and i32 [[VAL_29]], [[TMP0]] +; CHECK-NEXT: [[VAL_31:%.*]] = and i32 [[VAL_30]], [[TMP0]] +; CHECK-NEXT: [[VAL_32:%.*]] = and i32 [[VAL_31]], [[TMP0]] +; CHECK-NEXT: [[VAL_33:%.*]] = and i32 [[VAL_32]], [[TMP0]] +; CHECK-NEXT: [[VAL_35:%.*]] = and i32 [[VAL_33]], undef +; CHECK-NEXT: [[VAL_36:%.*]] = and i32 [[VAL_35]], [[TMP0]] +; CHECK-NEXT: [[VAL_37:%.*]] = and i32 [[VAL_36]], [[TMP0]] +; CHECK-NEXT: [[VAL_38:%.*]] = and i32 [[VAL_37]], [[TMP0]] +; CHECK-NEXT: [[VAL_40:%.*]] = and i32 [[VAL_38]], undef +; CHECK-NEXT: [[RDX_SHUF:%.*]] = shufflevector <8 x i32> [[TMP3]], <8 x i32> undef, <8 x i32> +; CHECK-NEXT: [[BIN_RDX:%.*]] = and <8 x i32> [[TMP3]], [[RDX_SHUF]] +; CHECK-NEXT: [[RDX_SHUF1:%.*]] = shufflevector <8 x i32> [[BIN_RDX]], <8 x i32> undef, <8 x i32> +; CHECK-NEXT: [[BIN_RDX2:%.*]] = and <8 x i32> [[BIN_RDX]], [[RDX_SHUF1]] +; CHECK-NEXT: [[RDX_SHUF3:%.*]] = shufflevector <8 x i32> [[BIN_RDX2]], <8 x i32> undef, <8 x i32> +; CHECK-NEXT: [[BIN_RDX4:%.*]] = and <8 x i32> [[BIN_RDX2]], [[RDX_SHUF3]] +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <8 x i32> [[BIN_RDX4]], i32 0 +; CHECK-NEXT: [[OP_EXTRA:%.*]] = and i32 [[TMP4]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA5:%.*]] = and i32 [[OP_EXTRA]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA6:%.*]] = and i32 [[OP_EXTRA5]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA7:%.*]] = and i32 [[OP_EXTRA6]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA8:%.*]] = and i32 [[OP_EXTRA7]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA9:%.*]] = and i32 [[OP_EXTRA8]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA10:%.*]] = and i32 [[OP_EXTRA9]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA11:%.*]] = and i32 [[OP_EXTRA10]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA12:%.*]] = and i32 [[OP_EXTRA11]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA13:%.*]] = and i32 [[OP_EXTRA12]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA14:%.*]] = and i32 [[OP_EXTRA13]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA15:%.*]] = and i32 [[OP_EXTRA14]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA16:%.*]] = and i32 [[OP_EXTRA15]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA17:%.*]] = and i32 [[OP_EXTRA16]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA18:%.*]] = and i32 [[OP_EXTRA17]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA19:%.*]] = and i32 [[OP_EXTRA18]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA20:%.*]] = and i32 [[OP_EXTRA19]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA21:%.*]] = and i32 [[OP_EXTRA20]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA22:%.*]] = and i32 [[OP_EXTRA21]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA23:%.*]] = and i32 [[OP_EXTRA22]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA24:%.*]] = and i32 [[OP_EXTRA23]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA25:%.*]] = and i32 [[OP_EXTRA24]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA26:%.*]] = and i32 [[OP_EXTRA25]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA27:%.*]] = and i32 [[OP_EXTRA26]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA28:%.*]] = and i32 [[OP_EXTRA27]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA29:%.*]] = and i32 [[OP_EXTRA28]], [[TMP0]] +; CHECK-NEXT: [[OP_EXTRA30:%.*]] = and i32 [[OP_EXTRA29]], [[TMP0]] +; CHECK-NEXT: [[VAL_42:%.*]] = and i32 [[VAL_40]], undef +; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x i32> undef, i32 [[OP_EXTRA30]], i32 0 +; CHECK-NEXT: [[TMP6:%.*]] = insertelement <2 x i32> [[TMP5]], i32 [[TMP2]], i32 1 +; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x i32> undef, i32 [[TMP2]], i32 0 +; CHECK-NEXT: [[TMP8:%.*]] = insertelement <2 x i32> [[TMP7]], i32 14910, i32 1 +; CHECK-NEXT: [[TMP9:%.*]] = and <2 x i32> [[TMP6]], [[TMP8]] +; CHECK-NEXT: [[TMP10:%.*]] = add <2 x i32> [[TMP6]], [[TMP8]] +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> +; CHECK-NEXT: [[TMP12:%.*]] = extractelement <2 x i32> [[TMP11]], i32 0 +; CHECK-NEXT: [[TMP13:%.*]] = insertelement <2 x i32> undef, i32 [[TMP12]], i32 0 +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x i32> [[TMP11]], i32 1 +; CHECK-NEXT: [[TMP15]] = insertelement <2 x i32> [[TMP13]], i32 [[TMP14]], i32 1 +; CHECK-NEXT: br label [[LOOP]] +; +; FORCE_REDUCTION-LABEL: @Test( +; FORCE_REDUCTION-NEXT: entry: +; FORCE_REDUCTION-NEXT: br label [[LOOP:%.*]] +; FORCE_REDUCTION: loop: +; FORCE_REDUCTION-NEXT: [[TMP1:%.*]] = phi <2 x i32> [ [[TMP13:%.*]], [[LOOP]] ], [ zeroinitializer, [[ENTRY:%.*]] ] +; FORCE_REDUCTION-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <4 x i32> +; FORCE_REDUCTION-NEXT: [[TMP2:%.*]] = extractelement <4 x i32> [[SHUFFLE]], i32 1 +; FORCE_REDUCTION-NEXT: [[TMP3:%.*]] = add <4 x i32> , [[SHUFFLE]] +; FORCE_REDUCTION-NEXT: [[VAL_1:%.*]] = and i32 [[TMP2]], undef +; FORCE_REDUCTION-NEXT: [[VAL_2:%.*]] = and i32 [[VAL_1]], [[TMP0:%.*]] +; FORCE_REDUCTION-NEXT: [[VAL_3:%.*]] = and i32 [[VAL_2]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_4:%.*]] = and i32 [[VAL_3]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_5:%.*]] = and i32 [[VAL_4]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_7:%.*]] = and i32 [[VAL_5]], undef +; FORCE_REDUCTION-NEXT: [[VAL_8:%.*]] = and i32 [[VAL_7]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_9:%.*]] = and i32 [[VAL_8]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_10:%.*]] = and i32 [[VAL_9]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_12:%.*]] = and i32 [[VAL_10]], undef +; FORCE_REDUCTION-NEXT: [[VAL_13:%.*]] = and i32 [[VAL_12]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_14:%.*]] = and i32 [[VAL_13]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_15:%.*]] = and i32 [[VAL_14]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_16:%.*]] = and i32 [[VAL_15]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_17:%.*]] = and i32 [[VAL_16]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_19:%.*]] = and i32 [[VAL_17]], undef +; FORCE_REDUCTION-NEXT: [[VAL_20:%.*]] = add i32 [[TMP2]], 1496 +; FORCE_REDUCTION-NEXT: [[VAL_21:%.*]] = and i32 [[VAL_19]], [[VAL_20]] +; FORCE_REDUCTION-NEXT: [[VAL_22:%.*]] = and i32 [[VAL_21]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_23:%.*]] = and i32 [[VAL_22]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_24:%.*]] = and i32 [[VAL_23]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_25:%.*]] = and i32 [[VAL_24]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_26:%.*]] = and i32 [[VAL_25]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_27:%.*]] = and i32 [[VAL_26]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_28:%.*]] = and i32 [[VAL_27]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_29:%.*]] = and i32 [[VAL_28]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_30:%.*]] = and i32 [[VAL_29]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_31:%.*]] = and i32 [[VAL_30]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_32:%.*]] = and i32 [[VAL_31]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_33:%.*]] = and i32 [[VAL_32]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_34:%.*]] = add i32 [[TMP2]], 8555 +; FORCE_REDUCTION-NEXT: [[VAL_35:%.*]] = and i32 [[VAL_33]], [[VAL_34]] +; FORCE_REDUCTION-NEXT: [[VAL_36:%.*]] = and i32 [[VAL_35]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_37:%.*]] = and i32 [[VAL_36]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[RDX_SHUF:%.*]] = shufflevector <4 x i32> [[TMP3]], <4 x i32> undef, <4 x i32> +; FORCE_REDUCTION-NEXT: [[BIN_RDX:%.*]] = and <4 x i32> [[TMP3]], [[RDX_SHUF]] +; FORCE_REDUCTION-NEXT: [[RDX_SHUF1:%.*]] = shufflevector <4 x i32> [[BIN_RDX]], <4 x i32> undef, <4 x i32> +; FORCE_REDUCTION-NEXT: [[BIN_RDX2:%.*]] = and <4 x i32> [[BIN_RDX]], [[RDX_SHUF1]] +; FORCE_REDUCTION-NEXT: [[TMP4:%.*]] = extractelement <4 x i32> [[BIN_RDX2]], i32 0 +; FORCE_REDUCTION-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], [[VAL_20]] +; FORCE_REDUCTION-NEXT: [[TMP6:%.*]] = and i32 [[TMP5]], [[VAL_34]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA:%.*]] = and i32 [[TMP6]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA3:%.*]] = and i32 [[OP_EXTRA]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA4:%.*]] = and i32 [[OP_EXTRA3]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA5:%.*]] = and i32 [[OP_EXTRA4]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA6:%.*]] = and i32 [[OP_EXTRA5]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA7:%.*]] = and i32 [[OP_EXTRA6]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA8:%.*]] = and i32 [[OP_EXTRA7]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA9:%.*]] = and i32 [[OP_EXTRA8]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA10:%.*]] = and i32 [[OP_EXTRA9]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA11:%.*]] = and i32 [[OP_EXTRA10]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA12:%.*]] = and i32 [[OP_EXTRA11]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA13:%.*]] = and i32 [[OP_EXTRA12]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA14:%.*]] = and i32 [[OP_EXTRA13]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA15:%.*]] = and i32 [[OP_EXTRA14]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA16:%.*]] = and i32 [[OP_EXTRA15]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA17:%.*]] = and i32 [[OP_EXTRA16]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA18:%.*]] = and i32 [[OP_EXTRA17]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA19:%.*]] = and i32 [[OP_EXTRA18]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA20:%.*]] = and i32 [[OP_EXTRA19]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA21:%.*]] = and i32 [[OP_EXTRA20]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA22:%.*]] = and i32 [[OP_EXTRA21]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA23:%.*]] = and i32 [[OP_EXTRA22]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA24:%.*]] = and i32 [[OP_EXTRA23]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA25:%.*]] = and i32 [[OP_EXTRA24]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA26:%.*]] = and i32 [[OP_EXTRA25]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA27:%.*]] = and i32 [[OP_EXTRA26]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA28:%.*]] = and i32 [[OP_EXTRA27]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[OP_EXTRA29:%.*]] = and i32 [[OP_EXTRA28]], [[TMP2]] +; FORCE_REDUCTION-NEXT: [[VAL_38:%.*]] = and i32 [[VAL_37]], [[TMP0]] +; FORCE_REDUCTION-NEXT: [[VAL_39:%.*]] = add i32 [[TMP2]], 12529 +; FORCE_REDUCTION-NEXT: [[VAL_40:%.*]] = and i32 [[OP_EXTRA29]], [[VAL_39]] +; FORCE_REDUCTION-NEXT: [[VAL_41:%.*]] = add i32 [[TMP2]], 13685 +; FORCE_REDUCTION-NEXT: [[TMP7:%.*]] = insertelement <2 x i32> undef, i32 [[VAL_40]], i32 0 +; FORCE_REDUCTION-NEXT: [[TMP8:%.*]] = insertelement <2 x i32> [[TMP7]], i32 [[TMP2]], i32 1 +; FORCE_REDUCTION-NEXT: [[TMP9:%.*]] = insertelement <2 x i32> undef, i32 [[VAL_41]], i32 0 +; FORCE_REDUCTION-NEXT: [[TMP10:%.*]] = insertelement <2 x i32> [[TMP9]], i32 14910, i32 1 +; FORCE_REDUCTION-NEXT: [[TMP11:%.*]] = and <2 x i32> [[TMP8]], [[TMP10]] +; FORCE_REDUCTION-NEXT: [[TMP12:%.*]] = add <2 x i32> [[TMP8]], [[TMP10]] +; FORCE_REDUCTION-NEXT: [[TMP13]] = shufflevector <2 x i32> [[TMP11]], <2 x i32> [[TMP12]], <2 x i32> +; FORCE_REDUCTION-NEXT: br label [[LOOP]] ; entry: br label %loop diff --git a/llvm/test/Transforms/SLPVectorizer/X86/PR40310.ll b/llvm/test/Transforms/SLPVectorizer/X86/PR40310.ll index 74e62e0e4ba2d..ad1434146a5b3 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/PR40310.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/PR40310.ll @@ -7,7 +7,7 @@ define void @mainTest(i32 %param, i32 * %vals, i32 %len) { ; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i32> , i32 [[PARAM:%.*]], i32 1 ; CHECK-NEXT: br label [[BCI_15:%.*]] ; CHECK: bci_15: -; CHECK-NEXT: [[TMP1:%.*]] = phi <2 x i32> [ [[TMP11:%.*]], [[BCI_15]] ], [ [[TMP0]], [[BCI_15_PREHEADER:%.*]] ] +; CHECK-NEXT: [[TMP1:%.*]] = phi <2 x i32> [ [[TMP7:%.*]], [[BCI_15]] ], [ [[TMP0]], [[BCI_15_PREHEADER:%.*]] ] ; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> undef, <16 x i32> ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <16 x i32> [[SHUFFLE]], i32 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <16 x i32> [[SHUFFLE]], i32 15 @@ -28,13 +28,6 @@ define void @mainTest(i32 %param, i32 * %vals, i32 %len) { ; CHECK-NEXT: [[V38:%.*]] = and i32 undef, [[V36]] ; CHECK-NEXT: [[V40:%.*]] = and i32 undef, [[V38]] ; CHECK-NEXT: [[V42:%.*]] = and i32 undef, [[V40]] -; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x i32> undef, i32 [[TMP2]], i32 0 -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <16 x i32> [[TMP4]], i32 0 -; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x i32> [[TMP5]], i32 [[TMP6]], i32 1 -; CHECK-NEXT: [[TMP8:%.*]] = insertelement <2 x i32> , i32 [[V42]], i32 1 -; CHECK-NEXT: [[TMP9:%.*]] = add <2 x i32> [[TMP7]], [[TMP8]] -; CHECK-NEXT: [[TMP10:%.*]] = and <2 x i32> [[TMP7]], [[TMP8]] -; CHECK-NEXT: [[TMP11]] = shufflevector <2 x i32> [[TMP9]], <2 x i32> [[TMP10]], <2 x i32> ; CHECK-NEXT: [[RDX_SHUF:%.*]] = shufflevector <16 x i32> [[TMP4]], <16 x i32> undef, <16 x i32> ; CHECK-NEXT: [[BIN_RDX:%.*]] = and <16 x i32> [[TMP4]], [[RDX_SHUF]] ; CHECK-NEXT: [[RDX_SHUF1:%.*]] = shufflevector <16 x i32> [[BIN_RDX]], <16 x i32> undef, <16 x i32> @@ -43,9 +36,12 @@ define void @mainTest(i32 %param, i32 * %vals, i32 %len) { ; CHECK-NEXT: [[BIN_RDX4:%.*]] = and <16 x i32> [[BIN_RDX2]], [[RDX_SHUF3]] ; CHECK-NEXT: [[RDX_SHUF5:%.*]] = shufflevector <16 x i32> [[BIN_RDX4]], <16 x i32> undef, <16 x i32> ; CHECK-NEXT: [[BIN_RDX6:%.*]] = and <16 x i32> [[BIN_RDX4]], [[RDX_SHUF5]] -; CHECK-NEXT: [[TMP12:%.*]] = extractelement <16 x i32> [[BIN_RDX6]], i32 0 -; CHECK-NEXT: [[OP_EXTRA:%.*]] = and i32 [[TMP12]], [[TMP2]] -; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x i32> [[TMP11]], i32 1 +; CHECK-NEXT: [[TMP5:%.*]] = extractelement <16 x i32> [[BIN_RDX6]], i32 0 +; CHECK-NEXT: [[OP_EXTRA:%.*]] = and i32 [[TMP5]], [[TMP2]] +; CHECK-NEXT: [[V43:%.*]] = and i32 undef, [[V42]] +; CHECK-NEXT: [[V44:%.*]] = add i32 [[TMP2]], 16 +; CHECK-NEXT: [[TMP6:%.*]] = insertelement <2 x i32> undef, i32 [[V44]], i32 0 +; CHECK-NEXT: [[TMP7]] = insertelement <2 x i32> [[TMP6]], i32 [[OP_EXTRA]], i32 1 ; CHECK-NEXT: br i1 true, label [[BCI_15]], label [[LOOPEXIT:%.*]] ; CHECK: loopexit: ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/SROA/basictest.ll b/llvm/test/Transforms/SROA/basictest.ll index a72da6399f22c..2c5829d6fcecb 100644 --- a/llvm/test/Transforms/SROA/basictest.ll +++ b/llvm/test/Transforms/SROA/basictest.ll @@ -1745,6 +1745,55 @@ entry: ret void } +declare void @llvm.lifetime.start.isVoid.i64.p0i8(i64, [10 x float]* nocapture) +declare void @llvm.lifetime.end.isVoid.i64.p0i8(i64, [10 x float]* nocapture) +@array = dso_local global [10 x float] undef, align 4 + +define void @test29(i32 %num, i32 %tid) { +; CHECK-LABEL: @test29( +; CHECK-NOT: alloca [10 x float] +; CHECK: ret void + +entry: + %ra = alloca [10 x float], align 4 + call void @llvm.lifetime.start.isVoid.i64.p0i8(i64 40, [10 x float]* nonnull %ra) + + %cmp1 = icmp sgt i32 %num, 0 + br i1 %cmp1, label %bb1, label %bb7 + +bb1: + %tobool = icmp eq i32 %tid, 0 + %conv.i = zext i32 %tid to i64 + %0 = bitcast [10 x float]* %ra to i32* + %1 = load i32, i32* %0, align 4 + %arrayidx5 = getelementptr inbounds [10 x float], [10 x float]* @array, i64 0, i64 %conv.i + %2 = bitcast float* %arrayidx5 to i32* + br label %bb2 + +bb2: + %i.02 = phi i32 [ %num, %bb1 ], [ %sub, %bb5 ] + br i1 %tobool, label %bb3, label %bb4 + +bb3: + br label %bb5 + +bb4: + store i32 %1, i32* %2, align 4 + br label %bb5 + +bb5: + %sub = add i32 %i.02, -1 + %cmp = icmp sgt i32 %sub, 0 + br i1 %cmp, label %bb2, label %bb6 + +bb6: + br label %bb7 + +bb7: + call void @llvm.lifetime.end.isVoid.i64.p0i8(i64 40, [10 x float]* nonnull %ra) + ret void +} + !0 = !{!1, !1, i64 0, i64 1} !1 = !{!2, i64 1, !"type_0"} !2 = !{!"root"} diff --git a/llvm/test/tools/llvm-dlltool/coff-weak-exports.def b/llvm/test/tools/llvm-dlltool/coff-weak-exports.def index dbc59be8ae189..60f835233a555 100644 --- a/llvm/test/tools/llvm-dlltool/coff-weak-exports.def +++ b/llvm/test/tools/llvm-dlltool/coff-weak-exports.def @@ -1,5 +1,6 @@ ; RUN: llvm-dlltool -m i386:x86-64 --input-def %s --output-lib %t.a ; RUN: llvm-nm %t.a | FileCheck %s +; RUN: llvm-readobj %t.a | FileCheck -check-prefix=ARCH %s LIBRARY test.dll EXPORTS @@ -26,3 +27,5 @@ ImpLibName3 = kernel32.Sleep ; CHECK-NEXT: W __imp_ImpLibName2 ; CHECK: T ImpLibName3 ; CHECK-NEXT: T __imp_ImpLibName3 + +; ARCH-NOT: unknown arch diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s index 07c68ab2618f1..0b2ae5f8e7a4f 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_loclists_startx_length.s @@ -6,7 +6,7 @@ # the final version which uses ULEB128 and not the U32. # CHECK: .debug_loclists contents: -# CHECK-NEXT: 0x00000000: locations list header: length = 0x0000000f, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 +# CHECK-NEXT: 0x00000000: locations list header: length = 0x0000000e, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000 # CHECK-NEXT: 0x00000000: # CHECK-NEXT: Addr idx 1 (w/ length 16): DW_OP_reg5 RDI @@ -21,7 +21,7 @@ .byte 3 # DW_LLE_startx_length .byte 0x01 # Index .uleb128 0x10 # Length - .short 1 # Loc expr size + .byte 1 # Loc expr size .byte 85 # DW_OP_reg5 .byte 0 # DW_LLE_end_of_list .Ldebug_loclist_table_end0: diff --git a/llvm/test/tools/llvm-mca/X86/Atom/resources-x87.s b/llvm/test/tools/llvm-mca/X86/Atom/resources-x87.s index c7a990a892eb6..eda0fdebb7d3c 100644 --- a/llvm/test/tools/llvm-mca/X86/Atom/resources-x87.s +++ b/llvm/test/tools/llvm-mca/X86/Atom/resources-x87.s @@ -5,7 +5,7 @@ f2xm1 fabs -fadd %st(0), %st(1) +fadd %st, %st(1) fadd %st(2) fadds (%ecx) faddl (%ecx) @@ -21,14 +21,14 @@ fchs fnclex -fcmovb %st(1), %st(0) -fcmovbe %st(1), %st(0) -fcmove %st(1), %st(0) -fcmovnb %st(1), %st(0) -fcmovnbe %st(1), %st(0) -fcmovne %st(1), %st(0) -fcmovnu %st(1), %st(0) -fcmovu %st(1), %st(0) +fcmovb %st(1), %st +fcmovbe %st(1), %st +fcmove %st(1), %st +fcmovnb %st(1), %st +fcmovnbe %st(1), %st +fcmovne %st(1), %st +fcmovnu %st(1), %st +fcmovu %st(1), %st fcom %st(1) fcom %st(3) @@ -47,7 +47,7 @@ fcos fdecstp -fdiv %st(0), %st(1) +fdiv %st, %st(1) fdiv %st(2) fdivs (%ecx) fdivl (%eax) @@ -56,7 +56,7 @@ fdivp %st(2) fidivs (%ecx) fidivl (%eax) -fdivr %st(0), %st(1) +fdivr %st, %st(1) fdivr %st(2) fdivrs (%ecx) fdivrl (%eax) @@ -106,7 +106,7 @@ fldln2 fldpi fldz -fmul %st(0), %st(1) +fmul %st, %st(1) fmul %st(2) fmuls (%ecx) fmull (%eax) @@ -153,7 +153,7 @@ fnstsw (%eax) frstor (%eax) fsave (%eax) -fsub %st(0), %st(1) +fsub %st, %st(1) fsub %st(2) fsubs (%ecx) fsubl (%eax) @@ -162,7 +162,7 @@ fsubp %st(2) fisubs (%ecx) fisubl (%eax) -fsubr %st(0), %st(1) +fsubr %st, %st(1) fsubr %st(2) fsubrs (%ecx) fsubrl (%eax) @@ -208,26 +208,26 @@ fyl2xp1 # CHECK: [1] [2] [3] [4] [5] [6] Instructions: # CHECK-NEXT: 1 99 49.50 U f2xm1 # CHECK-NEXT: 1 1 1.00 U fabs -# CHECK-NEXT: 1 5 5.00 U fadd %st(0), %st(1) -# CHECK-NEXT: 1 5 5.00 U fadd %st(2) +# CHECK-NEXT: 1 5 5.00 U fadd %st, %st(1) +# CHECK-NEXT: 1 5 5.00 U fadd %st(2), %st # CHECK-NEXT: 1 5 5.00 * U fadds (%ecx) # CHECK-NEXT: 1 5 5.00 * U faddl (%ecx) -# CHECK-NEXT: 1 5 5.00 U faddp %st(1) -# CHECK-NEXT: 1 5 5.00 U faddp %st(2) +# CHECK-NEXT: 1 5 5.00 U faddp %st, %st(1) +# CHECK-NEXT: 1 5 5.00 U faddp %st, %st(2) # CHECK-NEXT: 1 5 5.00 * U fiadds (%ecx) # CHECK-NEXT: 1 5 5.00 * U fiaddl (%ecx) # CHECK-NEXT: 1 100 0.50 U fbld (%ecx) # CHECK-NEXT: 1 100 0.50 U fbstp (%eax) # CHECK-NEXT: 1 1 1.00 U fchs # CHECK-NEXT: 1 25 12.50 U fnclex -# CHECK-NEXT: 1 9 4.50 U fcmovb %st(1), %st(0) -# CHECK-NEXT: 1 9 4.50 U fcmovbe %st(1), %st(0) -# CHECK-NEXT: 1 9 4.50 U fcmove %st(1), %st(0) -# CHECK-NEXT: 1 9 4.50 U fcmovnb %st(1), %st(0) -# CHECK-NEXT: 1 9 4.50 U fcmovnbe %st(1), %st(0) -# CHECK-NEXT: 1 9 4.50 U fcmovne %st(1), %st(0) -# CHECK-NEXT: 1 9 4.50 U fcmovnu %st(1), %st(0) -# CHECK-NEXT: 1 9 4.50 U fcmovu %st(1), %st(0) +# CHECK-NEXT: 1 9 4.50 U fcmovb %st(1), %st +# CHECK-NEXT: 1 9 4.50 U fcmovbe %st(1), %st +# CHECK-NEXT: 1 9 4.50 U fcmove %st(1), %st +# CHECK-NEXT: 1 9 4.50 U fcmovnb %st(1), %st +# CHECK-NEXT: 1 9 4.50 U fcmovnbe %st(1), %st +# CHECK-NEXT: 1 9 4.50 U fcmovne %st(1), %st +# CHECK-NEXT: 1 9 4.50 U fcmovnu %st(1), %st +# CHECK-NEXT: 1 9 4.50 U fcmovu %st(1), %st # CHECK-NEXT: 1 5 5.00 U fcom %st(1) # CHECK-NEXT: 1 5 5.00 U fcom %st(3) # CHECK-NEXT: 1 5 5.00 U fcoms (%ecx) @@ -237,24 +237,24 @@ fyl2xp1 # CHECK-NEXT: 1 5 5.00 U fcomps (%ecx) # CHECK-NEXT: 1 5 5.00 U fcompl (%eax) # CHECK-NEXT: 1 1 1.00 U fcompp -# CHECK-NEXT: 1 9 4.50 U fcomi %st(3) -# CHECK-NEXT: 1 9 4.50 U fcompi %st(3) +# CHECK-NEXT: 1 9 4.50 U fcomi %st(3), %st +# CHECK-NEXT: 1 9 4.50 U fcompi %st(3), %st # CHECK-NEXT: 1 174 87.00 U fcos # CHECK-NEXT: 1 1 0.50 U fdecstp -# CHECK-NEXT: 1 34 17.00 U fdiv %st(0), %st(1) -# CHECK-NEXT: 1 34 17.00 U fdiv %st(2) +# CHECK-NEXT: 1 34 17.00 U fdiv %st, %st(1) +# CHECK-NEXT: 1 34 17.00 U fdiv %st(2), %st # CHECK-NEXT: 1 34 17.00 * U fdivs (%ecx) # CHECK-NEXT: 1 34 17.00 * U fdivl (%eax) -# CHECK-NEXT: 1 34 17.00 U fdivp %st(1) -# CHECK-NEXT: 1 34 17.00 U fdivp %st(2) +# CHECK-NEXT: 1 34 17.00 U fdivp %st, %st(1) +# CHECK-NEXT: 1 34 17.00 U fdivp %st, %st(2) # CHECK-NEXT: 1 34 17.00 * U fidivs (%ecx) # CHECK-NEXT: 1 34 17.00 * U fidivl (%eax) -# CHECK-NEXT: 1 34 17.00 U fdivr %st(0), %st(1) -# CHECK-NEXT: 1 34 17.00 U fdivr %st(2) +# CHECK-NEXT: 1 34 17.00 U fdivr %st, %st(1) +# CHECK-NEXT: 1 34 17.00 U fdivr %st(2), %st # CHECK-NEXT: 1 34 17.00 * U fdivrs (%ecx) # CHECK-NEXT: 1 34 17.00 * U fdivrl (%eax) -# CHECK-NEXT: 1 34 17.00 U fdivrp %st(1) -# CHECK-NEXT: 1 34 17.00 U fdivrp %st(2) +# CHECK-NEXT: 1 34 17.00 U fdivrp %st, %st(1) +# CHECK-NEXT: 1 34 17.00 U fdivrp %st, %st(2) # CHECK-NEXT: 1 34 17.00 * U fidivrs (%ecx) # CHECK-NEXT: 1 34 17.00 * U fidivrl (%eax) # CHECK-NEXT: 1 1 0.50 U ffree %st(0) @@ -288,12 +288,12 @@ fyl2xp1 # CHECK-NEXT: 1 10 5.00 U fldln2 # CHECK-NEXT: 1 10 5.00 U fldpi # CHECK-NEXT: 1 1 0.50 U fldz -# CHECK-NEXT: 1 4 4.00 U fmul %st(0), %st(1) -# CHECK-NEXT: 1 4 4.00 U fmul %st(2) +# CHECK-NEXT: 1 4 4.00 U fmul %st, %st(1) +# CHECK-NEXT: 1 4 4.00 U fmul %st(2), %st # CHECK-NEXT: 1 4 4.00 * U fmuls (%ecx) # CHECK-NEXT: 1 4 4.00 * U fmull (%eax) -# CHECK-NEXT: 1 4 4.00 U fmulp %st(1) -# CHECK-NEXT: 1 4 4.00 U fmulp %st(2) +# CHECK-NEXT: 1 4 4.00 U fmulp %st, %st(1) +# CHECK-NEXT: 1 4 4.00 U fmulp %st, %st(2) # CHECK-NEXT: 1 4 4.00 * U fimuls (%ecx) # CHECK-NEXT: 1 4 4.00 * U fimull (%eax) # CHECK-NEXT: 1 1 0.50 U fnop @@ -321,20 +321,20 @@ fyl2xp1 # CHECK-NEXT: 1 100 0.50 U frstor (%eax) # CHECK-NEXT: 1 1 0.50 U wait # CHECK-NEXT: 1 100 0.50 U fnsave (%eax) -# CHECK-NEXT: 1 5 5.00 U fsub %st(0), %st(1) -# CHECK-NEXT: 1 5 5.00 U fsub %st(2) +# CHECK-NEXT: 1 5 5.00 U fsub %st, %st(1) +# CHECK-NEXT: 1 5 5.00 U fsub %st(2), %st # CHECK-NEXT: 1 5 5.00 * U fsubs (%ecx) # CHECK-NEXT: 1 5 5.00 * U fsubl (%eax) -# CHECK-NEXT: 1 5 5.00 U fsubp %st(1) -# CHECK-NEXT: 1 5 5.00 U fsubp %st(2) +# CHECK-NEXT: 1 5 5.00 U fsubp %st, %st(1) +# CHECK-NEXT: 1 5 5.00 U fsubp %st, %st(2) # CHECK-NEXT: 1 5 5.00 * U fisubs (%ecx) # CHECK-NEXT: 1 5 5.00 * U fisubl (%eax) -# CHECK-NEXT: 1 5 5.00 U fsubr %st(0), %st(1) -# CHECK-NEXT: 1 5 5.00 U fsubr %st(2) +# CHECK-NEXT: 1 5 5.00 U fsubr %st, %st(1) +# CHECK-NEXT: 1 5 5.00 U fsubr %st(2), %st # CHECK-NEXT: 1 5 5.00 * U fsubrs (%ecx) # CHECK-NEXT: 1 5 5.00 * U fsubrl (%eax) -# CHECK-NEXT: 1 5 5.00 U fsubrp %st(1) -# CHECK-NEXT: 1 5 5.00 U fsubrp %st(2) +# CHECK-NEXT: 1 5 5.00 U fsubrp %st, %st(1) +# CHECK-NEXT: 1 5 5.00 U fsubrp %st, %st(2) # CHECK-NEXT: 1 5 5.00 * U fisubrs (%ecx) # CHECK-NEXT: 1 5 5.00 * U fisubrl (%eax) # CHECK-NEXT: 1 9 4.50 U ftst @@ -343,8 +343,8 @@ fyl2xp1 # CHECK-NEXT: 1 1 1.00 U fucomp %st(1) # CHECK-NEXT: 1 1 1.00 U fucomp %st(3) # CHECK-NEXT: 1 1 1.00 U fucompp -# CHECK-NEXT: 1 9 4.50 U fucomi %st(3) -# CHECK-NEXT: 1 9 4.50 U fucompi %st(3) +# CHECK-NEXT: 1 9 4.50 U fucomi %st(3), %st +# CHECK-NEXT: 1 9 4.50 U fucompi %st(3), %st # CHECK-NEXT: 1 1 0.50 U wait # CHECK-NEXT: 1 1 1.00 U fxam # CHECK-NEXT: 1 1 1.00 U fxch %st(1) @@ -367,26 +367,26 @@ fyl2xp1 # CHECK-NEXT: [0] [1] Instructions: # CHECK-NEXT: 49.50 49.50 f2xm1 # CHECK-NEXT: - 1.00 fabs -# CHECK-NEXT: 5.00 - fadd %st(0), %st(1) -# CHECK-NEXT: 5.00 - fadd %st(2) +# CHECK-NEXT: 5.00 - fadd %st, %st(1) +# CHECK-NEXT: 5.00 - fadd %st(2), %st # CHECK-NEXT: 5.00 - fadds (%ecx) # CHECK-NEXT: 5.00 - faddl (%ecx) -# CHECK-NEXT: 5.00 - faddp %st(1) -# CHECK-NEXT: 5.00 - faddp %st(2) +# CHECK-NEXT: 5.00 - faddp %st, %st(1) +# CHECK-NEXT: 5.00 - faddp %st, %st(2) # CHECK-NEXT: 5.00 - fiadds (%ecx) # CHECK-NEXT: 5.00 - fiaddl (%ecx) # CHECK-NEXT: 0.50 0.50 fbld (%ecx) # CHECK-NEXT: 0.50 0.50 fbstp (%eax) # CHECK-NEXT: - 1.00 fchs # CHECK-NEXT: 12.50 12.50 fnclex -# CHECK-NEXT: 4.50 4.50 fcmovb %st(1), %st(0) -# CHECK-NEXT: 4.50 4.50 fcmovbe %st(1), %st(0) -# CHECK-NEXT: 4.50 4.50 fcmove %st(1), %st(0) -# CHECK-NEXT: 4.50 4.50 fcmovnb %st(1), %st(0) -# CHECK-NEXT: 4.50 4.50 fcmovnbe %st(1), %st(0) -# CHECK-NEXT: 4.50 4.50 fcmovne %st(1), %st(0) -# CHECK-NEXT: 4.50 4.50 fcmovnu %st(1), %st(0) -# CHECK-NEXT: 4.50 4.50 fcmovu %st(1), %st(0) +# CHECK-NEXT: 4.50 4.50 fcmovb %st(1), %st +# CHECK-NEXT: 4.50 4.50 fcmovbe %st(1), %st +# CHECK-NEXT: 4.50 4.50 fcmove %st(1), %st +# CHECK-NEXT: 4.50 4.50 fcmovnb %st(1), %st +# CHECK-NEXT: 4.50 4.50 fcmovnbe %st(1), %st +# CHECK-NEXT: 4.50 4.50 fcmovne %st(1), %st +# CHECK-NEXT: 4.50 4.50 fcmovnu %st(1), %st +# CHECK-NEXT: 4.50 4.50 fcmovu %st(1), %st # CHECK-NEXT: 5.00 - fcom %st(1) # CHECK-NEXT: 5.00 - fcom %st(3) # CHECK-NEXT: 5.00 - fcoms (%ecx) @@ -396,24 +396,24 @@ fyl2xp1 # CHECK-NEXT: 5.00 - fcomps (%ecx) # CHECK-NEXT: 5.00 - fcompl (%eax) # CHECK-NEXT: - 1.00 fcompp -# CHECK-NEXT: 4.50 4.50 fcomi %st(3) -# CHECK-NEXT: 4.50 4.50 fcompi %st(3) +# CHECK-NEXT: 4.50 4.50 fcomi %st(3), %st +# CHECK-NEXT: 4.50 4.50 fcompi %st(3), %st # CHECK-NEXT: 87.00 87.00 fcos # CHECK-NEXT: 0.50 0.50 fdecstp -# CHECK-NEXT: 17.00 17.00 fdiv %st(0), %st(1) -# CHECK-NEXT: 17.00 17.00 fdiv %st(2) +# CHECK-NEXT: 17.00 17.00 fdiv %st, %st(1) +# CHECK-NEXT: 17.00 17.00 fdiv %st(2), %st # CHECK-NEXT: 17.00 17.00 fdivs (%ecx) # CHECK-NEXT: 17.00 17.00 fdivl (%eax) -# CHECK-NEXT: 17.00 17.00 fdivp %st(1) -# CHECK-NEXT: 17.00 17.00 fdivp %st(2) +# CHECK-NEXT: 17.00 17.00 fdivp %st, %st(1) +# CHECK-NEXT: 17.00 17.00 fdivp %st, %st(2) # CHECK-NEXT: 17.00 17.00 fidivs (%ecx) # CHECK-NEXT: 17.00 17.00 fidivl (%eax) -# CHECK-NEXT: 17.00 17.00 fdivr %st(0), %st(1) -# CHECK-NEXT: 17.00 17.00 fdivr %st(2) +# CHECK-NEXT: 17.00 17.00 fdivr %st, %st(1) +# CHECK-NEXT: 17.00 17.00 fdivr %st(2), %st # CHECK-NEXT: 17.00 17.00 fdivrs (%ecx) # CHECK-NEXT: 17.00 17.00 fdivrl (%eax) -# CHECK-NEXT: 17.00 17.00 fdivrp %st(1) -# CHECK-NEXT: 17.00 17.00 fdivrp %st(2) +# CHECK-NEXT: 17.00 17.00 fdivrp %st, %st(1) +# CHECK-NEXT: 17.00 17.00 fdivrp %st, %st(2) # CHECK-NEXT: 17.00 17.00 fidivrs (%ecx) # CHECK-NEXT: 17.00 17.00 fidivrl (%eax) # CHECK-NEXT: 0.50 0.50 ffree %st(0) @@ -447,12 +447,12 @@ fyl2xp1 # CHECK-NEXT: 5.00 5.00 fldln2 # CHECK-NEXT: 5.00 5.00 fldpi # CHECK-NEXT: 0.50 0.50 fldz -# CHECK-NEXT: 4.00 - fmul %st(0), %st(1) -# CHECK-NEXT: 4.00 - fmul %st(2) +# CHECK-NEXT: 4.00 - fmul %st, %st(1) +# CHECK-NEXT: 4.00 - fmul %st(2), %st # CHECK-NEXT: 4.00 - fmuls (%ecx) # CHECK-NEXT: 4.00 - fmull (%eax) -# CHECK-NEXT: 4.00 - fmulp %st(1) -# CHECK-NEXT: 4.00 - fmulp %st(2) +# CHECK-NEXT: 4.00 - fmulp %st, %st(1) +# CHECK-NEXT: 4.00 - fmulp %st, %st(2) # CHECK-NEXT: 4.00 - fimuls (%ecx) # CHECK-NEXT: 4.00 - fimull (%eax) # CHECK-NEXT: 0.50 0.50 fnop @@ -480,20 +480,20 @@ fyl2xp1 # CHECK-NEXT: 0.50 0.50 frstor (%eax) # CHECK-NEXT: 0.50 0.50 wait # CHECK-NEXT: 0.50 0.50 fnsave (%eax) -# CHECK-NEXT: 5.00 - fsub %st(0), %st(1) -# CHECK-NEXT: 5.00 - fsub %st(2) +# CHECK-NEXT: 5.00 - fsub %st, %st(1) +# CHECK-NEXT: 5.00 - fsub %st(2), %st # CHECK-NEXT: 5.00 - fsubs (%ecx) # CHECK-NEXT: 5.00 - fsubl (%eax) -# CHECK-NEXT: 5.00 - fsubp %st(1) -# CHECK-NEXT: 5.00 - fsubp %st(2) +# CHECK-NEXT: 5.00 - fsubp %st, %st(1) +# CHECK-NEXT: 5.00 - fsubp %st, %st(2) # CHECK-NEXT: 5.00 - fisubs (%ecx) # CHECK-NEXT: 5.00 - fisubl (%eax) -# CHECK-NEXT: 5.00 - fsubr %st(0), %st(1) -# CHECK-NEXT: 5.00 - fsubr %st(2) +# CHECK-NEXT: 5.00 - fsubr %st, %st(1) +# CHECK-NEXT: 5.00 - fsubr %st(2), %st # CHECK-NEXT: 5.00 - fsubrs (%ecx) # CHECK-NEXT: 5.00 - fsubrl (%eax) -# CHECK-NEXT: 5.00 - fsubrp %st(1) -# CHECK-NEXT: 5.00 - fsubrp %st(2) +# CHECK-NEXT: 5.00 - fsubrp %st, %st(1) +# CHECK-NEXT: 5.00 - fsubrp %st, %st(2) # CHECK-NEXT: 5.00 - fisubrs (%ecx) # CHECK-NEXT: 5.00 - fisubrl (%eax) # CHECK-NEXT: 4.50 4.50 ftst @@ -502,8 +502,8 @@ fyl2xp1 # CHECK-NEXT: - 1.00 fucomp %st(1) # CHECK-NEXT: - 1.00 fucomp %st(3) # CHECK-NEXT: - 1.00 fucompp -# CHECK-NEXT: 4.50 4.50 fucomi %st(3) -# CHECK-NEXT: 4.50 4.50 fucompi %st(3) +# CHECK-NEXT: 4.50 4.50 fucomi %st(3), %st +# CHECK-NEXT: 4.50 4.50 fucompi %st(3), %st # CHECK-NEXT: 0.50 0.50 wait # CHECK-NEXT: 1.00 - fxam # CHECK-NEXT: 1.00 1.00 fxch %st(1) diff --git a/llvm/test/tools/llvm-mca/X86/BdVer2/resources-x87.s b/llvm/test/tools/llvm-mca/X86/BdVer2/resources-x87.s index ad72714c74c1b..4cdddf01104b0 100644 --- a/llvm/test/tools/llvm-mca/X86/BdVer2/resources-x87.s +++ b/llvm/test/tools/llvm-mca/X86/BdVer2/resources-x87.s @@ -5,7 +5,7 @@ f2xm1 fabs -fadd %st(0), %st(1) +fadd %st, %st(1) fadd %st(2) fadds (%ecx) faddl (%ecx) @@ -21,14 +21,14 @@ fchs fnclex -fcmovb %st(1), %st(0) -fcmovbe %st(1), %st(0) -fcmove %st(1), %st(0) -fcmovnb %st(1), %st(0) -fcmovnbe %st(1), %st(0) -fcmovne %st(1), %st(0) -fcmovnu %st(1), %st(0) -fcmovu %st(1), %st(0) +fcmovb %st(1), %st +fcmovbe %st(1), %st +fcmove %st(1), %st +fcmovnb %st(1), %st +fcmovnbe %st(1), %st +fcmovne %st(1), %st +fcmovnu %st(1), %st +fcmovu %st(1), %st fcom %st(1) fcom %st(3) @@ -47,7 +47,7 @@ fcos fdecstp -fdiv %st(0), %st(1) +fdiv %st, %st(1) fdiv %st(2) fdivs (%ecx) fdivl (%eax) @@ -56,7 +56,7 @@ fdivp %st(2) fidivs (%ecx) fidivl (%eax) -fdivr %st(0), %st(1) +fdivr %st, %st(1) fdivr %st(2) fdivrs (%ecx) fdivrl (%eax) @@ -106,7 +106,7 @@ fldln2 fldpi fldz -fmul %st(0), %st(1) +fmul %st, %st(1) fmul %st(2) fmuls (%ecx) fmull (%eax) @@ -153,7 +153,7 @@ fnstsw (%eax) frstor (%eax) fsave (%eax) -fsub %st(0), %st(1) +fsub %st, %st(1) fsub %st(2) fsubs (%ecx) fsubl (%eax) @@ -162,7 +162,7 @@ fsubp %st(2) fisubs (%ecx) fisubl (%eax) -fsubr %st(0), %st(1) +fsubr %st, %st(1) fsubr %st(2) fsubrs (%ecx) fsubrl (%eax) @@ -208,26 +208,26 @@ fyl2xp1 # CHECK: [1] [2] [3] [4] [5] [6] Instructions: # CHECK-NEXT: 1 100 0.50 U f2xm1 # CHECK-NEXT: 1 1 1.00 U fabs -# CHECK-NEXT: 1 5 1.00 U fadd %st(0), %st(1) -# CHECK-NEXT: 1 5 1.00 U fadd %st(2) +# CHECK-NEXT: 1 5 1.00 U fadd %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fadd %st(2), %st # CHECK-NEXT: 1 10 1.00 * U fadds (%ecx) # CHECK-NEXT: 1 10 1.00 * U faddl (%ecx) -# CHECK-NEXT: 1 5 1.00 U faddp %st(1) -# CHECK-NEXT: 1 5 1.00 U faddp %st(2) +# CHECK-NEXT: 1 5 1.00 U faddp %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U faddp %st, %st(2) # CHECK-NEXT: 1 10 1.00 * U fiadds (%ecx) # CHECK-NEXT: 1 10 1.00 * U fiaddl (%ecx) # CHECK-NEXT: 1 100 0.50 U fbld (%ecx) # CHECK-NEXT: 1 100 0.50 U fbstp (%eax) # CHECK-NEXT: 1 1 1.00 U fchs # CHECK-NEXT: 1 100 0.50 U fnclex -# CHECK-NEXT: 1 1 1.00 U fcmovb %st(1), %st(0) -# CHECK-NEXT: 1 1 1.00 U fcmovbe %st(1), %st(0) -# CHECK-NEXT: 1 1 1.00 U fcmove %st(1), %st(0) -# CHECK-NEXT: 1 1 1.00 U fcmovnb %st(1), %st(0) -# CHECK-NEXT: 1 1 1.00 U fcmovnbe %st(1), %st(0) -# CHECK-NEXT: 1 1 1.00 U fcmovne %st(1), %st(0) -# CHECK-NEXT: 1 1 1.00 U fcmovnu %st(1), %st(0) -# CHECK-NEXT: 1 1 1.00 U fcmovu %st(1), %st(0) +# CHECK-NEXT: 1 1 1.00 U fcmovb %st(1), %st +# CHECK-NEXT: 1 1 1.00 U fcmovbe %st(1), %st +# CHECK-NEXT: 1 1 1.00 U fcmove %st(1), %st +# CHECK-NEXT: 1 1 1.00 U fcmovnb %st(1), %st +# CHECK-NEXT: 1 1 1.00 U fcmovnbe %st(1), %st +# CHECK-NEXT: 1 1 1.00 U fcmovne %st(1), %st +# CHECK-NEXT: 1 1 1.00 U fcmovnu %st(1), %st +# CHECK-NEXT: 1 1 1.00 U fcmovu %st(1), %st # CHECK-NEXT: 2 1 1.00 U fcom %st(1) # CHECK-NEXT: 2 1 1.00 U fcom %st(3) # CHECK-NEXT: 1 6 1.00 U fcoms (%ecx) @@ -237,24 +237,24 @@ fyl2xp1 # CHECK-NEXT: 1 6 1.00 U fcomps (%ecx) # CHECK-NEXT: 1 6 1.00 U fcompl (%eax) # CHECK-NEXT: 1 100 0.50 U fcompp -# CHECK-NEXT: 2 1 1.00 U fcomi %st(3) -# CHECK-NEXT: 2 1 1.00 U fcompi %st(3) +# CHECK-NEXT: 2 1 1.00 U fcomi %st(3), %st +# CHECK-NEXT: 2 1 1.00 U fcompi %st(3), %st # CHECK-NEXT: 1 100 0.50 U fcos # CHECK-NEXT: 1 100 0.50 U fdecstp -# CHECK-NEXT: 1 9 9.50 U fdiv %st(0), %st(1) -# CHECK-NEXT: 1 9 9.50 U fdiv %st(2) +# CHECK-NEXT: 1 9 9.50 U fdiv %st, %st(1) +# CHECK-NEXT: 1 9 9.50 U fdiv %st(2), %st # CHECK-NEXT: 1 14 9.50 * U fdivs (%ecx) # CHECK-NEXT: 1 14 9.50 * U fdivl (%eax) -# CHECK-NEXT: 1 9 9.50 U fdivp %st(1) -# CHECK-NEXT: 1 9 9.50 U fdivp %st(2) +# CHECK-NEXT: 1 9 9.50 U fdivp %st, %st(1) +# CHECK-NEXT: 1 9 9.50 U fdivp %st, %st(2) # CHECK-NEXT: 1 14 9.50 * U fidivs (%ecx) # CHECK-NEXT: 1 14 9.50 * U fidivl (%eax) -# CHECK-NEXT: 1 9 9.50 U fdivr %st(0), %st(1) -# CHECK-NEXT: 1 9 9.50 U fdivr %st(2) +# CHECK-NEXT: 1 9 9.50 U fdivr %st, %st(1) +# CHECK-NEXT: 1 9 9.50 U fdivr %st(2), %st # CHECK-NEXT: 1 14 9.50 * U fdivrs (%ecx) # CHECK-NEXT: 1 14 9.50 * U fdivrl (%eax) -# CHECK-NEXT: 1 9 9.50 U fdivrp %st(1) -# CHECK-NEXT: 1 9 9.50 U fdivrp %st(2) +# CHECK-NEXT: 1 9 9.50 U fdivrp %st, %st(1) +# CHECK-NEXT: 1 9 9.50 U fdivrp %st, %st(2) # CHECK-NEXT: 1 14 9.50 * U fidivrs (%ecx) # CHECK-NEXT: 1 14 9.50 * U fidivrl (%eax) # CHECK-NEXT: 1 100 0.50 U ffree %st(0) @@ -288,12 +288,12 @@ fyl2xp1 # CHECK-NEXT: 1 3 1.00 U fldln2 # CHECK-NEXT: 1 3 1.00 U fldpi # CHECK-NEXT: 1 3 1.00 U fldz -# CHECK-NEXT: 1 5 1.00 U fmul %st(0), %st(1) -# CHECK-NEXT: 1 5 1.00 U fmul %st(2) +# CHECK-NEXT: 1 5 1.00 U fmul %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fmul %st(2), %st # CHECK-NEXT: 1 10 1.00 * U fmuls (%ecx) # CHECK-NEXT: 1 10 1.00 * U fmull (%eax) -# CHECK-NEXT: 1 5 1.00 U fmulp %st(1) -# CHECK-NEXT: 1 5 1.00 U fmulp %st(2) +# CHECK-NEXT: 1 5 1.00 U fmulp %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fmulp %st, %st(2) # CHECK-NEXT: 1 10 1.00 * U fimuls (%ecx) # CHECK-NEXT: 1 10 1.00 * U fimull (%eax) # CHECK-NEXT: 1 1 0.50 U fnop @@ -321,20 +321,20 @@ fyl2xp1 # CHECK-NEXT: 1 100 0.50 U frstor (%eax) # CHECK-NEXT: 1 100 0.50 U wait # CHECK-NEXT: 1 100 0.50 U fnsave (%eax) -# CHECK-NEXT: 1 5 1.00 U fsub %st(0), %st(1) -# CHECK-NEXT: 1 5 1.00 U fsub %st(2) +# CHECK-NEXT: 1 5 1.00 U fsub %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fsub %st(2), %st # CHECK-NEXT: 1 10 1.00 * U fsubs (%ecx) # CHECK-NEXT: 1 10 1.00 * U fsubl (%eax) -# CHECK-NEXT: 1 5 1.00 U fsubp %st(1) -# CHECK-NEXT: 1 5 1.00 U fsubp %st(2) +# CHECK-NEXT: 1 5 1.00 U fsubp %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fsubp %st, %st(2) # CHECK-NEXT: 1 10 1.00 * U fisubs (%ecx) # CHECK-NEXT: 1 10 1.00 * U fisubl (%eax) -# CHECK-NEXT: 1 5 1.00 U fsubr %st(0), %st(1) -# CHECK-NEXT: 1 5 1.00 U fsubr %st(2) +# CHECK-NEXT: 1 5 1.00 U fsubr %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fsubr %st(2), %st # CHECK-NEXT: 1 10 1.00 * U fsubrs (%ecx) # CHECK-NEXT: 1 10 1.00 * U fsubrl (%eax) -# CHECK-NEXT: 1 5 1.00 U fsubrp %st(1) -# CHECK-NEXT: 1 5 1.00 U fsubrp %st(2) +# CHECK-NEXT: 1 5 1.00 U fsubrp %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fsubrp %st, %st(2) # CHECK-NEXT: 1 10 1.00 * U fisubrs (%ecx) # CHECK-NEXT: 1 10 1.00 * U fisubrl (%eax) # CHECK-NEXT: 1 1 1.00 U ftst @@ -343,8 +343,8 @@ fyl2xp1 # CHECK-NEXT: 2 1 1.00 U fucomp %st(1) # CHECK-NEXT: 2 1 1.00 U fucomp %st(3) # CHECK-NEXT: 1 1 1.00 U fucompp -# CHECK-NEXT: 2 1 1.00 U fucomi %st(3) -# CHECK-NEXT: 2 1 1.00 U fucompi %st(3) +# CHECK-NEXT: 2 1 1.00 U fucomi %st(3), %st +# CHECK-NEXT: 2 1 1.00 U fucompi %st(3), %st # CHECK-NEXT: 1 100 0.50 U wait # CHECK-NEXT: 1 100 0.50 U fxam # CHECK-NEXT: 1 1 0.50 U fxch %st(1) @@ -388,26 +388,26 @@ fyl2xp1 # CHECK-NEXT: [0.0] [0.1] [1] [2] [3] [4] [5] [6] [7.0] [7.1] [8.0] [8.1] [9] [10] [11] [12] [13] [14] [15] [16.0] [16.1] [17] [18] Instructions: # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - f2xm1 # CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - fabs -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fadd %st(0), %st(1) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fadd %st(2) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fadd %st, %st(1) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fadd %st(2), %st # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - 1.00 - - - - 0.50 0.50 - - fadds (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - 1.00 - - - - 0.50 0.50 - - faddl (%ecx) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - faddp %st(1) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - faddp %st(2) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - faddp %st, %st(1) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - faddp %st, %st(2) # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - 1.00 - - - - 0.50 0.50 - - fiadds (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - 1.00 - - - - 0.50 0.50 - - fiaddl (%ecx) # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - fbld (%ecx) # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - fbstp (%eax) # CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - fchs # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - fnclex -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmovb %st(1), %st(0) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmovbe %st(1), %st(0) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmove %st(1), %st(0) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmovnb %st(1), %st(0) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmovnbe %st(1), %st(0) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmovne %st(1), %st(0) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmovnu %st(1), %st(0) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmovu %st(1), %st(0) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmovb %st(1), %st +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmovbe %st(1), %st +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmove %st(1), %st +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmovnb %st(1), %st +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmovnbe %st(1), %st +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmovne %st(1), %st +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmovnu %st(1), %st +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcmovu %st(1), %st # CHECK-NEXT: - - - - - 1.00 - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcom %st(1) # CHECK-NEXT: - - - - - 1.00 - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcom %st(3) # CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - fcoms (%ecx) @@ -417,24 +417,24 @@ fyl2xp1 # CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - fcomps (%ecx) # CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - fcompl (%eax) # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - fcompp -# CHECK-NEXT: - - - - - 1.00 - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcomi %st(3) -# CHECK-NEXT: - - - - - 1.00 - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcompi %st(3) +# CHECK-NEXT: - - - - - 1.00 - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcomi %st(3), %st +# CHECK-NEXT: - - - - - 1.00 - - 0.50 0.50 - - - - 1.00 - - - - - - - - fcompi %st(3), %st # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - fcos # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - fdecstp -# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdiv %st(0), %st(1) -# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdiv %st(2) +# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdiv %st, %st(1) +# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdiv %st(2), %st # CHECK-NEXT: 0.50 0.50 - - - - - - 9.50 9.50 - - - - - 1.00 - - - 0.50 0.50 - - fdivs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - 9.50 9.50 - - - - - 1.00 - - - 0.50 0.50 - - fdivl (%eax) -# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdivp %st(1) -# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdivp %st(2) +# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdivp %st, %st(1) +# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdivp %st, %st(2) # CHECK-NEXT: 0.50 0.50 - - - - - - 9.50 9.50 - - - - - 1.00 - - - 0.50 0.50 - - fidivs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - 9.50 9.50 - - - - - 1.00 - - - 0.50 0.50 - - fidivl (%eax) -# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdivr %st(0), %st(1) -# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdivr %st(2) +# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdivr %st, %st(1) +# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdivr %st(2), %st # CHECK-NEXT: 0.50 0.50 - - - - - - 9.50 9.50 - - - - - 1.00 - - - 0.50 0.50 - - fdivrs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - 9.50 9.50 - - - - - 1.00 - - - 0.50 0.50 - - fdivrl (%eax) -# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdivrp %st(1) -# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdivrp %st(2) +# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdivrp %st, %st(1) +# CHECK-NEXT: - - - - - - - - 9.50 9.50 - - - - - 1.00 - - - - - - - fdivrp %st, %st(2) # CHECK-NEXT: 0.50 0.50 - - - - - - 9.50 9.50 - - - - - 1.00 - - - 0.50 0.50 - - fidivrs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - 9.50 9.50 - - - - - 1.00 - - - 0.50 0.50 - - fidivrl (%eax) # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - ffree %st(0) @@ -468,12 +468,12 @@ fyl2xp1 # CHECK-NEXT: - - - - - - - - - - - - - 1.00 - 1.00 - - - - - - - fldln2 # CHECK-NEXT: - - - - - - - - - - - - - 1.00 - 1.00 - - - - - - - fldpi # CHECK-NEXT: - - - - - - - - - - - - - 1.00 - 1.00 - - - - - - - fldz -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - fmul %st(0), %st(1) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - fmul %st(2) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - fmul %st, %st(1) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - fmul %st(2), %st # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - - 1.00 - - - 0.50 0.50 - - fmuls (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - - 1.00 - - - 0.50 0.50 - - fmull (%eax) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - fmulp %st(1) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - fmulp %st(2) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - fmulp %st, %st(1) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - fmulp %st, %st(2) # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - - 1.00 - - - 0.50 0.50 - - fimuls (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - - 1.00 - - - 0.50 0.50 - - fimull (%eax) # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - fnop @@ -501,20 +501,20 @@ fyl2xp1 # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - frstor (%eax) # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - wait # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - fnsave (%eax) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsub %st(0), %st(1) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsub %st(2) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsub %st, %st(1) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsub %st(2), %st # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - 1.00 - - - - 0.50 0.50 - - fsubs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - 1.00 - - - - 0.50 0.50 - - fsubl (%eax) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsubp %st(1) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsubp %st(2) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsubp %st, %st(1) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsubp %st, %st(2) # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - 1.00 - - - - 0.50 0.50 - - fisubs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - 1.00 - - - - 0.50 0.50 - - fisubl (%eax) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsubr %st(0), %st(1) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsubr %st(2) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsubr %st, %st(1) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsubr %st(2), %st # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - 1.00 - - - - 0.50 0.50 - - fsubrs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - 1.00 - - - - 0.50 0.50 - - fsubrl (%eax) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsubrp %st(1) -# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsubrp %st(2) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsubrp %st, %st(1) +# CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - 1.00 - - - - - - - - fsubrp %st, %st(2) # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - 1.00 - - - - 0.50 0.50 - - fisubrs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 0.50 - - - - 1.00 - - - - 0.50 0.50 - - fisubrl (%eax) # CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - ftst @@ -523,8 +523,8 @@ fyl2xp1 # CHECK-NEXT: - - - - - 1.00 - - 0.50 0.50 - - - - 1.00 - - - - - - - - fucomp %st(1) # CHECK-NEXT: - - - - - 1.00 - - 0.50 0.50 - - - - 1.00 - - - - - - - - fucomp %st(3) # CHECK-NEXT: - - - - - - - - 0.50 0.50 - - - - - 1.00 - - - - - - - fucompp -# CHECK-NEXT: - - - - - 1.00 - - 0.50 0.50 - - - - 1.00 - - - - - - - - fucomi %st(3) -# CHECK-NEXT: - - - - - 1.00 - - 0.50 0.50 - - - - 1.00 - - - - - - - - fucompi %st(3) +# CHECK-NEXT: - - - - - 1.00 - - 0.50 0.50 - - - - 1.00 - - - - - - - - fucomi %st(3), %st +# CHECK-NEXT: - - - - - 1.00 - - 0.50 0.50 - - - - 1.00 - - - - - - - - fucompi %st(3), %st # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - wait # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - fxam # CHECK-NEXT: - - - - - 0.50 0.50 - - - - - - - - - - - - - - - - fxch %st(1) diff --git a/llvm/test/tools/llvm-mca/X86/Broadwell/resources-x87.s b/llvm/test/tools/llvm-mca/X86/Broadwell/resources-x87.s index 5cb92be47eabb..2f3a69da99d07 100644 --- a/llvm/test/tools/llvm-mca/X86/Broadwell/resources-x87.s +++ b/llvm/test/tools/llvm-mca/X86/Broadwell/resources-x87.s @@ -5,7 +5,7 @@ f2xm1 fabs -fadd %st(0), %st(1) +fadd %st, %st(1) fadd %st(2) fadds (%ecx) faddl (%ecx) @@ -21,14 +21,14 @@ fchs fnclex -fcmovb %st(1), %st(0) -fcmovbe %st(1), %st(0) -fcmove %st(1), %st(0) -fcmovnb %st(1), %st(0) -fcmovnbe %st(1), %st(0) -fcmovne %st(1), %st(0) -fcmovnu %st(1), %st(0) -fcmovu %st(1), %st(0) +fcmovb %st(1), %st +fcmovbe %st(1), %st +fcmove %st(1), %st +fcmovnb %st(1), %st +fcmovnbe %st(1), %st +fcmovne %st(1), %st +fcmovnu %st(1), %st +fcmovu %st(1), %st fcom %st(1) fcom %st(3) @@ -47,7 +47,7 @@ fcos fdecstp -fdiv %st(0), %st(1) +fdiv %st, %st(1) fdiv %st(2) fdivs (%ecx) fdivl (%eax) @@ -56,7 +56,7 @@ fdivp %st(2) fidivs (%ecx) fidivl (%eax) -fdivr %st(0), %st(1) +fdivr %st, %st(1) fdivr %st(2) fdivrs (%ecx) fdivrl (%eax) @@ -106,7 +106,7 @@ fldln2 fldpi fldz -fmul %st(0), %st(1) +fmul %st, %st(1) fmul %st(2) fmuls (%ecx) fmull (%eax) @@ -153,7 +153,7 @@ fnstsw (%eax) frstor (%eax) fsave (%eax) -fsub %st(0), %st(1) +fsub %st, %st(1) fsub %st(2) fsubs (%ecx) fsubl (%eax) @@ -162,7 +162,7 @@ fsubp %st(2) fisubs (%ecx) fisubl (%eax) -fsubr %st(0), %st(1) +fsubr %st, %st(1) fsubr %st(2) fsubrs (%ecx) fsubrl (%eax) @@ -208,26 +208,26 @@ fyl2xp1 # CHECK: [1] [2] [3] [4] [5] [6] Instructions: # CHECK-NEXT: 1 100 0.25 U f2xm1 # CHECK-NEXT: 1 1 1.00 U fabs -# CHECK-NEXT: 1 3 1.00 U fadd %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fadd %st(2) +# CHECK-NEXT: 1 3 1.00 U fadd %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fadd %st(2), %st # CHECK-NEXT: 2 9 1.00 * U fadds (%ecx) # CHECK-NEXT: 2 9 1.00 * U faddl (%ecx) -# CHECK-NEXT: 1 3 1.00 U faddp %st(1) -# CHECK-NEXT: 1 3 1.00 U faddp %st(2) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(2) # CHECK-NEXT: 3 12 2.00 * U fiadds (%ecx) # CHECK-NEXT: 3 12 2.00 * U fiaddl (%ecx) # CHECK-NEXT: 1 100 0.25 U fbld (%ecx) # CHECK-NEXT: 2 1 1.00 U fbstp (%eax) # CHECK-NEXT: 1 1 1.00 U fchs # CHECK-NEXT: 4 4 1.00 U fnclex -# CHECK-NEXT: 1 3 1.00 U fcmovb %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovbe %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmove %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnb %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnbe %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovne %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnu %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovu %st(1), %st(0) +# CHECK-NEXT: 1 3 1.00 U fcmovb %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovbe %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmove %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnb %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnbe %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovne %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnu %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovu %st(1), %st # CHECK-NEXT: 1 1 1.00 U fcom %st(1) # CHECK-NEXT: 1 1 1.00 U fcom %st(3) # CHECK-NEXT: 2 7 1.00 U fcoms (%ecx) @@ -237,24 +237,24 @@ fyl2xp1 # CHECK-NEXT: 2 7 1.00 U fcomps (%ecx) # CHECK-NEXT: 2 7 1.00 U fcompl (%eax) # CHECK-NEXT: 1 100 0.25 U fcompp -# CHECK-NEXT: 1 3 1.00 U fcomi %st(3) -# CHECK-NEXT: 1 3 1.00 U fcompi %st(3) +# CHECK-NEXT: 1 3 1.00 U fcomi %st(3), %st +# CHECK-NEXT: 1 3 1.00 U fcompi %st(3), %st # CHECK-NEXT: 1 100 0.25 U fcos # CHECK-NEXT: 2 2 1.00 U fdecstp -# CHECK-NEXT: 1 15 1.00 U fdiv %st(0), %st(1) -# CHECK-NEXT: 1 20 1.00 U fdiv %st(2) +# CHECK-NEXT: 1 15 1.00 U fdiv %st, %st(1) +# CHECK-NEXT: 1 20 1.00 U fdiv %st(2), %st # CHECK-NEXT: 2 21 1.00 * U fdivs (%ecx) # CHECK-NEXT: 2 21 1.00 * U fdivl (%eax) -# CHECK-NEXT: 1 15 1.00 U fdivp %st(1) -# CHECK-NEXT: 1 15 1.00 U fdivp %st(2) +# CHECK-NEXT: 1 15 1.00 U fdivp %st, %st(1) +# CHECK-NEXT: 1 15 1.00 U fdivp %st, %st(2) # CHECK-NEXT: 3 24 1.00 * U fidivs (%ecx) # CHECK-NEXT: 3 24 1.00 * U fidivl (%eax) -# CHECK-NEXT: 1 20 1.00 U fdivr %st(0), %st(1) -# CHECK-NEXT: 1 15 1.00 U fdivr %st(2) +# CHECK-NEXT: 1 20 1.00 U fdivr %st, %st(1) +# CHECK-NEXT: 1 15 1.00 U fdivr %st(2), %st # CHECK-NEXT: 2 26 1.00 * U fdivrs (%ecx) # CHECK-NEXT: 2 26 1.00 * U fdivrl (%eax) -# CHECK-NEXT: 1 20 1.00 U fdivrp %st(1) -# CHECK-NEXT: 1 20 1.00 U fdivrp %st(2) +# CHECK-NEXT: 1 20 1.00 U fdivrp %st, %st(1) +# CHECK-NEXT: 1 20 1.00 U fdivrp %st, %st(2) # CHECK-NEXT: 3 29 1.00 * U fidivrs (%ecx) # CHECK-NEXT: 3 29 1.00 * U fidivrl (%eax) # CHECK-NEXT: 1 100 0.25 U ffree %st(0) @@ -288,12 +288,12 @@ fyl2xp1 # CHECK-NEXT: 2 1 1.00 U fldln2 # CHECK-NEXT: 2 1 1.00 U fldpi # CHECK-NEXT: 1 1 0.50 U fldz -# CHECK-NEXT: 1 5 1.00 U fmul %st(0), %st(1) -# CHECK-NEXT: 1 5 1.00 U fmul %st(2) +# CHECK-NEXT: 1 5 1.00 U fmul %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fmul %st(2), %st # CHECK-NEXT: 2 11 1.00 * U fmuls (%ecx) # CHECK-NEXT: 2 11 1.00 * U fmull (%eax) -# CHECK-NEXT: 1 5 1.00 U fmulp %st(1) -# CHECK-NEXT: 1 5 1.00 U fmulp %st(2) +# CHECK-NEXT: 1 5 1.00 U fmulp %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fmulp %st, %st(2) # CHECK-NEXT: 3 14 1.00 * U fimuls (%ecx) # CHECK-NEXT: 3 14 1.00 * U fimull (%eax) # CHECK-NEXT: 1 1 0.50 U fnop @@ -321,20 +321,20 @@ fyl2xp1 # CHECK-NEXT: 1 100 0.25 U frstor (%eax) # CHECK-NEXT: 2 2 0.50 U wait # CHECK-NEXT: 1 100 0.25 U fnsave (%eax) -# CHECK-NEXT: 1 3 1.00 U fsub %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsub %st(2) +# CHECK-NEXT: 1 3 1.00 U fsub %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsub %st(2), %st # CHECK-NEXT: 2 9 1.00 * U fsubs (%ecx) # CHECK-NEXT: 2 9 1.00 * U fsubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(2) # CHECK-NEXT: 3 12 2.00 * U fisubs (%ecx) # CHECK-NEXT: 3 12 2.00 * U fisubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubr %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubr %st(2), %st # CHECK-NEXT: 2 9 1.00 * U fsubrs (%ecx) # CHECK-NEXT: 2 9 1.00 * U fsubrl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(2) # CHECK-NEXT: 3 12 2.00 * U fisubrs (%ecx) # CHECK-NEXT: 3 12 2.00 * U fisubrl (%eax) # CHECK-NEXT: 1 3 1.00 U ftst @@ -343,8 +343,8 @@ fyl2xp1 # CHECK-NEXT: 1 1 1.00 U fucomp %st(1) # CHECK-NEXT: 1 1 1.00 U fucomp %st(3) # CHECK-NEXT: 1 3 1.00 U fucompp -# CHECK-NEXT: 1 3 1.00 U fucomi %st(3) -# CHECK-NEXT: 1 3 1.00 U fucompi %st(3) +# CHECK-NEXT: 1 3 1.00 U fucomi %st(3), %st +# CHECK-NEXT: 1 3 1.00 U fucompi %st(3), %st # CHECK-NEXT: 2 2 0.50 U wait # CHECK-NEXT: 1 100 0.25 U fxam # CHECK-NEXT: 12 14 4.00 U fxch %st(1) @@ -375,26 +375,26 @@ fyl2xp1 # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] Instructions: # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - f2xm1 # CHECK-NEXT: - - - - - - - 1.00 - - fabs -# CHECK-NEXT: - - - 1.00 - - - - - - fadd %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - - - - - - fadd %st(2) +# CHECK-NEXT: - - - 1.00 - - - - - - fadd %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - - - fadd %st(2), %st # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fadds (%ecx) # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - faddl (%ecx) -# CHECK-NEXT: - - - 1.00 - - - - - - faddp %st(1) -# CHECK-NEXT: - - - 1.00 - - - - - - faddp %st(2) +# CHECK-NEXT: - - - 1.00 - - - - - - faddp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - - - faddp %st, %st(2) # CHECK-NEXT: - - - 2.00 0.50 0.50 - - - - fiadds (%ecx) # CHECK-NEXT: - - - 2.00 0.50 0.50 - - - - fiaddl (%ecx) # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fbld (%ecx) # CHECK-NEXT: - - - - 0.33 0.33 1.00 - - 0.33 fbstp (%eax) # CHECK-NEXT: - - - - - - - 1.00 - - fchs # CHECK-NEXT: - - 1.00 1.00 - - - 1.00 1.00 - fnclex -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovb %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovbe %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmove %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnb %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnbe %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovne %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnu %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovu %st(1), %st(0) +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovb %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovbe %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmove %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnb %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnbe %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovne %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnu %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovu %st(1), %st # CHECK-NEXT: - - - 1.00 - - - - - - fcom %st(1) # CHECK-NEXT: - - - 1.00 - - - - - - fcom %st(3) # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fcoms (%ecx) @@ -404,24 +404,24 @@ fyl2xp1 # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fcomps (%ecx) # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fcompl (%eax) # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fcompp -# CHECK-NEXT: - - - 1.00 - - - - - - fcomi %st(3) -# CHECK-NEXT: - - - 1.00 - - - - - - fcompi %st(3) +# CHECK-NEXT: - - - 1.00 - - - - - - fcomi %st(3), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcompi %st(3), %st # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fcos # CHECK-NEXT: - - 1.00 1.00 - - - - - - fdecstp -# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st(0), %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st(2), %st # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivs (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivl (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st, %st(2) # CHECK-NEXT: - - 1.00 1.00 0.50 0.50 - - - - fidivs (%ecx) # CHECK-NEXT: - - 1.00 1.00 0.50 0.50 - - - - fidivl (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st(0), %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st(2), %st # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivrs (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivrl (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st, %st(2) # CHECK-NEXT: - - 1.00 1.00 0.50 0.50 - - - - fidivrs (%ecx) # CHECK-NEXT: - - 1.00 1.00 0.50 0.50 - - - - fidivrl (%eax) # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - ffree %st(0) @@ -455,12 +455,12 @@ fyl2xp1 # CHECK-NEXT: - - 1.00 1.00 - - - - - - fldln2 # CHECK-NEXT: - - 1.00 1.00 - - - - - - fldpi # CHECK-NEXT: - - 0.50 0.50 - - - - - - fldz -# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st(0), %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st(2), %st # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fmuls (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fmull (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st, %st(2) # CHECK-NEXT: - - 1.00 1.00 0.50 0.50 - - - - fimuls (%ecx) # CHECK-NEXT: - - 1.00 1.00 0.50 0.50 - - - - fimull (%eax) # CHECK-NEXT: - - 0.50 0.50 - - - - - - fnop @@ -488,20 +488,20 @@ fyl2xp1 # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - frstor (%eax) # CHECK-NEXT: - - 0.50 0.50 - - - 0.50 0.50 - wait # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fnsave (%eax) -# CHECK-NEXT: - - - 1.00 - - - - - - fsub %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - - - - - - fsub %st(2) +# CHECK-NEXT: - - - 1.00 - - - - - - fsub %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - - - fsub %st(2), %st # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fsubs (%ecx) # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fsubl (%eax) -# CHECK-NEXT: - - - 1.00 - - - - - - fsubp %st(1) -# CHECK-NEXT: - - - 1.00 - - - - - - fsubp %st(2) +# CHECK-NEXT: - - - 1.00 - - - - - - fsubp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - - - fsubp %st, %st(2) # CHECK-NEXT: - - - 2.00 0.50 0.50 - - - - fisubs (%ecx) # CHECK-NEXT: - - - 2.00 0.50 0.50 - - - - fisubl (%eax) -# CHECK-NEXT: - - - 1.00 - - - - - - fsubr %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - - - - - - fsubr %st(2) +# CHECK-NEXT: - - - 1.00 - - - - - - fsubr %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - - - fsubr %st(2), %st # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fsubrs (%ecx) # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fsubrl (%eax) -# CHECK-NEXT: - - - 1.00 - - - - - - fsubrp %st(1) -# CHECK-NEXT: - - - 1.00 - - - - - - fsubrp %st(2) +# CHECK-NEXT: - - - 1.00 - - - - - - fsubrp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - - - fsubrp %st, %st(2) # CHECK-NEXT: - - - 2.00 0.50 0.50 - - - - fisubrs (%ecx) # CHECK-NEXT: - - - 2.00 0.50 0.50 - - - - fisubrl (%eax) # CHECK-NEXT: - - - 1.00 - - - - - - ftst @@ -510,8 +510,8 @@ fyl2xp1 # CHECK-NEXT: - - - 1.00 - - - - - - fucomp %st(1) # CHECK-NEXT: - - - 1.00 - - - - - - fucomp %st(3) # CHECK-NEXT: - - - 1.00 - - - - - - fucompp -# CHECK-NEXT: - - - 1.00 - - - - - - fucomi %st(3) -# CHECK-NEXT: - - - 1.00 - - - - - - fucompi %st(3) +# CHECK-NEXT: - - - 1.00 - - - - - - fucomi %st(3), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fucompi %st(3), %st # CHECK-NEXT: - - 0.50 0.50 - - - 0.50 0.50 - wait # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fxam # CHECK-NEXT: - - 3.25 2.25 - - - 1.25 5.25 - fxch %st(1) diff --git a/llvm/test/tools/llvm-mca/X86/BtVer2/resources-x87.s b/llvm/test/tools/llvm-mca/X86/BtVer2/resources-x87.s index a0e431f6dfe45..2b6b2c4972731 100644 --- a/llvm/test/tools/llvm-mca/X86/BtVer2/resources-x87.s +++ b/llvm/test/tools/llvm-mca/X86/BtVer2/resources-x87.s @@ -5,7 +5,7 @@ f2xm1 fabs -fadd %st(0), %st(1) +fadd %st, %st(1) fadd %st(2) fadds (%ecx) faddl (%ecx) @@ -21,14 +21,14 @@ fchs fnclex -fcmovb %st(1), %st(0) -fcmovbe %st(1), %st(0) -fcmove %st(1), %st(0) -fcmovnb %st(1), %st(0) -fcmovnbe %st(1), %st(0) -fcmovne %st(1), %st(0) -fcmovnu %st(1), %st(0) -fcmovu %st(1), %st(0) +fcmovb %st(1), %st +fcmovbe %st(1), %st +fcmove %st(1), %st +fcmovnb %st(1), %st +fcmovnbe %st(1), %st +fcmovne %st(1), %st +fcmovnu %st(1), %st +fcmovu %st(1), %st fcom %st(1) fcom %st(3) @@ -47,7 +47,7 @@ fcos fdecstp -fdiv %st(0), %st(1) +fdiv %st, %st(1) fdiv %st(2) fdivs (%ecx) fdivl (%eax) @@ -56,7 +56,7 @@ fdivp %st(2) fidivs (%ecx) fidivl (%eax) -fdivr %st(0), %st(1) +fdivr %st, %st(1) fdivr %st(2) fdivrs (%ecx) fdivrl (%eax) @@ -106,7 +106,7 @@ fldln2 fldpi fldz -fmul %st(0), %st(1) +fmul %st, %st(1) fmul %st(2) fmuls (%ecx) fmull (%eax) @@ -153,7 +153,7 @@ fnstsw (%eax) frstor (%eax) fsave (%eax) -fsub %st(0), %st(1) +fsub %st, %st(1) fsub %st(2) fsubs (%ecx) fsubl (%eax) @@ -162,7 +162,7 @@ fsubp %st(2) fisubs (%ecx) fisubl (%eax) -fsubr %st(0), %st(1) +fsubr %st, %st(1) fsubr %st(2) fsubrs (%ecx) fsubrl (%eax) @@ -208,26 +208,26 @@ fyl2xp1 # CHECK: [1] [2] [3] [4] [5] [6] Instructions: # CHECK-NEXT: 1 100 0.50 U f2xm1 # CHECK-NEXT: 1 2 1.00 U fabs -# CHECK-NEXT: 1 3 1.00 U fadd %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fadd %st(2) +# CHECK-NEXT: 1 3 1.00 U fadd %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fadd %st(2), %st # CHECK-NEXT: 1 8 1.00 * U fadds (%ecx) # CHECK-NEXT: 1 8 1.00 * U faddl (%ecx) -# CHECK-NEXT: 1 3 1.00 U faddp %st(1) -# CHECK-NEXT: 1 3 1.00 U faddp %st(2) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(2) # CHECK-NEXT: 1 8 1.00 * U fiadds (%ecx) # CHECK-NEXT: 1 8 1.00 * U fiaddl (%ecx) # CHECK-NEXT: 1 100 0.50 U fbld (%ecx) # CHECK-NEXT: 1 100 0.50 U fbstp (%eax) # CHECK-NEXT: 1 2 1.00 U fchs # CHECK-NEXT: 1 100 0.50 U fnclex -# CHECK-NEXT: 1 3 1.00 U fcmovb %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovbe %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmove %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnb %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnbe %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovne %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnu %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovu %st(1), %st(0) +# CHECK-NEXT: 1 3 1.00 U fcmovb %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovbe %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmove %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnb %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnbe %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovne %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnu %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovu %st(1), %st # CHECK-NEXT: 1 3 1.00 U fcom %st(1) # CHECK-NEXT: 1 3 1.00 U fcom %st(3) # CHECK-NEXT: 1 8 1.00 U fcoms (%ecx) @@ -237,24 +237,24 @@ fyl2xp1 # CHECK-NEXT: 1 8 1.00 U fcomps (%ecx) # CHECK-NEXT: 1 8 1.00 U fcompl (%eax) # CHECK-NEXT: 1 100 0.50 U fcompp -# CHECK-NEXT: 1 3 1.00 U fcomi %st(3) -# CHECK-NEXT: 1 3 1.00 U fcompi %st(3) +# CHECK-NEXT: 1 3 1.00 U fcomi %st(3), %st +# CHECK-NEXT: 1 3 1.00 U fcompi %st(3), %st # CHECK-NEXT: 1 100 0.50 U fcos # CHECK-NEXT: 1 100 0.50 U fdecstp -# CHECK-NEXT: 1 19 19.00 U fdiv %st(0), %st(1) -# CHECK-NEXT: 1 19 19.00 U fdiv %st(2) +# CHECK-NEXT: 1 19 19.00 U fdiv %st, %st(1) +# CHECK-NEXT: 1 19 19.00 U fdiv %st(2), %st # CHECK-NEXT: 1 24 19.00 * U fdivs (%ecx) # CHECK-NEXT: 1 24 19.00 * U fdivl (%eax) -# CHECK-NEXT: 1 19 19.00 U fdivp %st(1) -# CHECK-NEXT: 1 19 19.00 U fdivp %st(2) +# CHECK-NEXT: 1 19 19.00 U fdivp %st, %st(1) +# CHECK-NEXT: 1 19 19.00 U fdivp %st, %st(2) # CHECK-NEXT: 1 24 19.00 * U fidivs (%ecx) # CHECK-NEXT: 1 24 19.00 * U fidivl (%eax) -# CHECK-NEXT: 1 19 19.00 U fdivr %st(0), %st(1) -# CHECK-NEXT: 1 19 19.00 U fdivr %st(2) +# CHECK-NEXT: 1 19 19.00 U fdivr %st, %st(1) +# CHECK-NEXT: 1 19 19.00 U fdivr %st(2), %st # CHECK-NEXT: 1 24 19.00 * U fdivrs (%ecx) # CHECK-NEXT: 1 24 19.00 * U fdivrl (%eax) -# CHECK-NEXT: 1 19 19.00 U fdivrp %st(1) -# CHECK-NEXT: 1 19 19.00 U fdivrp %st(2) +# CHECK-NEXT: 1 19 19.00 U fdivrp %st, %st(1) +# CHECK-NEXT: 1 19 19.00 U fdivrp %st, %st(2) # CHECK-NEXT: 1 24 19.00 * U fidivrs (%ecx) # CHECK-NEXT: 1 24 19.00 * U fidivrl (%eax) # CHECK-NEXT: 1 100 0.50 U ffree %st(0) @@ -288,12 +288,12 @@ fyl2xp1 # CHECK-NEXT: 1 3 1.00 U fldln2 # CHECK-NEXT: 1 3 1.00 U fldpi # CHECK-NEXT: 1 3 1.00 U fldz -# CHECK-NEXT: 1 2 1.00 U fmul %st(0), %st(1) -# CHECK-NEXT: 1 2 1.00 U fmul %st(2) +# CHECK-NEXT: 1 2 1.00 U fmul %st, %st(1) +# CHECK-NEXT: 1 2 1.00 U fmul %st(2), %st # CHECK-NEXT: 1 7 1.00 * U fmuls (%ecx) # CHECK-NEXT: 1 7 1.00 * U fmull (%eax) -# CHECK-NEXT: 1 2 1.00 U fmulp %st(1) -# CHECK-NEXT: 1 2 1.00 U fmulp %st(2) +# CHECK-NEXT: 1 2 1.00 U fmulp %st, %st(1) +# CHECK-NEXT: 1 2 1.00 U fmulp %st, %st(2) # CHECK-NEXT: 1 7 1.00 * U fimuls (%ecx) # CHECK-NEXT: 1 7 1.00 * U fimull (%eax) # CHECK-NEXT: 1 1 0.50 U fnop @@ -321,20 +321,20 @@ fyl2xp1 # CHECK-NEXT: 1 100 0.50 U frstor (%eax) # CHECK-NEXT: 1 100 0.50 U wait # CHECK-NEXT: 1 100 0.50 U fnsave (%eax) -# CHECK-NEXT: 1 3 1.00 U fsub %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsub %st(2) +# CHECK-NEXT: 1 3 1.00 U fsub %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsub %st(2), %st # CHECK-NEXT: 1 8 1.00 * U fsubs (%ecx) # CHECK-NEXT: 1 8 1.00 * U fsubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(2) # CHECK-NEXT: 1 8 1.00 * U fisubs (%ecx) # CHECK-NEXT: 1 8 1.00 * U fisubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubr %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubr %st(2), %st # CHECK-NEXT: 1 8 1.00 * U fsubrs (%ecx) # CHECK-NEXT: 1 8 1.00 * U fsubrl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(2) # CHECK-NEXT: 1 8 1.00 * U fisubrs (%ecx) # CHECK-NEXT: 1 8 1.00 * U fisubrl (%eax) # CHECK-NEXT: 1 3 1.00 U ftst @@ -343,8 +343,8 @@ fyl2xp1 # CHECK-NEXT: 1 3 1.00 U fucomp %st(1) # CHECK-NEXT: 1 3 1.00 U fucomp %st(3) # CHECK-NEXT: 1 3 1.00 U fucompp -# CHECK-NEXT: 1 3 1.00 U fucomi %st(3) -# CHECK-NEXT: 1 3 1.00 U fucompi %st(3) +# CHECK-NEXT: 1 3 1.00 U fucomi %st(3), %st +# CHECK-NEXT: 1 3 1.00 U fucompi %st(3), %st # CHECK-NEXT: 1 100 0.50 U wait # CHECK-NEXT: 1 100 0.50 U fxam # CHECK-NEXT: 1 1 0.50 U fxch %st(1) @@ -379,26 +379,26 @@ fyl2xp1 # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - f2xm1 # CHECK-NEXT: - - - - 1.00 - 1.00 - - - - - - - fabs -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fadd %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fadd %st(2) +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fadd %st, %st(1) +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fadd %st(2), %st # CHECK-NEXT: - - - 1.00 - 1.00 - 1.00 - - - - - - fadds (%ecx) # CHECK-NEXT: - - - 1.00 - 1.00 - 1.00 - - - - - - faddl (%ecx) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - faddp %st(1) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - faddp %st(2) +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - faddp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - faddp %st, %st(2) # CHECK-NEXT: - - - 1.00 - 1.00 - 1.00 - - - - - - fiadds (%ecx) # CHECK-NEXT: - - - 1.00 - 1.00 - 1.00 - - - - - - fiaddl (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - fbld (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - fbstp (%eax) # CHECK-NEXT: - - - - 1.00 - 1.00 - - - - - - - fchs # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - fnclex -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmovb %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmovbe %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmove %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmovnb %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmovnbe %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmovne %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmovnu %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmovu %st(1), %st(0) +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmovb %st(1), %st +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmovbe %st(1), %st +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmove %st(1), %st +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmovnb %st(1), %st +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmovnbe %st(1), %st +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmovne %st(1), %st +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmovnu %st(1), %st +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fcmovu %st(1), %st # CHECK-NEXT: 1.00 - - 1.00 - 1.00 - - - - - - - - fcom %st(1) # CHECK-NEXT: 1.00 - - 1.00 - 1.00 - - - - - - - - fcom %st(3) # CHECK-NEXT: 1.00 - - 1.00 - 1.00 - 1.00 - - - - - - fcoms (%ecx) @@ -408,24 +408,24 @@ fyl2xp1 # CHECK-NEXT: 1.00 - - 1.00 - 1.00 - 1.00 - - - - - - fcomps (%ecx) # CHECK-NEXT: 1.00 - - 1.00 - 1.00 - 1.00 - - - - - - fcompl (%eax) # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - fcompp -# CHECK-NEXT: 1.00 - - 1.00 - 1.00 - - - - - - - - fcomi %st(3) -# CHECK-NEXT: 1.00 - - 1.00 - 1.00 - - - - - - - - fcompi %st(3) +# CHECK-NEXT: 1.00 - - 1.00 - 1.00 - - - - - - - - fcomi %st(3), %st +# CHECK-NEXT: 1.00 - - 1.00 - 1.00 - - - - - - - - fcompi %st(3), %st # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - fcos # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - fdecstp -# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdiv %st(0), %st(1) -# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdiv %st(2) +# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdiv %st, %st(1) +# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdiv %st(2), %st # CHECK-NEXT: - - - - 19.00 - 1.00 1.00 - - - - - - fdivs (%ecx) # CHECK-NEXT: - - - - 19.00 - 1.00 1.00 - - - - - - fdivl (%eax) -# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdivp %st(1) -# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdivp %st(2) +# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdivp %st, %st(1) +# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdivp %st, %st(2) # CHECK-NEXT: - - - - 19.00 - 1.00 1.00 - - - - - - fidivs (%ecx) # CHECK-NEXT: - - - - 19.00 - 1.00 1.00 - - - - - - fidivl (%eax) -# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdivr %st(0), %st(1) -# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdivr %st(2) +# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdivr %st, %st(1) +# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdivr %st(2), %st # CHECK-NEXT: - - - - 19.00 - 1.00 1.00 - - - - - - fdivrs (%ecx) # CHECK-NEXT: - - - - 19.00 - 1.00 1.00 - - - - - - fdivrl (%eax) -# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdivrp %st(1) -# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdivrp %st(2) +# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdivrp %st, %st(1) +# CHECK-NEXT: - - - - 19.00 - 1.00 - - - - - - - fdivrp %st, %st(2) # CHECK-NEXT: - - - - 19.00 - 1.00 1.00 - - - - - - fidivrs (%ecx) # CHECK-NEXT: - - - - 19.00 - 1.00 1.00 - - - - - - fidivrl (%eax) # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - ffree %st(0) @@ -459,12 +459,12 @@ fyl2xp1 # CHECK-NEXT: - - - - - - 1.00 - - - 1.00 - - - fldln2 # CHECK-NEXT: - - - - - - 1.00 - - - 1.00 - - - fldpi # CHECK-NEXT: - - - - - - 1.00 - - - 1.00 - - - fldz -# CHECK-NEXT: - - - - 1.00 - 1.00 - - - - - - - fmul %st(0), %st(1) -# CHECK-NEXT: - - - - 1.00 - 1.00 - - - - - - - fmul %st(2) +# CHECK-NEXT: - - - - 1.00 - 1.00 - - - - - - - fmul %st, %st(1) +# CHECK-NEXT: - - - - 1.00 - 1.00 - - - - - - - fmul %st(2), %st # CHECK-NEXT: - - - - 1.00 - 1.00 1.00 - - - - - - fmuls (%ecx) # CHECK-NEXT: - - - - 1.00 - 1.00 1.00 - - - - - - fmull (%eax) -# CHECK-NEXT: - - - - 1.00 - 1.00 - - - - - - - fmulp %st(1) -# CHECK-NEXT: - - - - 1.00 - 1.00 - - - - - - - fmulp %st(2) +# CHECK-NEXT: - - - - 1.00 - 1.00 - - - - - - - fmulp %st, %st(1) +# CHECK-NEXT: - - - - 1.00 - 1.00 - - - - - - - fmulp %st, %st(2) # CHECK-NEXT: - - - - 1.00 - 1.00 1.00 - - - - - - fimuls (%ecx) # CHECK-NEXT: - - - - 1.00 - 1.00 1.00 - - - - - - fimull (%eax) # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - fnop @@ -492,20 +492,20 @@ fyl2xp1 # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - frstor (%eax) # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - wait # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - fnsave (%eax) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsub %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsub %st(2) +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsub %st, %st(1) +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsub %st(2), %st # CHECK-NEXT: - - - 1.00 - 1.00 - 1.00 - - - - - - fsubs (%ecx) # CHECK-NEXT: - - - 1.00 - 1.00 - 1.00 - - - - - - fsubl (%eax) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsubp %st(1) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsubp %st(2) +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsubp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsubp %st, %st(2) # CHECK-NEXT: - - - 1.00 - 1.00 - 1.00 - - - - - - fisubs (%ecx) # CHECK-NEXT: - - - 1.00 - 1.00 - 1.00 - - - - - - fisubl (%eax) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsubr %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsubr %st(2) +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsubr %st, %st(1) +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsubr %st(2), %st # CHECK-NEXT: - - - 1.00 - 1.00 - 1.00 - - - - - - fsubrs (%ecx) # CHECK-NEXT: - - - 1.00 - 1.00 - 1.00 - - - - - - fsubrl (%eax) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsubrp %st(1) -# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsubrp %st(2) +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsubrp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - 1.00 - - - - - - - - fsubrp %st, %st(2) # CHECK-NEXT: - - - 1.00 - 1.00 - 1.00 - - - - - - fisubrs (%ecx) # CHECK-NEXT: - - - 1.00 - 1.00 - 1.00 - - - - - - fisubrl (%eax) # CHECK-NEXT: 1.00 - - 1.00 - 1.00 - - - - - - - - ftst @@ -514,8 +514,8 @@ fyl2xp1 # CHECK-NEXT: 1.00 - - 1.00 - 1.00 - - - - - - - - fucomp %st(1) # CHECK-NEXT: 1.00 - - 1.00 - 1.00 - - - - - - - - fucomp %st(3) # CHECK-NEXT: 1.00 - - 1.00 - 1.00 - - - - - - - - fucompp -# CHECK-NEXT: 1.00 - - 1.00 - 1.00 - - - - - - - - fucomi %st(3) -# CHECK-NEXT: 1.00 - - 1.00 - 1.00 - - - - - - - - fucompi %st(3) +# CHECK-NEXT: 1.00 - - 1.00 - 1.00 - - - - - - - - fucomi %st(3), %st +# CHECK-NEXT: 1.00 - - 1.00 - 1.00 - - - - - - - - fucompi %st(3), %st # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - wait # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - fxam # CHECK-NEXT: 0.50 0.50 - - - - - - - - - - - - fxch %st(1) diff --git a/llvm/test/tools/llvm-mca/X86/Generic/resources-x87.s b/llvm/test/tools/llvm-mca/X86/Generic/resources-x87.s index 1cba9a7d77fc2..1f3e51e58b33c 100644 --- a/llvm/test/tools/llvm-mca/X86/Generic/resources-x87.s +++ b/llvm/test/tools/llvm-mca/X86/Generic/resources-x87.s @@ -5,7 +5,7 @@ f2xm1 fabs -fadd %st(0), %st(1) +fadd %st, %st(1) fadd %st(2) fadds (%ecx) faddl (%ecx) @@ -21,14 +21,14 @@ fchs fnclex -fcmovb %st(1), %st(0) -fcmovbe %st(1), %st(0) -fcmove %st(1), %st(0) -fcmovnb %st(1), %st(0) -fcmovnbe %st(1), %st(0) -fcmovne %st(1), %st(0) -fcmovnu %st(1), %st(0) -fcmovu %st(1), %st(0) +fcmovb %st(1), %st +fcmovbe %st(1), %st +fcmove %st(1), %st +fcmovnb %st(1), %st +fcmovnbe %st(1), %st +fcmovne %st(1), %st +fcmovnu %st(1), %st +fcmovu %st(1), %st fcom %st(1) fcom %st(3) @@ -47,7 +47,7 @@ fcos fdecstp -fdiv %st(0), %st(1) +fdiv %st, %st(1) fdiv %st(2) fdivs (%ecx) fdivl (%eax) @@ -56,7 +56,7 @@ fdivp %st(2) fidivs (%ecx) fidivl (%eax) -fdivr %st(0), %st(1) +fdivr %st, %st(1) fdivr %st(2) fdivrs (%ecx) fdivrl (%eax) @@ -106,7 +106,7 @@ fldln2 fldpi fldz -fmul %st(0), %st(1) +fmul %st, %st(1) fmul %st(2) fmuls (%ecx) fmull (%eax) @@ -153,7 +153,7 @@ fnstsw (%eax) frstor (%eax) fsave (%eax) -fsub %st(0), %st(1) +fsub %st, %st(1) fsub %st(2) fsubs (%ecx) fsubl (%eax) @@ -162,7 +162,7 @@ fsubp %st(2) fisubs (%ecx) fisubl (%eax) -fsubr %st(0), %st(1) +fsubr %st, %st(1) fsubr %st(2) fsubrs (%ecx) fsubrl (%eax) @@ -208,26 +208,26 @@ fyl2xp1 # CHECK: [1] [2] [3] [4] [5] [6] Instructions: # CHECK-NEXT: 1 100 0.33 U f2xm1 # CHECK-NEXT: 1 1 1.00 U fabs -# CHECK-NEXT: 1 3 1.00 U fadd %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fadd %st(2) +# CHECK-NEXT: 1 3 1.00 U fadd %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fadd %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fadds (%ecx) # CHECK-NEXT: 2 10 1.00 * U faddl (%ecx) -# CHECK-NEXT: 1 3 1.00 U faddp %st(1) -# CHECK-NEXT: 1 3 1.00 U faddp %st(2) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fiadds (%ecx) # CHECK-NEXT: 3 13 2.00 * U fiaddl (%ecx) # CHECK-NEXT: 1 100 0.33 U fbld (%ecx) # CHECK-NEXT: 1 100 0.33 U fbstp (%eax) # CHECK-NEXT: 1 1 1.00 U fchs # CHECK-NEXT: 1 100 0.33 U fnclex -# CHECK-NEXT: 3 3 2.00 U fcmovb %st(1), %st(0) -# CHECK-NEXT: 3 3 2.00 U fcmovbe %st(1), %st(0) -# CHECK-NEXT: 3 3 2.00 U fcmove %st(1), %st(0) -# CHECK-NEXT: 3 3 2.00 U fcmovnb %st(1), %st(0) -# CHECK-NEXT: 3 3 2.00 U fcmovnbe %st(1), %st(0) -# CHECK-NEXT: 3 3 2.00 U fcmovne %st(1), %st(0) -# CHECK-NEXT: 3 3 2.00 U fcmovnu %st(1), %st(0) -# CHECK-NEXT: 3 3 2.00 U fcmovu %st(1), %st(0) +# CHECK-NEXT: 3 3 2.00 U fcmovb %st(1), %st +# CHECK-NEXT: 3 3 2.00 U fcmovbe %st(1), %st +# CHECK-NEXT: 3 3 2.00 U fcmove %st(1), %st +# CHECK-NEXT: 3 3 2.00 U fcmovnb %st(1), %st +# CHECK-NEXT: 3 3 2.00 U fcmovnbe %st(1), %st +# CHECK-NEXT: 3 3 2.00 U fcmovne %st(1), %st +# CHECK-NEXT: 3 3 2.00 U fcmovnu %st(1), %st +# CHECK-NEXT: 3 3 2.00 U fcmovu %st(1), %st # CHECK-NEXT: 1 1 1.00 U fcom %st(1) # CHECK-NEXT: 1 1 1.00 U fcom %st(3) # CHECK-NEXT: 2 8 1.00 U fcoms (%ecx) @@ -237,24 +237,24 @@ fyl2xp1 # CHECK-NEXT: 2 8 1.00 U fcomps (%ecx) # CHECK-NEXT: 2 8 1.00 U fcompl (%eax) # CHECK-NEXT: 1 100 0.33 U fcompp -# CHECK-NEXT: 3 3 1.00 U fcomi %st(3) -# CHECK-NEXT: 3 3 1.00 U fcompi %st(3) +# CHECK-NEXT: 3 3 1.00 U fcomi %st(3), %st +# CHECK-NEXT: 3 3 1.00 U fcompi %st(3), %st # CHECK-NEXT: 1 100 0.33 U fcos # CHECK-NEXT: 1 1 1.00 U fdecstp -# CHECK-NEXT: 1 14 14.00 U fdiv %st(0), %st(1) -# CHECK-NEXT: 1 14 14.00 U fdiv %st(2) +# CHECK-NEXT: 1 14 14.00 U fdiv %st, %st(1) +# CHECK-NEXT: 1 14 14.00 U fdiv %st(2), %st # CHECK-NEXT: 2 31 1.00 * U fdivs (%ecx) # CHECK-NEXT: 2 31 1.00 * U fdivl (%eax) -# CHECK-NEXT: 1 14 14.00 U fdivp %st(1) -# CHECK-NEXT: 1 14 14.00 U fdivp %st(2) +# CHECK-NEXT: 1 14 14.00 U fdivp %st, %st(1) +# CHECK-NEXT: 1 14 14.00 U fdivp %st, %st(2) # CHECK-NEXT: 3 34 1.00 * U fidivs (%ecx) # CHECK-NEXT: 3 34 1.00 * U fidivl (%eax) -# CHECK-NEXT: 1 14 14.00 U fdivr %st(0), %st(1) -# CHECK-NEXT: 1 14 14.00 U fdivr %st(2) +# CHECK-NEXT: 1 14 14.00 U fdivr %st, %st(1) +# CHECK-NEXT: 1 14 14.00 U fdivr %st(2), %st # CHECK-NEXT: 2 31 1.00 * U fdivrs (%ecx) # CHECK-NEXT: 2 31 1.00 * U fdivrl (%eax) -# CHECK-NEXT: 1 14 14.00 U fdivrp %st(1) -# CHECK-NEXT: 1 14 14.00 U fdivrp %st(2) +# CHECK-NEXT: 1 14 14.00 U fdivrp %st, %st(1) +# CHECK-NEXT: 1 14 14.00 U fdivrp %st, %st(2) # CHECK-NEXT: 3 34 1.00 * U fidivrs (%ecx) # CHECK-NEXT: 3 34 1.00 * U fidivrl (%eax) # CHECK-NEXT: 1 1 1.00 U ffree %st(0) @@ -288,12 +288,12 @@ fyl2xp1 # CHECK-NEXT: 2 1 1.00 U fldln2 # CHECK-NEXT: 2 1 1.00 U fldpi # CHECK-NEXT: 1 1 1.00 U fldz -# CHECK-NEXT: 1 5 1.00 U fmul %st(0), %st(1) -# CHECK-NEXT: 1 5 1.00 U fmul %st(2) +# CHECK-NEXT: 1 5 1.00 U fmul %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fmul %st(2), %st # CHECK-NEXT: 2 12 1.00 * U fmuls (%ecx) # CHECK-NEXT: 2 12 1.00 * U fmull (%eax) -# CHECK-NEXT: 1 5 1.00 U fmulp %st(1) -# CHECK-NEXT: 1 5 1.00 U fmulp %st(2) +# CHECK-NEXT: 1 5 1.00 U fmulp %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fmulp %st, %st(2) # CHECK-NEXT: 3 15 1.00 * U fimuls (%ecx) # CHECK-NEXT: 3 15 1.00 * U fimull (%eax) # CHECK-NEXT: 1 1 1.00 U fnop @@ -321,20 +321,20 @@ fyl2xp1 # CHECK-NEXT: 1 100 0.33 U frstor (%eax) # CHECK-NEXT: 1 100 0.33 U wait # CHECK-NEXT: 1 100 0.33 U fnsave (%eax) -# CHECK-NEXT: 1 3 1.00 U fsub %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsub %st(2) +# CHECK-NEXT: 1 3 1.00 U fsub %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsub %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fsubs (%ecx) # CHECK-NEXT: 2 10 1.00 * U fsubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fisubs (%ecx) # CHECK-NEXT: 3 13 2.00 * U fisubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubr %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubr %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fsubrs (%ecx) # CHECK-NEXT: 2 10 1.00 * U fsubrl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fisubrs (%ecx) # CHECK-NEXT: 3 13 2.00 * U fisubrl (%eax) # CHECK-NEXT: 1 3 1.00 U ftst @@ -343,8 +343,8 @@ fyl2xp1 # CHECK-NEXT: 1 1 1.00 U fucomp %st(1) # CHECK-NEXT: 1 1 1.00 U fucomp %st(3) # CHECK-NEXT: 1 3 1.00 U fucompp -# CHECK-NEXT: 3 3 1.00 U fucomi %st(3) -# CHECK-NEXT: 3 3 1.00 U fucompi %st(3) +# CHECK-NEXT: 3 3 1.00 U fucomi %st(3), %st +# CHECK-NEXT: 3 3 1.00 U fucompi %st(3), %st # CHECK-NEXT: 1 100 0.33 U wait # CHECK-NEXT: 1 100 0.33 U fxam # CHECK-NEXT: 1 1 0.33 U fxch %st(1) @@ -373,26 +373,26 @@ fyl2xp1 # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - f2xm1 # CHECK-NEXT: - - - - - 1.00 - - fabs -# CHECK-NEXT: - - - 1.00 - - - - fadd %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - - - - fadd %st(2) +# CHECK-NEXT: - - - 1.00 - - - - fadd %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - fadd %st(2), %st # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fadds (%ecx) # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 faddl (%ecx) -# CHECK-NEXT: - - - 1.00 - - - - faddp %st(1) -# CHECK-NEXT: - - - 1.00 - - - - faddp %st(2) +# CHECK-NEXT: - - - 1.00 - - - - faddp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - faddp %st, %st(2) # CHECK-NEXT: - - - 2.00 - - 0.50 0.50 fiadds (%ecx) # CHECK-NEXT: - - - 2.00 - - 0.50 0.50 fiaddl (%ecx) # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fbld (%ecx) # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fbstp (%eax) # CHECK-NEXT: - - - - - 1.00 - - fchs # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fnclex -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovb %st(1), %st(0) -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovbe %st(1), %st(0) -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmove %st(1), %st(0) -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovnb %st(1), %st(0) -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovnbe %st(1), %st(0) -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovne %st(1), %st(0) -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovnu %st(1), %st(0) -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovu %st(1), %st(0) +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovb %st(1), %st +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovbe %st(1), %st +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmove %st(1), %st +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovnb %st(1), %st +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovnbe %st(1), %st +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovne %st(1), %st +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovnu %st(1), %st +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovu %st(1), %st # CHECK-NEXT: - - - 1.00 - - - - fcom %st(1) # CHECK-NEXT: - - - 1.00 - - - - fcom %st(3) # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fcoms (%ecx) @@ -402,24 +402,24 @@ fyl2xp1 # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fcomps (%ecx) # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fcompl (%eax) # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fcompp -# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fcomi %st(3) -# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fcompi %st(3) +# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fcomi %st(3), %st +# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fcompi %st(3), %st # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fcos # CHECK-NEXT: - - - - - 1.00 - - fdecstp -# CHECK-NEXT: - 14.00 1.00 - - - - - fdiv %st(0), %st(1) -# CHECK-NEXT: - 14.00 1.00 - - - - - fdiv %st(2) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdiv %st, %st(1) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdiv %st(2), %st # CHECK-NEXT: - - 1.00 - - - 0.50 0.50 fdivs (%ecx) # CHECK-NEXT: - - 1.00 - - - 0.50 0.50 fdivl (%eax) -# CHECK-NEXT: - 14.00 1.00 - - - - - fdivp %st(1) -# CHECK-NEXT: - 14.00 1.00 - - - - - fdivp %st(2) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdivp %st, %st(1) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdivp %st, %st(2) # CHECK-NEXT: - - 1.00 1.00 - - 0.50 0.50 fidivs (%ecx) # CHECK-NEXT: - - 1.00 1.00 - - 0.50 0.50 fidivl (%eax) -# CHECK-NEXT: - 14.00 1.00 - - - - - fdivr %st(0), %st(1) -# CHECK-NEXT: - 14.00 1.00 - - - - - fdivr %st(2) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdivr %st, %st(1) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdivr %st(2), %st # CHECK-NEXT: - - 1.00 - - - 0.50 0.50 fdivrs (%ecx) # CHECK-NEXT: - - 1.00 - - - 0.50 0.50 fdivrl (%eax) -# CHECK-NEXT: - 14.00 1.00 - - - - - fdivrp %st(1) -# CHECK-NEXT: - 14.00 1.00 - - - - - fdivrp %st(2) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdivrp %st, %st(1) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdivrp %st, %st(2) # CHECK-NEXT: - - 1.00 1.00 - - 0.50 0.50 fidivrs (%ecx) # CHECK-NEXT: - - 1.00 1.00 - - 0.50 0.50 fidivrl (%eax) # CHECK-NEXT: - - - - - 1.00 - - ffree %st(0) @@ -453,12 +453,12 @@ fyl2xp1 # CHECK-NEXT: - - 1.00 1.00 - - - - fldln2 # CHECK-NEXT: - - 1.00 1.00 - - - - fldpi # CHECK-NEXT: - - - - - 1.00 - - fldz -# CHECK-NEXT: - - 1.00 - - - - - fmul %st(0), %st(1) -# CHECK-NEXT: - - 1.00 - - - - - fmul %st(2) +# CHECK-NEXT: - - 1.00 - - - - - fmul %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - fmul %st(2), %st # CHECK-NEXT: - - 1.00 - - - 0.50 0.50 fmuls (%ecx) # CHECK-NEXT: - - 1.00 - - - 0.50 0.50 fmull (%eax) -# CHECK-NEXT: - - 1.00 - - - - - fmulp %st(1) -# CHECK-NEXT: - - 1.00 - - - - - fmulp %st(2) +# CHECK-NEXT: - - 1.00 - - - - - fmulp %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - fmulp %st, %st(2) # CHECK-NEXT: - - 1.00 1.00 - - 0.50 0.50 fimuls (%ecx) # CHECK-NEXT: - - 1.00 1.00 - - 0.50 0.50 fimull (%eax) # CHECK-NEXT: - - - - - 1.00 - - fnop @@ -486,20 +486,20 @@ fyl2xp1 # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - frstor (%eax) # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - wait # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fnsave (%eax) -# CHECK-NEXT: - - - 1.00 - - - - fsub %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - - - - fsub %st(2) +# CHECK-NEXT: - - - 1.00 - - - - fsub %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - fsub %st(2), %st # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fsubs (%ecx) # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fsubl (%eax) -# CHECK-NEXT: - - - 1.00 - - - - fsubp %st(1) -# CHECK-NEXT: - - - 1.00 - - - - fsubp %st(2) +# CHECK-NEXT: - - - 1.00 - - - - fsubp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - fsubp %st, %st(2) # CHECK-NEXT: - - - 2.00 - - 0.50 0.50 fisubs (%ecx) # CHECK-NEXT: - - - 2.00 - - 0.50 0.50 fisubl (%eax) -# CHECK-NEXT: - - - 1.00 - - - - fsubr %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - - - - fsubr %st(2) +# CHECK-NEXT: - - - 1.00 - - - - fsubr %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - fsubr %st(2), %st # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fsubrs (%ecx) # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fsubrl (%eax) -# CHECK-NEXT: - - - 1.00 - - - - fsubrp %st(1) -# CHECK-NEXT: - - - 1.00 - - - - fsubrp %st(2) +# CHECK-NEXT: - - - 1.00 - - - - fsubrp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - fsubrp %st, %st(2) # CHECK-NEXT: - - - 2.00 - - 0.50 0.50 fisubrs (%ecx) # CHECK-NEXT: - - - 2.00 - - 0.50 0.50 fisubrl (%eax) # CHECK-NEXT: - - - 1.00 - - - - ftst @@ -508,8 +508,8 @@ fyl2xp1 # CHECK-NEXT: - - - 1.00 - - - - fucomp %st(1) # CHECK-NEXT: - - - 1.00 - - - - fucomp %st(3) # CHECK-NEXT: - - - 1.00 - - - - fucompp -# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fucomi %st(3) -# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fucompi %st(3) +# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fucomi %st(3), %st +# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fucompi %st(3), %st # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - wait # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fxam # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fxch %st(1) diff --git a/llvm/test/tools/llvm-mca/X86/Haswell/resources-x87.s b/llvm/test/tools/llvm-mca/X86/Haswell/resources-x87.s index 53006bbc3296e..7da8b2802a9a1 100644 --- a/llvm/test/tools/llvm-mca/X86/Haswell/resources-x87.s +++ b/llvm/test/tools/llvm-mca/X86/Haswell/resources-x87.s @@ -5,7 +5,7 @@ f2xm1 fabs -fadd %st(0), %st(1) +fadd %st, %st(1) fadd %st(2) fadds (%ecx) faddl (%ecx) @@ -21,14 +21,14 @@ fchs fnclex -fcmovb %st(1), %st(0) -fcmovbe %st(1), %st(0) -fcmove %st(1), %st(0) -fcmovnb %st(1), %st(0) -fcmovnbe %st(1), %st(0) -fcmovne %st(1), %st(0) -fcmovnu %st(1), %st(0) -fcmovu %st(1), %st(0) +fcmovb %st(1), %st +fcmovbe %st(1), %st +fcmove %st(1), %st +fcmovnb %st(1), %st +fcmovnbe %st(1), %st +fcmovne %st(1), %st +fcmovnu %st(1), %st +fcmovu %st(1), %st fcom %st(1) fcom %st(3) @@ -47,7 +47,7 @@ fcos fdecstp -fdiv %st(0), %st(1) +fdiv %st, %st(1) fdiv %st(2) fdivs (%ecx) fdivl (%eax) @@ -56,7 +56,7 @@ fdivp %st(2) fidivs (%ecx) fidivl (%eax) -fdivr %st(0), %st(1) +fdivr %st, %st(1) fdivr %st(2) fdivrs (%ecx) fdivrl (%eax) @@ -106,7 +106,7 @@ fldln2 fldpi fldz -fmul %st(0), %st(1) +fmul %st, %st(1) fmul %st(2) fmuls (%ecx) fmull (%eax) @@ -153,7 +153,7 @@ fnstsw (%eax) frstor (%eax) fsave (%eax) -fsub %st(0), %st(1) +fsub %st, %st(1) fsub %st(2) fsubs (%ecx) fsubl (%eax) @@ -162,7 +162,7 @@ fsubp %st(2) fisubs (%ecx) fisubl (%eax) -fsubr %st(0), %st(1) +fsubr %st, %st(1) fsubr %st(2) fsubrs (%ecx) fsubrl (%eax) @@ -208,26 +208,26 @@ fyl2xp1 # CHECK: [1] [2] [3] [4] [5] [6] Instructions: # CHECK-NEXT: 1 100 0.25 U f2xm1 # CHECK-NEXT: 1 1 1.00 U fabs -# CHECK-NEXT: 1 3 1.00 U fadd %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fadd %st(2) +# CHECK-NEXT: 1 3 1.00 U fadd %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fadd %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fadds (%ecx) # CHECK-NEXT: 2 10 1.00 * U faddl (%ecx) -# CHECK-NEXT: 1 3 1.00 U faddp %st(1) -# CHECK-NEXT: 1 3 1.00 U faddp %st(2) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fiadds (%ecx) # CHECK-NEXT: 3 13 2.00 * U fiaddl (%ecx) # CHECK-NEXT: 43 47 10.75 U fbld (%ecx) # CHECK-NEXT: 2 1 1.00 U fbstp (%eax) # CHECK-NEXT: 1 1 1.00 U fchs # CHECK-NEXT: 4 4 1.00 U fnclex -# CHECK-NEXT: 1 3 1.00 U fcmovb %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovbe %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmove %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnb %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnbe %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovne %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnu %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovu %st(1), %st(0) +# CHECK-NEXT: 1 3 1.00 U fcmovb %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovbe %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmove %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnb %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnbe %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovne %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnu %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovu %st(1), %st # CHECK-NEXT: 1 1 1.00 U fcom %st(1) # CHECK-NEXT: 1 1 1.00 U fcom %st(3) # CHECK-NEXT: 2 8 1.00 U fcoms (%ecx) @@ -237,24 +237,24 @@ fyl2xp1 # CHECK-NEXT: 2 8 1.00 U fcomps (%ecx) # CHECK-NEXT: 2 8 1.00 U fcompl (%eax) # CHECK-NEXT: 2 1 0.50 U fcompp -# CHECK-NEXT: 3 1 0.50 U fcomi %st(3) -# CHECK-NEXT: 3 1 0.50 U fcompi %st(3) +# CHECK-NEXT: 3 1 0.50 U fcomi %st(3), %st +# CHECK-NEXT: 3 1 0.50 U fcompi %st(3), %st # CHECK-NEXT: 1 100 0.25 U fcos # CHECK-NEXT: 2 2 1.00 U fdecstp -# CHECK-NEXT: 1 24 1.00 U fdiv %st(0), %st(1) -# CHECK-NEXT: 1 20 1.00 U fdiv %st(2) +# CHECK-NEXT: 1 24 1.00 U fdiv %st, %st(1) +# CHECK-NEXT: 1 20 1.00 U fdiv %st(2), %st # CHECK-NEXT: 2 31 1.00 * U fdivs (%ecx) # CHECK-NEXT: 2 31 1.00 * U fdivl (%eax) -# CHECK-NEXT: 1 24 1.00 U fdivp %st(1) -# CHECK-NEXT: 1 24 1.00 U fdivp %st(2) +# CHECK-NEXT: 1 24 1.00 U fdivp %st, %st(1) +# CHECK-NEXT: 1 24 1.00 U fdivp %st, %st(2) # CHECK-NEXT: 3 34 1.00 * U fidivs (%ecx) # CHECK-NEXT: 3 34 1.00 * U fidivl (%eax) -# CHECK-NEXT: 1 20 1.00 U fdivr %st(0), %st(1) -# CHECK-NEXT: 1 24 1.00 U fdivr %st(2) +# CHECK-NEXT: 1 20 1.00 U fdivr %st, %st(1) +# CHECK-NEXT: 1 24 1.00 U fdivr %st(2), %st # CHECK-NEXT: 2 27 1.00 * U fdivrs (%ecx) # CHECK-NEXT: 2 27 1.00 * U fdivrl (%eax) -# CHECK-NEXT: 1 20 1.00 U fdivrp %st(1) -# CHECK-NEXT: 1 20 1.00 U fdivrp %st(2) +# CHECK-NEXT: 1 20 1.00 U fdivrp %st, %st(1) +# CHECK-NEXT: 1 20 1.00 U fdivrp %st, %st(2) # CHECK-NEXT: 3 30 1.00 * U fidivrs (%ecx) # CHECK-NEXT: 3 30 1.00 * U fidivrl (%eax) # CHECK-NEXT: 1 1 0.50 U ffree %st(0) @@ -288,12 +288,12 @@ fyl2xp1 # CHECK-NEXT: 2 1 1.00 U fldln2 # CHECK-NEXT: 2 1 1.00 U fldpi # CHECK-NEXT: 1 1 0.50 U fldz -# CHECK-NEXT: 1 5 1.00 U fmul %st(0), %st(1) -# CHECK-NEXT: 1 5 1.00 U fmul %st(2) +# CHECK-NEXT: 1 5 1.00 U fmul %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fmul %st(2), %st # CHECK-NEXT: 2 12 1.00 * U fmuls (%ecx) # CHECK-NEXT: 2 12 1.00 * U fmull (%eax) -# CHECK-NEXT: 1 5 1.00 U fmulp %st(1) -# CHECK-NEXT: 1 5 1.00 U fmulp %st(2) +# CHECK-NEXT: 1 5 1.00 U fmulp %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fmulp %st, %st(2) # CHECK-NEXT: 3 15 1.00 * U fimuls (%ecx) # CHECK-NEXT: 3 15 1.00 * U fimull (%eax) # CHECK-NEXT: 1 1 0.50 U fnop @@ -321,20 +321,20 @@ fyl2xp1 # CHECK-NEXT: 90 1 22.50 U frstor (%eax) # CHECK-NEXT: 2 2 0.50 U wait # CHECK-NEXT: 147 1 36.75 U fnsave (%eax) -# CHECK-NEXT: 1 3 1.00 U fsub %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsub %st(2) +# CHECK-NEXT: 1 3 1.00 U fsub %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsub %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fsubs (%ecx) # CHECK-NEXT: 2 10 1.00 * U fsubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fisubs (%ecx) # CHECK-NEXT: 3 13 2.00 * U fisubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubr %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubr %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fsubrs (%ecx) # CHECK-NEXT: 2 10 1.00 * U fsubrl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fisubrs (%ecx) # CHECK-NEXT: 3 13 2.00 * U fisubrl (%eax) # CHECK-NEXT: 1 1 1.00 U ftst @@ -343,8 +343,8 @@ fyl2xp1 # CHECK-NEXT: 1 1 1.00 U fucomp %st(1) # CHECK-NEXT: 1 1 1.00 U fucomp %st(3) # CHECK-NEXT: 2 1 0.50 U fucompp -# CHECK-NEXT: 3 1 0.50 U fucomi %st(3) -# CHECK-NEXT: 3 1 0.50 U fucompi %st(3) +# CHECK-NEXT: 3 1 0.50 U fucomi %st(3), %st +# CHECK-NEXT: 3 1 0.50 U fucompi %st(3), %st # CHECK-NEXT: 2 2 0.50 U wait # CHECK-NEXT: 2 1 2.00 U fxam # CHECK-NEXT: 15 17 4.00 U fxch %st(1) @@ -375,26 +375,26 @@ fyl2xp1 # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] Instructions: # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - f2xm1 # CHECK-NEXT: - - 1.00 - - - - - - - fabs -# CHECK-NEXT: - - - 1.00 - - - - - - fadd %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - - - - - - fadd %st(2) +# CHECK-NEXT: - - - 1.00 - - - - - - fadd %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - - - fadd %st(2), %st # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fadds (%ecx) # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - faddl (%ecx) -# CHECK-NEXT: - - - 1.00 - - - - - - faddp %st(1) -# CHECK-NEXT: - - - 1.00 - - - - - - faddp %st(2) +# CHECK-NEXT: - - - 1.00 - - - - - - faddp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - - - faddp %st, %st(2) # CHECK-NEXT: - - - 2.00 0.50 0.50 - - - - fiadds (%ecx) # CHECK-NEXT: - - - 2.00 0.50 0.50 - - - - fiaddl (%ecx) # CHECK-NEXT: - - - - - - - - - - fbld (%ecx) # CHECK-NEXT: - - - - 0.33 0.33 1.00 - - 0.33 fbstp (%eax) # CHECK-NEXT: - - 1.00 - - - - - - - fchs # CHECK-NEXT: - - 1.00 1.00 - - - 1.00 1.00 - fnclex -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovb %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovbe %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmove %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnb %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnbe %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovne %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnu %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovu %st(1), %st(0) +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovb %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovbe %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmove %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnb %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnbe %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovne %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnu %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovu %st(1), %st # CHECK-NEXT: - - - 1.00 - - - - - - fcom %st(1) # CHECK-NEXT: - - - 1.00 - - - - - - fcom %st(3) # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fcoms (%ecx) @@ -404,24 +404,24 @@ fyl2xp1 # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fcomps (%ecx) # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fcompl (%eax) # CHECK-NEXT: - - 0.50 0.50 - - - - - - fcompp -# CHECK-NEXT: - - 0.50 0.50 - - - - - - fcomi %st(3) -# CHECK-NEXT: - - 0.50 0.50 - - - - - - fcompi %st(3) +# CHECK-NEXT: - - 0.50 0.50 - - - - - - fcomi %st(3), %st +# CHECK-NEXT: - - 0.50 0.50 - - - - - - fcompi %st(3), %st # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fcos # CHECK-NEXT: - - 1.00 1.00 - - - - - - fdecstp -# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st(0), %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st(2), %st # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivs (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivl (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st, %st(2) # CHECK-NEXT: - - 1.00 1.00 0.50 0.50 - - - - fidivs (%ecx) # CHECK-NEXT: - - 1.00 1.00 0.50 0.50 - - - - fidivl (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st(0), %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st(2), %st # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivrs (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivrl (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st, %st(2) # CHECK-NEXT: - - 1.00 1.00 0.50 0.50 - - - - fidivrs (%ecx) # CHECK-NEXT: - - 1.00 1.00 0.50 0.50 - - - - fidivrl (%eax) # CHECK-NEXT: - - 0.50 0.50 - - - - - - ffree %st(0) @@ -455,12 +455,12 @@ fyl2xp1 # CHECK-NEXT: - - 1.00 1.00 - - - - - - fldln2 # CHECK-NEXT: - - 1.00 1.00 - - - - - - fldpi # CHECK-NEXT: - - 0.50 0.50 - - - - - - fldz -# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st(0), %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st(2), %st # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fmuls (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fmull (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st, %st(2) # CHECK-NEXT: - - 1.00 1.00 0.50 0.50 - - - - fimuls (%ecx) # CHECK-NEXT: - - 1.00 1.00 0.50 0.50 - - - - fimull (%eax) # CHECK-NEXT: - - 0.50 0.50 - - - - - - fnop @@ -488,20 +488,20 @@ fyl2xp1 # CHECK-NEXT: - - - - - - - - - - frstor (%eax) # CHECK-NEXT: - - 0.50 0.50 - - - 0.50 0.50 - wait # CHECK-NEXT: - - - - - - - - - - fnsave (%eax) -# CHECK-NEXT: - - - 1.00 - - - - - - fsub %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - - - - - - fsub %st(2) +# CHECK-NEXT: - - - 1.00 - - - - - - fsub %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - - - fsub %st(2), %st # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fsubs (%ecx) # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fsubl (%eax) -# CHECK-NEXT: - - - 1.00 - - - - - - fsubp %st(1) -# CHECK-NEXT: - - - 1.00 - - - - - - fsubp %st(2) +# CHECK-NEXT: - - - 1.00 - - - - - - fsubp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - - - fsubp %st, %st(2) # CHECK-NEXT: - - - 2.00 0.50 0.50 - - - - fisubs (%ecx) # CHECK-NEXT: - - - 2.00 0.50 0.50 - - - - fisubl (%eax) -# CHECK-NEXT: - - - 1.00 - - - - - - fsubr %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - - - - - - fsubr %st(2) +# CHECK-NEXT: - - - 1.00 - - - - - - fsubr %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - - - fsubr %st(2), %st # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fsubrs (%ecx) # CHECK-NEXT: - - - 1.00 0.50 0.50 - - - - fsubrl (%eax) -# CHECK-NEXT: - - - 1.00 - - - - - - fsubrp %st(1) -# CHECK-NEXT: - - - 1.00 - - - - - - fsubrp %st(2) +# CHECK-NEXT: - - - 1.00 - - - - - - fsubrp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - - - fsubrp %st, %st(2) # CHECK-NEXT: - - - 2.00 0.50 0.50 - - - - fisubrs (%ecx) # CHECK-NEXT: - - - 2.00 0.50 0.50 - - - - fisubrl (%eax) # CHECK-NEXT: - - - 1.00 - - - - - - ftst @@ -510,8 +510,8 @@ fyl2xp1 # CHECK-NEXT: - - - 1.00 - - - - - - fucomp %st(1) # CHECK-NEXT: - - - 1.00 - - - - - - fucomp %st(3) # CHECK-NEXT: - - 0.50 0.50 - - - - - - fucompp -# CHECK-NEXT: - - 0.50 0.50 - - - - - - fucomi %st(3) -# CHECK-NEXT: - - 0.50 0.50 - - - - - - fucompi %st(3) +# CHECK-NEXT: - - 0.50 0.50 - - - - - - fucomi %st(3), %st +# CHECK-NEXT: - - 0.50 0.50 - - - - - - fucompi %st(3), %st # CHECK-NEXT: - - 0.50 0.50 - - - 0.50 0.50 - wait # CHECK-NEXT: - - - 2.00 - - - - - - fxam # CHECK-NEXT: - - 4.00 3.00 - - - 3.00 5.00 - fxch %st(1) diff --git a/llvm/test/tools/llvm-mca/X86/SLM/resources-x87.s b/llvm/test/tools/llvm-mca/X86/SLM/resources-x87.s index fe5de61296f56..d6d42e957bfe3 100644 --- a/llvm/test/tools/llvm-mca/X86/SLM/resources-x87.s +++ b/llvm/test/tools/llvm-mca/X86/SLM/resources-x87.s @@ -5,7 +5,7 @@ f2xm1 fabs -fadd %st(0), %st(1) +fadd %st, %st(1) fadd %st(2) fadds (%ecx) faddl (%ecx) @@ -21,14 +21,14 @@ fchs fnclex -fcmovb %st(1), %st(0) -fcmovbe %st(1), %st(0) -fcmove %st(1), %st(0) -fcmovnb %st(1), %st(0) -fcmovnbe %st(1), %st(0) -fcmovne %st(1), %st(0) -fcmovnu %st(1), %st(0) -fcmovu %st(1), %st(0) +fcmovb %st(1), %st +fcmovbe %st(1), %st +fcmove %st(1), %st +fcmovnb %st(1), %st +fcmovnbe %st(1), %st +fcmovne %st(1), %st +fcmovnu %st(1), %st +fcmovu %st(1), %st fcom %st(1) fcom %st(3) @@ -47,7 +47,7 @@ fcos fdecstp -fdiv %st(0), %st(1) +fdiv %st, %st(1) fdiv %st(2) fdivs (%ecx) fdivl (%eax) @@ -56,7 +56,7 @@ fdivp %st(2) fidivs (%ecx) fidivl (%eax) -fdivr %st(0), %st(1) +fdivr %st, %st(1) fdivr %st(2) fdivrs (%ecx) fdivrl (%eax) @@ -106,7 +106,7 @@ fldln2 fldpi fldz -fmul %st(0), %st(1) +fmul %st, %st(1) fmul %st(2) fmuls (%ecx) fmull (%eax) @@ -153,7 +153,7 @@ fnstsw (%eax) frstor (%eax) fsave (%eax) -fsub %st(0), %st(1) +fsub %st, %st(1) fsub %st(2) fsubs (%ecx) fsubl (%eax) @@ -162,7 +162,7 @@ fsubp %st(2) fisubs (%ecx) fisubl (%eax) -fsubr %st(0), %st(1) +fsubr %st, %st(1) fsubr %st(2) fsubrs (%ecx) fsubrl (%eax) @@ -208,26 +208,26 @@ fyl2xp1 # CHECK: [1] [2] [3] [4] [5] [6] Instructions: # CHECK-NEXT: 1 100 1.00 U f2xm1 # CHECK-NEXT: 1 1 0.50 U fabs -# CHECK-NEXT: 1 3 1.00 U fadd %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fadd %st(2) +# CHECK-NEXT: 1 3 1.00 U fadd %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fadd %st(2), %st # CHECK-NEXT: 1 6 1.00 * U fadds (%ecx) # CHECK-NEXT: 1 6 1.00 * U faddl (%ecx) -# CHECK-NEXT: 1 3 1.00 U faddp %st(1) -# CHECK-NEXT: 1 3 1.00 U faddp %st(2) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(2) # CHECK-NEXT: 1 6 1.00 * U fiadds (%ecx) # CHECK-NEXT: 1 6 1.00 * U fiaddl (%ecx) # CHECK-NEXT: 1 100 1.00 U fbld (%ecx) # CHECK-NEXT: 1 100 1.00 U fbstp (%eax) # CHECK-NEXT: 1 1 0.50 U fchs # CHECK-NEXT: 1 100 1.00 U fnclex -# CHECK-NEXT: 1 3 1.00 U fcmovb %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovbe %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmove %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnb %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnbe %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovne %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnu %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovu %st(1), %st(0) +# CHECK-NEXT: 1 3 1.00 U fcmovb %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovbe %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmove %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnb %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnbe %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovne %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnu %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovu %st(1), %st # CHECK-NEXT: 1 3 1.00 U fcom %st(1) # CHECK-NEXT: 1 3 1.00 U fcom %st(3) # CHECK-NEXT: 1 6 1.00 U fcoms (%ecx) @@ -237,24 +237,24 @@ fyl2xp1 # CHECK-NEXT: 1 6 1.00 U fcomps (%ecx) # CHECK-NEXT: 1 6 1.00 U fcompl (%eax) # CHECK-NEXT: 1 100 1.00 U fcompp -# CHECK-NEXT: 1 3 1.00 U fcomi %st(3) -# CHECK-NEXT: 1 3 1.00 U fcompi %st(3) +# CHECK-NEXT: 1 3 1.00 U fcomi %st(3), %st +# CHECK-NEXT: 1 3 1.00 U fcompi %st(3), %st # CHECK-NEXT: 1 100 1.00 U fcos # CHECK-NEXT: 1 100 1.00 U fdecstp -# CHECK-NEXT: 1 19 17.00 U fdiv %st(0), %st(1) -# CHECK-NEXT: 1 19 17.00 U fdiv %st(2) +# CHECK-NEXT: 1 19 17.00 U fdiv %st, %st(1) +# CHECK-NEXT: 1 19 17.00 U fdiv %st(2), %st # CHECK-NEXT: 1 22 17.00 * U fdivs (%ecx) # CHECK-NEXT: 1 22 17.00 * U fdivl (%eax) -# CHECK-NEXT: 1 19 17.00 U fdivp %st(1) -# CHECK-NEXT: 1 19 17.00 U fdivp %st(2) +# CHECK-NEXT: 1 19 17.00 U fdivp %st, %st(1) +# CHECK-NEXT: 1 19 17.00 U fdivp %st, %st(2) # CHECK-NEXT: 1 22 17.00 * U fidivs (%ecx) # CHECK-NEXT: 1 22 17.00 * U fidivl (%eax) -# CHECK-NEXT: 1 19 17.00 U fdivr %st(0), %st(1) -# CHECK-NEXT: 1 19 17.00 U fdivr %st(2) +# CHECK-NEXT: 1 19 17.00 U fdivr %st, %st(1) +# CHECK-NEXT: 1 19 17.00 U fdivr %st(2), %st # CHECK-NEXT: 1 22 17.00 * U fdivrs (%ecx) # CHECK-NEXT: 1 22 17.00 * U fdivrl (%eax) -# CHECK-NEXT: 1 19 17.00 U fdivrp %st(1) -# CHECK-NEXT: 1 19 17.00 U fdivrp %st(2) +# CHECK-NEXT: 1 19 17.00 U fdivrp %st, %st(1) +# CHECK-NEXT: 1 19 17.00 U fdivrp %st, %st(2) # CHECK-NEXT: 1 22 17.00 * U fidivrs (%ecx) # CHECK-NEXT: 1 22 17.00 * U fidivrl (%eax) # CHECK-NEXT: 1 100 1.00 U ffree %st(0) @@ -288,12 +288,12 @@ fyl2xp1 # CHECK-NEXT: 2 1 1.00 U fldln2 # CHECK-NEXT: 2 1 1.00 U fldpi # CHECK-NEXT: 1 1 0.50 U fldz -# CHECK-NEXT: 1 5 2.00 U fmul %st(0), %st(1) -# CHECK-NEXT: 1 5 2.00 U fmul %st(2) +# CHECK-NEXT: 1 5 2.00 U fmul %st, %st(1) +# CHECK-NEXT: 1 5 2.00 U fmul %st(2), %st # CHECK-NEXT: 1 8 2.00 * U fmuls (%ecx) # CHECK-NEXT: 1 8 2.00 * U fmull (%eax) -# CHECK-NEXT: 1 5 2.00 U fmulp %st(1) -# CHECK-NEXT: 1 5 2.00 U fmulp %st(2) +# CHECK-NEXT: 1 5 2.00 U fmulp %st, %st(1) +# CHECK-NEXT: 1 5 2.00 U fmulp %st, %st(2) # CHECK-NEXT: 1 8 2.00 * U fimuls (%ecx) # CHECK-NEXT: 1 8 2.00 * U fimull (%eax) # CHECK-NEXT: 1 1 0.50 U fnop @@ -321,20 +321,20 @@ fyl2xp1 # CHECK-NEXT: 1 100 1.00 U frstor (%eax) # CHECK-NEXT: 1 100 1.00 U wait # CHECK-NEXT: 1 100 1.00 U fnsave (%eax) -# CHECK-NEXT: 1 3 1.00 U fsub %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsub %st(2) +# CHECK-NEXT: 1 3 1.00 U fsub %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsub %st(2), %st # CHECK-NEXT: 1 6 1.00 * U fsubs (%ecx) # CHECK-NEXT: 1 6 1.00 * U fsubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(2) # CHECK-NEXT: 1 6 1.00 * U fisubs (%ecx) # CHECK-NEXT: 1 6 1.00 * U fisubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubr %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubr %st(2), %st # CHECK-NEXT: 1 6 1.00 * U fsubrs (%ecx) # CHECK-NEXT: 1 6 1.00 * U fsubrl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(2) # CHECK-NEXT: 1 6 1.00 * U fisubrs (%ecx) # CHECK-NEXT: 1 6 1.00 * U fisubrl (%eax) # CHECK-NEXT: 1 3 1.00 U ftst @@ -343,8 +343,8 @@ fyl2xp1 # CHECK-NEXT: 1 3 1.00 U fucomp %st(1) # CHECK-NEXT: 1 3 1.00 U fucomp %st(3) # CHECK-NEXT: 1 3 1.00 U fucompp -# CHECK-NEXT: 1 3 1.00 U fucomi %st(3) -# CHECK-NEXT: 1 3 1.00 U fucompi %st(3) +# CHECK-NEXT: 1 3 1.00 U fucomi %st(3), %st +# CHECK-NEXT: 1 3 1.00 U fucompi %st(3), %st # CHECK-NEXT: 1 100 1.00 U wait # CHECK-NEXT: 1 100 1.00 U fxam # CHECK-NEXT: 1 1 0.50 U fxch %st(1) @@ -373,26 +373,26 @@ fyl2xp1 # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] Instructions: # CHECK-NEXT: - - - 1.00 - - - - f2xm1 # CHECK-NEXT: - - - 0.50 0.50 - - - fabs -# CHECK-NEXT: - - - - 1.00 - - - fadd %st(0), %st(1) -# CHECK-NEXT: - - - - 1.00 - - - fadd %st(2) +# CHECK-NEXT: - - - - 1.00 - - - fadd %st, %st(1) +# CHECK-NEXT: - - - - 1.00 - - - fadd %st(2), %st # CHECK-NEXT: - - - - 1.00 - - 1.00 fadds (%ecx) # CHECK-NEXT: - - - - 1.00 - - 1.00 faddl (%ecx) -# CHECK-NEXT: - - - - 1.00 - - - faddp %st(1) -# CHECK-NEXT: - - - - 1.00 - - - faddp %st(2) +# CHECK-NEXT: - - - - 1.00 - - - faddp %st, %st(1) +# CHECK-NEXT: - - - - 1.00 - - - faddp %st, %st(2) # CHECK-NEXT: - - - - 1.00 - - 1.00 fiadds (%ecx) # CHECK-NEXT: - - - - 1.00 - - 1.00 fiaddl (%ecx) # CHECK-NEXT: - - - 1.00 - - - - fbld (%ecx) # CHECK-NEXT: - - - 1.00 - - - - fbstp (%eax) # CHECK-NEXT: - - - 0.50 0.50 - - - fchs # CHECK-NEXT: - - - 1.00 - - - - fnclex -# CHECK-NEXT: - - - - 1.00 - - - fcmovb %st(1), %st(0) -# CHECK-NEXT: - - - - 1.00 - - - fcmovbe %st(1), %st(0) -# CHECK-NEXT: - - - - 1.00 - - - fcmove %st(1), %st(0) -# CHECK-NEXT: - - - - 1.00 - - - fcmovnb %st(1), %st(0) -# CHECK-NEXT: - - - - 1.00 - - - fcmovnbe %st(1), %st(0) -# CHECK-NEXT: - - - - 1.00 - - - fcmovne %st(1), %st(0) -# CHECK-NEXT: - - - - 1.00 - - - fcmovnu %st(1), %st(0) -# CHECK-NEXT: - - - - 1.00 - - - fcmovu %st(1), %st(0) +# CHECK-NEXT: - - - - 1.00 - - - fcmovb %st(1), %st +# CHECK-NEXT: - - - - 1.00 - - - fcmovbe %st(1), %st +# CHECK-NEXT: - - - - 1.00 - - - fcmove %st(1), %st +# CHECK-NEXT: - - - - 1.00 - - - fcmovnb %st(1), %st +# CHECK-NEXT: - - - - 1.00 - - - fcmovnbe %st(1), %st +# CHECK-NEXT: - - - - 1.00 - - - fcmovne %st(1), %st +# CHECK-NEXT: - - - - 1.00 - - - fcmovnu %st(1), %st +# CHECK-NEXT: - - - - 1.00 - - - fcmovu %st(1), %st # CHECK-NEXT: - - - - 1.00 - - - fcom %st(1) # CHECK-NEXT: - - - - 1.00 - - - fcom %st(3) # CHECK-NEXT: - - - - 1.00 - - 1.00 fcoms (%ecx) @@ -402,24 +402,24 @@ fyl2xp1 # CHECK-NEXT: - - - - 1.00 - - 1.00 fcomps (%ecx) # CHECK-NEXT: - - - - 1.00 - - 1.00 fcompl (%eax) # CHECK-NEXT: - - - 1.00 - - - - fcompp -# CHECK-NEXT: - - - - 1.00 - - - fcomi %st(3) -# CHECK-NEXT: - - - - 1.00 - - - fcompi %st(3) +# CHECK-NEXT: - - - - 1.00 - - - fcomi %st(3), %st +# CHECK-NEXT: - - - - 1.00 - - - fcompi %st(3), %st # CHECK-NEXT: - - - 1.00 - - - - fcos # CHECK-NEXT: - - - 1.00 - - - - fdecstp -# CHECK-NEXT: - 17.00 - 1.00 - - - - fdiv %st(0), %st(1) -# CHECK-NEXT: - 17.00 - 1.00 - - - - fdiv %st(2) +# CHECK-NEXT: - 17.00 - 1.00 - - - - fdiv %st, %st(1) +# CHECK-NEXT: - 17.00 - 1.00 - - - - fdiv %st(2), %st # CHECK-NEXT: - 17.00 - 1.00 - - - 1.00 fdivs (%ecx) # CHECK-NEXT: - 17.00 - 1.00 - - - 1.00 fdivl (%eax) -# CHECK-NEXT: - 17.00 - 1.00 - - - - fdivp %st(1) -# CHECK-NEXT: - 17.00 - 1.00 - - - - fdivp %st(2) +# CHECK-NEXT: - 17.00 - 1.00 - - - - fdivp %st, %st(1) +# CHECK-NEXT: - 17.00 - 1.00 - - - - fdivp %st, %st(2) # CHECK-NEXT: - 17.00 - 1.00 - - - 1.00 fidivs (%ecx) # CHECK-NEXT: - 17.00 - 1.00 - - - 1.00 fidivl (%eax) -# CHECK-NEXT: - 17.00 - 1.00 - - - - fdivr %st(0), %st(1) -# CHECK-NEXT: - 17.00 - 1.00 - - - - fdivr %st(2) +# CHECK-NEXT: - 17.00 - 1.00 - - - - fdivr %st, %st(1) +# CHECK-NEXT: - 17.00 - 1.00 - - - - fdivr %st(2), %st # CHECK-NEXT: - 17.00 - 1.00 - - - 1.00 fdivrs (%ecx) # CHECK-NEXT: - 17.00 - 1.00 - - - 1.00 fdivrl (%eax) -# CHECK-NEXT: - 17.00 - 1.00 - - - - fdivrp %st(1) -# CHECK-NEXT: - 17.00 - 1.00 - - - - fdivrp %st(2) +# CHECK-NEXT: - 17.00 - 1.00 - - - - fdivrp %st, %st(1) +# CHECK-NEXT: - 17.00 - 1.00 - - - - fdivrp %st, %st(2) # CHECK-NEXT: - 17.00 - 1.00 - - - 1.00 fidivrs (%ecx) # CHECK-NEXT: - 17.00 - 1.00 - - - 1.00 fidivrl (%eax) # CHECK-NEXT: - - - 1.00 - - - - ffree %st(0) @@ -453,12 +453,12 @@ fyl2xp1 # CHECK-NEXT: - - - 1.00 1.00 - - - fldln2 # CHECK-NEXT: - - - 1.00 1.00 - - - fldpi # CHECK-NEXT: - - - 0.50 0.50 - - - fldz -# CHECK-NEXT: - - 2.00 1.00 - - - - fmul %st(0), %st(1) -# CHECK-NEXT: - - 2.00 1.00 - - - - fmul %st(2) +# CHECK-NEXT: - - 2.00 1.00 - - - - fmul %st, %st(1) +# CHECK-NEXT: - - 2.00 1.00 - - - - fmul %st(2), %st # CHECK-NEXT: - - 2.00 1.00 - - - 1.00 fmuls (%ecx) # CHECK-NEXT: - - 2.00 1.00 - - - 1.00 fmull (%eax) -# CHECK-NEXT: - - 2.00 1.00 - - - - fmulp %st(1) -# CHECK-NEXT: - - 2.00 1.00 - - - - fmulp %st(2) +# CHECK-NEXT: - - 2.00 1.00 - - - - fmulp %st, %st(1) +# CHECK-NEXT: - - 2.00 1.00 - - - - fmulp %st, %st(2) # CHECK-NEXT: - - 2.00 1.00 - - - 1.00 fimuls (%ecx) # CHECK-NEXT: - - 2.00 1.00 - - - 1.00 fimull (%eax) # CHECK-NEXT: - - - - - - - - fnop @@ -486,20 +486,20 @@ fyl2xp1 # CHECK-NEXT: - - - 1.00 - - - - frstor (%eax) # CHECK-NEXT: - - - 1.00 - - - - wait # CHECK-NEXT: - - - 1.00 - - - - fnsave (%eax) -# CHECK-NEXT: - - - - 1.00 - - - fsub %st(0), %st(1) -# CHECK-NEXT: - - - - 1.00 - - - fsub %st(2) +# CHECK-NEXT: - - - - 1.00 - - - fsub %st, %st(1) +# CHECK-NEXT: - - - - 1.00 - - - fsub %st(2), %st # CHECK-NEXT: - - - - 1.00 - - 1.00 fsubs (%ecx) # CHECK-NEXT: - - - - 1.00 - - 1.00 fsubl (%eax) -# CHECK-NEXT: - - - - 1.00 - - - fsubp %st(1) -# CHECK-NEXT: - - - - 1.00 - - - fsubp %st(2) +# CHECK-NEXT: - - - - 1.00 - - - fsubp %st, %st(1) +# CHECK-NEXT: - - - - 1.00 - - - fsubp %st, %st(2) # CHECK-NEXT: - - - - 1.00 - - 1.00 fisubs (%ecx) # CHECK-NEXT: - - - - 1.00 - - 1.00 fisubl (%eax) -# CHECK-NEXT: - - - - 1.00 - - - fsubr %st(0), %st(1) -# CHECK-NEXT: - - - - 1.00 - - - fsubr %st(2) +# CHECK-NEXT: - - - - 1.00 - - - fsubr %st, %st(1) +# CHECK-NEXT: - - - - 1.00 - - - fsubr %st(2), %st # CHECK-NEXT: - - - - 1.00 - - 1.00 fsubrs (%ecx) # CHECK-NEXT: - - - - 1.00 - - 1.00 fsubrl (%eax) -# CHECK-NEXT: - - - - 1.00 - - - fsubrp %st(1) -# CHECK-NEXT: - - - - 1.00 - - - fsubrp %st(2) +# CHECK-NEXT: - - - - 1.00 - - - fsubrp %st, %st(1) +# CHECK-NEXT: - - - - 1.00 - - - fsubrp %st, %st(2) # CHECK-NEXT: - - - - 1.00 - - 1.00 fisubrs (%ecx) # CHECK-NEXT: - - - - 1.00 - - 1.00 fisubrl (%eax) # CHECK-NEXT: - - - - 1.00 - - - ftst @@ -508,8 +508,8 @@ fyl2xp1 # CHECK-NEXT: - - - - 1.00 - - - fucomp %st(1) # CHECK-NEXT: - - - - 1.00 - - - fucomp %st(3) # CHECK-NEXT: - - - - 1.00 - - - fucompp -# CHECK-NEXT: - - - - 1.00 - - - fucomi %st(3) -# CHECK-NEXT: - - - - 1.00 - - - fucompi %st(3) +# CHECK-NEXT: - - - - 1.00 - - - fucomi %st(3), %st +# CHECK-NEXT: - - - - 1.00 - - - fucompi %st(3), %st # CHECK-NEXT: - - - 1.00 - - - - wait # CHECK-NEXT: - - - 1.00 - - - - fxam # CHECK-NEXT: - - - - - 0.50 0.50 - fxch %st(1) diff --git a/llvm/test/tools/llvm-mca/X86/SandyBridge/resources-x87.s b/llvm/test/tools/llvm-mca/X86/SandyBridge/resources-x87.s index 332f365f1fdd3..1bed53326ced6 100644 --- a/llvm/test/tools/llvm-mca/X86/SandyBridge/resources-x87.s +++ b/llvm/test/tools/llvm-mca/X86/SandyBridge/resources-x87.s @@ -5,7 +5,7 @@ f2xm1 fabs -fadd %st(0), %st(1) +fadd %st, %st(1) fadd %st(2) fadds (%ecx) faddl (%ecx) @@ -21,14 +21,14 @@ fchs fnclex -fcmovb %st(1), %st(0) -fcmovbe %st(1), %st(0) -fcmove %st(1), %st(0) -fcmovnb %st(1), %st(0) -fcmovnbe %st(1), %st(0) -fcmovne %st(1), %st(0) -fcmovnu %st(1), %st(0) -fcmovu %st(1), %st(0) +fcmovb %st(1), %st +fcmovbe %st(1), %st +fcmove %st(1), %st +fcmovnb %st(1), %st +fcmovnbe %st(1), %st +fcmovne %st(1), %st +fcmovnu %st(1), %st +fcmovu %st(1), %st fcom %st(1) fcom %st(3) @@ -47,7 +47,7 @@ fcos fdecstp -fdiv %st(0), %st(1) +fdiv %st, %st(1) fdiv %st(2) fdivs (%ecx) fdivl (%eax) @@ -56,7 +56,7 @@ fdivp %st(2) fidivs (%ecx) fidivl (%eax) -fdivr %st(0), %st(1) +fdivr %st, %st(1) fdivr %st(2) fdivrs (%ecx) fdivrl (%eax) @@ -106,7 +106,7 @@ fldln2 fldpi fldz -fmul %st(0), %st(1) +fmul %st, %st(1) fmul %st(2) fmuls (%ecx) fmull (%eax) @@ -153,7 +153,7 @@ fnstsw (%eax) frstor (%eax) fsave (%eax) -fsub %st(0), %st(1) +fsub %st, %st(1) fsub %st(2) fsubs (%ecx) fsubl (%eax) @@ -162,7 +162,7 @@ fsubp %st(2) fisubs (%ecx) fisubl (%eax) -fsubr %st(0), %st(1) +fsubr %st, %st(1) fsubr %st(2) fsubrs (%ecx) fsubrl (%eax) @@ -208,26 +208,26 @@ fyl2xp1 # CHECK: [1] [2] [3] [4] [5] [6] Instructions: # CHECK-NEXT: 1 100 0.33 U f2xm1 # CHECK-NEXT: 1 1 1.00 U fabs -# CHECK-NEXT: 1 3 1.00 U fadd %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fadd %st(2) +# CHECK-NEXT: 1 3 1.00 U fadd %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fadd %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fadds (%ecx) # CHECK-NEXT: 2 10 1.00 * U faddl (%ecx) -# CHECK-NEXT: 1 3 1.00 U faddp %st(1) -# CHECK-NEXT: 1 3 1.00 U faddp %st(2) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fiadds (%ecx) # CHECK-NEXT: 3 13 2.00 * U fiaddl (%ecx) # CHECK-NEXT: 1 100 0.33 U fbld (%ecx) # CHECK-NEXT: 1 100 0.33 U fbstp (%eax) # CHECK-NEXT: 1 1 1.00 U fchs # CHECK-NEXT: 1 100 0.33 U fnclex -# CHECK-NEXT: 3 3 2.00 U fcmovb %st(1), %st(0) -# CHECK-NEXT: 3 3 2.00 U fcmovbe %st(1), %st(0) -# CHECK-NEXT: 3 3 2.00 U fcmove %st(1), %st(0) -# CHECK-NEXT: 3 3 2.00 U fcmovnb %st(1), %st(0) -# CHECK-NEXT: 3 3 2.00 U fcmovnbe %st(1), %st(0) -# CHECK-NEXT: 3 3 2.00 U fcmovne %st(1), %st(0) -# CHECK-NEXT: 3 3 2.00 U fcmovnu %st(1), %st(0) -# CHECK-NEXT: 3 3 2.00 U fcmovu %st(1), %st(0) +# CHECK-NEXT: 3 3 2.00 U fcmovb %st(1), %st +# CHECK-NEXT: 3 3 2.00 U fcmovbe %st(1), %st +# CHECK-NEXT: 3 3 2.00 U fcmove %st(1), %st +# CHECK-NEXT: 3 3 2.00 U fcmovnb %st(1), %st +# CHECK-NEXT: 3 3 2.00 U fcmovnbe %st(1), %st +# CHECK-NEXT: 3 3 2.00 U fcmovne %st(1), %st +# CHECK-NEXT: 3 3 2.00 U fcmovnu %st(1), %st +# CHECK-NEXT: 3 3 2.00 U fcmovu %st(1), %st # CHECK-NEXT: 1 1 1.00 U fcom %st(1) # CHECK-NEXT: 1 1 1.00 U fcom %st(3) # CHECK-NEXT: 2 8 1.00 U fcoms (%ecx) @@ -237,24 +237,24 @@ fyl2xp1 # CHECK-NEXT: 2 8 1.00 U fcomps (%ecx) # CHECK-NEXT: 2 8 1.00 U fcompl (%eax) # CHECK-NEXT: 1 100 0.33 U fcompp -# CHECK-NEXT: 3 3 1.00 U fcomi %st(3) -# CHECK-NEXT: 3 3 1.00 U fcompi %st(3) +# CHECK-NEXT: 3 3 1.00 U fcomi %st(3), %st +# CHECK-NEXT: 3 3 1.00 U fcompi %st(3), %st # CHECK-NEXT: 1 100 0.33 U fcos # CHECK-NEXT: 1 1 1.00 U fdecstp -# CHECK-NEXT: 1 14 14.00 U fdiv %st(0), %st(1) -# CHECK-NEXT: 1 14 14.00 U fdiv %st(2) +# CHECK-NEXT: 1 14 14.00 U fdiv %st, %st(1) +# CHECK-NEXT: 1 14 14.00 U fdiv %st(2), %st # CHECK-NEXT: 2 31 1.00 * U fdivs (%ecx) # CHECK-NEXT: 2 31 1.00 * U fdivl (%eax) -# CHECK-NEXT: 1 14 14.00 U fdivp %st(1) -# CHECK-NEXT: 1 14 14.00 U fdivp %st(2) +# CHECK-NEXT: 1 14 14.00 U fdivp %st, %st(1) +# CHECK-NEXT: 1 14 14.00 U fdivp %st, %st(2) # CHECK-NEXT: 3 34 1.00 * U fidivs (%ecx) # CHECK-NEXT: 3 34 1.00 * U fidivl (%eax) -# CHECK-NEXT: 1 14 14.00 U fdivr %st(0), %st(1) -# CHECK-NEXT: 1 14 14.00 U fdivr %st(2) +# CHECK-NEXT: 1 14 14.00 U fdivr %st, %st(1) +# CHECK-NEXT: 1 14 14.00 U fdivr %st(2), %st # CHECK-NEXT: 2 31 1.00 * U fdivrs (%ecx) # CHECK-NEXT: 2 31 1.00 * U fdivrl (%eax) -# CHECK-NEXT: 1 14 14.00 U fdivrp %st(1) -# CHECK-NEXT: 1 14 14.00 U fdivrp %st(2) +# CHECK-NEXT: 1 14 14.00 U fdivrp %st, %st(1) +# CHECK-NEXT: 1 14 14.00 U fdivrp %st, %st(2) # CHECK-NEXT: 3 34 1.00 * U fidivrs (%ecx) # CHECK-NEXT: 3 34 1.00 * U fidivrl (%eax) # CHECK-NEXT: 1 1 1.00 U ffree %st(0) @@ -288,12 +288,12 @@ fyl2xp1 # CHECK-NEXT: 2 1 1.00 U fldln2 # CHECK-NEXT: 2 1 1.00 U fldpi # CHECK-NEXT: 1 1 1.00 U fldz -# CHECK-NEXT: 1 5 1.00 U fmul %st(0), %st(1) -# CHECK-NEXT: 1 5 1.00 U fmul %st(2) +# CHECK-NEXT: 1 5 1.00 U fmul %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fmul %st(2), %st # CHECK-NEXT: 2 12 1.00 * U fmuls (%ecx) # CHECK-NEXT: 2 12 1.00 * U fmull (%eax) -# CHECK-NEXT: 1 5 1.00 U fmulp %st(1) -# CHECK-NEXT: 1 5 1.00 U fmulp %st(2) +# CHECK-NEXT: 1 5 1.00 U fmulp %st, %st(1) +# CHECK-NEXT: 1 5 1.00 U fmulp %st, %st(2) # CHECK-NEXT: 3 15 1.00 * U fimuls (%ecx) # CHECK-NEXT: 3 15 1.00 * U fimull (%eax) # CHECK-NEXT: 1 1 1.00 U fnop @@ -321,20 +321,20 @@ fyl2xp1 # CHECK-NEXT: 1 100 0.33 U frstor (%eax) # CHECK-NEXT: 1 100 0.33 U wait # CHECK-NEXT: 1 100 0.33 U fnsave (%eax) -# CHECK-NEXT: 1 3 1.00 U fsub %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsub %st(2) +# CHECK-NEXT: 1 3 1.00 U fsub %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsub %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fsubs (%ecx) # CHECK-NEXT: 2 10 1.00 * U fsubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fisubs (%ecx) # CHECK-NEXT: 3 13 2.00 * U fisubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubr %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubr %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fsubrs (%ecx) # CHECK-NEXT: 2 10 1.00 * U fsubrl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fisubrs (%ecx) # CHECK-NEXT: 3 13 2.00 * U fisubrl (%eax) # CHECK-NEXT: 1 3 1.00 U ftst @@ -343,8 +343,8 @@ fyl2xp1 # CHECK-NEXT: 1 1 1.00 U fucomp %st(1) # CHECK-NEXT: 1 1 1.00 U fucomp %st(3) # CHECK-NEXT: 1 3 1.00 U fucompp -# CHECK-NEXT: 3 3 1.00 U fucomi %st(3) -# CHECK-NEXT: 3 3 1.00 U fucompi %st(3) +# CHECK-NEXT: 3 3 1.00 U fucomi %st(3), %st +# CHECK-NEXT: 3 3 1.00 U fucompi %st(3), %st # CHECK-NEXT: 1 100 0.33 U wait # CHECK-NEXT: 1 100 0.33 U fxam # CHECK-NEXT: 1 1 0.33 U fxch %st(1) @@ -373,26 +373,26 @@ fyl2xp1 # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - f2xm1 # CHECK-NEXT: - - - - - 1.00 - - fabs -# CHECK-NEXT: - - - 1.00 - - - - fadd %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - - - - fadd %st(2) +# CHECK-NEXT: - - - 1.00 - - - - fadd %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - fadd %st(2), %st # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fadds (%ecx) # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 faddl (%ecx) -# CHECK-NEXT: - - - 1.00 - - - - faddp %st(1) -# CHECK-NEXT: - - - 1.00 - - - - faddp %st(2) +# CHECK-NEXT: - - - 1.00 - - - - faddp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - faddp %st, %st(2) # CHECK-NEXT: - - - 2.00 - - 0.50 0.50 fiadds (%ecx) # CHECK-NEXT: - - - 2.00 - - 0.50 0.50 fiaddl (%ecx) # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fbld (%ecx) # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fbstp (%eax) # CHECK-NEXT: - - - - - 1.00 - - fchs # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fnclex -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovb %st(1), %st(0) -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovbe %st(1), %st(0) -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmove %st(1), %st(0) -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovnb %st(1), %st(0) -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovnbe %st(1), %st(0) -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovne %st(1), %st(0) -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovnu %st(1), %st(0) -# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovu %st(1), %st(0) +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovb %st(1), %st +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovbe %st(1), %st +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmove %st(1), %st +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovnb %st(1), %st +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovnbe %st(1), %st +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovne %st(1), %st +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovnu %st(1), %st +# CHECK-NEXT: - - 0.50 - - 2.50 - - fcmovu %st(1), %st # CHECK-NEXT: - - - 1.00 - - - - fcom %st(1) # CHECK-NEXT: - - - 1.00 - - - - fcom %st(3) # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fcoms (%ecx) @@ -402,24 +402,24 @@ fyl2xp1 # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fcomps (%ecx) # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fcompl (%eax) # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fcompp -# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fcomi %st(3) -# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fcompi %st(3) +# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fcomi %st(3), %st +# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fcompi %st(3), %st # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fcos # CHECK-NEXT: - - - - - 1.00 - - fdecstp -# CHECK-NEXT: - 14.00 1.00 - - - - - fdiv %st(0), %st(1) -# CHECK-NEXT: - 14.00 1.00 - - - - - fdiv %st(2) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdiv %st, %st(1) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdiv %st(2), %st # CHECK-NEXT: - - 1.00 - - - 0.50 0.50 fdivs (%ecx) # CHECK-NEXT: - - 1.00 - - - 0.50 0.50 fdivl (%eax) -# CHECK-NEXT: - 14.00 1.00 - - - - - fdivp %st(1) -# CHECK-NEXT: - 14.00 1.00 - - - - - fdivp %st(2) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdivp %st, %st(1) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdivp %st, %st(2) # CHECK-NEXT: - - 1.00 1.00 - - 0.50 0.50 fidivs (%ecx) # CHECK-NEXT: - - 1.00 1.00 - - 0.50 0.50 fidivl (%eax) -# CHECK-NEXT: - 14.00 1.00 - - - - - fdivr %st(0), %st(1) -# CHECK-NEXT: - 14.00 1.00 - - - - - fdivr %st(2) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdivr %st, %st(1) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdivr %st(2), %st # CHECK-NEXT: - - 1.00 - - - 0.50 0.50 fdivrs (%ecx) # CHECK-NEXT: - - 1.00 - - - 0.50 0.50 fdivrl (%eax) -# CHECK-NEXT: - 14.00 1.00 - - - - - fdivrp %st(1) -# CHECK-NEXT: - 14.00 1.00 - - - - - fdivrp %st(2) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdivrp %st, %st(1) +# CHECK-NEXT: - 14.00 1.00 - - - - - fdivrp %st, %st(2) # CHECK-NEXT: - - 1.00 1.00 - - 0.50 0.50 fidivrs (%ecx) # CHECK-NEXT: - - 1.00 1.00 - - 0.50 0.50 fidivrl (%eax) # CHECK-NEXT: - - - - - 1.00 - - ffree %st(0) @@ -453,12 +453,12 @@ fyl2xp1 # CHECK-NEXT: - - 1.00 1.00 - - - - fldln2 # CHECK-NEXT: - - 1.00 1.00 - - - - fldpi # CHECK-NEXT: - - - - - 1.00 - - fldz -# CHECK-NEXT: - - 1.00 - - - - - fmul %st(0), %st(1) -# CHECK-NEXT: - - 1.00 - - - - - fmul %st(2) +# CHECK-NEXT: - - 1.00 - - - - - fmul %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - fmul %st(2), %st # CHECK-NEXT: - - 1.00 - - - 0.50 0.50 fmuls (%ecx) # CHECK-NEXT: - - 1.00 - - - 0.50 0.50 fmull (%eax) -# CHECK-NEXT: - - 1.00 - - - - - fmulp %st(1) -# CHECK-NEXT: - - 1.00 - - - - - fmulp %st(2) +# CHECK-NEXT: - - 1.00 - - - - - fmulp %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - fmulp %st, %st(2) # CHECK-NEXT: - - 1.00 1.00 - - 0.50 0.50 fimuls (%ecx) # CHECK-NEXT: - - 1.00 1.00 - - 0.50 0.50 fimull (%eax) # CHECK-NEXT: - - - - - 1.00 - - fnop @@ -486,20 +486,20 @@ fyl2xp1 # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - frstor (%eax) # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - wait # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fnsave (%eax) -# CHECK-NEXT: - - - 1.00 - - - - fsub %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - - - - fsub %st(2) +# CHECK-NEXT: - - - 1.00 - - - - fsub %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - fsub %st(2), %st # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fsubs (%ecx) # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fsubl (%eax) -# CHECK-NEXT: - - - 1.00 - - - - fsubp %st(1) -# CHECK-NEXT: - - - 1.00 - - - - fsubp %st(2) +# CHECK-NEXT: - - - 1.00 - - - - fsubp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - fsubp %st, %st(2) # CHECK-NEXT: - - - 2.00 - - 0.50 0.50 fisubs (%ecx) # CHECK-NEXT: - - - 2.00 - - 0.50 0.50 fisubl (%eax) -# CHECK-NEXT: - - - 1.00 - - - - fsubr %st(0), %st(1) -# CHECK-NEXT: - - - 1.00 - - - - fsubr %st(2) +# CHECK-NEXT: - - - 1.00 - - - - fsubr %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - fsubr %st(2), %st # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fsubrs (%ecx) # CHECK-NEXT: - - - 1.00 - - 0.50 0.50 fsubrl (%eax) -# CHECK-NEXT: - - - 1.00 - - - - fsubrp %st(1) -# CHECK-NEXT: - - - 1.00 - - - - fsubrp %st(2) +# CHECK-NEXT: - - - 1.00 - - - - fsubrp %st, %st(1) +# CHECK-NEXT: - - - 1.00 - - - - fsubrp %st, %st(2) # CHECK-NEXT: - - - 2.00 - - 0.50 0.50 fisubrs (%ecx) # CHECK-NEXT: - - - 2.00 - - 0.50 0.50 fisubrl (%eax) # CHECK-NEXT: - - - 1.00 - - - - ftst @@ -508,8 +508,8 @@ fyl2xp1 # CHECK-NEXT: - - - 1.00 - - - - fucomp %st(1) # CHECK-NEXT: - - - 1.00 - - - - fucomp %st(3) # CHECK-NEXT: - - - 1.00 - - - - fucompp -# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fucomi %st(3) -# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fucompi %st(3) +# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fucomi %st(3), %st +# CHECK-NEXT: - - 1.00 1.00 - 1.00 - - fucompi %st(3), %st # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - wait # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fxam # CHECK-NEXT: - - 0.33 0.33 - 0.33 - - fxch %st(1) diff --git a/llvm/test/tools/llvm-mca/X86/SkylakeClient/resources-x87.s b/llvm/test/tools/llvm-mca/X86/SkylakeClient/resources-x87.s index 7be9d699573ac..6cd4439a25c1f 100644 --- a/llvm/test/tools/llvm-mca/X86/SkylakeClient/resources-x87.s +++ b/llvm/test/tools/llvm-mca/X86/SkylakeClient/resources-x87.s @@ -5,7 +5,7 @@ f2xm1 fabs -fadd %st(0), %st(1) +fadd %st, %st(1) fadd %st(2) fadds (%ecx) faddl (%ecx) @@ -21,14 +21,14 @@ fchs fnclex -fcmovb %st(1), %st(0) -fcmovbe %st(1), %st(0) -fcmove %st(1), %st(0) -fcmovnb %st(1), %st(0) -fcmovnbe %st(1), %st(0) -fcmovne %st(1), %st(0) -fcmovnu %st(1), %st(0) -fcmovu %st(1), %st(0) +fcmovb %st(1), %st +fcmovbe %st(1), %st +fcmove %st(1), %st +fcmovnb %st(1), %st +fcmovnbe %st(1), %st +fcmovne %st(1), %st +fcmovnu %st(1), %st +fcmovu %st(1), %st fcom %st(1) fcom %st(3) @@ -47,7 +47,7 @@ fcos fdecstp -fdiv %st(0), %st(1) +fdiv %st, %st(1) fdiv %st(2) fdivs (%ecx) fdivl (%eax) @@ -56,7 +56,7 @@ fdivp %st(2) fidivs (%ecx) fidivl (%eax) -fdivr %st(0), %st(1) +fdivr %st, %st(1) fdivr %st(2) fdivrs (%ecx) fdivrl (%eax) @@ -106,7 +106,7 @@ fldln2 fldpi fldz -fmul %st(0), %st(1) +fmul %st, %st(1) fmul %st(2) fmuls (%ecx) fmull (%eax) @@ -153,7 +153,7 @@ fnstsw (%eax) frstor (%eax) fsave (%eax) -fsub %st(0), %st(1) +fsub %st, %st(1) fsub %st(2) fsubs (%ecx) fsubl (%eax) @@ -162,7 +162,7 @@ fsubp %st(2) fisubs (%ecx) fisubl (%eax) -fsubr %st(0), %st(1) +fsubr %st, %st(1) fsubr %st(2) fsubrs (%ecx) fsubrl (%eax) @@ -208,26 +208,26 @@ fyl2xp1 # CHECK: [1] [2] [3] [4] [5] [6] Instructions: # CHECK-NEXT: 1 100 0.25 U f2xm1 # CHECK-NEXT: 1 1 1.00 U fabs -# CHECK-NEXT: 1 3 1.00 U fadd %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fadd %st(2) +# CHECK-NEXT: 1 3 1.00 U fadd %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fadd %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fadds (%ecx) # CHECK-NEXT: 2 10 1.00 * U faddl (%ecx) -# CHECK-NEXT: 1 3 1.00 U faddp %st(1) -# CHECK-NEXT: 1 3 1.00 U faddp %st(2) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fiadds (%ecx) # CHECK-NEXT: 3 13 2.00 * U fiaddl (%ecx) # CHECK-NEXT: 1 100 0.25 U fbld (%ecx) # CHECK-NEXT: 2 1 1.00 U fbstp (%eax) # CHECK-NEXT: 1 1 1.00 U fchs # CHECK-NEXT: 4 4 1.00 U fnclex -# CHECK-NEXT: 1 3 1.00 U fcmovb %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovbe %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmove %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnb %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnbe %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovne %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnu %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovu %st(1), %st(0) +# CHECK-NEXT: 1 3 1.00 U fcmovb %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovbe %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmove %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnb %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnbe %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovne %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnu %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovu %st(1), %st # CHECK-NEXT: 1 1 1.00 U fcom %st(1) # CHECK-NEXT: 1 1 1.00 U fcom %st(3) # CHECK-NEXT: 2 8 1.00 U fcoms (%ecx) @@ -237,24 +237,24 @@ fyl2xp1 # CHECK-NEXT: 2 8 1.00 U fcomps (%ecx) # CHECK-NEXT: 2 8 1.00 U fcompl (%eax) # CHECK-NEXT: 1 100 0.25 U fcompp -# CHECK-NEXT: 1 2 1.00 U fcomi %st(3) -# CHECK-NEXT: 1 2 1.00 U fcompi %st(3) +# CHECK-NEXT: 1 2 1.00 U fcomi %st(3), %st +# CHECK-NEXT: 1 2 1.00 U fcompi %st(3), %st # CHECK-NEXT: 1 100 0.25 U fcos # CHECK-NEXT: 2 2 1.00 U fdecstp -# CHECK-NEXT: 1 15 1.00 U fdiv %st(0), %st(1) -# CHECK-NEXT: 1 20 1.00 U fdiv %st(2) +# CHECK-NEXT: 1 15 1.00 U fdiv %st, %st(1) +# CHECK-NEXT: 1 20 1.00 U fdiv %st(2), %st # CHECK-NEXT: 2 22 1.00 * U fdivs (%ecx) # CHECK-NEXT: 2 22 1.00 * U fdivl (%eax) -# CHECK-NEXT: 1 15 1.00 U fdivp %st(1) -# CHECK-NEXT: 1 15 1.00 U fdivp %st(2) +# CHECK-NEXT: 1 15 1.00 U fdivp %st, %st(1) +# CHECK-NEXT: 1 15 1.00 U fdivp %st, %st(2) # CHECK-NEXT: 3 25 1.00 * U fidivs (%ecx) # CHECK-NEXT: 3 25 1.00 * U fidivl (%eax) -# CHECK-NEXT: 1 20 1.00 U fdivr %st(0), %st(1) -# CHECK-NEXT: 1 15 1.00 U fdivr %st(2) +# CHECK-NEXT: 1 20 1.00 U fdivr %st, %st(1) +# CHECK-NEXT: 1 15 1.00 U fdivr %st(2), %st # CHECK-NEXT: 2 27 1.00 * U fdivrs (%ecx) # CHECK-NEXT: 2 27 1.00 * U fdivrl (%eax) -# CHECK-NEXT: 1 20 1.00 U fdivrp %st(1) -# CHECK-NEXT: 1 20 1.00 U fdivrp %st(2) +# CHECK-NEXT: 1 20 1.00 U fdivrp %st, %st(1) +# CHECK-NEXT: 1 20 1.00 U fdivrp %st, %st(2) # CHECK-NEXT: 3 30 1.00 * U fidivrs (%ecx) # CHECK-NEXT: 3 30 1.00 * U fidivrl (%eax) # CHECK-NEXT: 1 100 0.25 U ffree %st(0) @@ -288,12 +288,12 @@ fyl2xp1 # CHECK-NEXT: 2 1 1.00 U fldln2 # CHECK-NEXT: 2 1 1.00 U fldpi # CHECK-NEXT: 1 1 0.50 U fldz -# CHECK-NEXT: 1 4 1.00 U fmul %st(0), %st(1) -# CHECK-NEXT: 1 4 1.00 U fmul %st(2) +# CHECK-NEXT: 1 4 1.00 U fmul %st, %st(1) +# CHECK-NEXT: 1 4 1.00 U fmul %st(2), %st # CHECK-NEXT: 2 11 1.00 * U fmuls (%ecx) # CHECK-NEXT: 2 11 1.00 * U fmull (%eax) -# CHECK-NEXT: 1 4 1.00 U fmulp %st(1) -# CHECK-NEXT: 1 4 1.00 U fmulp %st(2) +# CHECK-NEXT: 1 4 1.00 U fmulp %st, %st(1) +# CHECK-NEXT: 1 4 1.00 U fmulp %st, %st(2) # CHECK-NEXT: 3 14 1.00 * U fimuls (%ecx) # CHECK-NEXT: 3 14 1.00 * U fimull (%eax) # CHECK-NEXT: 1 1 0.50 U fnop @@ -321,20 +321,20 @@ fyl2xp1 # CHECK-NEXT: 1 100 0.25 U frstor (%eax) # CHECK-NEXT: 2 2 0.50 U wait # CHECK-NEXT: 1 100 0.25 U fnsave (%eax) -# CHECK-NEXT: 1 3 1.00 U fsub %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsub %st(2) +# CHECK-NEXT: 1 3 1.00 U fsub %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsub %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fsubs (%ecx) # CHECK-NEXT: 2 10 1.00 * U fsubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fisubs (%ecx) # CHECK-NEXT: 3 13 2.00 * U fisubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubr %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubr %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fsubrs (%ecx) # CHECK-NEXT: 2 10 1.00 * U fsubrl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fisubrs (%ecx) # CHECK-NEXT: 3 13 2.00 * U fisubrl (%eax) # CHECK-NEXT: 1 2 1.00 U ftst @@ -343,8 +343,8 @@ fyl2xp1 # CHECK-NEXT: 1 1 1.00 U fucomp %st(1) # CHECK-NEXT: 1 1 1.00 U fucomp %st(3) # CHECK-NEXT: 1 2 1.00 U fucompp -# CHECK-NEXT: 1 2 1.00 U fucomi %st(3) -# CHECK-NEXT: 1 2 1.00 U fucompi %st(3) +# CHECK-NEXT: 1 2 1.00 U fucomi %st(3), %st +# CHECK-NEXT: 1 2 1.00 U fucompi %st(3), %st # CHECK-NEXT: 2 2 0.50 U wait # CHECK-NEXT: 1 100 0.25 U fxam # CHECK-NEXT: 15 17 4.00 U fxch %st(1) @@ -375,26 +375,26 @@ fyl2xp1 # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] Instructions: # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - f2xm1 # CHECK-NEXT: - - 1.00 - - - - - - - fabs -# CHECK-NEXT: - - - - - - - 1.00 - - fadd %st(0), %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - fadd %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - fadd %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - fadd %st(2), %st # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fadds (%ecx) # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - faddl (%ecx) -# CHECK-NEXT: - - - - - - - 1.00 - - faddp %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - faddp %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - faddp %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - faddp %st, %st(2) # CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - fiadds (%ecx) # CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - fiaddl (%ecx) # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fbld (%ecx) # CHECK-NEXT: - - - - 0.33 0.33 1.00 - - 0.33 fbstp (%eax) # CHECK-NEXT: - - 1.00 - - - - - - - fchs # CHECK-NEXT: - - 1.00 1.00 - - - 1.00 1.00 - fnclex -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovb %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovbe %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmove %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnb %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnbe %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovne %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnu %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovu %st(1), %st(0) +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovb %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovbe %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmove %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnb %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnbe %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovne %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnu %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovu %st(1), %st # CHECK-NEXT: - - - - - - - 1.00 - - fcom %st(1) # CHECK-NEXT: - - - - - - - 1.00 - - fcom %st(3) # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fcoms (%ecx) @@ -404,24 +404,24 @@ fyl2xp1 # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fcomps (%ecx) # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fcompl (%eax) # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fcompp -# CHECK-NEXT: - - 1.00 - - - - - - - fcomi %st(3) -# CHECK-NEXT: - - 1.00 - - - - - - - fcompi %st(3) +# CHECK-NEXT: - - 1.00 - - - - - - - fcomi %st(3), %st +# CHECK-NEXT: - - 1.00 - - - - - - - fcompi %st(3), %st # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fcos # CHECK-NEXT: - - 1.00 - - - - 1.00 - - fdecstp -# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st(0), %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st(2), %st # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivs (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivl (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st, %st(2) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - fidivs (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - fidivl (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st(0), %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st(2), %st # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivrs (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivrl (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st, %st(2) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - fidivrs (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - fidivrl (%eax) # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - ffree %st(0) @@ -455,12 +455,12 @@ fyl2xp1 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - fldln2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - fldpi # CHECK-NEXT: - - 0.50 - - - - 0.50 - - fldz -# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st(0), %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st(2), %st # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fmuls (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fmull (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st, %st(2) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - fimuls (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - fimull (%eax) # CHECK-NEXT: - - 0.50 - - - - 0.50 - - fnop @@ -488,20 +488,20 @@ fyl2xp1 # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - frstor (%eax) # CHECK-NEXT: - - 0.50 0.50 - - - 0.50 0.50 - wait # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fnsave (%eax) -# CHECK-NEXT: - - - - - - - 1.00 - - fsub %st(0), %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - fsub %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - fsub %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - fsub %st(2), %st # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fsubs (%ecx) # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fsubl (%eax) -# CHECK-NEXT: - - - - - - - 1.00 - - fsubp %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - fsubp %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - fsubp %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - fsubp %st, %st(2) # CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - fisubs (%ecx) # CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - fisubl (%eax) -# CHECK-NEXT: - - - - - - - 1.00 - - fsubr %st(0), %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - fsubr %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - fsubr %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - fsubr %st(2), %st # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fsubrs (%ecx) # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fsubrl (%eax) -# CHECK-NEXT: - - - - - - - 1.00 - - fsubrp %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - fsubrp %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - fsubrp %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - fsubrp %st, %st(2) # CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - fisubrs (%ecx) # CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - fisubrl (%eax) # CHECK-NEXT: - - 1.00 - - - - - - - ftst @@ -510,8 +510,8 @@ fyl2xp1 # CHECK-NEXT: - - - - - - - 1.00 - - fucomp %st(1) # CHECK-NEXT: - - - - - - - 1.00 - - fucomp %st(3) # CHECK-NEXT: - - 1.00 - - - - - - - fucompp -# CHECK-NEXT: - - 1.00 - - - - - - - fucomi %st(3) -# CHECK-NEXT: - - 1.00 - - - - - - - fucompi %st(3) +# CHECK-NEXT: - - 1.00 - - - - - - - fucomi %st(3), %st +# CHECK-NEXT: - - 1.00 - - - - - - - fucompi %st(3), %st # CHECK-NEXT: - - 0.50 0.50 - - - 0.50 0.50 - wait # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fxam # CHECK-NEXT: - - 4.00 2.00 - - - 4.00 5.00 - fxch %st(1) diff --git a/llvm/test/tools/llvm-mca/X86/SkylakeServer/resources-x87.s b/llvm/test/tools/llvm-mca/X86/SkylakeServer/resources-x87.s index aecb4a7ab9211..75cca5297704b 100644 --- a/llvm/test/tools/llvm-mca/X86/SkylakeServer/resources-x87.s +++ b/llvm/test/tools/llvm-mca/X86/SkylakeServer/resources-x87.s @@ -5,7 +5,7 @@ f2xm1 fabs -fadd %st(0), %st(1) +fadd %st, %st(1) fadd %st(2) fadds (%ecx) faddl (%ecx) @@ -21,14 +21,14 @@ fchs fnclex -fcmovb %st(1), %st(0) -fcmovbe %st(1), %st(0) -fcmove %st(1), %st(0) -fcmovnb %st(1), %st(0) -fcmovnbe %st(1), %st(0) -fcmovne %st(1), %st(0) -fcmovnu %st(1), %st(0) -fcmovu %st(1), %st(0) +fcmovb %st(1), %st +fcmovbe %st(1), %st +fcmove %st(1), %st +fcmovnb %st(1), %st +fcmovnbe %st(1), %st +fcmovne %st(1), %st +fcmovnu %st(1), %st +fcmovu %st(1), %st fcom %st(1) fcom %st(3) @@ -47,7 +47,7 @@ fcos fdecstp -fdiv %st(0), %st(1) +fdiv %st, %st(1) fdiv %st(2) fdivs (%ecx) fdivl (%eax) @@ -56,7 +56,7 @@ fdivp %st(2) fidivs (%ecx) fidivl (%eax) -fdivr %st(0), %st(1) +fdivr %st, %st(1) fdivr %st(2) fdivrs (%ecx) fdivrl (%eax) @@ -106,7 +106,7 @@ fldln2 fldpi fldz -fmul %st(0), %st(1) +fmul %st, %st(1) fmul %st(2) fmuls (%ecx) fmull (%eax) @@ -153,7 +153,7 @@ fnstsw (%eax) frstor (%eax) fsave (%eax) -fsub %st(0), %st(1) +fsub %st, %st(1) fsub %st(2) fsubs (%ecx) fsubl (%eax) @@ -162,7 +162,7 @@ fsubp %st(2) fisubs (%ecx) fisubl (%eax) -fsubr %st(0), %st(1) +fsubr %st, %st(1) fsubr %st(2) fsubrs (%ecx) fsubrl (%eax) @@ -208,26 +208,26 @@ fyl2xp1 # CHECK: [1] [2] [3] [4] [5] [6] Instructions: # CHECK-NEXT: 1 100 0.25 U f2xm1 # CHECK-NEXT: 1 1 1.00 U fabs -# CHECK-NEXT: 1 3 1.00 U fadd %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fadd %st(2) +# CHECK-NEXT: 1 3 1.00 U fadd %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fadd %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fadds (%ecx) # CHECK-NEXT: 2 10 1.00 * U faddl (%ecx) -# CHECK-NEXT: 1 3 1.00 U faddp %st(1) -# CHECK-NEXT: 1 3 1.00 U faddp %st(2) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fiadds (%ecx) # CHECK-NEXT: 3 13 2.00 * U fiaddl (%ecx) # CHECK-NEXT: 1 100 0.25 U fbld (%ecx) # CHECK-NEXT: 2 1 1.00 U fbstp (%eax) # CHECK-NEXT: 1 1 1.00 U fchs # CHECK-NEXT: 4 4 1.00 U fnclex -# CHECK-NEXT: 1 3 1.00 U fcmovb %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovbe %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmove %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnb %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnbe %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovne %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovnu %st(1), %st(0) -# CHECK-NEXT: 1 3 1.00 U fcmovu %st(1), %st(0) +# CHECK-NEXT: 1 3 1.00 U fcmovb %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovbe %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmove %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnb %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnbe %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovne %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovnu %st(1), %st +# CHECK-NEXT: 1 3 1.00 U fcmovu %st(1), %st # CHECK-NEXT: 1 1 1.00 U fcom %st(1) # CHECK-NEXT: 1 1 1.00 U fcom %st(3) # CHECK-NEXT: 2 8 1.00 U fcoms (%ecx) @@ -237,24 +237,24 @@ fyl2xp1 # CHECK-NEXT: 2 8 1.00 U fcomps (%ecx) # CHECK-NEXT: 2 8 1.00 U fcompl (%eax) # CHECK-NEXT: 1 100 0.25 U fcompp -# CHECK-NEXT: 1 2 1.00 U fcomi %st(3) -# CHECK-NEXT: 1 2 1.00 U fcompi %st(3) +# CHECK-NEXT: 1 2 1.00 U fcomi %st(3), %st +# CHECK-NEXT: 1 2 1.00 U fcompi %st(3), %st # CHECK-NEXT: 1 100 0.25 U fcos # CHECK-NEXT: 2 2 1.00 U fdecstp -# CHECK-NEXT: 1 15 1.00 U fdiv %st(0), %st(1) -# CHECK-NEXT: 1 20 1.00 U fdiv %st(2) +# CHECK-NEXT: 1 15 1.00 U fdiv %st, %st(1) +# CHECK-NEXT: 1 20 1.00 U fdiv %st(2), %st # CHECK-NEXT: 2 22 1.00 * U fdivs (%ecx) # CHECK-NEXT: 2 22 1.00 * U fdivl (%eax) -# CHECK-NEXT: 1 15 1.00 U fdivp %st(1) -# CHECK-NEXT: 1 15 1.00 U fdivp %st(2) +# CHECK-NEXT: 1 15 1.00 U fdivp %st, %st(1) +# CHECK-NEXT: 1 15 1.00 U fdivp %st, %st(2) # CHECK-NEXT: 3 25 1.00 * U fidivs (%ecx) # CHECK-NEXT: 3 25 1.00 * U fidivl (%eax) -# CHECK-NEXT: 1 20 1.00 U fdivr %st(0), %st(1) -# CHECK-NEXT: 1 15 1.00 U fdivr %st(2) +# CHECK-NEXT: 1 20 1.00 U fdivr %st, %st(1) +# CHECK-NEXT: 1 15 1.00 U fdivr %st(2), %st # CHECK-NEXT: 2 27 1.00 * U fdivrs (%ecx) # CHECK-NEXT: 2 27 1.00 * U fdivrl (%eax) -# CHECK-NEXT: 1 20 1.00 U fdivrp %st(1) -# CHECK-NEXT: 1 20 1.00 U fdivrp %st(2) +# CHECK-NEXT: 1 20 1.00 U fdivrp %st, %st(1) +# CHECK-NEXT: 1 20 1.00 U fdivrp %st, %st(2) # CHECK-NEXT: 3 30 1.00 * U fidivrs (%ecx) # CHECK-NEXT: 3 30 1.00 * U fidivrl (%eax) # CHECK-NEXT: 1 100 0.25 U ffree %st(0) @@ -288,12 +288,12 @@ fyl2xp1 # CHECK-NEXT: 2 1 1.00 U fldln2 # CHECK-NEXT: 2 1 1.00 U fldpi # CHECK-NEXT: 1 1 0.50 U fldz -# CHECK-NEXT: 1 4 1.00 U fmul %st(0), %st(1) -# CHECK-NEXT: 1 4 1.00 U fmul %st(2) +# CHECK-NEXT: 1 4 1.00 U fmul %st, %st(1) +# CHECK-NEXT: 1 4 1.00 U fmul %st(2), %st # CHECK-NEXT: 2 11 1.00 * U fmuls (%ecx) # CHECK-NEXT: 2 11 1.00 * U fmull (%eax) -# CHECK-NEXT: 1 4 1.00 U fmulp %st(1) -# CHECK-NEXT: 1 4 1.00 U fmulp %st(2) +# CHECK-NEXT: 1 4 1.00 U fmulp %st, %st(1) +# CHECK-NEXT: 1 4 1.00 U fmulp %st, %st(2) # CHECK-NEXT: 3 14 1.00 * U fimuls (%ecx) # CHECK-NEXT: 3 14 1.00 * U fimull (%eax) # CHECK-NEXT: 1 1 0.50 U fnop @@ -321,20 +321,20 @@ fyl2xp1 # CHECK-NEXT: 1 100 0.25 U frstor (%eax) # CHECK-NEXT: 2 2 0.50 U wait # CHECK-NEXT: 1 100 0.25 U fnsave (%eax) -# CHECK-NEXT: 1 3 1.00 U fsub %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsub %st(2) +# CHECK-NEXT: 1 3 1.00 U fsub %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsub %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fsubs (%ecx) # CHECK-NEXT: 2 10 1.00 * U fsubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fisubs (%ecx) # CHECK-NEXT: 3 13 2.00 * U fisubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubr %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubr %st(2), %st # CHECK-NEXT: 2 10 1.00 * U fsubrs (%ecx) # CHECK-NEXT: 2 10 1.00 * U fsubrl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(2) # CHECK-NEXT: 3 13 2.00 * U fisubrs (%ecx) # CHECK-NEXT: 3 13 2.00 * U fisubrl (%eax) # CHECK-NEXT: 1 2 1.00 U ftst @@ -343,8 +343,8 @@ fyl2xp1 # CHECK-NEXT: 1 1 1.00 U fucomp %st(1) # CHECK-NEXT: 1 1 1.00 U fucomp %st(3) # CHECK-NEXT: 1 2 1.00 U fucompp -# CHECK-NEXT: 1 2 1.00 U fucomi %st(3) -# CHECK-NEXT: 1 2 1.00 U fucompi %st(3) +# CHECK-NEXT: 1 2 1.00 U fucomi %st(3), %st +# CHECK-NEXT: 1 2 1.00 U fucompi %st(3), %st # CHECK-NEXT: 2 2 0.50 U wait # CHECK-NEXT: 1 100 0.25 U fxam # CHECK-NEXT: 15 17 4.00 U fxch %st(1) @@ -375,26 +375,26 @@ fyl2xp1 # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] Instructions: # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - f2xm1 # CHECK-NEXT: - - 1.00 - - - - - - - fabs -# CHECK-NEXT: - - - - - - - 1.00 - - fadd %st(0), %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - fadd %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - fadd %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - fadd %st(2), %st # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fadds (%ecx) # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - faddl (%ecx) -# CHECK-NEXT: - - - - - - - 1.00 - - faddp %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - faddp %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - faddp %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - faddp %st, %st(2) # CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - fiadds (%ecx) # CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - fiaddl (%ecx) # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fbld (%ecx) # CHECK-NEXT: - - - - 0.33 0.33 1.00 - - 0.33 fbstp (%eax) # CHECK-NEXT: - - 1.00 - - - - - - - fchs # CHECK-NEXT: - - 1.00 1.00 - - - 1.00 1.00 - fnclex -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovb %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovbe %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmove %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnb %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnbe %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovne %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnu %st(1), %st(0) -# CHECK-NEXT: - - - 1.00 - - - - - - fcmovu %st(1), %st(0) +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovb %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovbe %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmove %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnb %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnbe %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovne %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovnu %st(1), %st +# CHECK-NEXT: - - - 1.00 - - - - - - fcmovu %st(1), %st # CHECK-NEXT: - - - - - - - 1.00 - - fcom %st(1) # CHECK-NEXT: - - - - - - - 1.00 - - fcom %st(3) # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fcoms (%ecx) @@ -404,24 +404,24 @@ fyl2xp1 # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fcomps (%ecx) # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fcompl (%eax) # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fcompp -# CHECK-NEXT: - - 1.00 - - - - - - - fcomi %st(3) -# CHECK-NEXT: - - 1.00 - - - - - - - fcompi %st(3) +# CHECK-NEXT: - - 1.00 - - - - - - - fcomi %st(3), %st +# CHECK-NEXT: - - 1.00 - - - - - - - fcompi %st(3), %st # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fcos # CHECK-NEXT: - - 1.00 - - - - 1.00 - - fdecstp -# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st(0), %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdiv %st(2), %st # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivs (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivl (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivp %st, %st(2) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - fidivs (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - fidivl (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st(0), %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivr %st(2), %st # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivrs (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fdivrl (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fdivrp %st, %st(2) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - fidivrs (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - fidivrl (%eax) # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - ffree %st(0) @@ -455,12 +455,12 @@ fyl2xp1 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - fldln2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - fldpi # CHECK-NEXT: - - 0.50 - - - - 0.50 - - fldz -# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st(0), %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fmul %st(2), %st # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fmuls (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - fmull (%eax) -# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st(1) -# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st(2) +# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st, %st(1) +# CHECK-NEXT: - - 1.00 - - - - - - - fmulp %st, %st(2) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - fimuls (%ecx) # CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - fimull (%eax) # CHECK-NEXT: - - 0.50 - - - - 0.50 - - fnop @@ -488,20 +488,20 @@ fyl2xp1 # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - frstor (%eax) # CHECK-NEXT: - - 0.50 0.50 - - - 0.50 0.50 - wait # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fnsave (%eax) -# CHECK-NEXT: - - - - - - - 1.00 - - fsub %st(0), %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - fsub %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - fsub %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - fsub %st(2), %st # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fsubs (%ecx) # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fsubl (%eax) -# CHECK-NEXT: - - - - - - - 1.00 - - fsubp %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - fsubp %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - fsubp %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - fsubp %st, %st(2) # CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - fisubs (%ecx) # CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - fisubl (%eax) -# CHECK-NEXT: - - - - - - - 1.00 - - fsubr %st(0), %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - fsubr %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - fsubr %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - fsubr %st(2), %st # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fsubrs (%ecx) # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - fsubrl (%eax) -# CHECK-NEXT: - - - - - - - 1.00 - - fsubrp %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - fsubrp %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - fsubrp %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - fsubrp %st, %st(2) # CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - fisubrs (%ecx) # CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - fisubrl (%eax) # CHECK-NEXT: - - 1.00 - - - - - - - ftst @@ -510,8 +510,8 @@ fyl2xp1 # CHECK-NEXT: - - - - - - - 1.00 - - fucomp %st(1) # CHECK-NEXT: - - - - - - - 1.00 - - fucomp %st(3) # CHECK-NEXT: - - 1.00 - - - - - - - fucompp -# CHECK-NEXT: - - 1.00 - - - - - - - fucomi %st(3) -# CHECK-NEXT: - - 1.00 - - - - - - - fucompi %st(3) +# CHECK-NEXT: - - 1.00 - - - - - - - fucomi %st(3), %st +# CHECK-NEXT: - - 1.00 - - - - - - - fucompi %st(3), %st # CHECK-NEXT: - - 0.50 0.50 - - - 0.50 0.50 - wait # CHECK-NEXT: - - 0.25 0.25 - - - 0.25 0.25 - fxam # CHECK-NEXT: - - 4.00 2.00 - - - 4.00 5.00 - fxch %st(1) diff --git a/llvm/test/tools/llvm-mca/X86/Znver1/resources-x87.s b/llvm/test/tools/llvm-mca/X86/Znver1/resources-x87.s index 2f5f6ef08f1c7..030b71fb7b63f 100644 --- a/llvm/test/tools/llvm-mca/X86/Znver1/resources-x87.s +++ b/llvm/test/tools/llvm-mca/X86/Znver1/resources-x87.s @@ -5,7 +5,7 @@ f2xm1 fabs -fadd %st(0), %st(1) +fadd %st, %st(1) fadd %st(2) fadds (%ecx) faddl (%ecx) @@ -21,14 +21,14 @@ fchs fnclex -fcmovb %st(1), %st(0) -fcmovbe %st(1), %st(0) -fcmove %st(1), %st(0) -fcmovnb %st(1), %st(0) -fcmovnbe %st(1), %st(0) -fcmovne %st(1), %st(0) -fcmovnu %st(1), %st(0) -fcmovu %st(1), %st(0) +fcmovb %st(1), %st +fcmovbe %st(1), %st +fcmove %st(1), %st +fcmovnb %st(1), %st +fcmovnbe %st(1), %st +fcmovne %st(1), %st +fcmovnu %st(1), %st +fcmovu %st(1), %st fcom %st(1) fcom %st(3) @@ -47,7 +47,7 @@ fcos fdecstp -fdiv %st(0), %st(1) +fdiv %st, %st(1) fdiv %st(2) fdivs (%ecx) fdivl (%eax) @@ -56,7 +56,7 @@ fdivp %st(2) fidivs (%ecx) fidivl (%eax) -fdivr %st(0), %st(1) +fdivr %st, %st(1) fdivr %st(2) fdivrs (%ecx) fdivrl (%eax) @@ -106,7 +106,7 @@ fldln2 fldpi fldz -fmul %st(0), %st(1) +fmul %st, %st(1) fmul %st(2) fmuls (%ecx) fmull (%eax) @@ -153,7 +153,7 @@ fnstsw (%eax) frstor (%eax) fsave (%eax) -fsub %st(0), %st(1) +fsub %st, %st(1) fsub %st(2) fsubs (%ecx) fsubl (%eax) @@ -162,7 +162,7 @@ fsubp %st(2) fisubs (%ecx) fisubl (%eax) -fsubr %st(0), %st(1) +fsubr %st, %st(1) fsubr %st(2) fsubrs (%ecx) fsubrl (%eax) @@ -208,26 +208,26 @@ fyl2xp1 # CHECK: [1] [2] [3] [4] [5] [6] Instructions: # CHECK-NEXT: 1 100 0.25 U f2xm1 # CHECK-NEXT: 1 2 1.00 U fabs -# CHECK-NEXT: 1 3 1.00 U fadd %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fadd %st(2) +# CHECK-NEXT: 1 3 1.00 U fadd %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fadd %st(2), %st # CHECK-NEXT: 1 10 1.00 * U fadds (%ecx) # CHECK-NEXT: 1 10 1.00 * U faddl (%ecx) -# CHECK-NEXT: 1 3 1.00 U faddp %st(1) -# CHECK-NEXT: 1 3 1.00 U faddp %st(2) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U faddp %st, %st(2) # CHECK-NEXT: 1 10 1.00 * U fiadds (%ecx) # CHECK-NEXT: 1 10 1.00 * U fiaddl (%ecx) # CHECK-NEXT: 1 100 0.25 U fbld (%ecx) # CHECK-NEXT: 1 100 0.25 U fbstp (%eax) # CHECK-NEXT: 1 1 1.00 U fchs # CHECK-NEXT: 1 100 0.25 U fnclex -# CHECK-NEXT: 1 100 0.25 U fcmovb %st(1), %st(0) -# CHECK-NEXT: 1 100 0.25 U fcmovbe %st(1), %st(0) -# CHECK-NEXT: 1 100 0.25 U fcmove %st(1), %st(0) -# CHECK-NEXT: 1 100 0.25 U fcmovnb %st(1), %st(0) -# CHECK-NEXT: 1 100 0.25 U fcmovnbe %st(1), %st(0) -# CHECK-NEXT: 1 100 0.25 U fcmovne %st(1), %st(0) -# CHECK-NEXT: 1 100 0.25 U fcmovnu %st(1), %st(0) -# CHECK-NEXT: 1 100 0.25 U fcmovu %st(1), %st(0) +# CHECK-NEXT: 1 100 0.25 U fcmovb %st(1), %st +# CHECK-NEXT: 1 100 0.25 U fcmovbe %st(1), %st +# CHECK-NEXT: 1 100 0.25 U fcmove %st(1), %st +# CHECK-NEXT: 1 100 0.25 U fcmovnb %st(1), %st +# CHECK-NEXT: 1 100 0.25 U fcmovnbe %st(1), %st +# CHECK-NEXT: 1 100 0.25 U fcmovne %st(1), %st +# CHECK-NEXT: 1 100 0.25 U fcmovnu %st(1), %st +# CHECK-NEXT: 1 100 0.25 U fcmovu %st(1), %st # CHECK-NEXT: 1 1 1.00 U fcom %st(1) # CHECK-NEXT: 1 1 1.00 U fcom %st(3) # CHECK-NEXT: 1 8 1.00 U fcoms (%ecx) @@ -237,24 +237,24 @@ fyl2xp1 # CHECK-NEXT: 1 8 1.00 U fcomps (%ecx) # CHECK-NEXT: 1 8 1.00 U fcompl (%eax) # CHECK-NEXT: 1 1 1.00 U fcompp -# CHECK-NEXT: 1 9 0.50 U fcomi %st(3) -# CHECK-NEXT: 1 9 0.50 U fcompi %st(3) +# CHECK-NEXT: 1 9 0.50 U fcomi %st(3), %st +# CHECK-NEXT: 1 9 0.50 U fcompi %st(3), %st # CHECK-NEXT: 1 100 0.25 U fcos # CHECK-NEXT: 1 11 1.00 U fdecstp -# CHECK-NEXT: 1 15 1.00 U fdiv %st(0), %st(1) -# CHECK-NEXT: 1 15 1.00 U fdiv %st(2) +# CHECK-NEXT: 1 15 1.00 U fdiv %st, %st(1) +# CHECK-NEXT: 1 15 1.00 U fdiv %st(2), %st # CHECK-NEXT: 1 22 1.00 * U fdivs (%ecx) # CHECK-NEXT: 1 22 1.00 * U fdivl (%eax) -# CHECK-NEXT: 1 15 1.00 U fdivp %st(1) -# CHECK-NEXT: 1 15 1.00 U fdivp %st(2) +# CHECK-NEXT: 1 15 1.00 U fdivp %st, %st(1) +# CHECK-NEXT: 1 15 1.00 U fdivp %st, %st(2) # CHECK-NEXT: 1 22 1.00 * U fidivs (%ecx) # CHECK-NEXT: 1 22 1.00 * U fidivl (%eax) -# CHECK-NEXT: 1 15 1.00 U fdivr %st(0), %st(1) -# CHECK-NEXT: 1 15 1.00 U fdivr %st(2) +# CHECK-NEXT: 1 15 1.00 U fdivr %st, %st(1) +# CHECK-NEXT: 1 15 1.00 U fdivr %st(2), %st # CHECK-NEXT: 1 22 1.00 * U fdivrs (%ecx) # CHECK-NEXT: 1 22 1.00 * U fdivrl (%eax) -# CHECK-NEXT: 1 15 1.00 U fdivrp %st(1) -# CHECK-NEXT: 1 15 1.00 U fdivrp %st(2) +# CHECK-NEXT: 1 15 1.00 U fdivrp %st, %st(1) +# CHECK-NEXT: 1 15 1.00 U fdivrp %st, %st(2) # CHECK-NEXT: 1 22 1.00 * U fidivrs (%ecx) # CHECK-NEXT: 1 22 1.00 * U fidivrl (%eax) # CHECK-NEXT: 1 11 1.00 U ffree %st(0) @@ -288,12 +288,12 @@ fyl2xp1 # CHECK-NEXT: 1 11 1.00 U fldln2 # CHECK-NEXT: 1 11 1.00 U fldpi # CHECK-NEXT: 1 8 0.50 U fldz -# CHECK-NEXT: 1 3 0.50 U fmul %st(0), %st(1) -# CHECK-NEXT: 1 3 0.50 U fmul %st(2) +# CHECK-NEXT: 1 3 0.50 U fmul %st, %st(1) +# CHECK-NEXT: 1 3 0.50 U fmul %st(2), %st # CHECK-NEXT: 2 10 0.50 * U fmuls (%ecx) # CHECK-NEXT: 2 10 0.50 * U fmull (%eax) -# CHECK-NEXT: 1 3 0.50 U fmulp %st(1) -# CHECK-NEXT: 1 3 0.50 U fmulp %st(2) +# CHECK-NEXT: 1 3 0.50 U fmulp %st, %st(1) +# CHECK-NEXT: 1 3 0.50 U fmulp %st, %st(2) # CHECK-NEXT: 2 10 0.50 * U fimuls (%ecx) # CHECK-NEXT: 2 10 0.50 * U fimull (%eax) # CHECK-NEXT: 1 1 1.00 U fnop @@ -321,20 +321,20 @@ fyl2xp1 # CHECK-NEXT: 1 100 0.25 U frstor (%eax) # CHECK-NEXT: 1 1 1.00 U wait # CHECK-NEXT: 1 100 0.25 U fnsave (%eax) -# CHECK-NEXT: 1 3 1.00 U fsub %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsub %st(2) +# CHECK-NEXT: 1 3 1.00 U fsub %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsub %st(2), %st # CHECK-NEXT: 1 10 1.00 * U fsubs (%ecx) # CHECK-NEXT: 1 10 1.00 * U fsubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubp %st, %st(2) # CHECK-NEXT: 1 10 1.00 * U fisubs (%ecx) # CHECK-NEXT: 1 10 1.00 * U fisubl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(0), %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubr %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubr %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubr %st(2), %st # CHECK-NEXT: 1 10 1.00 * U fsubrs (%ecx) # CHECK-NEXT: 1 10 1.00 * U fsubrl (%eax) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(1) -# CHECK-NEXT: 1 3 1.00 U fsubrp %st(2) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(1) +# CHECK-NEXT: 1 3 1.00 U fsubrp %st, %st(2) # CHECK-NEXT: 1 10 1.00 * U fisubrs (%ecx) # CHECK-NEXT: 1 10 1.00 * U fisubrl (%eax) # CHECK-NEXT: 1 1 1.00 U ftst @@ -343,8 +343,8 @@ fyl2xp1 # CHECK-NEXT: 1 1 1.00 U fucomp %st(1) # CHECK-NEXT: 1 1 1.00 U fucomp %st(3) # CHECK-NEXT: 1 1 1.00 U fucompp -# CHECK-NEXT: 1 9 0.50 U fucomi %st(3) -# CHECK-NEXT: 1 9 0.50 U fucompi %st(3) +# CHECK-NEXT: 1 9 0.50 U fucomi %st(3), %st +# CHECK-NEXT: 1 9 0.50 U fucompi %st(3), %st # CHECK-NEXT: 1 1 1.00 U wait # CHECK-NEXT: 1 1 1.00 U fxam # CHECK-NEXT: 1 1 0.25 U fxch %st(1) @@ -377,26 +377,26 @@ fyl2xp1 # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] Instructions: # CHECK-NEXT: - - - - - - - - - - - - f2xm1 # CHECK-NEXT: - - - - - - - - - - 1.00 - fabs -# CHECK-NEXT: - - - - - - - 1.00 - - - - fadd %st(0), %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - - - fadd %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - - - fadd %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - - - fadd %st(2), %st # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - fadds (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - faddl (%ecx) -# CHECK-NEXT: - - - - - - - 1.00 - - - - faddp %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - - - faddp %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - - - faddp %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - - - faddp %st, %st(2) # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - fiadds (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - fiaddl (%ecx) # CHECK-NEXT: - - - - - - - - - - - - fbld (%ecx) # CHECK-NEXT: - - - - - - - - - - - - fbstp (%eax) # CHECK-NEXT: - - - - - - - - - - 1.00 - fchs # CHECK-NEXT: - - - - - - - - - - - - fnclex -# CHECK-NEXT: - - - - - - - - - - - - fcmovb %st(1), %st(0) -# CHECK-NEXT: - - - - - - - - - - - - fcmovbe %st(1), %st(0) -# CHECK-NEXT: - - - - - - - - - - - - fcmove %st(1), %st(0) -# CHECK-NEXT: - - - - - - - - - - - - fcmovnb %st(1), %st(0) -# CHECK-NEXT: - - - - - - - - - - - - fcmovnbe %st(1), %st(0) -# CHECK-NEXT: - - - - - - - - - - - - fcmovne %st(1), %st(0) -# CHECK-NEXT: - - - - - - - - - - - - fcmovnu %st(1), %st(0) -# CHECK-NEXT: - - - - - - - - - - - - fcmovu %st(1), %st(0) +# CHECK-NEXT: - - - - - - - - - - - - fcmovb %st(1), %st +# CHECK-NEXT: - - - - - - - - - - - - fcmovbe %st(1), %st +# CHECK-NEXT: - - - - - - - - - - - - fcmove %st(1), %st +# CHECK-NEXT: - - - - - - - - - - - - fcmovnb %st(1), %st +# CHECK-NEXT: - - - - - - - - - - - - fcmovnbe %st(1), %st +# CHECK-NEXT: - - - - - - - - - - - - fcmovne %st(1), %st +# CHECK-NEXT: - - - - - - - - - - - - fcmovnu %st(1), %st +# CHECK-NEXT: - - - - - - - - - - - - fcmovu %st(1), %st # CHECK-NEXT: - - - - - - - 1.00 - - - - fcom %st(1) # CHECK-NEXT: - - - - - - - 1.00 - - - - fcom %st(3) # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - fcoms (%ecx) @@ -406,24 +406,24 @@ fyl2xp1 # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - fcomps (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - fcompl (%eax) # CHECK-NEXT: - - - - - - - 1.00 - - - - fcompp -# CHECK-NEXT: 0.50 0.50 - - - - - 0.50 - 0.50 - - fcomi %st(3) -# CHECK-NEXT: 0.50 0.50 - - - - - 0.50 - 0.50 - - fcompi %st(3) +# CHECK-NEXT: 0.50 0.50 - - - - - 0.50 - 0.50 - - fcomi %st(3), %st +# CHECK-NEXT: 0.50 0.50 - - - - - 0.50 - 0.50 - - fcompi %st(3), %st # CHECK-NEXT: - - - - - - - - - - - - fcos # CHECK-NEXT: 0.50 0.50 - - - - - - - - 1.00 - fdecstp -# CHECK-NEXT: - - - - - - - - - - 1.00 - fdiv %st(0), %st(1) -# CHECK-NEXT: - - - - - - - - - - 1.00 - fdiv %st(2) +# CHECK-NEXT: - - - - - - - - - - 1.00 - fdiv %st, %st(1) +# CHECK-NEXT: - - - - - - - - - - 1.00 - fdiv %st(2), %st # CHECK-NEXT: 0.50 0.50 - - - - - - - - 1.00 - fdivs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - - - 1.00 - fdivl (%eax) -# CHECK-NEXT: - - - - - - - - - - 1.00 - fdivp %st(1) -# CHECK-NEXT: - - - - - - - - - - 1.00 - fdivp %st(2) +# CHECK-NEXT: - - - - - - - - - - 1.00 - fdivp %st, %st(1) +# CHECK-NEXT: - - - - - - - - - - 1.00 - fdivp %st, %st(2) # CHECK-NEXT: 0.50 0.50 - - - - - - - - 1.00 - fidivs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - - - 1.00 - fidivl (%eax) -# CHECK-NEXT: - - - - - - - - - - 1.00 - fdivr %st(0), %st(1) -# CHECK-NEXT: - - - - - - - - - - 1.00 - fdivr %st(2) +# CHECK-NEXT: - - - - - - - - - - 1.00 - fdivr %st, %st(1) +# CHECK-NEXT: - - - - - - - - - - 1.00 - fdivr %st(2), %st # CHECK-NEXT: 0.50 0.50 - - - - - - - - 1.00 - fdivrs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - - - 1.00 - fdivrl (%eax) -# CHECK-NEXT: - - - - - - - - - - 1.00 - fdivrp %st(1) -# CHECK-NEXT: - - - - - - - - - - 1.00 - fdivrp %st(2) +# CHECK-NEXT: - - - - - - - - - - 1.00 - fdivrp %st, %st(1) +# CHECK-NEXT: - - - - - - - - - - 1.00 - fdivrp %st, %st(2) # CHECK-NEXT: 0.50 0.50 - - - - - - - - 1.00 - fidivrs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - - - - 1.00 - fidivrl (%eax) # CHECK-NEXT: 0.50 0.50 - - - - - - - - 1.00 - ffree %st(0) @@ -457,12 +457,12 @@ fyl2xp1 # CHECK-NEXT: 0.50 0.50 - - - - - - - - 1.00 - fldln2 # CHECK-NEXT: 0.50 0.50 - - - - - - - - 1.00 - fldpi # CHECK-NEXT: 0.50 0.50 - - - - - - 0.50 - 0.50 - fldz -# CHECK-NEXT: - - - - - - - 0.50 0.50 - - - fmul %st(0), %st(1) -# CHECK-NEXT: - - - - - - - 0.50 0.50 - - - fmul %st(2) +# CHECK-NEXT: - - - - - - - 0.50 0.50 - - - fmul %st, %st(1) +# CHECK-NEXT: - - - - - - - 0.50 0.50 - - - fmul %st(2), %st # CHECK-NEXT: 0.50 0.50 - - - - - 0.50 0.50 - - - fmuls (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - 0.50 0.50 - - - fmull (%eax) -# CHECK-NEXT: - - - - - - - 0.50 0.50 - - - fmulp %st(1) -# CHECK-NEXT: - - - - - - - 0.50 0.50 - - - fmulp %st(2) +# CHECK-NEXT: - - - - - - - 0.50 0.50 - - - fmulp %st, %st(1) +# CHECK-NEXT: - - - - - - - 0.50 0.50 - - - fmulp %st, %st(2) # CHECK-NEXT: 0.50 0.50 - - - - - 0.50 0.50 - - - fimuls (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - 0.50 0.50 - - - fimull (%eax) # CHECK-NEXT: - - - - - - - 1.00 - - - - fnop @@ -490,20 +490,20 @@ fyl2xp1 # CHECK-NEXT: - - - - - - - - - - - - frstor (%eax) # CHECK-NEXT: - - - - - - - 1.00 - - - - wait # CHECK-NEXT: - - - - - - - - - - - - fnsave (%eax) -# CHECK-NEXT: - - - - - - - 1.00 - - - - fsub %st(0), %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - - - fsub %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - - - fsub %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - - - fsub %st(2), %st # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - fsubs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - fsubl (%eax) -# CHECK-NEXT: - - - - - - - 1.00 - - - - fsubp %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - - - fsubp %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - - - fsubp %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - - - fsubp %st, %st(2) # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - fisubs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - fisubl (%eax) -# CHECK-NEXT: - - - - - - - 1.00 - - - - fsubr %st(0), %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - - - fsubr %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - - - fsubr %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - - - fsubr %st(2), %st # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - fsubrs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - fsubrl (%eax) -# CHECK-NEXT: - - - - - - - 1.00 - - - - fsubrp %st(1) -# CHECK-NEXT: - - - - - - - 1.00 - - - - fsubrp %st(2) +# CHECK-NEXT: - - - - - - - 1.00 - - - - fsubrp %st, %st(1) +# CHECK-NEXT: - - - - - - - 1.00 - - - - fsubrp %st, %st(2) # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - fisubrs (%ecx) # CHECK-NEXT: 0.50 0.50 - - - - - 1.00 - - - - fisubrl (%eax) # CHECK-NEXT: - - - - - - - 1.00 - - - - ftst @@ -512,8 +512,8 @@ fyl2xp1 # CHECK-NEXT: - - - - - - - 1.00 - - - - fucomp %st(1) # CHECK-NEXT: - - - - - - - 1.00 - - - - fucomp %st(3) # CHECK-NEXT: - - - - - - - 1.00 - - - - fucompp -# CHECK-NEXT: 0.50 0.50 - - - - - 0.50 - 0.50 - - fucomi %st(3) -# CHECK-NEXT: 0.50 0.50 - - - - - 0.50 - 0.50 - - fucompi %st(3) +# CHECK-NEXT: 0.50 0.50 - - - - - 0.50 - 0.50 - - fucomi %st(3), %st +# CHECK-NEXT: 0.50 0.50 - - - - - 0.50 - 0.50 - - fucompi %st(3), %st # CHECK-NEXT: - - - - - - - 1.00 - - - - wait # CHECK-NEXT: - - - - - - - - - - 1.00 - fxam # CHECK-NEXT: - - - - - - - 0.25 0.25 0.25 0.25 - fxch %st(1) diff --git a/llvm/test/tools/llvm-objdump/AMDGPU/source-lines.ll b/llvm/test/tools/llvm-objdump/AMDGPU/source-lines.ll index 748f04754e4b3..4a4203d2a52e0 100644 --- a/llvm/test/tools/llvm-objdump/AMDGPU/source-lines.ll +++ b/llvm/test/tools/llvm-objdump/AMDGPU/source-lines.ll @@ -12,7 +12,7 @@ ; LINE: v_mov_b32_e32 v{{[0-9]+}}, 0x888 ; LINE: ; {{.*}}source-lines.cl:3 ; LINE: ; {{.*}}source-lines.cl:4 -; LINE: v_add_u32_e32 +; LINE: v_add_u32_e64 ; LINE: ; {{.*}}source-lines.cl:5 ; LINE: flat_store_dword ; Epilogue. @@ -28,7 +28,7 @@ ; SOURCE: v_mov_b32_e32 v{{[0-9]+}}, 0x888 ; SOURCE: ; int var1 = 0x888; ; SOURCE: ; int var2 = var0 + var1; -; SOURCE: v_add_u32_e32 +; SOURCE: v_add_u32_e64 ; SOURCE: ; *Out = var2; ; SOURCE: flat_store_dword ; Epilogue. diff --git a/llvm/test/tools/llvm-objdump/PowerPC/branch-offset.s b/llvm/test/tools/llvm-objdump/PowerPC/branch-offset.s new file mode 100644 index 0000000000000..b0b3f05f9cdb5 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/PowerPC/branch-offset.s @@ -0,0 +1,43 @@ +# RUN: llvm-mc -triple=powerpc64le-unknown-linux -filetype=obj %s -o %t.o +# RUN: llvm-objdump -d %t.o | FileCheck %s + +# RUN: llvm-mc -triple=powerpc64-unknown-linux -filetype=obj %s -o %t.o +# RUN: llvm-objdump -d %t.o | FileCheck %s + +# RUN: llvm-mc -triple=powerpc-unknown-linux -filetype=obj %s -o %t.o +# RUN: llvm-objdump -d %t.o | FileCheck %s + +# CHECK: 0000000000000000 callee_back: +# CHECK: 18: {{.*}} bl .-24 +# CHECK: 20: {{.*}} bl .+16 +# CHECK: 0000000000000030 callee_forward: + + .text + .global caller + .type caller,@function + .type callee_forward,@function + .type callee_back,@function + + .p2align 4 +callee_back: + li 3, 55 + blr + + .p2align 4 +caller: +.Lgep: + addis 2, 12, .TOC.-.Lgep@ha + addi 2, 2, .TOC.-.Lgep@l +.Llep: + .localentry caller, .Llep-.Lgep + bl callee_back + mr 31, 3 + bl callee_forward + add 3, 3, 31 + blr + + .p2align 4 +callee_forward: + li 3, 66 + blr + diff --git a/llvm/test/tools/llvm-objdump/PowerPC/lit.local.cfg b/llvm/test/tools/llvm-objdump/PowerPC/lit.local.cfg new file mode 100644 index 0000000000000..b77510721e100 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/PowerPC/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'PowerPC' in config.root.targets: + config.unsupported = True diff --git a/llvm/test/tools/llvm-objdump/eh_frame-coff.test b/llvm/test/tools/llvm-objdump/eh_frame-coff.test index 74eceeec4f31a..cb481939dcc83 100644 --- a/llvm/test/tools/llvm-objdump/eh_frame-coff.test +++ b/llvm/test/tools/llvm-objdump/eh_frame-coff.test @@ -8,7 +8,7 @@ # CHECK: Code alignment factor: 1 # CHECK: Data alignment factor: -4 # CHECK: Return address column: 8 -# CHECK: Personality Address: 004025d7 +# CHECK: Personality Address: 00000000004025d7 # CHECK: Augmentation data: 00 D7 25 40 00 00 00 # CHECK: DW_CFA_def_cfa: reg4 +4 @@ -17,7 +17,7 @@ # CHECK: DW_CFA_nop: # CHECK: 00000020 0000001c 00000024 FDE cie=00000024 pc=00401410...00401488 -# CHECK: LSDA Address: 00406000 +# CHECK: LSDA Address: 0000000000406000 # CHECK: DW_CFA_advance_loc: 1 # CHECK: DW_CFA_def_cfa_offset: +8 # CHECK: DW_CFA_offset: reg5 -8 diff --git a/llvm/test/tools/llvm-objdump/elf-symbol-visibility.test b/llvm/test/tools/llvm-objdump/elf-symbol-visibility.test new file mode 100644 index 0000000000000..da7f6d285166a --- /dev/null +++ b/llvm/test/tools/llvm-objdump/elf-symbol-visibility.test @@ -0,0 +1,37 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-objdump --syms %t | FileCheck %s + +# CHECK: SYMBOL TABLE: +# CHECK-NEXT: .text 00000000 default +# CHECK-NEXT: .text 00000000 .internal internal +# CHECK-NEXT: .text 00000000 .hidden hidden +# CHECK-NEXT: .text 00000000 .protected protected +# CHECK-NEXT: .text 00000000 0x20 mips_pic + +!ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] +Symbols: + Local: + - Name: default + Section: .text + - Name: internal + Visibility: STV_INTERNAL + Section: .text + - Name: hidden + Visibility: STV_HIDDEN + Section: .text + - Name: protected + Visibility: STV_PROTECTED + Section: .text + - Name: mips_pic + Other: [ STO_MIPS_PIC ] + Section: .text diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index ba8d3c5b8d5c0..9bd4528ef7f7e 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -2087,20 +2087,38 @@ void llvm::printSymbolTable(const ObjectFile *O, StringRef ArchiveName, outs() << SectionName; } - outs() << '\t'; if (Common || isa(O)) { uint64_t Val = Common ? Symbol.getAlignment() : ELFSymbolRef(Symbol).getSize(); - outs() << format("\t %08" PRIx64 " ", Val); + outs() << format("\t%08" PRIx64, Val); } - if (Hidden) - outs() << ".hidden "; + if (isa(O)) { + uint8_t Other = ELFSymbolRef(Symbol).getOther(); + switch (Other) { + case ELF::STV_DEFAULT: + break; + case ELF::STV_INTERNAL: + outs() << " .internal"; + break; + case ELF::STV_HIDDEN: + outs() << " .hidden"; + break; + case ELF::STV_PROTECTED: + outs() << " .protected"; + break; + default: + outs() << format(" 0x%02x", Other); + break; + } + } else if (Hidden) { + outs() << " .hidden"; + } if (Demangle) - outs() << demangle(Name) << '\n'; + outs() << ' ' << demangle(Name) << '\n'; else - outs() << Name << '\n'; + outs() << ' ' << Name << '\n'; } } diff --git a/llvm/tools/llvm-xray/xray-converter.cpp b/llvm/tools/llvm-xray/xray-converter.cpp index 3f153b99bc936..a682dbe53e3bd 100644 --- a/llvm/tools/llvm-xray/xray-converter.cpp +++ b/llvm/tools/llvm-xray/xray-converter.cpp @@ -18,7 +18,6 @@ #include "llvm/Support/EndianStream.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormatVariadic.h" -#include "llvm/Support/JSON.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" @@ -242,6 +241,31 @@ StackTrieNode *findOrCreateStackNode( return CurrentStack; } +void writeTraceViewerRecord(uint16_t Version, raw_ostream &OS, int32_t FuncId, + uint32_t TId, uint32_t PId, bool Symbolize, + const FuncIdConversionHelper &FuncIdHelper, + double EventTimestampUs, + const StackTrieNode &StackCursor, + StringRef FunctionPhenotype) { + OS << " "; + if (Version >= 3) { + OS << llvm::formatv( + R"({ "name" : "{0}", "ph" : "{1}", "tid" : "{2}", "pid" : "{3}", )" + R"("ts" : "{4:f4}", "sf" : "{5}" })", + (Symbolize ? FuncIdHelper.SymbolOrNumber(FuncId) + : llvm::to_string(FuncId)), + FunctionPhenotype, TId, PId, EventTimestampUs, + StackCursor.ExtraData.id); + } else { + OS << llvm::formatv( + R"({ "name" : "{0}", "ph" : "{1}", "tid" : "{2}", "pid" : "1", )" + R"("ts" : "{3:f3}", "sf" : "{4}" })", + (Symbolize ? FuncIdHelper.SymbolOrNumber(FuncId) + : llvm::to_string(FuncId)), + FunctionPhenotype, TId, EventTimestampUs, StackCursor.ExtraData.id); + } +} + } // namespace void TraceConverter::exportAsChromeTraceEventFormat(const Trace &Records, @@ -252,14 +276,18 @@ void TraceConverter::exportAsChromeTraceEventFormat(const Trace &Records, unsigned id_counter = 0; + OS << "{\n \"traceEvents\": ["; DenseMap StackCursorByThreadId{}; DenseMap> StackRootsByThreadId{}; DenseMap StacksByStackId{}; std::forward_list NodeStore{}; - - // Create a JSON Array which will hold all trace events. - json::Array TraceEvents; + int loop_count = 0; for (const auto &R : Records) { + if (loop_count++ == 0) + OS << "\n"; + else + OS << ",\n"; + // Chrome trace event format always wants data in micros. // CyclesPerMicro = CycleHertz / 10^6 // TSC / CyclesPerMicro == TSC * 10^6 / CycleHertz == MicroTimestamp @@ -284,15 +312,8 @@ void TraceConverter::exportAsChromeTraceEventFormat(const Trace &Records, // type of B for begin or E for end, thread id, process id, // timestamp in microseconds, and a stack frame id. The ids are logged // in an id dictionary after the events. - TraceEvents.push_back(json::Object({ - {"name", Symbolize ? FuncIdHelper.SymbolOrNumber(R.FuncId) - : llvm::to_string(R.FuncId)}, - {"ph", "B"}, - {"tid", llvm::to_string(R.TId)}, - {"pid", llvm::to_string(Version >= 3 ? R.PId : 1)}, - {"ts", llvm::formatv("{0:f4}", EventTimestampUs)}, - {"sf", llvm::to_string(StackCursor->ExtraData.id)}, - })); + writeTraceViewerRecord(Version, OS, R.FuncId, R.TId, R.PId, Symbolize, + FuncIdHelper, EventTimestampUs, *StackCursor, "B"); break; case RecordTypes::EXIT: case RecordTypes::TAIL_EXIT: @@ -303,51 +324,43 @@ void TraceConverter::exportAsChromeTraceEventFormat(const Trace &Records, // (And/Or in loop termination below) StackTrieNode *PreviousCursor = nullptr; do { - TraceEvents.push_back(json::Object({ - {"name", Symbolize - ? FuncIdHelper.SymbolOrNumber(StackCursor->FuncId) - : llvm::to_string(StackCursor->FuncId)}, - {"ph", "E"}, - {"tid", llvm::to_string(R.TId)}, - {"pid", llvm::to_string(Version >= 3 ? R.PId : 1)}, - {"ts", llvm::formatv("{0:f4}", EventTimestampUs)}, - {"sf", llvm::to_string(StackCursor->ExtraData.id)}, - })); + if (PreviousCursor != nullptr) { + OS << ",\n"; + } + writeTraceViewerRecord(Version, OS, StackCursor->FuncId, R.TId, R.PId, + Symbolize, FuncIdHelper, EventTimestampUs, + *StackCursor, "E"); PreviousCursor = StackCursor; StackCursor = StackCursor->Parent; } while (PreviousCursor->FuncId != R.FuncId && StackCursor != nullptr); break; } } + OS << "\n ],\n"; // Close the Trace Events array. + OS << " " + << "\"displayTimeUnit\": \"ns\",\n"; // The stackFrames dictionary substantially reduces size of the output file by // avoiding repeating the entire call stack of function names for each entry. - json::Object StackFrames; - for (const auto &Stack : StacksByStackId) { - const auto &StackId = Stack.first; - const auto &StackFunctionNode = Stack.second; - json::Object::iterator It; - std::tie(It, std::ignore) = StackFrames.insert({ - llvm::to_string(StackId), - json::Object{ - {"name", - Symbolize ? FuncIdHelper.SymbolOrNumber(StackFunctionNode->FuncId) - : llvm::to_string(StackFunctionNode->FuncId)}}, - }); - - if (StackFunctionNode->Parent != nullptr) - It->second.getAsObject()->insert( - {"parent", llvm::to_string(StackFunctionNode->Parent->ExtraData.id)}); + OS << R"( "stackFrames": {)"; + int stack_frame_count = 0; + for (auto map_iter : StacksByStackId) { + if (stack_frame_count++ == 0) + OS << "\n"; + else + OS << ",\n"; + OS << " "; + OS << llvm::formatv( + R"("{0}" : { "name" : "{1}")", map_iter.first, + (Symbolize ? FuncIdHelper.SymbolOrNumber(map_iter.second->FuncId) + : llvm::to_string(map_iter.second->FuncId))); + if (map_iter.second->Parent != nullptr) + OS << llvm::formatv(R"(, "parent": "{0}")", + map_iter.second->Parent->ExtraData.id); + OS << " }"; } - - json::Object TraceJSON{ - {"displayTimeUnit", "ns"}, - {"traceEvents", std::move(TraceEvents)}, - {"stackFrames", std::move(StackFrames)}, - }; - - // Pretty-print the JSON using two spaces for indentations. - OS << formatv("{0:2}", json::Value(std::move(TraceJSON))); + OS << "\n }\n"; // Close the stack frames map. + OS << "}\n"; // Close the JSON entry. } namespace llvm { diff --git a/llvm/tools/yaml2obj/yaml2wasm.cpp b/llvm/tools/yaml2obj/yaml2wasm.cpp index 2d3e3b71f0868..7d08e62bcedd8 100644 --- a/llvm/tools/yaml2obj/yaml2wasm.cpp +++ b/llvm/tools/yaml2obj/yaml2wasm.cpp @@ -172,7 +172,8 @@ int WasmWriter::writeSectionContent(raw_ostream &OS, case wasm::WASM_SYMBOL_TYPE_GLOBAL: case wasm::WASM_SYMBOL_TYPE_EVENT: encodeULEB128(Info.ElementIndex, SubSection.GetStream()); - if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) + if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 || + (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) writeStringRef(Info.Name, SubSection.GetStream()); break; case wasm::WASM_SYMBOL_TYPE_DATA: diff --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp index 2f9b428b8cfe8..463609edb73b3 100644 --- a/llvm/utils/TableGen/X86RecognizableInstr.cpp +++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -842,6 +842,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("f32mem", TYPE_M) TYPE("ssmem", TYPE_M) TYPE("RST", TYPE_ST) + TYPE("RSTi", TYPE_ST) TYPE("i128mem", TYPE_M) TYPE("i256mem", TYPE_M) TYPE("i512mem", TYPE_M) @@ -964,6 +965,7 @@ OperandEncoding RecognizableInstr::rmRegisterEncodingFromString(const std::string &s, uint8_t OpSize) { ENCODING("RST", ENCODING_FP) + ENCODING("RSTi", ENCODING_FP) ENCODING("GR16", ENCODING_RM) ENCODING("GR32", ENCODING_RM) ENCODING("GR32orGR64", ENCODING_RM) diff --git a/llvm/utils/git-svn/git-llvm b/llvm/utils/git-svn/git-llvm index 53c0b24ae2c85..bf234301f1321 100755 --- a/llvm/utils/git-svn/git-llvm +++ b/llvm/utils/git-svn/git-llvm @@ -42,7 +42,7 @@ else: # It's *almost* a straightforward mapping from the monorepo to svn... GIT_TO_SVN_DIR = { - d: (d + '/trunk') + d: (d + '/branches/release_80') for d in [ 'clang-tools-extra', 'compiler-rt', @@ -63,8 +63,8 @@ GIT_TO_SVN_DIR = { 'pstl', ] } -GIT_TO_SVN_DIR.update({'clang': 'cfe/trunk'}) -GIT_TO_SVN_DIR.update({'': 'monorepo-root/trunk'}) +GIT_TO_SVN_DIR.update({'clang': 'cfe/branches/release_80'}) +GIT_TO_SVN_DIR.update({'': 'monorepo-root/branches/release_80'}) VERBOSE = False QUIET = False diff --git a/llvm/utils/lit/lit/__init__.py b/llvm/utils/lit/lit/__init__.py index 0d849d16f076e..023bed817075f 100644 --- a/llvm/utils/lit/lit/__init__.py +++ b/llvm/utils/lit/lit/__init__.py @@ -2,7 +2,7 @@ __author__ = 'Daniel Dunbar' __email__ = 'daniel@minormatter.com' -__versioninfo__ = (0, 8, 0) +__versioninfo__ = (0, 8, 1) __version__ = '.'.join(str(v) for v in __versioninfo__) + 'dev' __all__ = [] diff --git a/llvm/utils/release/build_llvm_package.bat b/llvm/utils/release/build_llvm_package.bat index 51f425633a3d6..6a0b19b719605 100755 --- a/llvm/utils/release/build_llvm_package.bat +++ b/llvm/utils/release/build_llvm_package.bat @@ -54,7 +54,7 @@ svn.exe export -r %revision% http://llvm.org/svn/llvm-project/lldb/%branch% llvm REM Setting CMAKE_CL_SHOWINCLUDES_PREFIX to work around PR27226. set cmake_flags=-DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_INSTALL_TOOLCHAIN_ONLY=ON -DCMAKE_INSTALL_UCRT_LIBRARIES=ON -DCLANG_FORMAT_VS_VERSION=%clang_format_vs_version% -DPACKAGE_VERSION=%package_version% -DLLDB_RELOCATABLE_PYTHON=1 -DLLDB_TEST_COMPILER=%cd%\build32_stage0\bin\clang.exe -DCMAKE_CL_SHOWINCLUDES_PREFIX="Note: including file: " -REM TODO: Run all tests, including lld and compiler-rt. +REM TODO: Run the "check-all" tests. set "VSCMD_START_DIR=%CD%" call "%vsdevcmd%" -arch=x86 @@ -66,7 +66,9 @@ REM Work around VS2017 bug by using MinSizeRel. cmake -GNinja %cmake_flags% -DPYTHON_HOME=%python32_dir% -DCMAKE_BUILD_TYPE=MinSizeRel ..\llvm || exit /b ninja all || ninja all || ninja all || exit /b ninja check || ninja check || ninja check || exit /b -ninja check-clang || ninja check-clang || ninja check-clang || exit /b +ninja check-clang || ninja check-clang || ninja check-clang || exit /b +ninja check-lld || ninja check-lld || ninja check-lld || exit /b +ninja check-sanitizer || ninja check-sanitizer || ninja check-sanitizer || exit /b cd.. mkdir build32 @@ -76,7 +78,9 @@ set CXX=..\build32_stage0\bin\clang-cl cmake -GNinja %cmake_flags% -DPYTHON_HOME=%python32_dir% ..\llvm || exit /b ninja all || ninja all || ninja all || exit /b ninja check || ninja check || ninja check || exit /b -ninja check-clang || ninja check-clang || ninja check-clang || exit /b +ninja check-clang || ninja check-clang || ninja check-clang || exit /b +ninja check-lld || ninja check-lld || ninja check-lld || exit /b +ninja check-sanitizer || ninja check-sanitizer || ninja check-sanitizer || exit /b ninja package || exit /b cd .. @@ -101,7 +105,9 @@ REM Work around VS2017 bug by using MinSizeRel. cmake -GNinja %cmake_flags% -DPYTHON_HOME=%python64_dir% -DCMAKE_BUILD_TYPE=MinSizeRel ..\llvm || exit /b ninja all || ninja all || ninja all || exit /b ninja check || ninja check || ninja check || exit /b -ninja check-clang || ninja check-clang || ninja check-clang || exit /b +ninja check-clang || ninja check-clang || ninja check-clang || exit /b +ninja check-lld || ninja check-lld || ninja check-lld || exit /b +ninja check-sanitizer || ninja check-sanitizer || ninja check-sanitizer || exit /b cd.. mkdir build64 @@ -111,6 +117,8 @@ set CXX=..\build64_stage0\bin\clang-cl cmake -GNinja %cmake_flags% -DPYTHON_HOME=%python64_dir% ..\llvm || exit /b ninja all || ninja all || ninja all || exit /b ninja check || ninja check || ninja check || exit /b -ninja check-clang || ninja check-clang || ninja check-clang || exit /b +ninja check-clang || ninja check-clang || ninja check-clang || exit /b +ninja check-lld || ninja check-lld || ninja check-lld || exit /b +ninja check-sanitizer || ninja check-sanitizer || ninja check-sanitizer || exit /b ninja package || exit /b cd .. diff --git a/llvm/utils/release/merge-request.sh b/llvm/utils/release/merge-request.sh index 333b9043af356..c9763ee3cec43 100755 --- a/llvm/utils/release/merge-request.sh +++ b/llvm/utils/release/merge-request.sh @@ -101,6 +101,9 @@ case $stable_version in 7.0) release_metabug="39106" ;; + 8.0) + release_metabug="41221" + ;; *) echo "error: invalid stable version" exit 1 diff --git a/openmp/runtime/src/kmp_atomic.h b/openmp/runtime/src/kmp_atomic.h index 288916cd27c9d..004d1a6cdd6bc 100644 --- a/openmp/runtime/src/kmp_atomic.h +++ b/openmp/runtime/src/kmp_atomic.h @@ -364,7 +364,7 @@ static inline void __kmp_acquire_atomic_lock(kmp_atomic_lock_t *lck, #if OMPT_SUPPORT && OMPT_OPTIONAL if (ompt_enabled.ompt_callback_mutex_acquire) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( - ompt_mutex_atomic, 0, kmp_mutex_impl_queuing, (ompt_wait_id_t)lck, + ompt_mutex_atomic, 0, kmp_mutex_impl_queuing, (ompt_wait_id_t)(uintptr_t)lck, OMPT_GET_RETURN_ADDRESS(0)); } #endif @@ -374,7 +374,7 @@ static inline void __kmp_acquire_atomic_lock(kmp_atomic_lock_t *lck, #if OMPT_SUPPORT && OMPT_OPTIONAL if (ompt_enabled.ompt_callback_mutex_acquired) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( - ompt_mutex_atomic, (ompt_wait_id_t)lck, OMPT_GET_RETURN_ADDRESS(0)); + ompt_mutex_atomic, (ompt_wait_id_t)(uintptr_t)lck, OMPT_GET_RETURN_ADDRESS(0)); } #endif } @@ -390,7 +390,7 @@ static inline void __kmp_release_atomic_lock(kmp_atomic_lock_t *lck, #if OMPT_SUPPORT && OMPT_OPTIONAL if (ompt_enabled.ompt_callback_mutex_released) { ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( - ompt_mutex_atomic, (ompt_wait_id_t)lck, OMPT_GET_RETURN_ADDRESS(0)); + ompt_mutex_atomic, (ompt_wait_id_t)(uintptr_t)lck, OMPT_GET_RETURN_ADDRESS(0)); } #endif } diff --git a/openmp/runtime/src/kmp_csupport.cpp b/openmp/runtime/src/kmp_csupport.cpp index 61d4a93011205..3afefed560fd6 100644 --- a/openmp/runtime/src/kmp_csupport.cpp +++ b/openmp/runtime/src/kmp_csupport.cpp @@ -848,7 +848,7 @@ void __kmpc_ordered(ident_t *loc, kmp_int32 gtid) { if (ompt_enabled.enabled) { OMPT_STORE_RETURN_ADDRESS(gtid); team = __kmp_team_from_gtid(gtid); - lck = (ompt_wait_id_t)&team->t.t_ordered.dt.t_value; + lck = (ompt_wait_id_t)(uintptr_t)&team->t.t_ordered.dt.t_value; /* OMPT state update */ th->th.ompt_thread_info.wait_id = lck; th->th.ompt_thread_info.state = ompt_state_wait_ordered; @@ -857,8 +857,8 @@ void __kmpc_ordered(ident_t *loc, kmp_int32 gtid) { codeptr_ra = OMPT_LOAD_RETURN_ADDRESS(gtid); if (ompt_enabled.ompt_callback_mutex_acquire) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( - ompt_mutex_ordered, omp_lock_hint_none, kmp_mutex_impl_spin, - (ompt_wait_id_t)lck, codeptr_ra); + ompt_mutex_ordered, omp_lock_hint_none, kmp_mutex_impl_spin, lck, + codeptr_ra); } } #endif @@ -877,7 +877,7 @@ void __kmpc_ordered(ident_t *loc, kmp_int32 gtid) { /* OMPT event callback */ if (ompt_enabled.ompt_callback_mutex_acquired) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( - ompt_mutex_ordered, (ompt_wait_id_t)lck, codeptr_ra); + ompt_mutex_ordered, (ompt_wait_id_t)(uintptr_t)lck, codeptr_ra); } } #endif @@ -917,7 +917,8 @@ void __kmpc_end_ordered(ident_t *loc, kmp_int32 gtid) { if (ompt_enabled.ompt_callback_mutex_released) { ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( ompt_mutex_ordered, - (ompt_wait_id_t)&__kmp_team_from_gtid(gtid)->t.t_ordered.dt.t_value, + (ompt_wait_id_t)(uintptr_t)&__kmp_team_from_gtid(gtid) + ->t.t_ordered.dt.t_value, OMPT_LOAD_RETURN_ADDRESS(gtid)); } #endif @@ -1188,7 +1189,7 @@ void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, ti = __kmp_threads[global_tid]->th.ompt_thread_info; /* OMPT state update */ prev_state = ti.state; - ti.wait_id = (ompt_wait_id_t)lck; + ti.wait_id = (ompt_wait_id_t)(uintptr_t)lck; ti.state = ompt_state_wait_critical; /* OMPT event callback */ @@ -1196,7 +1197,7 @@ void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, if (ompt_enabled.ompt_callback_mutex_acquire) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( ompt_mutex_critical, omp_lock_hint_none, __ompt_get_mutex_impl_type(), - (ompt_wait_id_t)crit, codeptr_ra); + (ompt_wait_id_t)(uintptr_t)lck, codeptr_ra); } } #endif @@ -1216,7 +1217,7 @@ void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, /* OMPT event callback */ if (ompt_enabled.ompt_callback_mutex_acquired) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( - ompt_mutex_critical, (ompt_wait_id_t)crit, codeptr_ra); + ompt_mutex_critical, (ompt_wait_id_t)(uintptr_t)lck, codeptr_ra); } } #endif @@ -1402,14 +1403,15 @@ void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, ti = __kmp_threads[global_tid]->th.ompt_thread_info; /* OMPT state update */ prev_state = ti.state; - ti.wait_id = (ompt_wait_id_t)lck; + ti.wait_id = (ompt_wait_id_t)(uintptr_t)lck; ti.state = ompt_state_wait_critical; /* OMPT event callback */ if (ompt_enabled.ompt_callback_mutex_acquire) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( ompt_mutex_critical, (unsigned int)hint, - __ompt_get_mutex_impl_type(crit), (ompt_wait_id_t)crit, codeptr); + __ompt_get_mutex_impl_type(crit), (ompt_wait_id_t)(uintptr_t)lck, + codeptr); } } #endif @@ -1440,14 +1442,15 @@ void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, ti = __kmp_threads[global_tid]->th.ompt_thread_info; /* OMPT state update */ prev_state = ti.state; - ti.wait_id = (ompt_wait_id_t)lck; + ti.wait_id = (ompt_wait_id_t)(uintptr_t)lck; ti.state = ompt_state_wait_critical; /* OMPT event callback */ if (ompt_enabled.ompt_callback_mutex_acquire) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( ompt_mutex_critical, (unsigned int)hint, - __ompt_get_mutex_impl_type(0, ilk), (ompt_wait_id_t)crit, codeptr); + __ompt_get_mutex_impl_type(0, ilk), (ompt_wait_id_t)(uintptr_t)lck, + codeptr); } } #endif @@ -1467,7 +1470,7 @@ void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, /* OMPT event callback */ if (ompt_enabled.ompt_callback_mutex_acquired) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( - ompt_mutex_critical, (ompt_wait_id_t)crit, codeptr); + ompt_mutex_critical, (ompt_wait_id_t)(uintptr_t)lck, codeptr); } } #endif @@ -1565,7 +1568,8 @@ void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, OMPT_STORE_RETURN_ADDRESS(global_tid); if (ompt_enabled.ompt_callback_mutex_released) { ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( - ompt_mutex_critical, (ompt_wait_id_t)crit, OMPT_LOAD_RETURN_ADDRESS(0)); + ompt_mutex_critical, (ompt_wait_id_t)(uintptr_t)lck, + OMPT_LOAD_RETURN_ADDRESS(0)); } #endif @@ -2189,8 +2193,8 @@ void __kmpc_init_lock_with_hint(ident_t *loc, kmp_int32 gtid, void **user_lock, if (ompt_enabled.ompt_callback_lock_init) { ompt_callbacks.ompt_callback(ompt_callback_lock_init)( ompt_mutex_lock, (omp_lock_hint_t)hint, - __ompt_get_mutex_impl_type(user_lock), (ompt_wait_id_t)user_lock, - codeptr); + __ompt_get_mutex_impl_type(user_lock), + (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif } @@ -2213,8 +2217,8 @@ void __kmpc_init_nest_lock_with_hint(ident_t *loc, kmp_int32 gtid, if (ompt_enabled.ompt_callback_lock_init) { ompt_callbacks.ompt_callback(ompt_callback_lock_init)( ompt_mutex_nest_lock, (omp_lock_hint_t)hint, - __ompt_get_mutex_impl_type(user_lock), (ompt_wait_id_t)user_lock, - codeptr); + __ompt_get_mutex_impl_type(user_lock), + (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif } @@ -2239,8 +2243,8 @@ void __kmpc_init_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_lock_init) { ompt_callbacks.ompt_callback(ompt_callback_lock_init)( ompt_mutex_lock, omp_lock_hint_none, - __ompt_get_mutex_impl_type(user_lock), (ompt_wait_id_t)user_lock, - codeptr); + __ompt_get_mutex_impl_type(user_lock), + (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif @@ -2282,7 +2286,7 @@ void __kmpc_init_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_lock_init) { ompt_callbacks.ompt_callback(ompt_callback_lock_init)( ompt_mutex_lock, omp_lock_hint_none, __ompt_get_mutex_impl_type(), - (ompt_wait_id_t)user_lock, codeptr); + (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif @@ -2311,8 +2315,8 @@ void __kmpc_init_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_lock_init) { ompt_callbacks.ompt_callback(ompt_callback_lock_init)( ompt_mutex_nest_lock, omp_lock_hint_none, - __ompt_get_mutex_impl_type(user_lock), (ompt_wait_id_t)user_lock, - codeptr); + __ompt_get_mutex_impl_type(user_lock), + (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif @@ -2357,7 +2361,7 @@ void __kmpc_init_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_lock_init) { ompt_callbacks.ompt_callback(ompt_callback_lock_init)( ompt_mutex_nest_lock, omp_lock_hint_none, __ompt_get_mutex_impl_type(), - (ompt_wait_id_t)user_lock, codeptr); + (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif @@ -2393,7 +2397,7 @@ void __kmpc_destroy_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { lck = (kmp_user_lock_p)user_lock; } ompt_callbacks.ompt_callback(ompt_callback_lock_destroy)( - ompt_mutex_lock, (ompt_wait_id_t)user_lock, codeptr); + ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif KMP_D_LOCK_FUNC(user_lock, destroy)((kmp_dyna_lock_t *)user_lock); @@ -2421,7 +2425,7 @@ void __kmpc_destroy_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { codeptr = OMPT_GET_RETURN_ADDRESS(0); if (ompt_enabled.ompt_callback_lock_destroy) { ompt_callbacks.ompt_callback(ompt_callback_lock_destroy)( - ompt_mutex_lock, (ompt_wait_id_t)user_lock, codeptr); + ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif @@ -2461,7 +2465,7 @@ void __kmpc_destroy_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { codeptr = OMPT_GET_RETURN_ADDRESS(0); if (ompt_enabled.ompt_callback_lock_destroy) { ompt_callbacks.ompt_callback(ompt_callback_lock_destroy)( - ompt_mutex_nest_lock, (ompt_wait_id_t)user_lock, codeptr); + ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif KMP_D_LOCK_FUNC(user_lock, destroy)((kmp_dyna_lock_t *)user_lock); @@ -2493,7 +2497,7 @@ void __kmpc_destroy_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { codeptr = OMPT_GET_RETURN_ADDRESS(0); if (ompt_enabled.ompt_callback_lock_destroy) { ompt_callbacks.ompt_callback(ompt_callback_lock_destroy)( - ompt_mutex_nest_lock, (ompt_wait_id_t)user_lock, codeptr); + ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif @@ -2538,8 +2542,8 @@ void __kmpc_set_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_mutex_acquire) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( ompt_mutex_lock, omp_lock_hint_none, - __ompt_get_mutex_impl_type(user_lock), (ompt_wait_id_t)user_lock, - codeptr); + __ompt_get_mutex_impl_type(user_lock), + (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif #if KMP_USE_INLINED_TAS @@ -2560,7 +2564,7 @@ void __kmpc_set_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { #if OMPT_SUPPORT && OMPT_OPTIONAL if (ompt_enabled.ompt_callback_mutex_acquired) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( - ompt_mutex_lock, (ompt_wait_id_t)user_lock, codeptr); + ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif @@ -2593,7 +2597,7 @@ void __kmpc_set_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_mutex_acquire) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( ompt_mutex_lock, omp_lock_hint_none, __ompt_get_mutex_impl_type(), - (ompt_wait_id_t)lck, codeptr); + (ompt_wait_id_t)(uintptr_t)lck, codeptr); } #endif @@ -2606,7 +2610,7 @@ void __kmpc_set_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { #if OMPT_SUPPORT && OMPT_OPTIONAL if (ompt_enabled.ompt_callback_mutex_acquired) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( - ompt_mutex_lock, (ompt_wait_id_t)lck, codeptr); + ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); } #endif @@ -2628,8 +2632,8 @@ void __kmpc_set_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_mutex_acquire) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( ompt_mutex_nest_lock, omp_lock_hint_none, - __ompt_get_mutex_impl_type(user_lock), (ompt_wait_id_t)user_lock, - codeptr); + __ompt_get_mutex_impl_type(user_lock), + (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } } #endif @@ -2646,13 +2650,14 @@ void __kmpc_set_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_mutex_acquired) { // lock_first ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( - ompt_mutex_nest_lock, (ompt_wait_id_t)user_lock, codeptr); + ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock, + codeptr); } } else { if (ompt_enabled.ompt_callback_nest_lock) { // lock_next ompt_callbacks.ompt_callback(ompt_callback_nest_lock)( - ompt_scope_begin, (ompt_wait_id_t)user_lock, codeptr); + ompt_scope_begin, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } } } @@ -2690,7 +2695,8 @@ void __kmpc_set_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_mutex_acquire) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( ompt_mutex_nest_lock, omp_lock_hint_none, - __ompt_get_mutex_impl_type(), (ompt_wait_id_t)lck, codeptr); + __ompt_get_mutex_impl_type(), (ompt_wait_id_t)(uintptr_t)lck, + codeptr); } } #endif @@ -2707,13 +2713,13 @@ void __kmpc_set_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_mutex_acquired) { // lock_first ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( - ompt_mutex_nest_lock, (ompt_wait_id_t)lck, codeptr); + ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); } } else { if (ompt_enabled.ompt_callback_nest_lock) { // lock_next ompt_callbacks.ompt_callback(ompt_callback_nest_lock)( - ompt_scope_begin, (ompt_wait_id_t)lck, codeptr); + ompt_scope_begin, (ompt_wait_id_t)(uintptr_t)lck, codeptr); } } } @@ -2749,7 +2755,7 @@ void __kmpc_unset_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { codeptr = OMPT_GET_RETURN_ADDRESS(0); if (ompt_enabled.ompt_callback_mutex_released) { ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( - ompt_mutex_lock, (ompt_wait_id_t)user_lock, codeptr); + ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif @@ -2778,7 +2784,7 @@ void __kmpc_unset_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { codeptr = OMPT_GET_RETURN_ADDRESS(0); if (ompt_enabled.ompt_callback_mutex_released) { ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( - ompt_mutex_lock, (ompt_wait_id_t)lck, codeptr); + ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); } #endif @@ -2810,7 +2816,7 @@ void __kmpc_unset_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { codeptr = OMPT_GET_RETURN_ADDRESS(0); if (ompt_enabled.ompt_callback_mutex_released) { ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( - ompt_mutex_lock, (ompt_wait_id_t)lck, codeptr); + ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); } #endif @@ -2838,12 +2844,13 @@ void __kmpc_unset_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_mutex_released) { // release_lock_last ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( - ompt_mutex_nest_lock, (ompt_wait_id_t)user_lock, codeptr); + ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock, + codeptr); } } else if (ompt_enabled.ompt_callback_nest_lock) { // release_lock_prev ompt_callbacks.ompt_callback(ompt_callback_nest_lock)( - ompt_scope_end, (ompt_wait_id_t)user_lock, codeptr); + ompt_scope_end, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } } #endif @@ -2887,12 +2894,12 @@ void __kmpc_unset_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_mutex_released) { // release_lock_last ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( - ompt_mutex_nest_lock, (ompt_wait_id_t)lck, codeptr); + ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); } } else if (ompt_enabled.ompt_callback_nest_lock) { // release_lock_previous ompt_callbacks.ompt_callback(ompt_callback_nest_lock)( - ompt_mutex_scope_end, (ompt_wait_id_t)lck, codeptr); + ompt_mutex_scope_end, (ompt_wait_id_t)(uintptr_t)lck, codeptr); } } #endif @@ -2929,12 +2936,12 @@ void __kmpc_unset_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_mutex_released) { // release_lock_last ompt_callbacks.ompt_callback(ompt_callback_mutex_released)( - ompt_mutex_nest_lock, (ompt_wait_id_t)lck, codeptr); + ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); } } else if (ompt_enabled.ompt_callback_nest_lock) { // release_lock_previous ompt_callbacks.ompt_callback(ompt_callback_nest_lock)( - ompt_mutex_scope_end, (ompt_wait_id_t)lck, codeptr); + ompt_mutex_scope_end, (ompt_wait_id_t)(uintptr_t)lck, codeptr); } } #endif @@ -2960,8 +2967,8 @@ int __kmpc_test_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_mutex_acquire) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( ompt_mutex_lock, omp_lock_hint_none, - __ompt_get_mutex_impl_type(user_lock), (ompt_wait_id_t)user_lock, - codeptr); + __ompt_get_mutex_impl_type(user_lock), + (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif #if KMP_USE_INLINED_TAS @@ -2983,7 +2990,7 @@ int __kmpc_test_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { #if OMPT_SUPPORT && OMPT_OPTIONAL if (ompt_enabled.ompt_callback_mutex_acquired) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( - ompt_mutex_lock, (ompt_wait_id_t)user_lock, codeptr); + ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif return FTN_TRUE; @@ -3024,7 +3031,7 @@ int __kmpc_test_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_mutex_acquire) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( ompt_mutex_lock, omp_lock_hint_none, __ompt_get_mutex_impl_type(), - (ompt_wait_id_t)lck, codeptr); + (ompt_wait_id_t)(uintptr_t)lck, codeptr); } #endif @@ -3039,7 +3046,7 @@ int __kmpc_test_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { #if OMPT_SUPPORT && OMPT_OPTIONAL if (rc && ompt_enabled.ompt_callback_mutex_acquired) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( - ompt_mutex_lock, (ompt_wait_id_t)lck, codeptr); + ompt_mutex_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); } #endif @@ -3065,8 +3072,8 @@ int __kmpc_test_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_mutex_acquire) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( ompt_mutex_nest_lock, omp_lock_hint_none, - __ompt_get_mutex_impl_type(user_lock), (ompt_wait_id_t)user_lock, - codeptr); + __ompt_get_mutex_impl_type(user_lock), + (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } #endif rc = KMP_D_LOCK_FUNC(user_lock, test)((kmp_dyna_lock_t *)user_lock, gtid); @@ -3083,13 +3090,14 @@ int __kmpc_test_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_mutex_acquired) { // lock_first ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( - ompt_mutex_nest_lock, (ompt_wait_id_t)user_lock, codeptr); + ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)user_lock, + codeptr); } } else { if (ompt_enabled.ompt_callback_nest_lock) { // lock_next ompt_callbacks.ompt_callback(ompt_callback_nest_lock)( - ompt_scope_begin, (ompt_wait_id_t)user_lock, codeptr); + ompt_scope_begin, (ompt_wait_id_t)(uintptr_t)user_lock, codeptr); } } } @@ -3130,7 +3138,8 @@ int __kmpc_test_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { ompt_enabled.ompt_callback_mutex_acquire) { ompt_callbacks.ompt_callback(ompt_callback_mutex_acquire)( ompt_mutex_nest_lock, omp_lock_hint_none, - __ompt_get_mutex_impl_type(), (ompt_wait_id_t)lck, codeptr); + __ompt_get_mutex_impl_type(), (ompt_wait_id_t)(uintptr_t)lck, + codeptr); } #endif @@ -3148,13 +3157,13 @@ int __kmpc_test_nest_lock(ident_t *loc, kmp_int32 gtid, void **user_lock) { if (ompt_enabled.ompt_callback_mutex_acquired) { // lock_first ompt_callbacks.ompt_callback(ompt_callback_mutex_acquired)( - ompt_mutex_nest_lock, (ompt_wait_id_t)lck, codeptr); + ompt_mutex_nest_lock, (ompt_wait_id_t)(uintptr_t)lck, codeptr); } } else { if (ompt_enabled.ompt_callback_nest_lock) { // lock_next ompt_callbacks.ompt_callback(ompt_callback_nest_lock)( - ompt_mutex_scope_begin, (ompt_wait_id_t)lck, codeptr); + ompt_mutex_scope_begin, (ompt_wait_id_t)(uintptr_t)lck, codeptr); } } } diff --git a/openmp/runtime/src/ompt-general.cpp b/openmp/runtime/src/ompt-general.cpp index cea00fff07acc..80a859196e68d 100644 --- a/openmp/runtime/src/ompt-general.cpp +++ b/openmp/runtime/src/ompt-general.cpp @@ -450,9 +450,6 @@ OMPT_API_ROUTINE ompt_set_result_t ompt_set_callback(ompt_callbacks_t which, OMPT_API_ROUTINE int ompt_get_callback(ompt_callbacks_t which, ompt_callback_t *callback) { - if (!ompt_enabled.enabled) - return ompt_get_callback_failure; - switch (which) { #define ompt_event_macro(event_name, callback_type, event_id) \ @@ -460,7 +457,7 @@ OMPT_API_ROUTINE int ompt_get_callback(ompt_callbacks_t which, if (ompt_event_implementation_status(event_name)) { \ ompt_callback_t mycb = \ (ompt_callback_t)ompt_callbacks.ompt_callback(event_name); \ - if (ompt_enabled.event_name && mycb) { \ + if (mycb) { \ *callback = mycb; \ return ompt_get_callback_success; \ } \ @@ -483,15 +480,11 @@ OMPT_API_ROUTINE int ompt_get_callback(ompt_callbacks_t which, OMPT_API_ROUTINE int ompt_get_parallel_info(int ancestor_level, ompt_data_t **parallel_data, int *team_size) { - if (!ompt_enabled.enabled) - return 0; return __ompt_get_parallel_info_internal(ancestor_level, parallel_data, team_size); } OMPT_API_ROUTINE int ompt_get_state(ompt_wait_id_t *wait_id) { - if (!ompt_enabled.enabled) - return ompt_state_work_serial; int thread_state = __ompt_get_state_internal(wait_id); if (thread_state == ompt_state_undefined) { @@ -506,8 +499,6 @@ OMPT_API_ROUTINE int ompt_get_state(ompt_wait_id_t *wait_id) { ****************************************************************************/ OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void) { - if (!ompt_enabled.enabled) - return NULL; return __ompt_get_thread_data_internal(); } @@ -516,8 +507,6 @@ OMPT_API_ROUTINE int ompt_get_task_info(int ancestor_level, int *type, ompt_frame_t **task_frame, ompt_data_t **parallel_data, int *thread_num) { - if (!ompt_enabled.enabled) - return 0; return __ompt_get_task_info_internal(ancestor_level, type, task_data, task_frame, parallel_data, thread_num); } @@ -592,7 +581,7 @@ OMPT_API_ROUTINE int ompt_get_place_num(void) { #if !KMP_AFFINITY_SUPPORTED return -1; #else - if (!ompt_enabled.enabled || __kmp_get_gtid() < 0) + if (__kmp_get_gtid() < 0) return -1; int gtid; @@ -613,7 +602,7 @@ OMPT_API_ROUTINE int ompt_get_partition_place_nums(int place_nums_size, #if !KMP_AFFINITY_SUPPORTED return 0; #else - if (!ompt_enabled.enabled || __kmp_get_gtid() < 0) + if (__kmp_get_gtid() < 0) return 0; int i, gtid, place_num, first_place, last_place, start, end; @@ -648,7 +637,7 @@ OMPT_API_ROUTINE int ompt_get_partition_place_nums(int place_nums_size, ****************************************************************************/ OMPT_API_ROUTINE int ompt_get_proc_id(void) { - if (!ompt_enabled.enabled || __kmp_get_gtid() < 0) + if (__kmp_get_gtid() < 0) return -1; #if KMP_OS_LINUX return sched_getcpu(); diff --git a/openmp/runtime/src/ompt-specific.cpp b/openmp/runtime/src/ompt-specific.cpp index a6d02ddb85e3c..b985f84614481 100644 --- a/openmp/runtime/src/ompt-specific.cpp +++ b/openmp/runtime/src/ompt-specific.cpp @@ -211,7 +211,7 @@ ompt_data_t *__ompt_get_thread_data_internal() { void __ompt_thread_assign_wait_id(void *variable) { kmp_info_t *ti = ompt_get_thread(); - ti->th.ompt_thread_info.wait_id = (ompt_wait_id_t)variable; + ti->th.ompt_thread_info.wait_id = (ompt_wait_id_t)(uintptr_t)variable; } int __ompt_get_state_internal(ompt_wait_id_t *omp_wait_id) { diff --git a/openmp/runtime/test/ompt/misc/api_calls_without_ompt.c b/openmp/runtime/test/ompt/misc/api_calls_without_ompt.c deleted file mode 100644 index 976c20f47f1e2..0000000000000 --- a/openmp/runtime/test/ompt/misc/api_calls_without_ompt.c +++ /dev/null @@ -1,148 +0,0 @@ -// RUN: %libomp-compile-and-run | FileCheck %s -// REQUIRES: ompt - -#define _BSD_SOURCE -#define _DEFAULT_SOURCE - -#include -#include -#include -#include - -static ompt_set_callback_t ompt_set_callback; -static ompt_get_callback_t ompt_get_callback; -static ompt_get_state_t ompt_get_state; -static ompt_get_task_info_t ompt_get_task_info; -static ompt_get_thread_data_t ompt_get_thread_data; -static ompt_get_parallel_info_t ompt_get_parallel_info; -static ompt_get_unique_id_t ompt_get_unique_id; -static ompt_get_num_procs_t ompt_get_num_procs; -static ompt_get_num_places_t ompt_get_num_places; -static ompt_get_place_proc_ids_t ompt_get_place_proc_ids; -static ompt_get_place_num_t ompt_get_place_num; -static ompt_get_partition_place_nums_t ompt_get_partition_place_nums; -static ompt_get_proc_id_t ompt_get_proc_id; -static ompt_enumerate_states_t ompt_enumerate_states; -static ompt_enumerate_mutex_impls_t ompt_enumerate_mutex_impls; - -int main() { - // Call OpenMP API function to force initialization of OMPT. - // (omp_get_thread_num() does not work because it just returns 0 if the - // runtime isn't initialized yet...) - omp_get_num_threads(); - - ompt_data_t *tdata = ompt_get_thread_data(); - uint64_t tvalue = tdata ? tdata->value : 0; - - printf("%" PRIu64 ": ompt_get_num_places()=%d\n", tvalue, - ompt_get_num_places()); - - printf("%" PRIu64 ": ompt_get_place_proc_ids()=%d\n", tvalue, - ompt_get_place_proc_ids(0, 0, NULL)); - - printf("%" PRIu64 ": ompt_get_place_num()=%d\n", tvalue, - ompt_get_place_num()); - - printf("%" PRIu64 ": ompt_get_partition_place_nums()=%d\n", tvalue, - ompt_get_partition_place_nums(0, NULL)); - - printf("%" PRIu64 ": ompt_get_proc_id()=%d\n", tvalue, ompt_get_proc_id()); - - printf("%" PRIu64 ": ompt_get_num_procs()=%d\n", tvalue, - ompt_get_num_procs()); - - ompt_callback_t callback; - printf("%" PRIu64 ": ompt_get_callback()=%d\n", tvalue, - ompt_get_callback(ompt_callback_thread_begin, &callback)); - - printf("%" PRIu64 ": ompt_get_state()=%d\n", tvalue, ompt_get_state(NULL)); - - int state = omp_state_undefined; - const char *state_name; - printf("%" PRIu64 ": ompt_enumerate_states()=%d\n", tvalue, - ompt_enumerate_states(state, &state, &state_name)); - - int impl = ompt_mutex_impl_unknown; - const char *impl_name; - printf("%" PRIu64 ": ompt_enumerate_mutex_impls()=%d\n", tvalue, - ompt_enumerate_mutex_impls(impl, &impl, &impl_name)); - - printf("%" PRIu64 ": ompt_get_thread_data()=%p\n", tvalue, - ompt_get_thread_data()); - - printf("%" PRIu64 ": ompt_get_parallel_info()=%d\n", tvalue, - ompt_get_parallel_info(0, NULL, NULL)); - - printf("%" PRIu64 ": ompt_get_task_info()=%d\n", tvalue, - ompt_get_task_info(0, NULL, NULL, NULL, NULL, NULL)); - - // Check if libomp supports the callbacks for this test. - - // CHECK: 0: NULL_POINTER=[[NULL:.*$]] - - // CHECK: {{^}}[[MASTER_ID:[0-9]+]]: ompt_get_num_places()={{[0-9]+}} - - // CHECK: {{^}}[[MASTER_ID]]: ompt_get_place_proc_ids()={{[0-9]+}} - - // CHECK: {{^}}[[MASTER_ID]]: ompt_get_place_num()=-1 - - // CHECK: {{^}}[[MASTER_ID]]: ompt_get_partition_place_nums()=0 - - // CHECK: {{^}}[[MASTER_ID]]: ompt_get_proc_id()=-1 - - // CHECK: {{^}}[[MASTER_ID]]: ompt_get_num_procs()={{[0-9]+}} - - // CHECK: {{^}}[[MASTER_ID]]: ompt_get_callback()=0 - - // CHECK: {{^}}[[MASTER_ID]]: ompt_get_state()=0 - - // CHECK: {{^}}[[MASTER_ID]]: ompt_enumerate_states()=1 - - // CHECK: {{^}}[[MASTER_ID]]: ompt_enumerate_mutex_impls()=1 - - // CHECK: {{^}}[[MASTER_ID]]: ompt_get_thread_data()=[[NULL]] - - // CHECK: {{^}}[[MASTER_ID]]: ompt_get_parallel_info()=0 - - // CHECK: {{^}}[[MASTER_ID]]: ompt_get_task_info()=0 - - return 0; -} - -int ompt_initialize(ompt_function_lookup_t lookup, ompt_data_t *tool_data) { - ompt_set_callback = (ompt_set_callback_t)lookup("ompt_set_callback"); - ompt_get_callback = (ompt_get_callback_t)lookup("ompt_get_callback"); - ompt_get_state = (ompt_get_state_t)lookup("ompt_get_state"); - ompt_get_task_info = (ompt_get_task_info_t)lookup("ompt_get_task_info"); - ompt_get_thread_data = (ompt_get_thread_data_t)lookup("ompt_get_thread_data"); - ompt_get_parallel_info = - (ompt_get_parallel_info_t)lookup("ompt_get_parallel_info"); - ompt_get_unique_id = (ompt_get_unique_id_t)lookup("ompt_get_unique_id"); - - ompt_get_num_procs = (ompt_get_num_procs_t)lookup("ompt_get_num_procs"); - ompt_get_num_places = (ompt_get_num_places_t)lookup("ompt_get_num_places"); - ompt_get_place_proc_ids = - (ompt_get_place_proc_ids_t)lookup("ompt_get_place_proc_ids"); - ompt_get_place_num = (ompt_get_place_num_t)lookup("ompt_get_place_num"); - ompt_get_partition_place_nums = - (ompt_get_partition_place_nums_t)lookup("ompt_get_partition_place_nums"); - ompt_get_proc_id = (ompt_get_proc_id_t)lookup("ompt_get_proc_id"); - ompt_enumerate_states = - (ompt_enumerate_states_t)lookup("ompt_enumerate_states"); - ompt_enumerate_mutex_impls = - (ompt_enumerate_mutex_impls_t)lookup("ompt_enumerate_mutex_impls"); - - printf("0: NULL_POINTER=%p\n", (void *)NULL); - return 0; // no success -> OMPT not enabled -} - -void ompt_finalize(ompt_data_t *tool_data) { - printf("0: ompt_event_runtime_shutdown\n"); -} - -ompt_start_tool_result_t *ompt_start_tool(unsigned int omp_version, - const char *runtime_version) { - static ompt_start_tool_result_t ompt_start_tool_result = {&ompt_initialize, - &ompt_finalize, 0}; - return &ompt_start_tool_result; -} diff --git a/openmp/runtime/test/ompt/synchronization/lock.c b/openmp/runtime/test/ompt/synchronization/lock.c index eae15757d6f28..2a934ee855aba 100644 --- a/openmp/runtime/test/ompt/synchronization/lock.c +++ b/openmp/runtime/test/ompt/synchronization/lock.c @@ -10,7 +10,7 @@ int main() print_ids(0); omp_lock_t lock; - printf("%" PRIu64 ": &lock: %" PRIu64 "\n", ompt_get_thread_data()->value, (uint64_t) &lock); + printf("%" PRIu64 ": &lock: %" PRIu64 "\n", ompt_get_thread_data()->value, (ompt_wait_id_t)(uintptr_t) &lock); omp_init_lock(&lock); print_fuzzy_address(1); omp_set_lock(&lock); diff --git a/openmp/runtime/test/ompt/synchronization/nest_lock.c b/openmp/runtime/test/ompt/synchronization/nest_lock.c index c83ceaf5d0d13..159048e2e74de 100644 --- a/openmp/runtime/test/ompt/synchronization/nest_lock.c +++ b/openmp/runtime/test/ompt/synchronization/nest_lock.c @@ -10,7 +10,7 @@ int main() print_ids(0); omp_nest_lock_t nest_lock; - printf("%" PRIu64 ": &nest_lock: %lli\n", ompt_get_thread_data()->value, (long long) &nest_lock); + printf("%" PRIu64 ": &nest_lock: %lli\n", ompt_get_thread_data()->value, (ompt_wait_id_t)(uintptr_t) &nest_lock); omp_init_nest_lock(&nest_lock); print_fuzzy_address(1); omp_set_nest_lock(&nest_lock);