From ba13fa2a5d57581bff1a7e9322234af30f4882f6 Mon Sep 17 00:00:00 2001 From: Michael Spencer Date: Fri, 8 Mar 2024 23:30:33 -0800 Subject: [PATCH 001/953] [llvm][Support] Add and use errnoAsErrorCode (#84423) LLVM is inconsistent about how it converts `errno` to `std::error_code`. This can cause problems because values outside of `std::errc` compare differently if one is system and one is generic on POSIX systems. This is even more of a problem on Windows where use of the system category is just wrong, as that is for Windows errors, which have a completely different mapping than POSIX/generic errors. This patch fixes one instance of this mistake in `JSONTransport.cpp`. This patch adds `errnoAsErrorCode()` which makes it so people do not need to think about this issue in the future. It also cleans up a lot of usage of `errno` in LLVM and Clang. --- clang-tools-extra/clangd/JSONTransport.cpp | 3 +- .../linux/DirectoryWatcher-linux.cpp | 9 +-- llvm/include/llvm/Support/Error.h | 14 ++++ llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp | 9 +-- .../ExecutorSharedMemoryMapperService.cpp | 11 ++- llvm/lib/Object/ArchiveWriter.cpp | 2 +- llvm/lib/Support/AutoConvert.cpp | 8 +-- llvm/lib/Support/LockFileManager.cpp | 2 +- llvm/lib/Support/Path.cpp | 19 ++---- llvm/lib/Support/RandomNumberGenerator.cpp | 7 +- llvm/lib/Support/Unix/Memory.inc | 10 +-- llvm/lib/Support/Unix/Path.inc | 67 +++++++++---------- llvm/lib/Support/Unix/Process.inc | 12 ++-- llvm/lib/Support/Windows/Process.inc | 2 +- llvm/lib/Support/Windows/Program.inc | 4 +- llvm/lib/Support/raw_ostream.cpp | 6 +- llvm/lib/Support/raw_socket_stream.cpp | 2 +- 17 files changed, 94 insertions(+), 93 deletions(-) diff --git a/clang-tools-extra/clangd/JSONTransport.cpp b/clang-tools-extra/clangd/JSONTransport.cpp index 346c7dfb66a1..3c0e198433f3 100644 --- a/clang-tools-extra/clangd/JSONTransport.cpp +++ b/clang-tools-extra/clangd/JSONTransport.cpp @@ -107,8 +107,7 @@ public: return error(std::make_error_code(std::errc::operation_canceled), "Got signal, shutting down"); if (ferror(In)) - return llvm::errorCodeToError( - std::error_code(errno, std::system_category())); + return llvm::errorCodeToError(llvm::errnoAsErrorCode()); if (readRawMessage(JSON)) { ThreadCrashReporter ScopedReporter([&JSON]() { auto &OS = llvm::errs(); diff --git a/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp b/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp index beca9586988b..2ffbc1a22695 100644 --- a/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp +++ b/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp @@ -333,8 +333,7 @@ llvm::Expected> clang::DirectoryWatcher::creat const int InotifyFD = inotify_init1(IN_CLOEXEC); if (InotifyFD == -1) return llvm::make_error( - std::string("inotify_init1() error: ") + strerror(errno), - llvm::inconvertibleErrorCode()); + llvm::errnoAsErrorCode(), std::string(": inotify_init1()")); const int InotifyWD = inotify_add_watch( InotifyFD, Path.str().c_str(), @@ -346,15 +345,13 @@ llvm::Expected> clang::DirectoryWatcher::creat ); if (InotifyWD == -1) return llvm::make_error( - std::string("inotify_add_watch() error: ") + strerror(errno), - llvm::inconvertibleErrorCode()); + llvm::errnoAsErrorCode(), std::string(": inotify_add_watch()")); auto InotifyPollingStopper = SemaphorePipe::create(); if (!InotifyPollingStopper) return llvm::make_error( - std::string("SemaphorePipe::create() error: ") + strerror(errno), - llvm::inconvertibleErrorCode()); + llvm::errnoAsErrorCode(), std::string(": SemaphorePipe::create()")); return std::make_unique( Path, Receiver, WaitForInitialSync, InotifyFD, InotifyWD, diff --git a/llvm/include/llvm/Support/Error.h b/llvm/include/llvm/Support/Error.h index bb4f38f7ec35..894b6484336a 100644 --- a/llvm/include/llvm/Support/Error.h +++ b/llvm/include/llvm/Support/Error.h @@ -1180,6 +1180,20 @@ Error errorCodeToError(std::error_code EC); /// will trigger a call to abort(). std::error_code errorToErrorCode(Error Err); +/// Helper to get errno as an std::error_code. +/// +/// errno should always be represented using the generic category as that's what +/// both libc++ and libstdc++ do. On POSIX systems you can also represent them +/// using the system category, however this makes them compare differently for +/// values outside of those used by `std::errc` if one is generic and the other +/// is system. +/// +/// See the libc++ and libstdc++ implementations of `default_error_condition` on +/// the system category for more details on what the difference is. +inline std::error_code errnoAsErrorCode() { + return std::error_code(errno, std::generic_category()); +} + /// Convert an ErrorOr to an Expected. template Expected errorOrToExpected(ErrorOr &&EO) { if (auto EC = EO.getError()) diff --git a/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp b/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp index 9cfe547c84c3..2c87b344083e 100644 --- a/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp +++ b/llvm/lib/ExecutionEngine/Orc/MemoryMapper.cpp @@ -241,8 +241,7 @@ void SharedMemoryMapper::reserve(size_t NumBytes, int SharedMemoryFile = shm_open(SharedMemoryName.c_str(), O_RDWR, 0700); if (SharedMemoryFile < 0) { - return OnReserved(errorCodeToError( - std::error_code(errno, std::generic_category()))); + return OnReserved(errorCodeToError(errnoAsErrorCode())); } // this prevents other processes from accessing it by name @@ -251,8 +250,7 @@ void SharedMemoryMapper::reserve(size_t NumBytes, LocalAddr = mmap(nullptr, NumBytes, PROT_READ | PROT_WRITE, MAP_SHARED, SharedMemoryFile, 0); if (LocalAddr == MAP_FAILED) { - return OnReserved(errorCodeToError( - std::error_code(errno, std::generic_category()))); + return OnReserved(errorCodeToError(errnoAsErrorCode())); } close(SharedMemoryFile); @@ -376,8 +374,7 @@ void SharedMemoryMapper::release(ArrayRef Bases, #if defined(LLVM_ON_UNIX) if (munmap(Reservations[Base].LocalAddr, Reservations[Base].Size) != 0) - Err = joinErrors(std::move(Err), errorCodeToError(std::error_code( - errno, std::generic_category()))); + Err = joinErrors(std::move(Err), errorCodeToError(errnoAsErrorCode())); #elif defined(_WIN32) diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp index e8b0e240ac1f..6614beec760f 100644 --- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp +++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.cpp @@ -62,15 +62,15 @@ ExecutorSharedMemoryMapperService::reserve(uint64_t Size) { int SharedMemoryFile = shm_open(SharedMemoryName.c_str(), O_RDWR | O_CREAT | O_EXCL, 0700); if (SharedMemoryFile < 0) - return errorCodeToError(std::error_code(errno, std::generic_category())); + return errorCodeToError(errnoAsErrorCode()); // by default size is 0 if (ftruncate(SharedMemoryFile, Size) < 0) - return errorCodeToError(std::error_code(errno, std::generic_category())); + return errorCodeToError(errnoAsErrorCode()); void *Addr = mmap(nullptr, Size, PROT_NONE, MAP_SHARED, SharedMemoryFile, 0); if (Addr == MAP_FAILED) - return errorCodeToError(std::error_code(errno, std::generic_category())); + return errorCodeToError(errnoAsErrorCode()); close(SharedMemoryFile); @@ -140,7 +140,7 @@ Expected ExecutorSharedMemoryMapperService::initialize( NativeProt |= PROT_EXEC; if (mprotect(Segment.Addr.toPtr(), Segment.Size, NativeProt)) - return errorCodeToError(std::error_code(errno, std::generic_category())); + return errorCodeToError(errnoAsErrorCode()); #elif defined(_WIN32) @@ -240,8 +240,7 @@ Error ExecutorSharedMemoryMapperService::release( #if defined(LLVM_ON_UNIX) if (munmap(Base.toPtr(), Size) != 0) - Err = joinErrors(std::move(Err), errorCodeToError(std::error_code( - errno, std::generic_category()))); + Err = joinErrors(std::move(Err), errorCodeToError(errnoAsErrorCode())); #elif defined(_WIN32) (void)Size; diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp index 96e4ec1ee0b7..be51093933a8 100644 --- a/llvm/lib/Object/ArchiveWriter.cpp +++ b/llvm/lib/Object/ArchiveWriter.cpp @@ -926,7 +926,7 @@ Expected computeArchiveRelativePath(StringRef From, StringRef To) { ErrorOr> PathToOrErr = canonicalizePath(To); ErrorOr> DirFromOrErr = canonicalizePath(From); if (!PathToOrErr || !DirFromOrErr) - return errorCodeToError(std::error_code(errno, std::generic_category())); + return errorCodeToError(errnoAsErrorCode()); const SmallString<128> &PathTo = *PathToOrErr; const SmallString<128> &DirFrom = sys::path::parent_path(*DirFromOrErr); diff --git a/llvm/lib/Support/AutoConvert.cpp b/llvm/lib/Support/AutoConvert.cpp index 8170e553ac6e..74842e9167bd 100644 --- a/llvm/lib/Support/AutoConvert.cpp +++ b/llvm/lib/Support/AutoConvert.cpp @@ -82,21 +82,21 @@ int enableAutoConversion(int FD) { std::error_code llvm::disableAutoConversion(int FD) { if (::disableAutoConversion(FD) == -1) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } std::error_code llvm::enableAutoConversion(int FD) { if (::enableAutoConversion(FD) == -1) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } std::error_code llvm::restoreStdHandleAutoConversion(int FD) { if (::restoreStdHandleAutoConversion(FD) == -1) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } @@ -111,7 +111,7 @@ std::error_code llvm::setFileTag(int FD, int CCSID, bool Text) { Tag.ft_rsvflags = 0; if (fcntl(FD, F_SETTAG, &Tag) == -1) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } diff --git a/llvm/lib/Support/LockFileManager.cpp b/llvm/lib/Support/LockFileManager.cpp index facdc5a0d7d4..083f8d7b37be 100644 --- a/llvm/lib/Support/LockFileManager.cpp +++ b/llvm/lib/Support/LockFileManager.cpp @@ -87,7 +87,7 @@ static std::error_code getHostID(SmallVectorImpl &HostID) { struct timespec wait = {1, 0}; // 1 second. uuid_t uuid; if (gethostuuid(uuid, &wait) != 0) - return std::error_code(errno, std::system_category()); + return errnoAsErrorCode(); uuid_string_t UUIDStr; uuid_unparse(uuid, UUIDStr); diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp index acee228a0d04..4db9bc80b415 100644 --- a/llvm/lib/Support/Path.cpp +++ b/llvm/lib/Support/Path.cpp @@ -23,7 +23,6 @@ #include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include -#include #if !defined(_MSC_VER) && !defined(__MINGW32__) #include @@ -1010,7 +1009,7 @@ static std::error_code copy_file_internal(int ReadFD, int WriteFD) { delete[] Buf; if (BytesRead < 0 || BytesWritten < 0) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } @@ -1060,7 +1059,7 @@ ErrorOr md5_contents(int FD) { } if (BytesRead < 0) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); MD5::MD5Result Result; Hash.final(Result); return Result; @@ -1228,7 +1227,7 @@ TempFile::~TempFile() { assert(Done); } Error TempFile::discard() { Done = true; if (FD != -1 && close(FD) == -1) { - std::error_code EC = std::error_code(errno, std::generic_category()); + std::error_code EC = errnoAsErrorCode(); return errorCodeToError(EC); } FD = -1; @@ -1297,10 +1296,8 @@ Error TempFile::keep(const Twine &Name) { if (!RenameEC) TmpName = ""; - if (close(FD) == -1) { - std::error_code EC(errno, std::generic_category()); - return errorCodeToError(EC); - } + if (close(FD) == -1) + return errorCodeToError(errnoAsErrorCode()); FD = -1; return errorCodeToError(RenameEC); @@ -1319,10 +1316,8 @@ Error TempFile::keep() { TmpName = ""; - if (close(FD) == -1) { - std::error_code EC(errno, std::generic_category()); - return errorCodeToError(EC); - } + if (close(FD) == -1) + return errorCodeToError(errnoAsErrorCode()); FD = -1; return Error::success(); diff --git a/llvm/lib/Support/RandomNumberGenerator.cpp b/llvm/lib/Support/RandomNumberGenerator.cpp index aea0132a93fe..12fe109dbc2b 100644 --- a/llvm/lib/Support/RandomNumberGenerator.cpp +++ b/llvm/lib/Support/RandomNumberGenerator.cpp @@ -18,6 +18,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Error.h" #include "llvm/Support/raw_ostream.h" #ifdef _WIN32 #include "llvm/Support/Windows/WindowsSupport.h" @@ -81,14 +82,14 @@ std::error_code llvm::getRandomBytes(void *Buffer, size_t Size) { std::error_code Ret; ssize_t BytesRead = read(Fd, Buffer, Size); if (BytesRead == -1) - Ret = std::error_code(errno, std::system_category()); + Ret = errnoAsErrorCode(); else if (BytesRead != static_cast(Size)) Ret = std::error_code(EIO, std::system_category()); if (close(Fd) == -1) - Ret = std::error_code(errno, std::system_category()); + Ret = errnoAsErrorCode(); return Ret; } - return std::error_code(errno, std::system_category()); + return errnoAsErrorCode(); #endif } diff --git a/llvm/lib/Support/Unix/Memory.inc b/llvm/lib/Support/Unix/Memory.inc index 69bd1164343d..bac208a7d543 100644 --- a/llvm/lib/Support/Unix/Memory.inc +++ b/llvm/lib/Support/Unix/Memory.inc @@ -86,7 +86,7 @@ MemoryBlock Memory::allocateMappedMemory(size_t NumBytes, #else fd = open("/dev/zero", O_RDWR); if (fd == -1) { - EC = std::error_code(errno, std::generic_category()); + EC = errnoAsErrorCode(); return MemoryBlock(); } #endif @@ -122,7 +122,7 @@ MemoryBlock Memory::allocateMappedMemory(size_t NumBytes, return allocateMappedMemory(NumBytes, nullptr, PFlags, EC); } - EC = std::error_code(errno, std::generic_category()); + EC = errnoAsErrorCode(); #if !defined(MAP_ANON) close(fd); #endif @@ -153,7 +153,7 @@ std::error_code Memory::releaseMappedMemory(MemoryBlock &M) { return std::error_code(); if (0 != ::munmap(M.Address, M.AllocatedSize)) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); M.Address = nullptr; M.AllocatedSize = 0; @@ -186,7 +186,7 @@ std::error_code Memory::protectMappedMemory(const MemoryBlock &M, if (InvalidateCache && !(Protect & PROT_READ)) { int Result = ::mprotect((void *)Start, End - Start, Protect | PROT_READ); if (Result != 0) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); Memory::InvalidateInstructionCache(M.Address, M.AllocatedSize); InvalidateCache = false; @@ -196,7 +196,7 @@ std::error_code Memory::protectMappedMemory(const MemoryBlock &M, int Result = ::mprotect((void *)Start, End - Start, Protect); if (Result != 0) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); if (InvalidateCache) Memory::InvalidateInstructionCache(M.Address, M.AllocatedSize); diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc index 9f89d63bb0fd..968e2c459f3f 100644 --- a/llvm/lib/Support/Unix/Path.inc +++ b/llvm/lib/Support/Unix/Path.inc @@ -357,7 +357,7 @@ uint32_t file_status::getLinkCount() const { return fs_st_nlinks; } ErrorOr disk_space(const Twine &Path) { struct STATVFS Vfs; if (::STATVFS(const_cast(Path.str().c_str()), &Vfs)) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); auto FrSize = STATVFS_F_FRSIZE(Vfs); space_info SpaceInfo; SpaceInfo.capacity = static_cast(Vfs.f_blocks) * FrSize; @@ -386,7 +386,7 @@ std::error_code current_path(SmallVectorImpl &result) { // See if there was a real error. if (errno != ENOMEM) { result.clear(); - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); } // Otherwise there just wasn't enough space. result.resize_for_overwrite(result.capacity() * 2); @@ -403,7 +403,7 @@ std::error_code set_current_path(const Twine &path) { StringRef p = path.toNullTerminatedStringRef(path_storage); if (::chdir(p.begin()) == -1) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } @@ -415,7 +415,7 @@ std::error_code create_directory(const Twine &path, bool IgnoreExisting, if (::mkdir(p.begin(), Perms) == -1) { if (errno != EEXIST || !IgnoreExisting) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); } return std::error_code(); @@ -431,7 +431,7 @@ std::error_code create_link(const Twine &to, const Twine &from) { StringRef t = to.toNullTerminatedStringRef(to_storage); if (::symlink(t.begin(), f.begin()) == -1) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } @@ -444,7 +444,7 @@ std::error_code create_hard_link(const Twine &to, const Twine &from) { StringRef t = to.toNullTerminatedStringRef(to_storage); if (::link(t.begin(), f.begin()) == -1) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } @@ -456,7 +456,7 @@ std::error_code remove(const Twine &path, bool IgnoreNonExisting) { struct stat buf; if (lstat(p.begin(), &buf) != 0) { if (errno != ENOENT || !IgnoreNonExisting) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } @@ -470,7 +470,7 @@ std::error_code remove(const Twine &path, bool IgnoreNonExisting) { if (::remove(p.begin()) == -1) { if (errno != ENOENT || !IgnoreNonExisting) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); } return std::error_code(); @@ -563,7 +563,7 @@ static bool is_local_impl(struct STATVFS &Vfs) { std::error_code is_local(const Twine &Path, bool &Result) { struct STATVFS Vfs; if (::STATVFS(const_cast(Path.str().c_str()), &Vfs)) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); Result = is_local_impl(Vfs); return std::error_code(); @@ -572,7 +572,7 @@ std::error_code is_local(const Twine &Path, bool &Result) { std::error_code is_local(int FD, bool &Result) { struct STATVFS Vfs; if (::FSTATVFS(FD, &Vfs)) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); Result = is_local_impl(Vfs); return std::error_code(); @@ -586,7 +586,7 @@ std::error_code rename(const Twine &from, const Twine &to) { StringRef t = to.toNullTerminatedStringRef(to_storage); if (::rename(f.begin(), t.begin()) == -1) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } @@ -595,7 +595,7 @@ std::error_code resize_file(int FD, uint64_t Size) { // Use ftruncate as a fallback. It may or may not allocate space. At least on // OS X with HFS+ it does. if (::ftruncate(FD, Size) == -1) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } @@ -617,7 +617,7 @@ std::error_code access(const Twine &Path, AccessMode Mode) { StringRef P = Path.toNullTerminatedStringRef(PathStorage); if (::access(P.begin(), convertAccessMode(Mode)) == -1) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); if (Mode == AccessMode::Execute) { // Don't say that directories are executable. @@ -726,7 +726,7 @@ static file_type typeForMode(mode_t Mode) { static std::error_code fillStatus(int StatRet, const struct stat &Status, file_status &Result) { if (StatRet != 0) { - std::error_code EC(errno, std::generic_category()); + std::error_code EC = errnoAsErrorCode(); if (EC == errc::no_such_file_or_directory) Result = file_status(file_type::file_not_found); else @@ -782,13 +782,13 @@ std::error_code setPermissions(const Twine &Path, perms Permissions) { StringRef P = Path.toNullTerminatedStringRef(PathStorage); if (::chmod(P.begin(), Permissions)) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } std::error_code setPermissions(int FD, perms Permissions) { if (::fchmod(FD, Permissions)) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } @@ -799,7 +799,7 @@ std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime, Times[0] = sys::toTimeSpec(AccessTime); Times[1] = sys::toTimeSpec(ModificationTime); if (::futimens(FD, Times)) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); #elif defined(HAVE_FUTIMES) timeval Times[2]; @@ -809,7 +809,7 @@ std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime, sys::toTimeVal(std::chrono::time_point_cast( ModificationTime)); if (::futimes(FD, Times)) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); #elif defined(__MVS__) attrib_t Attr; @@ -819,7 +819,7 @@ std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime, Attr.att_mtimechg = 1; Attr.att_mtime = sys::toTimeT(ModificationTime); if (::__fchattr(FD, &Attr, sizeof(Attr)) != 0) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); #else #warning Missing futimes() and futimens() @@ -858,7 +858,7 @@ std::error_code mapped_file_region::init(int FD, uint64_t Offset, Mapping = ::mmap(nullptr, Size, prot, flags, FD, Offset); if (Mapping == MAP_FAILED) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } @@ -897,7 +897,7 @@ std::error_code detail::directory_iterator_construct(detail::DirIterState &it, SmallString<128> path_null(path); DIR *directory = ::opendir(path_null.c_str()); if (!directory) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); it.IterationHandle = reinterpret_cast(directory); // Add something for replace_filename to replace. @@ -932,7 +932,7 @@ std::error_code detail::directory_iterator_increment(detail::DirIterState &It) { errno = 0; dirent *CurDir = ::readdir(reinterpret_cast(It.IterationHandle)); if (CurDir == nullptr && errno != 0) { - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); } else if (CurDir != nullptr) { StringRef Name(CurDir->d_name); if ((Name.size() == 1 && Name[0] == '.') || @@ -1023,7 +1023,7 @@ std::error_code openFile(const Twine &Name, int &ResultFD, // when open is overloaded, such as in Bionic. auto Open = [&]() { return ::open(P.begin(), OpenFlags, Mode); }; if ((ResultFD = sys::RetryAfterSignal(-1, Open)) < 0) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); #ifndef O_CLOEXEC if (!(Flags & OF_ChildInherit)) { int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC); @@ -1087,10 +1087,10 @@ std::error_code openFile(const Twine &Name, int &ResultFD, * open(). */ if ((Flags & OF_Append) && lseek(ResultFD, 0, SEEK_END) == -1) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); struct stat Stat; if (fstat(ResultFD, &Stat) == -1) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); if (S_ISREG(Stat.st_mode)) { bool DoSetTag = (Access & FA_Write) && (Disp != CD_OpenExisting) && !Stat.st_tag.ft_txtflag && !Stat.st_tag.ft_ccsid && @@ -1190,7 +1190,7 @@ Expected readNativeFile(file_t FD, MutableArrayRef Buf) { #endif ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size); if (ssize_t(NumRead) == -1) - return errorCodeToError(std::error_code(errno, std::generic_category())); + return errorCodeToError(errnoAsErrorCode()); return NumRead; } @@ -1206,11 +1206,11 @@ Expected readNativeFileSlice(file_t FD, MutableArrayRef Buf, sys::RetryAfterSignal(-1, ::pread, FD, Buf.data(), Size, Offset); #else if (lseek(FD, Offset, SEEK_SET) == -1) - return errorCodeToError(std::error_code(errno, std::generic_category())); + return errorCodeToError(errnoAsErrorCode()); ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size); #endif if (NumRead == -1) - return errorCodeToError(std::error_code(errno, std::generic_category())); + return errorCodeToError(errnoAsErrorCode()); return NumRead; } @@ -1243,8 +1243,7 @@ std::error_code lockFile(int FD) { Lock.l_len = 0; if (::fcntl(FD, F_SETLKW, &Lock) != -1) return std::error_code(); - int Error = errno; - return std::error_code(Error, std::generic_category()); + return errnoAsErrorCode(); } std::error_code unlockFile(int FD) { @@ -1255,7 +1254,7 @@ std::error_code unlockFile(int FD) { Lock.l_len = 0; if (::fcntl(FD, F_SETLK, &Lock) != -1) return std::error_code(); - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); } std::error_code closeFile(file_t &F) { @@ -1321,7 +1320,7 @@ std::error_code real_path(const Twine &path, SmallVectorImpl &dest, StringRef P = path.toNullTerminatedStringRef(Storage); char Buffer[PATH_MAX]; if (::realpath(P.begin(), Buffer) == nullptr) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); dest.append(Buffer, Buffer + strlen(Buffer)); return std::error_code(); } @@ -1330,7 +1329,7 @@ std::error_code changeFileOwnership(int FD, uint32_t Owner, uint32_t Group) { auto FChown = [&]() { return ::fchown(FD, Owner, Group); }; // Retry if fchown call fails due to interruption. if ((sys::RetryAfterSignal(-1, FChown)) < 0) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } @@ -1513,7 +1512,7 @@ std::error_code copy_file(const Twine &From, const Twine &To) { #endif if (!copyfile(FromS.c_str(), ToS.c_str(), /*State=*/NULL, COPYFILE_DATA)) return std::error_code(); - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); } #endif // __APPLE__ diff --git a/llvm/lib/Support/Unix/Process.inc b/llvm/lib/Support/Unix/Process.inc index ecba37da9827..ae90924cae1b 100644 --- a/llvm/lib/Support/Unix/Process.inc +++ b/llvm/lib/Support/Unix/Process.inc @@ -86,7 +86,7 @@ Expected Process::getPageSize() { #error Cannot get the page size on this machine #endif if (page_size == -1) - return errorCodeToError(std::error_code(errno, std::generic_category())); + return errorCodeToError(errnoAsErrorCode()); return static_cast(page_size); } @@ -235,7 +235,7 @@ std::error_code Process::FixupStandardFileDescriptors() { assert(errno && "expected errno to be set if fstat failed!"); // fstat should return EBADF if the file descriptor is closed. if (errno != EBADF) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); } // if fstat succeeds, move on to the next FD. if (!errno) @@ -247,13 +247,13 @@ std::error_code Process::FixupStandardFileDescriptors() { // RetryAfterSignal when open is overloaded, such as in Bionic. auto Open = [&]() { return ::open("/dev/null", O_RDWR); }; if ((NullFD = RetryAfterSignal(-1, Open)) < 0) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); } if (NullFD == StandardFD) FDC.keepOpen(); else if (dup2(NullFD, StandardFD) < 0) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); } return std::error_code(); } @@ -262,7 +262,7 @@ std::error_code Process::SafelyCloseFileDescriptor(int FD) { // Create a signal set filled with *all* signals. sigset_t FullSet, SavedSet; if (sigfillset(&FullSet) < 0 || sigfillset(&SavedSet) < 0) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); // Atomically swap our current signal mask with a full mask. #if LLVM_ENABLE_THREADS @@ -270,7 +270,7 @@ std::error_code Process::SafelyCloseFileDescriptor(int FD) { return std::error_code(EC, std::generic_category()); #else if (sigprocmask(SIG_SETMASK, &FullSet, &SavedSet) < 0) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); #endif // Attempt to close the file descriptor. // We need to save the error, if one occurs, because our subsequent call to diff --git a/llvm/lib/Support/Windows/Process.inc b/llvm/lib/Support/Windows/Process.inc index 6b4b723d4744..34d294b232c3 100644 --- a/llvm/lib/Support/Windows/Process.inc +++ b/llvm/lib/Support/Windows/Process.inc @@ -276,7 +276,7 @@ std::error_code Process::FixupStandardFileDescriptors() { std::error_code Process::SafelyCloseFileDescriptor(int FD) { if (::close(FD) < 0) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } diff --git a/llvm/lib/Support/Windows/Program.inc b/llvm/lib/Support/Windows/Program.inc index d98d55f317a3..799af5559966 100644 --- a/llvm/lib/Support/Windows/Program.inc +++ b/llvm/lib/Support/Windows/Program.inc @@ -506,14 +506,14 @@ std::error_code llvm::sys::ChangeStdoutMode(sys::fs::OpenFlags Flags) { std::error_code sys::ChangeStdinToBinary() { int result = _setmode(_fileno(stdin), _O_BINARY); if (result == -1) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } std::error_code sys::ChangeStdoutToBinary() { int result = _setmode(_fileno(stdout), _O_BINARY); if (result == -1) - return std::error_code(errno, std::generic_category()); + return errnoAsErrorCode(); return std::error_code(); } diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp index c7064d2dfedc..8cb7b5ac68ea 100644 --- a/llvm/lib/Support/raw_ostream.cpp +++ b/llvm/lib/Support/raw_ostream.cpp @@ -794,7 +794,7 @@ void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { } #endif // Otherwise it's a non-recoverable error. Note it and quit. - error_detected(std::error_code(errno, std::generic_category())); + error_detected(errnoAsErrorCode()); break; } @@ -824,7 +824,7 @@ uint64_t raw_fd_ostream::seek(uint64_t off) { pos = ::lseek(FD, off, SEEK_SET); #endif if (pos == (uint64_t)-1) - error_detected(std::error_code(errno, std::generic_category())); + error_detected(errnoAsErrorCode()); return pos; } @@ -946,7 +946,7 @@ ssize_t raw_fd_stream::read(char *Ptr, size_t Size) { if (Ret >= 0) inc_pos(Ret); else - error_detected(std::error_code(errno, std::generic_category())); + error_detected(errnoAsErrorCode()); return Ret; } diff --git a/llvm/lib/Support/raw_socket_stream.cpp b/llvm/lib/Support/raw_socket_stream.cpp index a65865bcede1..afb0ed11b2c2 100644 --- a/llvm/lib/Support/raw_socket_stream.cpp +++ b/llvm/lib/Support/raw_socket_stream.cpp @@ -52,7 +52,7 @@ static std::error_code getLastSocketErrorCode() { #ifdef _WIN32 return std::error_code(::WSAGetLastError(), std::system_category()); #else - return std::error_code(errno, std::system_category()); + return errnoAsErrorCode(); #endif } -- GitLab From def038bc40fae7d6756dde9c41677d76ad0387d2 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Sat, 9 Mar 2024 00:33:21 -0800 Subject: [PATCH 002/953] Revert "[clang] Fix crash when declaring invalid lambda member" (#84615) Reverts llvm/llvm-project#74110 Fails on many bots: https://lab.llvm.org/buildbot/#/builders/5/builds/41633 --- clang/docs/ReleaseNotes.rst | 5 +---- clang/lib/AST/DeclCXX.cpp | 7 ++++--- clang/test/SemaCXX/lambda-expressions.cpp | 18 ++++++++---------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8935a610722a..690fc7ed271a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -258,9 +258,6 @@ Bug Fixes in This Version operator. Fixes (#GH83267). -- Fixes an assertion failure on invalid code when trying to define member - functions in lambdas. - Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -411,7 +408,7 @@ RISC-V Support CUDA/HIP Language Changes ^^^^^^^^^^^^^^^^^^^^^^^^^ -- PTX is no longer included by default when compiling for CUDA. Using +- PTX is no longer included by default when compiling for CUDA. Using ``--cuda-include-ptx=all`` will return the old behavior. CUDA Support diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 645ec2f7563b..1c3dcf63465c 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1567,9 +1567,10 @@ bool CXXRecordDecl::isGenericLambda() const { #ifndef NDEBUG static bool allLookupResultsAreTheSame(const DeclContext::lookup_result &R) { - return llvm::all_of(R, [&](NamedDecl *D) { - return D->isInvalidDecl() || declaresSameEntity(D, R.front()); - }); + for (auto *D : R) + if (!declaresSameEntity(D, R.front())) + return false; + return true; } #endif diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp index 8907b08e1830..0516a5da31ae 100644 --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -1,4 +1,3 @@ -// RUN: %clang_cc1 -std=c++11 -Wno-unused-value -fsyntax-only -verify=expected,expected-cxx14,cxx11 -fblocks %s // RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify -verify=expected-cxx14 -fblocks %s // RUN: %clang_cc1 -std=c++17 -Wno-unused-value -verify -ast-dump -fblocks %s | FileCheck %s @@ -559,8 +558,8 @@ struct B { int x; A a = [&] { int y = x; }; A b = [&] { [&] { [&] { int y = x; }; }; }; - A d = [&](auto param) { int y = x; }; // cxx11-error {{'auto' not allowed in lambda parameter}} - A e = [&](auto param) { [&] { [&](auto param2) { int y = x; }; }; }; // cxx11-error 2 {{'auto' not allowed in lambda parameter}} + A d = [&](auto param) { int y = x; }; + A e = [&](auto param) { [&] { [&](auto param2) { int y = x; }; }; }; }; B b; @@ -590,7 +589,6 @@ struct S1 { void foo1() { auto s0 = S1{[name=]() {}}; // expected-error 2 {{expected expression}} auto s1 = S1{[name=name]() {}}; // expected-error {{use of undeclared identifier 'name'; did you mean 'name1'?}} - // cxx11-warning@-1 {{initialized lambda captures are a C++14 extension}} } } @@ -606,7 +604,7 @@ namespace PR25627_dont_odr_use_local_consts { namespace ConversionOperatorDoesNotHaveDeducedReturnType { auto x = [](int){}; - auto y = [](auto &v) -> void { v.n = 0; }; // cxx11-error {{'auto' not allowed in lambda parameter}} cxx11-note {{candidate function not viable}} cxx11-note {{conversion candidate}} + auto y = [](auto &v) -> void { v.n = 0; }; using T = decltype(x); using U = decltype(y); using ExpectedTypeT = void (*)(int); @@ -626,22 +624,22 @@ namespace ConversionOperatorDoesNotHaveDeducedReturnType { template friend constexpr U::operator ExpectedTypeU() const noexcept; #else - friend auto T::operator()(int) const; // cxx11-error {{'auto' return without trailing return type; deduced return types are a C++14 extension}} + friend auto T::operator()(int) const; friend T::operator ExpectedTypeT() const; template - friend void U::operator()(T&) const; // cxx11-error {{friend declaration of 'operator()' does not match any declaration}} + friend void U::operator()(T&) const; // FIXME: This should not match, as above. template - friend U::operator ExpectedTypeU() const; // cxx11-error {{friend declaration of 'operator void (*)(type-parameter-0-0 &)' does not match any declaration}} + friend U::operator ExpectedTypeU() const; #endif private: int n; }; - // Should be OK in C++14 and later: lambda's call operator is a friend. - void use(X &x) { y(x); } // cxx11-error {{no matching function for call to object}} + // Should be OK: lambda's call operator is a friend. + void use(X &x) { y(x); } // This used to crash in return type deduction for the conversion opreator. struct A { int n; void f() { +[](decltype(n)) {}; } }; -- GitLab From a84e66a92d7b97f68aa3ae7d2c5839f3fb0d291d Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Sat, 9 Mar 2024 09:43:07 +0100 Subject: [PATCH 003/953] [libc] Provide `LIBC_TYPES_HAS_INT64` (#83441) Umbrella bug #83182 --- libc/src/__support/UInt.h | 12 ++++++------ libc/src/__support/macros/properties/types.h | 7 ++++++- libc/src/string/memory_utils/op_generic.h | 9 +++------ libc/test/src/string/memory_utils/op_tests.cpp | 14 +++++++------- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h index c49c8314cd49..d92d61ed094e 100644 --- a/libc/src/__support/UInt.h +++ b/libc/src/__support/UInt.h @@ -14,10 +14,10 @@ #include "src/__support/CPP/limits.h" #include "src/__support/CPP/optional.h" #include "src/__support/CPP/type_traits.h" -#include "src/__support/macros/attributes.h" // LIBC_INLINE -#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY -#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 -#include "src/__support/math_extras.h" // SumCarry, DiffBorrow +#include "src/__support/macros/attributes.h" // LIBC_INLINE +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128, LIBC_TYPES_HAS_INT64 +#include "src/__support/math_extras.h" // SumCarry, DiffBorrow #include "src/__support/number_pair.h" #include // For size_t @@ -940,11 +940,11 @@ namespace internal { // availability. template struct WordTypeSelector : cpp::type_identity< -#if defined(UINT64_MAX) +#ifdef LIBC_TYPES_HAS_INT64 uint64_t #else uint32_t -#endif +#endif // LIBC_TYPES_HAS_INT64 > { }; // Except if we request 32 bits explicitly. diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h index 42345e4743ce..d43cf99e6859 100644 --- a/libc/src/__support/macros/properties/types.h +++ b/libc/src/__support/macros/properties/types.h @@ -17,7 +17,7 @@ #include "src/__support/macros/properties/cpu_features.h" #include "src/__support/macros/properties/os.h" -#include // __SIZEOF_INT128__ +#include // UINT64_MAX, __SIZEOF_INT128__ // 'long double' properties. #if (LDBL_MANT_DIG == 53) @@ -28,6 +28,11 @@ #define LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128 #endif +// int64 / uint64 support +#if defined(UINT64_MAX) +#define LIBC_TYPES_HAS_INT64 +#endif // UINT64_MAX + // int128 / uint128 support #if defined(__SIZEOF_INT128__) #define LIBC_TYPES_HAS_INT128 diff --git a/libc/src/string/memory_utils/op_generic.h b/libc/src/string/memory_utils/op_generic.h index 41fc1fa0f1ff..efaff80b7e4d 100644 --- a/libc/src/string/memory_utils/op_generic.h +++ b/libc/src/string/memory_utils/op_generic.h @@ -28,6 +28,7 @@ #include "src/__support/common.h" #include "src/__support/endian.h" #include "src/__support/macros/optimization.h" +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT64 #include "src/string/memory_utils/op_builtin.h" #include "src/string/memory_utils/utils.h" @@ -37,10 +38,6 @@ static_assert((UINTPTR_MAX == 4294967295U) || (UINTPTR_MAX == 18446744073709551615UL), "We currently only support 32- or 64-bit platforms"); -#if defined(UINT64_MAX) -#define LLVM_LIBC_HAS_UINT64 -#endif - namespace LIBC_NAMESPACE { // Compiler types using the vector attributes. using generic_v128 = uint8_t __attribute__((__vector_size__(16))); @@ -60,9 +57,9 @@ template struct is_scalar : cpp::false_type {}; template <> struct is_scalar : cpp::true_type {}; template <> struct is_scalar : cpp::true_type {}; template <> struct is_scalar : cpp::true_type {}; -#ifdef LLVM_LIBC_HAS_UINT64 +#ifdef LIBC_TYPES_HAS_INT64 template <> struct is_scalar : cpp::true_type {}; -#endif // LLVM_LIBC_HAS_UINT64 +#endif // LIBC_TYPES_HAS_INT64 // Meant to match std::numeric_limits interface. // NOLINTNEXTLINE(readability-identifier-naming) template constexpr bool is_scalar_v = is_scalar::value; diff --git a/libc/test/src/string/memory_utils/op_tests.cpp b/libc/test/src/string/memory_utils/op_tests.cpp index 15ac9607bf3e..95a04755eb4d 100644 --- a/libc/test/src/string/memory_utils/op_tests.cpp +++ b/libc/test/src/string/memory_utils/op_tests.cpp @@ -7,9 +7,9 @@ //===----------------------------------------------------------------------===// #include "memory_check_utils.h" +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT64 #include "src/string/memory_utils/op_aarch64.h" #include "src/string/memory_utils/op_builtin.h" -#include "src/string/memory_utils/op_generic.h" // LLVM_LIBC_HAS_UINT64 #include "src/string/memory_utils/op_riscv.h" #include "src/string/memory_utils/op_x86.h" #include "test/UnitTest/Test.h" @@ -124,9 +124,9 @@ using MemsetImplementations = testing::TypeList< builtin::Memset<32>, // builtin::Memset<64>, #endif -#ifdef LLVM_LIBC_HAS_UINT64 +#ifdef LIBC_TYPES_HAS_INT64 generic::Memset, generic::Memset>, -#endif +#endif // LIBC_TYPES_HAS_INT64 #ifdef __AVX512F__ generic::Memset, generic::Memset>, #endif @@ -210,9 +210,9 @@ using BcmpImplementations = testing::TypeList< #ifndef LIBC_TARGET_ARCH_IS_ARM // Removing non uint8_t types for ARM generic::Bcmp, generic::Bcmp, // -#ifdef LLVM_LIBC_HAS_UINT64 +#ifdef LIBC_TYPES_HAS_INT64 generic::Bcmp, -#endif // LLVM_LIBC_HAS_UINT64 +#endif // LIBC_TYPES_HAS_INT64 generic::BcmpSequence, generic::BcmpSequence, // generic::BcmpSequence, // @@ -292,9 +292,9 @@ using MemcmpImplementations = testing::TypeList< #ifndef LIBC_TARGET_ARCH_IS_ARM // Removing non uint8_t types for ARM generic::Memcmp, generic::Memcmp, // -#ifdef LLVM_LIBC_HAS_UINT64 +#ifdef LIBC_TYPES_HAS_INT64 generic::Memcmp, -#endif // LLVM_LIBC_HAS_UINT64 +#endif // LIBC_TYPES_HAS_INT64 generic::MemcmpSequence, generic::MemcmpSequence, // #endif // LIBC_TARGET_ARCH_IS_ARM -- GitLab From fd3eaf76ba3392a4406247d996e757ef49f7a8b2 Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Sat, 9 Mar 2024 09:07:22 +0000 Subject: [PATCH 004/953] [GISel] Enforce G_PTR_ADD RHS type matching index size for addr space (#84352) --- .../CodeGen/GlobalISel/LegalizerHelper.cpp | 9 +- llvm/lib/CodeGen/MachineVerifier.cpp | 10 + .../GlobalISel/combine-ptradd-int2ptr.mir | 10 +- .../AArch64/GlobalISel/legalize-ptr-add.mir | 17 -- .../prelegalizer-combiner-load-or-pattern.mir | 226 +++++++++--------- .../combine-extract-vector-load.mir | 13 +- .../GlobalISel/extractelement-stack-lower.ll | 21 +- .../AMDGPU/GlobalISel/extractelement.i128.ll | 110 ++++----- .../AMDGPU/GlobalISel/extractelement.i16.ll | 190 +++++---------- .../AMDGPU/GlobalISel/legalize-ptr-add.mir | 207 ---------------- .../GlobalISel/arm-legalize-load-store.mir | 28 --- .../X86/GlobalISel/legalize-ptr-add-32.mir | 55 +++++ .../X86/GlobalISel/legalize-ptr-add-64.mir | 55 +++++ .../X86/GlobalISel/legalize-ptr-add.mir | 224 ----------------- .../X86/GlobalISel/regbankselect-X86_64.mir | 19 +- llvm/test/MachineVerifier/test_g_ptr_add.mir | 6 +- 16 files changed, 382 insertions(+), 818 deletions(-) create mode 100644 llvm/test/CodeGen/X86/GlobalISel/legalize-ptr-add-32.mir create mode 100644 llvm/test/CodeGen/X86/GlobalISel/legalize-ptr-add-64.mir delete mode 100644 llvm/test/CodeGen/X86/GlobalISel/legalize-ptr-add.mir diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 2ec47f72aca3..bd3ff7265d51 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -4004,7 +4004,14 @@ Register LegalizerHelper::getVectorElementPointer(Register VecPtr, LLT VecTy, Index = clampVectorIndex(MIRBuilder, Index, VecTy); - LLT IdxTy = MRI.getType(Index); + // Convert index to the correct size for the address space. + const DataLayout &DL = MIRBuilder.getDataLayout(); + unsigned AS = MRI.getType(VecPtr).getAddressSpace(); + unsigned IndexSizeInBits = DL.getIndexSize(AS) * 8; + LLT IdxTy = MRI.getType(Index).changeElementSize(IndexSizeInBits); + if (IdxTy != MRI.getType(Index)) + Index = MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0); + auto Mul = MIRBuilder.buildMul(IdxTy, Index, MIRBuilder.buildConstant(IdxTy, EltSize)); diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp index ecb3bd33bdfd..9003f1dded87 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -1301,6 +1301,16 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { if (OffsetTy.isPointerOrPointerVector()) report("gep offset operand must not be a pointer", MI); + if (PtrTy.isPointerOrPointerVector()) { + const DataLayout &DL = MF->getDataLayout(); + unsigned AS = PtrTy.getAddressSpace(); + unsigned IndexSizeInBits = DL.getIndexSize(AS) * 8; + if (OffsetTy.getScalarSizeInBits() != IndexSizeInBits) { + report("gep offset operand must match index size for address space", + MI); + } + } + // TODO: Is the offset allowed to be a scalar with a vector? break; } diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-ptradd-int2ptr.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-ptradd-int2ptr.mir index 40e5e8ebb773..1233a0af4245 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-ptradd-int2ptr.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-ptradd-int2ptr.mir @@ -11,7 +11,7 @@ body: | ; CHECK: [[C:%[0-9]+]]:_(p64) = G_CONSTANT i64 44 ; CHECK: [[PTRTOINT:%[0-9]+]]:_(s64) = G_PTRTOINT [[C]](p64) ; CHECK: $x0 = COPY [[PTRTOINT]](s64) - %1:_(s32) = G_CONSTANT i32 42 + %1:_(s64) = G_CONSTANT i64 42 %2:_(s32) = G_CONSTANT i32 2 %3:_(p64) = G_INTTOPTR %2 %4:_(p64) = G_PTR_ADD %3, %1 @@ -26,7 +26,7 @@ body: | ; CHECK-LABEL: name: agc.test_combine_ptradd_constants_ptrres ; CHECK: [[C:%[0-9]+]]:_(p64) = G_CONSTANT i64 44 ; CHECK: $x0 = COPY [[C]](p64) - %1:_(s32) = G_CONSTANT i32 42 + %1:_(s64) = G_CONSTANT i64 42 %2:_(s32) = G_CONSTANT i32 2 %3:_(p64) = G_INTTOPTR %2 %4:_(p64) = G_PTR_ADD %3, %1 @@ -39,12 +39,12 @@ body: | liveins: $x0, $x1 ; Ensure non-constant G_PTR_ADDs are not folded. ; CHECK-LABEL: name: agc.test_not_combine_variable_ptradd - ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42 + ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 42 ; CHECK: [[COPY:%[0-9]+]]:_(p64) = COPY $x1 - ; CHECK: [[PTR_ADD:%[0-9]+]]:_(p64) = G_PTR_ADD [[COPY]], [[C]](s32) + ; CHECK: [[PTR_ADD:%[0-9]+]]:_(p64) = G_PTR_ADD [[COPY]], [[C]](s64) ; CHECK: [[PTRTOINT:%[0-9]+]]:_(s64) = G_PTRTOINT [[PTR_ADD]](p64) ; CHECK: $x0 = COPY [[PTRTOINT]](s64) - %1:_(s32) = G_CONSTANT i32 42 + %1:_(s64) = G_CONSTANT i64 42 %2:_(p64) = COPY $x1 %3:_(p64) = G_PTR_ADD %2, %1 %4:_(s64) = G_PTRTOINT %3 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ptr-add.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ptr-add.mir index 7bd9725d0fc8..1ecd36b55380 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ptr-add.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ptr-add.mir @@ -1,23 +1,6 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=aarch64 -run-pass=legalizer %s -o - | FileCheck %s --- -name: test_ptr_add_small -body: | - bb.0.entry: - ; CHECK-LABEL: name: test_ptr_add_small - ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1 - ; CHECK: [[SEXT_INREG:%[0-9]+]]:_(s64) = G_SEXT_INREG [[COPY1]], 8 - ; CHECK: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[SEXT_INREG]](s64) - ; CHECK: $x0 = COPY [[PTR_ADD]](p0) - %0:_(p0) = COPY $x0 - %1:_(s64) = COPY $x1 - %2:_(s8) = G_TRUNC %1(s64) - %3:_(p0) = G_PTR_ADD %0, %2(s8) - $x0 = COPY %3(p0) - -... ---- name: test_ptr_add_vec_p0 body: | bb.0.entry: diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-load-or-pattern.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-load-or-pattern.mir index 88d214e43c82..c30fab32fccb 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-load-or-pattern.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-load-or-pattern.mir @@ -38,18 +38,18 @@ body: | ; BIG: %full_load:_(s32) = G_BSWAP [[LOAD]] ; BIG: $w1 = COPY %full_load(s32) ; BIG: RET_ReallyLR implicit $w1 - %cst_1:_(s32) = G_CONSTANT i32 1 - %cst_2:_(s32) = G_CONSTANT i32 2 - %cst_3:_(s32) = G_CONSTANT i32 3 + %cst_1:_(s64) = G_CONSTANT i64 1 + %cst_2:_(s64) = G_CONSTANT i64 2 + %cst_3:_(s64) = G_CONSTANT i64 3 %cst_8:_(s32) = G_CONSTANT i32 8 %cst_16:_(s32) = G_CONSTANT i32 16 %cst_24:_(s32) = G_CONSTANT i32 24 %ptr:_(p0) = COPY $x1 - %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) - %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) - %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) + %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) + %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s64) + %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load (s8)) @@ -104,18 +104,18 @@ body: | ; BIG: %full_load:_(s32) = G_LOAD %ptr(p0) :: (load (s32), align 1) ; BIG: $w1 = COPY %full_load(s32) ; BIG: RET_ReallyLR implicit $w1 - %cst_1:_(s32) = G_CONSTANT i32 1 - %cst_2:_(s32) = G_CONSTANT i32 2 - %cst_3:_(s32) = G_CONSTANT i32 3 + %cst_1:_(s64) = G_CONSTANT i64 1 + %cst_2:_(s64) = G_CONSTANT i64 2 + %cst_3:_(s64) = G_CONSTANT i64 3 %cst_8:_(s32) = G_CONSTANT i32 8 %cst_16:_(s32) = G_CONSTANT i32 16 %cst_24:_(s32) = G_CONSTANT i32 24 %ptr:_(p0) = COPY $x1 - %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) - %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) - %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) + %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) + %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s64) + %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) %elt0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load (s8)) %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load (s8)) @@ -162,18 +162,18 @@ body: | ; BIG: %full_load:_(s32) = G_BSWAP [[LOAD]] ; BIG: $w1 = COPY %full_load(s32) ; BIG: RET_ReallyLR implicit $w1 - %cst_1:_(s32) = G_CONSTANT i32 1 - %cst_2:_(s32) = G_CONSTANT i32 2 - %cst_3:_(s32) = G_CONSTANT i32 3 + %cst_1:_(s64) = G_CONSTANT i64 1 + %cst_2:_(s64) = G_CONSTANT i64 2 + %cst_3:_(s64) = G_CONSTANT i64 3 %cst_8:_(s32) = G_CONSTANT i32 8 %cst_16:_(s32) = G_CONSTANT i32 16 %cst_24:_(s32) = G_CONSTANT i32 24 %ptr:_(p0) = COPY $x1 - %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) - %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) - %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) + %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) + %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s64) + %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load (s8)) @@ -414,35 +414,35 @@ body: | ; LITTLE-LABEL: name: nonzero_start_idx_positive_little_endian_pat ; LITTLE: liveins: $x0, $x1 - ; LITTLE: %cst_1:_(s32) = G_CONSTANT i32 1 + ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 ; LITTLE: %ptr:_(p0) = COPY $x0 - ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) + ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) ; LITTLE: %full_load:_(s32) = G_LOAD %ptr_elt_1(p0) :: (load (s32), align 1) ; LITTLE: $w1 = COPY %full_load(s32) ; LITTLE: RET_ReallyLR implicit $w1 ; BIG-LABEL: name: nonzero_start_idx_positive_little_endian_pat ; BIG: liveins: $x0, $x1 - ; BIG: %cst_1:_(s32) = G_CONSTANT i32 1 + ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 ; BIG: %ptr:_(p0) = COPY $x0 - ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) + ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) ; BIG: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD %ptr_elt_1(p0) :: (load (s32), align 1) ; BIG: %full_load:_(s32) = G_BSWAP [[LOAD]] ; BIG: $w1 = COPY %full_load(s32) ; BIG: RET_ReallyLR implicit $w1 - %cst_1:_(s32) = G_CONSTANT i32 1 - %cst_2:_(s32) = G_CONSTANT i32 2 - %cst_3:_(s32) = G_CONSTANT i32 3 - %cst_4:_(s32) = G_CONSTANT i32 4 + %cst_1:_(s64) = G_CONSTANT i64 1 + %cst_2:_(s64) = G_CONSTANT i64 2 + %cst_3:_(s64) = G_CONSTANT i64 3 + %cst_4:_(s64) = G_CONSTANT i64 4 %cst_8:_(s32) = G_CONSTANT i32 8 %cst_16:_(s32) = G_CONSTANT i32 16 %cst_24:_(s32) = G_CONSTANT i32 24 %ptr:_(p0) = COPY $x0 - %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) - %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) - %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) - %ptr_elt_4:_(p0) = G_PTR_ADD %ptr, %cst_4(s32) + %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) + %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s64) + %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) + %ptr_elt_4:_(p0) = G_PTR_ADD %ptr, %cst_4(s64) %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load (s8)) %elt3:_(s32) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load (s8)) @@ -476,35 +476,35 @@ body: | ; LITTLE-LABEL: name: nonzero_start_idx_positive_big_endian_pat ; LITTLE: liveins: $x0, $x1 - ; LITTLE: %cst_1:_(s32) = G_CONSTANT i32 1 + ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 ; LITTLE: %ptr:_(p0) = COPY $x0 - ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) + ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) ; LITTLE: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD %ptr_elt_1(p0) :: (load (s32), align 1) ; LITTLE: %full_load:_(s32) = G_BSWAP [[LOAD]] ; LITTLE: $w1 = COPY %full_load(s32) ; LITTLE: RET_ReallyLR implicit $w1 ; BIG-LABEL: name: nonzero_start_idx_positive_big_endian_pat ; BIG: liveins: $x0, $x1 - ; BIG: %cst_1:_(s32) = G_CONSTANT i32 1 + ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 ; BIG: %ptr:_(p0) = COPY $x0 - ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) + ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) ; BIG: %full_load:_(s32) = G_LOAD %ptr_elt_1(p0) :: (load (s32), align 1) ; BIG: $w1 = COPY %full_load(s32) ; BIG: RET_ReallyLR implicit $w1 - %cst_1:_(s32) = G_CONSTANT i32 1 - %cst_2:_(s32) = G_CONSTANT i32 2 - %cst_3:_(s32) = G_CONSTANT i32 3 - %cst_4:_(s32) = G_CONSTANT i32 4 + %cst_1:_(s64) = G_CONSTANT i64 1 + %cst_2:_(s64) = G_CONSTANT i64 2 + %cst_3:_(s64) = G_CONSTANT i64 3 + %cst_4:_(s64) = G_CONSTANT i64 4 %cst_8:_(s32) = G_CONSTANT i32 8 %cst_16:_(s32) = G_CONSTANT i32 16 %cst_24:_(s32) = G_CONSTANT i32 24 %ptr:_(p0) = COPY $x0 - %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) - %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) - %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) - %ptr_elt_4:_(p0) = G_PTR_ADD %ptr, %cst_4(s32) + %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) + %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s64) + %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) + %ptr_elt_4:_(p0) = G_PTR_ADD %ptr, %cst_4(s64) %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load (s8)) %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load (s8)) @@ -538,33 +538,33 @@ body: | ; LITTLE-LABEL: name: nonzero_start_idx_negative_little_endian_pat ; LITTLE: liveins: $x0, $x1 - ; LITTLE: %cst_neg_3:_(s32) = G_CONSTANT i32 -3 + ; LITTLE: %cst_neg_3:_(s64) = G_CONSTANT i64 -3 ; LITTLE: %ptr:_(p0) = COPY $x0 - ; LITTLE: %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s32) + ; LITTLE: %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s64) ; LITTLE: %full_load:_(s32) = G_LOAD %ptr_elt_neg_3(p0) :: (load (s32), align 1) ; LITTLE: $w1 = COPY %full_load(s32) ; LITTLE: RET_ReallyLR implicit $w1 ; BIG-LABEL: name: nonzero_start_idx_negative_little_endian_pat ; BIG: liveins: $x0, $x1 - ; BIG: %cst_neg_3:_(s32) = G_CONSTANT i32 -3 + ; BIG: %cst_neg_3:_(s64) = G_CONSTANT i64 -3 ; BIG: %ptr:_(p0) = COPY $x0 - ; BIG: %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s32) + ; BIG: %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s64) ; BIG: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD %ptr_elt_neg_3(p0) :: (load (s32), align 1) ; BIG: %full_load:_(s32) = G_BSWAP [[LOAD]] ; BIG: $w1 = COPY %full_load(s32) ; BIG: RET_ReallyLR implicit $w1 - %cst_neg_1:_(s32) = G_CONSTANT i32 -1 - %cst_neg_2:_(s32) = G_CONSTANT i32 -2 - %cst_neg_3:_(s32) = G_CONSTANT i32 -3 + %cst_neg_1:_(s64) = G_CONSTANT i64 -1 + %cst_neg_2:_(s64) = G_CONSTANT i64 -2 + %cst_neg_3:_(s64) = G_CONSTANT i64 -3 %cst_8:_(s32) = G_CONSTANT i32 8 %cst_16:_(s32) = G_CONSTANT i32 16 %cst_24:_(s32) = G_CONSTANT i32 24 %ptr:_(p0) = COPY $x0 - %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s32) - %ptr_elt_neg_2:_(p0) = G_PTR_ADD %ptr, %cst_neg_2(s32) - %ptr_elt_neg_1:_(p0) = G_PTR_ADD %ptr, %cst_neg_1(s32) + %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s64) + %ptr_elt_neg_2:_(p0) = G_PTR_ADD %ptr, %cst_neg_2(s64) + %ptr_elt_neg_1:_(p0) = G_PTR_ADD %ptr, %cst_neg_1(s64) %elt_neg_2:_(s32) = G_ZEXTLOAD %ptr_elt_neg_2(p0) :: (load (s8)) %elt_neg_1:_(s32) = G_ZEXTLOAD %ptr_elt_neg_1(p0) :: (load (s8)) @@ -598,33 +598,33 @@ body: | ; LITTLE-LABEL: name: nonzero_start_idx_negative_big_endian_pat ; LITTLE: liveins: $x0, $x1 - ; LITTLE: %cst_neg_3:_(s32) = G_CONSTANT i32 -3 + ; LITTLE: %cst_neg_3:_(s64) = G_CONSTANT i64 -3 ; LITTLE: %ptr:_(p0) = COPY $x0 - ; LITTLE: %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s32) + ; LITTLE: %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s64) ; LITTLE: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD %ptr_elt_neg_3(p0) :: (load (s32), align 1) ; LITTLE: %full_load:_(s32) = G_BSWAP [[LOAD]] ; LITTLE: $w1 = COPY %full_load(s32) ; LITTLE: RET_ReallyLR implicit $w1 ; BIG-LABEL: name: nonzero_start_idx_negative_big_endian_pat ; BIG: liveins: $x0, $x1 - ; BIG: %cst_neg_3:_(s32) = G_CONSTANT i32 -3 + ; BIG: %cst_neg_3:_(s64) = G_CONSTANT i64 -3 ; BIG: %ptr:_(p0) = COPY $x0 - ; BIG: %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s32) + ; BIG: %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s64) ; BIG: %full_load:_(s32) = G_LOAD %ptr_elt_neg_3(p0) :: (load (s32), align 1) ; BIG: $w1 = COPY %full_load(s32) ; BIG: RET_ReallyLR implicit $w1 - %cst_neg_1:_(s32) = G_CONSTANT i32 -1 - %cst_neg_2:_(s32) = G_CONSTANT i32 -2 - %cst_neg_3:_(s32) = G_CONSTANT i32 -3 + %cst_neg_1:_(s64) = G_CONSTANT i64 -1 + %cst_neg_2:_(s64) = G_CONSTANT i64 -2 + %cst_neg_3:_(s64) = G_CONSTANT i64 -3 %cst_8:_(s32) = G_CONSTANT i32 8 %cst_16:_(s32) = G_CONSTANT i32 16 %cst_24:_(s32) = G_CONSTANT i32 24 %ptr:_(p0) = COPY $x0 - %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s32) - %ptr_elt_neg_2:_(p0) = G_PTR_ADD %ptr, %cst_neg_2(s32) - %ptr_elt_neg_1:_(p0) = G_PTR_ADD %ptr, %cst_neg_1(s32) + %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s64) + %ptr_elt_neg_2:_(p0) = G_PTR_ADD %ptr, %cst_neg_2(s64) + %ptr_elt_neg_1:_(p0) = G_PTR_ADD %ptr, %cst_neg_1(s64) %elt_neg_3:_(s32) = G_ZEXTLOAD %ptr_elt_neg_3(p0) :: (load (s8)) %elt_neg_2:_(s32) = G_ZEXTLOAD %ptr_elt_neg_2(p0) :: (load (s8)) @@ -977,15 +977,15 @@ body: | ; LITTLE-LABEL: name: dont_combine_duplicate_idx ; LITTLE: liveins: $x0, $x1 - ; LITTLE: %cst_1:_(s32) = G_CONSTANT i32 1 - ; LITTLE: %reused_idx:_(s32) = G_CONSTANT i32 2 + ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 + ; LITTLE: %reused_idx:_(s64) = G_CONSTANT i64 2 ; LITTLE: %cst_8:_(s32) = G_CONSTANT i32 8 ; LITTLE: %cst_16:_(s32) = G_CONSTANT i32 16 ; LITTLE: %cst_24:_(s32) = G_CONSTANT i32 24 ; LITTLE: %ptr:_(p0) = COPY $x1 - ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) - ; LITTLE: %uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s32) - ; LITTLE: %also_uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s32) + ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) + ; LITTLE: %uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s64) + ; LITTLE: %also_uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s64) ; LITTLE: %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load (s8)) ; LITTLE: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load (s8)) ; LITTLE: %elt2:_(s32) = G_ZEXTLOAD %uses_idx_2(p0) :: (load (s8)) @@ -1000,15 +1000,15 @@ body: | ; LITTLE: RET_ReallyLR implicit $w1 ; BIG-LABEL: name: dont_combine_duplicate_idx ; BIG: liveins: $x0, $x1 - ; BIG: %cst_1:_(s32) = G_CONSTANT i32 1 - ; BIG: %reused_idx:_(s32) = G_CONSTANT i32 2 + ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 + ; BIG: %reused_idx:_(s64) = G_CONSTANT i64 2 ; BIG: %cst_8:_(s32) = G_CONSTANT i32 8 ; BIG: %cst_16:_(s32) = G_CONSTANT i32 16 ; BIG: %cst_24:_(s32) = G_CONSTANT i32 24 ; BIG: %ptr:_(p0) = COPY $x1 - ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) - ; BIG: %uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s32) - ; BIG: %also_uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s32) + ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) + ; BIG: %uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s64) + ; BIG: %also_uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s64) ; BIG: %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load (s8)) ; BIG: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load (s8)) ; BIG: %elt2:_(s32) = G_ZEXTLOAD %uses_idx_2(p0) :: (load (s8)) @@ -1021,17 +1021,17 @@ body: | ; BIG: %full_load:_(s32) = G_OR %or1, %or2 ; BIG: $w1 = COPY %full_load(s32) ; BIG: RET_ReallyLR implicit $w1 - %cst_1:_(s32) = G_CONSTANT i32 1 - %reused_idx:_(s32) = G_CONSTANT i32 2 + %cst_1:_(s64) = G_CONSTANT i64 1 + %reused_idx:_(s64) = G_CONSTANT i64 2 %cst_8:_(s32) = G_CONSTANT i32 8 %cst_16:_(s32) = G_CONSTANT i32 16 %cst_24:_(s32) = G_CONSTANT i32 24 %ptr:_(p0) = COPY $x1 - %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) - %uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s32) - %also_uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s32) + %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) + %uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s64) + %also_uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s64) %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load (s8)) @@ -1064,15 +1064,15 @@ body: | ; LITTLE-LABEL: name: dont_combine_duplicate_offset ; LITTLE: liveins: $x0, $x1 - ; LITTLE: %cst_1:_(s32) = G_CONSTANT i32 1 - ; LITTLE: %cst_2:_(s32) = G_CONSTANT i32 2 - ; LITTLE: %cst_3:_(s32) = G_CONSTANT i32 3 + ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 + ; LITTLE: %cst_2:_(s64) = G_CONSTANT i64 2 + ; LITTLE: %cst_3:_(s64) = G_CONSTANT i64 3 ; LITTLE: %cst_8:_(s32) = G_CONSTANT i32 8 ; LITTLE: %duplicate_shl_cst:_(s32) = G_CONSTANT i32 16 ; LITTLE: %ptr:_(p0) = COPY $x1 - ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) - ; LITTLE: %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) - ; LITTLE: %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) + ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) + ; LITTLE: %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s64) + ; LITTLE: %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) ; LITTLE: %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load (s8)) ; LITTLE: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load (s8)) ; LITTLE: %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load (s8)) @@ -1087,15 +1087,15 @@ body: | ; LITTLE: RET_ReallyLR implicit $w1 ; BIG-LABEL: name: dont_combine_duplicate_offset ; BIG: liveins: $x0, $x1 - ; BIG: %cst_1:_(s32) = G_CONSTANT i32 1 - ; BIG: %cst_2:_(s32) = G_CONSTANT i32 2 - ; BIG: %cst_3:_(s32) = G_CONSTANT i32 3 + ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 + ; BIG: %cst_2:_(s64) = G_CONSTANT i64 2 + ; BIG: %cst_3:_(s64) = G_CONSTANT i64 3 ; BIG: %cst_8:_(s32) = G_CONSTANT i32 8 ; BIG: %duplicate_shl_cst:_(s32) = G_CONSTANT i32 16 ; BIG: %ptr:_(p0) = COPY $x1 - ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) - ; BIG: %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) - ; BIG: %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) + ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) + ; BIG: %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s64) + ; BIG: %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) ; BIG: %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load (s8)) ; BIG: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load (s8)) ; BIG: %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load (s8)) @@ -1108,17 +1108,17 @@ body: | ; BIG: %full_load:_(s32) = G_OR %or1, %or2 ; BIG: $w1 = COPY %full_load(s32) ; BIG: RET_ReallyLR implicit $w1 - %cst_1:_(s32) = G_CONSTANT i32 1 - %cst_2:_(s32) = G_CONSTANT i32 2 - %cst_3:_(s32) = G_CONSTANT i32 3 + %cst_1:_(s64) = G_CONSTANT i64 1 + %cst_2:_(s64) = G_CONSTANT i64 2 + %cst_3:_(s64) = G_CONSTANT i64 3 %cst_8:_(s32) = G_CONSTANT i32 8 %duplicate_shl_cst:_(s32) = G_CONSTANT i32 16 %ptr:_(p0) = COPY $x1 - %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) - %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) - %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) + %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) + %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s64) + %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load (s8)) @@ -1153,16 +1153,16 @@ body: | ; LITTLE-LABEL: name: dont_combine_lowest_index_not_zero_offset ; LITTLE: liveins: $x0, $x1 - ; LITTLE: %cst_1:_(s32) = G_CONSTANT i32 1 - ; LITTLE: %cst_2:_(s32) = G_CONSTANT i32 2 - ; LITTLE: %cst_3:_(s32) = G_CONSTANT i32 3 + ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 + ; LITTLE: %cst_2:_(s64) = G_CONSTANT i64 2 + ; LITTLE: %cst_3:_(s64) = G_CONSTANT i64 3 ; LITTLE: %cst_8:_(s32) = G_CONSTANT i32 8 ; LITTLE: %cst_16:_(s32) = G_CONSTANT i32 16 ; LITTLE: %cst_24:_(s32) = G_CONSTANT i32 24 ; LITTLE: %ptr:_(p0) = COPY $x1 - ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) - ; LITTLE: %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) - ; LITTLE: %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) + ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) + ; LITTLE: %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s64) + ; LITTLE: %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) ; LITTLE: %lowest_idx_load:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load (s8)) ; LITTLE: %byte0:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load (s8)) ; LITTLE: %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load (s8)) @@ -1177,16 +1177,16 @@ body: | ; LITTLE: RET_ReallyLR implicit $w1 ; BIG-LABEL: name: dont_combine_lowest_index_not_zero_offset ; BIG: liveins: $x0, $x1 - ; BIG: %cst_1:_(s32) = G_CONSTANT i32 1 - ; BIG: %cst_2:_(s32) = G_CONSTANT i32 2 - ; BIG: %cst_3:_(s32) = G_CONSTANT i32 3 + ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 + ; BIG: %cst_2:_(s64) = G_CONSTANT i64 2 + ; BIG: %cst_3:_(s64) = G_CONSTANT i64 3 ; BIG: %cst_8:_(s32) = G_CONSTANT i32 8 ; BIG: %cst_16:_(s32) = G_CONSTANT i32 16 ; BIG: %cst_24:_(s32) = G_CONSTANT i32 24 ; BIG: %ptr:_(p0) = COPY $x1 - ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) - ; BIG: %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) - ; BIG: %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) + ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) + ; BIG: %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s64) + ; BIG: %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) ; BIG: %lowest_idx_load:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load (s8)) ; BIG: %byte0:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load (s8)) ; BIG: %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load (s8)) @@ -1199,18 +1199,18 @@ body: | ; BIG: %full_load:_(s32) = G_OR %or1, %or2 ; BIG: $w1 = COPY %full_load(s32) ; BIG: RET_ReallyLR implicit $w1 - %cst_1:_(s32) = G_CONSTANT i32 1 - %cst_2:_(s32) = G_CONSTANT i32 2 - %cst_3:_(s32) = G_CONSTANT i32 3 + %cst_1:_(s64) = G_CONSTANT i64 1 + %cst_2:_(s64) = G_CONSTANT i64 2 + %cst_3:_(s64) = G_CONSTANT i64 3 %cst_8:_(s32) = G_CONSTANT i32 8 %cst_16:_(s32) = G_CONSTANT i32 16 %cst_24:_(s32) = G_CONSTANT i32 24 %ptr:_(p0) = COPY $x1 - %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) - %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) - %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) + %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) + %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s64) + %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) ; This load is index 0 %lowest_idx_load:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load (s8)) diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-extract-vector-load.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-extract-vector-load.mir index aa72a9ec06ed..b49f51609851 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-extract-vector-load.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-extract-vector-load.mir @@ -8,8 +8,9 @@ tracksRegLiveness: true body: | bb.0: ; CHECK-LABEL: name: test_ptradd_crash__offset_smaller - ; CHECK: [[C:%[0-9]+]]:_(p1) = G_CONSTANT i64 12 - ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[C]](p1) :: (load (s32), addrspace 1) + ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 12 + ; CHECK-NEXT: [[INTTOPTR:%[0-9]+]]:_(p1) = G_INTTOPTR [[C]](s64) + ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[INTTOPTR]](p1) :: (load (s32), addrspace 1) ; CHECK-NEXT: $sgpr0 = COPY [[LOAD]](s32) ; CHECK-NEXT: SI_RETURN_TO_EPILOG implicit $sgpr0 %1:_(p1) = G_CONSTANT i64 0 @@ -27,8 +28,12 @@ tracksRegLiveness: true body: | bb.0: ; CHECK-LABEL: name: test_ptradd_crash__offset_wider - ; CHECK: [[C:%[0-9]+]]:_(p1) = G_CONSTANT i64 12 - ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[C]](p1) :: (load (s32), addrspace 1) + ; CHECK: [[C:%[0-9]+]]:_(s128) = G_CONSTANT i128 3 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s64) = G_TRUNC [[C]](s128) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2 + ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[TRUNC]], [[C1]](s64) + ; CHECK-NEXT: [[INTTOPTR:%[0-9]+]]:_(p1) = G_INTTOPTR [[SHL]](s64) + ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[INTTOPTR]](p1) :: (load (s32), addrspace 1) ; CHECK-NEXT: $sgpr0 = COPY [[LOAD]](s32) ; CHECK-NEXT: SI_RETURN_TO_EPILOG implicit $sgpr0 %1:_(p1) = G_CONSTANT i64 0 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/extractelement-stack-lower.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/extractelement-stack-lower.ll index b58c3b209863..43f3dcc86f42 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/extractelement-stack-lower.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/extractelement-stack-lower.ll @@ -11,9 +11,8 @@ define i32 @v_extract_v64i32_varidx(ptr addrspace(1) %ptr, i32 %idx) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v2, 63, v2 ; GFX9-NEXT: v_lshlrev_b32_e32 v2, 2, v2 -; GFX9-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v0, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v3, vcc +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc ; GFX9-NEXT: global_load_dword v0, v[0:1], off ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -28,10 +27,8 @@ define i32 @v_extract_v64i32_varidx(ptr addrspace(1) %ptr, i32 %idx) { ; GFX12-NEXT: v_and_b32_e32 v2, 63, v2 ; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) ; GFX12-NEXT: v_lshlrev_b32_e32 v2, 2, v2 -; GFX12-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX12-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_2) -; GFX12-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo +; GFX12-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, 0, v1, vcc_lo ; GFX12-NEXT: global_load_b32 v0, v[0:1], off ; GFX12-NEXT: s_wait_loadcnt 0x0 ; GFX12-NEXT: s_setpc_b64 s[30:31] @@ -46,9 +43,8 @@ define i16 @v_extract_v128i16_varidx(ptr addrspace(1) %ptr, i32 %idx) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v2, 0x7f, v2 ; GFX9-NEXT: v_lshlrev_b32_e32 v2, 1, v2 -; GFX9-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v0, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v3, vcc +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc ; GFX9-NEXT: global_load_ushort v0, v[0:1], off ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -63,10 +59,8 @@ define i16 @v_extract_v128i16_varidx(ptr addrspace(1) %ptr, i32 %idx) { ; GFX12-NEXT: v_and_b32_e32 v2, 0x7f, v2 ; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) ; GFX12-NEXT: v_lshlrev_b32_e32 v2, 1, v2 -; GFX12-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX12-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_2) -; GFX12-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo +; GFX12-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, 0, v1, vcc_lo ; GFX12-NEXT: global_load_u16 v0, v[0:1], off ; GFX12-NEXT: s_wait_loadcnt 0x0 ; GFX12-NEXT: s_setpc_b64 s[30:31] @@ -81,9 +75,8 @@ define i64 @v_extract_v32i64_varidx(ptr addrspace(1) %ptr, i32 %idx) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v2, 31, v2 ; GFX9-NEXT: v_lshlrev_b32_e32 v2, 3, v2 -; GFX9-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v0, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v3, vcc +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc ; GFX9-NEXT: global_load_dwordx2 v[0:1], v[0:1], off ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -98,10 +91,8 @@ define i64 @v_extract_v32i64_varidx(ptr addrspace(1) %ptr, i32 %idx) { ; GFX12-NEXT: v_and_b32_e32 v2, 31, v2 ; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) ; GFX12-NEXT: v_lshlrev_b32_e32 v2, 3, v2 -; GFX12-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX12-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_2) -; GFX12-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo +; GFX12-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, 0, v1, vcc_lo ; GFX12-NEXT: global_load_b64 v[0:1], v[0:1], off ; GFX12-NEXT: s_wait_loadcnt 0x0 ; GFX12-NEXT: s_setpc_b64 s[30:31] diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/extractelement.i128.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/extractelement.i128.ll index 057790617204..e1ce9ea14a2a 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/extractelement.i128.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/extractelement.i128.ll @@ -6,37 +6,44 @@ ; RUN: llc -global-isel -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx1100 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX11 %s define amdgpu_ps i128 @extractelement_sgpr_v4i128_sgpr_idx(ptr addrspace(4) inreg %ptr, i32 inreg %idx) { -; GCN-LABEL: extractelement_sgpr_v4i128_sgpr_idx: -; GCN: ; %bb.0: -; GCN-NEXT: s_and_b32 s0, s4, 3 -; GCN-NEXT: s_lshl_b32 s0, s0, 4 -; GCN-NEXT: s_ashr_i32 s1, s0, 31 -; GCN-NEXT: s_add_u32 s0, s2, s0 -; GCN-NEXT: s_addc_u32 s1, s3, s1 -; GCN-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 -; GCN-NEXT: s_waitcnt lgkmcnt(0) -; GCN-NEXT: ; return to shader part epilog +; GFX9-LABEL: extractelement_sgpr_v4i128_sgpr_idx: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_and_b32 s0, s4, 3 +; GFX9-NEXT: s_lshl_b32 s0, s0, 4 +; GFX9-NEXT: s_load_dwordx4 s[0:3], s[2:3], s0 offset:0x0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: ; return to shader part epilog +; +; GFX8-LABEL: extractelement_sgpr_v4i128_sgpr_idx: +; GFX8: ; %bb.0: +; GFX8-NEXT: s_and_b32 s0, s4, 3 +; GFX8-NEXT: s_lshl_b32 s0, s0, 4 +; GFX8-NEXT: s_load_dwordx4 s[0:3], s[2:3], s0 +; GFX8-NEXT: s_waitcnt lgkmcnt(0) +; GFX8-NEXT: ; return to shader part epilog +; +; GFX7-LABEL: extractelement_sgpr_v4i128_sgpr_idx: +; GFX7: ; %bb.0: +; GFX7-NEXT: s_and_b32 s0, s4, 3 +; GFX7-NEXT: s_lshl_b32 s0, s0, 4 +; GFX7-NEXT: s_load_dwordx4 s[0:3], s[2:3], s0 +; GFX7-NEXT: s_waitcnt lgkmcnt(0) +; GFX7-NEXT: ; return to shader part epilog ; ; GFX10-LABEL: extractelement_sgpr_v4i128_sgpr_idx: ; GFX10: ; %bb.0: ; GFX10-NEXT: s_and_b32 s0, s4, 3 ; GFX10-NEXT: s_lshl_b32 s0, s0, 4 -; GFX10-NEXT: s_ashr_i32 s1, s0, 31 -; GFX10-NEXT: s_add_u32 s0, s2, s0 -; GFX10-NEXT: s_addc_u32 s1, s3, s1 -; GFX10-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 +; GFX10-NEXT: s_load_dwordx4 s[0:3], s[2:3], s0 offset:0x0 ; GFX10-NEXT: s_waitcnt lgkmcnt(0) ; GFX10-NEXT: ; return to shader part epilog ; ; GFX11-LABEL: extractelement_sgpr_v4i128_sgpr_idx: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_and_b32 s0, s4, 3 -; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1) +; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) ; GFX11-NEXT: s_lshl_b32 s0, s0, 4 -; GFX11-NEXT: s_ashr_i32 s1, s0, 31 -; GFX11-NEXT: s_add_u32 s0, s2, s0 -; GFX11-NEXT: s_addc_u32 s1, s3, s1 -; GFX11-NEXT: s_load_b128 s[0:3], s[0:1], 0x0 +; GFX11-NEXT: s_load_b128 s[0:3], s[2:3], s0 offset:0x0 ; GFX11-NEXT: s_waitcnt lgkmcnt(0) ; GFX11-NEXT: ; return to shader part epilog %vector = load <4 x i128>, ptr addrspace(4) %ptr @@ -48,8 +55,8 @@ define amdgpu_ps i128 @extractelement_vgpr_v4i128_sgpr_idx(ptr addrspace(1) %ptr ; GFX9-LABEL: extractelement_vgpr_v4i128_sgpr_idx: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_and_b32 s0, s2, 3 +; GFX9-NEXT: s_mov_b32 s1, 0 ; GFX9-NEXT: s_lshl_b32 s0, s0, 4 -; GFX9-NEXT: s_ashr_i32 s1, s0, 31 ; GFX9-NEXT: v_mov_b32_e32 v3, s1 ; GFX9-NEXT: v_mov_b32_e32 v2, s0 ; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v0, v2 @@ -65,8 +72,8 @@ define amdgpu_ps i128 @extractelement_vgpr_v4i128_sgpr_idx(ptr addrspace(1) %ptr ; GFX8-LABEL: extractelement_vgpr_v4i128_sgpr_idx: ; GFX8: ; %bb.0: ; GFX8-NEXT: s_and_b32 s0, s2, 3 +; GFX8-NEXT: s_mov_b32 s1, 0 ; GFX8-NEXT: s_lshl_b32 s0, s0, 4 -; GFX8-NEXT: s_ashr_i32 s1, s0, 31 ; GFX8-NEXT: v_mov_b32_e32 v3, s1 ; GFX8-NEXT: v_mov_b32_e32 v2, s0 ; GFX8-NEXT: v_add_u32_e32 v0, vcc, v0, v2 @@ -82,10 +89,10 @@ define amdgpu_ps i128 @extractelement_vgpr_v4i128_sgpr_idx(ptr addrspace(1) %ptr ; GFX7-LABEL: extractelement_vgpr_v4i128_sgpr_idx: ; GFX7: ; %bb.0: ; GFX7-NEXT: s_and_b32 s0, s2, 3 +; GFX7-NEXT: s_mov_b32 s1, 0 ; GFX7-NEXT: s_lshl_b32 s0, s0, 4 -; GFX7-NEXT: s_ashr_i32 s1, s0, 31 -; GFX7-NEXT: s_mov_b32 s2, 0 ; GFX7-NEXT: s_mov_b32 s3, 0xf000 +; GFX7-NEXT: s_mov_b32 s2, s1 ; GFX7-NEXT: buffer_load_dwordx4 v[0:3], v[0:1], s[0:3], 0 addr64 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_readfirstlane_b32 s0, v0 @@ -97,8 +104,8 @@ define amdgpu_ps i128 @extractelement_vgpr_v4i128_sgpr_idx(ptr addrspace(1) %ptr ; GFX10-LABEL: extractelement_vgpr_v4i128_sgpr_idx: ; GFX10: ; %bb.0: ; GFX10-NEXT: s_and_b32 s0, s2, 3 +; GFX10-NEXT: s_mov_b32 s1, 0 ; GFX10-NEXT: s_lshl_b32 s0, s0, 4 -; GFX10-NEXT: s_ashr_i32 s1, s0, 31 ; GFX10-NEXT: v_mov_b32_e32 v3, s1 ; GFX10-NEXT: v_mov_b32_e32 v2, s0 ; GFX10-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 @@ -114,9 +121,8 @@ define amdgpu_ps i128 @extractelement_vgpr_v4i128_sgpr_idx(ptr addrspace(1) %ptr ; GFX11-LABEL: extractelement_vgpr_v4i128_sgpr_idx: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_and_b32 s0, s2, 3 -; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1) +; GFX11-NEXT: s_mov_b32 s1, 0 ; GFX11-NEXT: s_lshl_b32 s0, s0, 4 -; GFX11-NEXT: s_ashr_i32 s1, s0, 31 ; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(VALU_DEP_1) ; GFX11-NEXT: v_dual_mov_b32 v3, s1 :: v_dual_mov_b32 v2, s0 ; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 @@ -140,9 +146,8 @@ define i128 @extractelement_vgpr_v4i128_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v2, 3, v2 ; GFX9-NEXT: v_lshlrev_b32_e32 v2, 4, v2 -; GFX9-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v0, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v3, vcc +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc ; GFX9-NEXT: global_load_dwordx4 v[0:3], v[0:1], off ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -152,9 +157,8 @@ define i128 @extractelement_vgpr_v4i128_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx ; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX8-NEXT: v_and_b32_e32 v2, 3, v2 ; GFX8-NEXT: v_lshlrev_b32_e32 v2, 4, v2 -; GFX8-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX8-NEXT: v_add_u32_e32 v0, vcc, v0, v2 -; GFX8-NEXT: v_addc_u32_e32 v1, vcc, v1, v3, vcc +; GFX8-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GFX8-NEXT: flat_load_dwordx4 v[0:3], v[0:1] ; GFX8-NEXT: s_waitcnt vmcnt(0) ; GFX8-NEXT: s_setpc_b64 s[30:31] @@ -164,9 +168,8 @@ define i128 @extractelement_vgpr_v4i128_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX7-NEXT: v_and_b32_e32 v2, 3, v2 ; GFX7-NEXT: v_lshlrev_b32_e32 v2, 4, v2 -; GFX7-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX7-NEXT: v_add_i32_e32 v0, vcc, v0, v2 -; GFX7-NEXT: v_addc_u32_e32 v1, vcc, v1, v3, vcc +; GFX7-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GFX7-NEXT: s_mov_b32 s6, 0 ; GFX7-NEXT: s_mov_b32 s7, 0xf000 ; GFX7-NEXT: s_mov_b64 s[4:5], 0 @@ -179,9 +182,8 @@ define i128 @extractelement_vgpr_v4i128_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx ; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX10-NEXT: v_and_b32_e32 v2, 3, v2 ; GFX10-NEXT: v_lshlrev_b32_e32 v2, 4, v2 -; GFX10-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX10-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX10-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo +; GFX10-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, 0, v1, vcc_lo ; GFX10-NEXT: global_load_dwordx4 v[0:3], v[0:1], off ; GFX10-NEXT: s_waitcnt vmcnt(0) ; GFX10-NEXT: s_setpc_b64 s[30:31] @@ -192,10 +194,8 @@ define i128 @extractelement_vgpr_v4i128_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx ; GFX11-NEXT: v_and_b32_e32 v2, 3, v2 ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) ; GFX11-NEXT: v_lshlrev_b32_e32 v2, 4, v2 -; GFX11-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) -; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo +; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, 0, v1, vcc_lo ; GFX11-NEXT: global_load_b128 v[0:3], v[0:1], off ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: s_setpc_b64 s[30:31] @@ -208,13 +208,8 @@ define amdgpu_ps i128 @extractelement_sgpr_v4i128_vgpr_idx(ptr addrspace(4) inre ; GFX9-LABEL: extractelement_sgpr_v4i128_vgpr_idx: ; GFX9: ; %bb.0: ; GFX9-NEXT: v_and_b32_e32 v0, 3, v0 -; GFX9-NEXT: v_lshlrev_b32_e32 v2, 4, v0 -; GFX9-NEXT: v_mov_b32_e32 v0, s2 -; GFX9-NEXT: v_ashrrev_i32_e32 v3, 31, v2 -; GFX9-NEXT: v_mov_b32_e32 v1, s3 -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v0, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v3, vcc -; GFX9-NEXT: global_load_dwordx4 v[0:3], v[0:1], off +; GFX9-NEXT: v_lshlrev_b32_e32 v0, 4, v0 +; GFX9-NEXT: global_load_dwordx4 v[0:3], v0, s[2:3] ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_readfirstlane_b32 s0, v0 ; GFX9-NEXT: v_readfirstlane_b32 s1, v1 @@ -227,10 +222,9 @@ define amdgpu_ps i128 @extractelement_sgpr_v4i128_vgpr_idx(ptr addrspace(4) inre ; GFX8-NEXT: v_and_b32_e32 v0, 3, v0 ; GFX8-NEXT: v_lshlrev_b32_e32 v2, 4, v0 ; GFX8-NEXT: v_mov_b32_e32 v0, s2 -; GFX8-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX8-NEXT: v_mov_b32_e32 v1, s3 ; GFX8-NEXT: v_add_u32_e32 v0, vcc, v0, v2 -; GFX8-NEXT: v_addc_u32_e32 v1, vcc, v1, v3, vcc +; GFX8-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GFX8-NEXT: flat_load_dwordx4 v[0:3], v[0:1] ; GFX8-NEXT: s_waitcnt vmcnt(0) ; GFX8-NEXT: v_readfirstlane_b32 s0, v0 @@ -242,10 +236,10 @@ define amdgpu_ps i128 @extractelement_sgpr_v4i128_vgpr_idx(ptr addrspace(4) inre ; GFX7-LABEL: extractelement_sgpr_v4i128_vgpr_idx: ; GFX7: ; %bb.0: ; GFX7-NEXT: v_and_b32_e32 v0, 3, v0 -; GFX7-NEXT: v_lshlrev_b32_e32 v0, 4, v0 ; GFX7-NEXT: s_mov_b32 s0, s2 ; GFX7-NEXT: s_mov_b32 s1, s3 -; GFX7-NEXT: v_ashrrev_i32_e32 v1, 31, v0 +; GFX7-NEXT: v_lshlrev_b32_e32 v0, 4, v0 +; GFX7-NEXT: v_mov_b32_e32 v1, 0 ; GFX7-NEXT: s_mov_b32 s2, 0 ; GFX7-NEXT: s_mov_b32 s3, 0xf000 ; GFX7-NEXT: buffer_load_dwordx4 v[0:3], v[0:1], s[0:3], 0 addr64 @@ -259,13 +253,8 @@ define amdgpu_ps i128 @extractelement_sgpr_v4i128_vgpr_idx(ptr addrspace(4) inre ; GFX10-LABEL: extractelement_sgpr_v4i128_vgpr_idx: ; GFX10: ; %bb.0: ; GFX10-NEXT: v_and_b32_e32 v0, 3, v0 -; GFX10-NEXT: v_lshlrev_b32_e32 v2, 4, v0 -; GFX10-NEXT: v_mov_b32_e32 v0, s2 -; GFX10-NEXT: v_mov_b32_e32 v1, s3 -; GFX10-NEXT: v_ashrrev_i32_e32 v3, 31, v2 -; GFX10-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX10-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo -; GFX10-NEXT: global_load_dwordx4 v[0:3], v[0:1], off +; GFX10-NEXT: v_lshlrev_b32_e32 v0, 4, v0 +; GFX10-NEXT: global_load_dwordx4 v[0:3], v0, s[2:3] ; GFX10-NEXT: s_waitcnt vmcnt(0) ; GFX10-NEXT: v_readfirstlane_b32 s0, v0 ; GFX10-NEXT: v_readfirstlane_b32 s1, v1 @@ -276,14 +265,9 @@ define amdgpu_ps i128 @extractelement_sgpr_v4i128_vgpr_idx(ptr addrspace(4) inre ; GFX11-LABEL: extractelement_sgpr_v4i128_vgpr_idx: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_and_b32_e32 v0, 3, v0 -; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2) -; GFX11-NEXT: v_lshlrev_b32_e32 v2, 4, v0 -; GFX11-NEXT: v_dual_mov_b32 v0, s2 :: v_dual_mov_b32 v1, s3 -; GFX11-NEXT: v_ashrrev_i32_e32 v3, 31, v2 -; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) -; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo -; GFX11-NEXT: global_load_b128 v[0:3], v[0:1], off +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_lshlrev_b32_e32 v0, 4, v0 +; GFX11-NEXT: global_load_b128 v[0:3], v0, s[2:3] ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: v_readfirstlane_b32 s0, v0 ; GFX11-NEXT: v_readfirstlane_b32 s1, v1 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/extractelement.i16.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/extractelement.i16.ll index 6d772df3fa28..021f609053a0 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/extractelement.i16.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/extractelement.i16.ll @@ -10,11 +10,8 @@ define amdgpu_ps i16 @extractelement_sgpr_v4i16_sgpr_idx(ptr addrspace(4) inreg ; GFX9: ; %bb.0: ; GFX9-NEXT: s_and_b32 s0, s4, 3 ; GFX9-NEXT: s_lshl_b32 s0, s0, 1 -; GFX9-NEXT: s_ashr_i32 s1, s0, 31 -; GFX9-NEXT: s_add_u32 s0, s2, s0 -; GFX9-NEXT: s_addc_u32 s1, s3, s1 -; GFX9-NEXT: v_mov_b32_e32 v0, 0 -; GFX9-NEXT: global_load_ushort v0, v0, s[0:1] +; GFX9-NEXT: v_mov_b32_e32 v0, s0 +; GFX9-NEXT: global_load_ushort v0, v0, s[2:3] ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_readfirstlane_b32 s0, v0 ; GFX9-NEXT: ; return to shader part epilog @@ -23,9 +20,8 @@ define amdgpu_ps i16 @extractelement_sgpr_v4i16_sgpr_idx(ptr addrspace(4) inreg ; GFX8: ; %bb.0: ; GFX8-NEXT: s_and_b32 s0, s4, 3 ; GFX8-NEXT: s_lshl_b32 s0, s0, 1 -; GFX8-NEXT: s_ashr_i32 s1, s0, 31 ; GFX8-NEXT: s_add_u32 s0, s2, s0 -; GFX8-NEXT: s_addc_u32 s1, s3, s1 +; GFX8-NEXT: s_addc_u32 s1, s3, 0 ; GFX8-NEXT: v_mov_b32_e32 v0, s0 ; GFX8-NEXT: v_mov_b32_e32 v1, s1 ; GFX8-NEXT: flat_load_ushort v0, v[0:1] @@ -38,11 +34,11 @@ define amdgpu_ps i16 @extractelement_sgpr_v4i16_sgpr_idx(ptr addrspace(4) inreg ; GFX7-NEXT: s_mov_b32 s0, s2 ; GFX7-NEXT: s_and_b32 s2, s4, 3 ; GFX7-NEXT: s_lshl_b32 s4, s2, 1 -; GFX7-NEXT: s_ashr_i32 s5, s4, 31 +; GFX7-NEXT: s_mov_b32 s5, 0 ; GFX7-NEXT: v_mov_b32_e32 v0, s4 ; GFX7-NEXT: s_mov_b32 s1, s3 -; GFX7-NEXT: s_mov_b32 s2, 0 ; GFX7-NEXT: s_mov_b32 s3, 0xf000 +; GFX7-NEXT: s_mov_b32 s2, s5 ; GFX7-NEXT: v_mov_b32_e32 v1, s5 ; GFX7-NEXT: buffer_load_ushort v0, v[0:1], s[0:3], 0 addr64 ; GFX7-NEXT: s_waitcnt vmcnt(0) @@ -52,12 +48,9 @@ define amdgpu_ps i16 @extractelement_sgpr_v4i16_sgpr_idx(ptr addrspace(4) inreg ; GFX10-LABEL: extractelement_sgpr_v4i16_sgpr_idx: ; GFX10: ; %bb.0: ; GFX10-NEXT: s_and_b32 s0, s4, 3 -; GFX10-NEXT: v_mov_b32_e32 v0, 0 ; GFX10-NEXT: s_lshl_b32 s0, s0, 1 -; GFX10-NEXT: s_ashr_i32 s1, s0, 31 -; GFX10-NEXT: s_add_u32 s0, s2, s0 -; GFX10-NEXT: s_addc_u32 s1, s3, s1 -; GFX10-NEXT: global_load_ushort v0, v0, s[0:1] +; GFX10-NEXT: v_mov_b32_e32 v0, s0 +; GFX10-NEXT: global_load_ushort v0, v0, s[2:3] ; GFX10-NEXT: s_waitcnt vmcnt(0) ; GFX10-NEXT: v_readfirstlane_b32 s0, v0 ; GFX10-NEXT: ; return to shader part epilog @@ -65,13 +58,10 @@ define amdgpu_ps i16 @extractelement_sgpr_v4i16_sgpr_idx(ptr addrspace(4) inreg ; GFX11-LABEL: extractelement_sgpr_v4i16_sgpr_idx: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_and_b32 s0, s4, 3 -; GFX11-NEXT: v_mov_b32_e32 v0, 0 +; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1) ; GFX11-NEXT: s_lshl_b32 s0, s0, 1 -; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) -; GFX11-NEXT: s_ashr_i32 s1, s0, 31 -; GFX11-NEXT: s_add_u32 s0, s2, s0 -; GFX11-NEXT: s_addc_u32 s1, s3, s1 -; GFX11-NEXT: global_load_u16 v0, v0, s[0:1] +; GFX11-NEXT: v_mov_b32_e32 v0, s0 +; GFX11-NEXT: global_load_u16 v0, v0, s[2:3] ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: v_readfirstlane_b32 s0, v0 ; GFX11-NEXT: ; return to shader part epilog @@ -84,8 +74,8 @@ define amdgpu_ps i16 @extractelement_vgpr_v4i16_sgpr_idx(ptr addrspace(1) %ptr, ; GFX9-LABEL: extractelement_vgpr_v4i16_sgpr_idx: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_and_b32 s0, s2, 3 +; GFX9-NEXT: s_mov_b32 s1, 0 ; GFX9-NEXT: s_lshl_b32 s0, s0, 1 -; GFX9-NEXT: s_ashr_i32 s1, s0, 31 ; GFX9-NEXT: v_mov_b32_e32 v3, s1 ; GFX9-NEXT: v_mov_b32_e32 v2, s0 ; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v0, v2 @@ -98,8 +88,8 @@ define amdgpu_ps i16 @extractelement_vgpr_v4i16_sgpr_idx(ptr addrspace(1) %ptr, ; GFX8-LABEL: extractelement_vgpr_v4i16_sgpr_idx: ; GFX8: ; %bb.0: ; GFX8-NEXT: s_and_b32 s0, s2, 3 +; GFX8-NEXT: s_mov_b32 s1, 0 ; GFX8-NEXT: s_lshl_b32 s0, s0, 1 -; GFX8-NEXT: s_ashr_i32 s1, s0, 31 ; GFX8-NEXT: v_mov_b32_e32 v3, s1 ; GFX8-NEXT: v_mov_b32_e32 v2, s0 ; GFX8-NEXT: v_add_u32_e32 v0, vcc, v0, v2 @@ -112,10 +102,10 @@ define amdgpu_ps i16 @extractelement_vgpr_v4i16_sgpr_idx(ptr addrspace(1) %ptr, ; GFX7-LABEL: extractelement_vgpr_v4i16_sgpr_idx: ; GFX7: ; %bb.0: ; GFX7-NEXT: s_and_b32 s0, s2, 3 +; GFX7-NEXT: s_mov_b32 s1, 0 ; GFX7-NEXT: s_lshl_b32 s0, s0, 1 -; GFX7-NEXT: s_ashr_i32 s1, s0, 31 -; GFX7-NEXT: s_mov_b32 s2, 0 ; GFX7-NEXT: s_mov_b32 s3, 0xf000 +; GFX7-NEXT: s_mov_b32 s2, s1 ; GFX7-NEXT: buffer_load_ushort v0, v[0:1], s[0:3], 0 addr64 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_readfirstlane_b32 s0, v0 @@ -124,8 +114,8 @@ define amdgpu_ps i16 @extractelement_vgpr_v4i16_sgpr_idx(ptr addrspace(1) %ptr, ; GFX10-LABEL: extractelement_vgpr_v4i16_sgpr_idx: ; GFX10: ; %bb.0: ; GFX10-NEXT: s_and_b32 s0, s2, 3 +; GFX10-NEXT: s_mov_b32 s1, 0 ; GFX10-NEXT: s_lshl_b32 s0, s0, 1 -; GFX10-NEXT: s_ashr_i32 s1, s0, 31 ; GFX10-NEXT: v_mov_b32_e32 v3, s1 ; GFX10-NEXT: v_mov_b32_e32 v2, s0 ; GFX10-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 @@ -138,9 +128,8 @@ define amdgpu_ps i16 @extractelement_vgpr_v4i16_sgpr_idx(ptr addrspace(1) %ptr, ; GFX11-LABEL: extractelement_vgpr_v4i16_sgpr_idx: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_and_b32 s0, s2, 3 -; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1) +; GFX11-NEXT: s_mov_b32 s1, 0 ; GFX11-NEXT: s_lshl_b32 s0, s0, 1 -; GFX11-NEXT: s_ashr_i32 s1, s0, 31 ; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(VALU_DEP_1) ; GFX11-NEXT: v_dual_mov_b32 v3, s1 :: v_dual_mov_b32 v2, s0 ; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 @@ -161,9 +150,8 @@ define i16 @extractelement_vgpr_v4i16_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v2, 3, v2 ; GFX9-NEXT: v_lshlrev_b32_e32 v2, 1, v2 -; GFX9-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v0, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v3, vcc +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc ; GFX9-NEXT: global_load_ushort v0, v[0:1], off ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -173,9 +161,8 @@ define i16 @extractelement_vgpr_v4i16_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx) ; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX8-NEXT: v_and_b32_e32 v2, 3, v2 ; GFX8-NEXT: v_lshlrev_b32_e32 v2, 1, v2 -; GFX8-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX8-NEXT: v_add_u32_e32 v0, vcc, v0, v2 -; GFX8-NEXT: v_addc_u32_e32 v1, vcc, v1, v3, vcc +; GFX8-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GFX8-NEXT: flat_load_ushort v0, v[0:1] ; GFX8-NEXT: s_waitcnt vmcnt(0) ; GFX8-NEXT: s_setpc_b64 s[30:31] @@ -185,9 +172,8 @@ define i16 @extractelement_vgpr_v4i16_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx) ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX7-NEXT: v_and_b32_e32 v2, 3, v2 ; GFX7-NEXT: v_lshlrev_b32_e32 v2, 1, v2 -; GFX7-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX7-NEXT: v_add_i32_e32 v0, vcc, v0, v2 -; GFX7-NEXT: v_addc_u32_e32 v1, vcc, v1, v3, vcc +; GFX7-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GFX7-NEXT: s_mov_b32 s6, 0 ; GFX7-NEXT: s_mov_b32 s7, 0xf000 ; GFX7-NEXT: s_mov_b64 s[4:5], 0 @@ -200,9 +186,8 @@ define i16 @extractelement_vgpr_v4i16_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx) ; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX10-NEXT: v_and_b32_e32 v2, 3, v2 ; GFX10-NEXT: v_lshlrev_b32_e32 v2, 1, v2 -; GFX10-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX10-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX10-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo +; GFX10-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, 0, v1, vcc_lo ; GFX10-NEXT: global_load_ushort v0, v[0:1], off ; GFX10-NEXT: s_waitcnt vmcnt(0) ; GFX10-NEXT: s_setpc_b64 s[30:31] @@ -213,10 +198,8 @@ define i16 @extractelement_vgpr_v4i16_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx) ; GFX11-NEXT: v_and_b32_e32 v2, 3, v2 ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) ; GFX11-NEXT: v_lshlrev_b32_e32 v2, 1, v2 -; GFX11-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) -; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo +; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, 0, v1, vcc_lo ; GFX11-NEXT: global_load_u16 v0, v[0:1], off ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: s_setpc_b64 s[30:31] @@ -229,13 +212,8 @@ define amdgpu_ps i16 @extractelement_sgpr_v4i16_vgpr_idx(ptr addrspace(4) inreg ; GFX9-LABEL: extractelement_sgpr_v4i16_vgpr_idx: ; GFX9: ; %bb.0: ; GFX9-NEXT: v_and_b32_e32 v0, 3, v0 -; GFX9-NEXT: v_lshlrev_b32_e32 v2, 1, v0 -; GFX9-NEXT: v_mov_b32_e32 v0, s2 -; GFX9-NEXT: v_ashrrev_i32_e32 v3, 31, v2 -; GFX9-NEXT: v_mov_b32_e32 v1, s3 -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v0, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v3, vcc -; GFX9-NEXT: global_load_ushort v0, v[0:1], off +; GFX9-NEXT: v_lshlrev_b32_e32 v0, 1, v0 +; GFX9-NEXT: global_load_ushort v0, v0, s[2:3] ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_readfirstlane_b32 s0, v0 ; GFX9-NEXT: ; return to shader part epilog @@ -245,10 +223,9 @@ define amdgpu_ps i16 @extractelement_sgpr_v4i16_vgpr_idx(ptr addrspace(4) inreg ; GFX8-NEXT: v_and_b32_e32 v0, 3, v0 ; GFX8-NEXT: v_lshlrev_b32_e32 v2, 1, v0 ; GFX8-NEXT: v_mov_b32_e32 v0, s2 -; GFX8-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX8-NEXT: v_mov_b32_e32 v1, s3 ; GFX8-NEXT: v_add_u32_e32 v0, vcc, v0, v2 -; GFX8-NEXT: v_addc_u32_e32 v1, vcc, v1, v3, vcc +; GFX8-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GFX8-NEXT: flat_load_ushort v0, v[0:1] ; GFX8-NEXT: s_waitcnt vmcnt(0) ; GFX8-NEXT: v_readfirstlane_b32 s0, v0 @@ -257,10 +234,10 @@ define amdgpu_ps i16 @extractelement_sgpr_v4i16_vgpr_idx(ptr addrspace(4) inreg ; GFX7-LABEL: extractelement_sgpr_v4i16_vgpr_idx: ; GFX7: ; %bb.0: ; GFX7-NEXT: v_and_b32_e32 v0, 3, v0 -; GFX7-NEXT: v_lshlrev_b32_e32 v0, 1, v0 ; GFX7-NEXT: s_mov_b32 s0, s2 ; GFX7-NEXT: s_mov_b32 s1, s3 -; GFX7-NEXT: v_ashrrev_i32_e32 v1, 31, v0 +; GFX7-NEXT: v_lshlrev_b32_e32 v0, 1, v0 +; GFX7-NEXT: v_mov_b32_e32 v1, 0 ; GFX7-NEXT: s_mov_b32 s2, 0 ; GFX7-NEXT: s_mov_b32 s3, 0xf000 ; GFX7-NEXT: buffer_load_ushort v0, v[0:1], s[0:3], 0 addr64 @@ -271,13 +248,8 @@ define amdgpu_ps i16 @extractelement_sgpr_v4i16_vgpr_idx(ptr addrspace(4) inreg ; GFX10-LABEL: extractelement_sgpr_v4i16_vgpr_idx: ; GFX10: ; %bb.0: ; GFX10-NEXT: v_and_b32_e32 v0, 3, v0 -; GFX10-NEXT: v_lshlrev_b32_e32 v2, 1, v0 -; GFX10-NEXT: v_mov_b32_e32 v0, s2 -; GFX10-NEXT: v_mov_b32_e32 v1, s3 -; GFX10-NEXT: v_ashrrev_i32_e32 v3, 31, v2 -; GFX10-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX10-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo -; GFX10-NEXT: global_load_ushort v0, v[0:1], off +; GFX10-NEXT: v_lshlrev_b32_e32 v0, 1, v0 +; GFX10-NEXT: global_load_ushort v0, v0, s[2:3] ; GFX10-NEXT: s_waitcnt vmcnt(0) ; GFX10-NEXT: v_readfirstlane_b32 s0, v0 ; GFX10-NEXT: ; return to shader part epilog @@ -285,14 +257,9 @@ define amdgpu_ps i16 @extractelement_sgpr_v4i16_vgpr_idx(ptr addrspace(4) inreg ; GFX11-LABEL: extractelement_sgpr_v4i16_vgpr_idx: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_and_b32_e32 v0, 3, v0 -; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2) -; GFX11-NEXT: v_lshlrev_b32_e32 v2, 1, v0 -; GFX11-NEXT: v_dual_mov_b32 v0, s2 :: v_dual_mov_b32 v1, s3 -; GFX11-NEXT: v_ashrrev_i32_e32 v3, 31, v2 -; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) -; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo -; GFX11-NEXT: global_load_u16 v0, v[0:1], off +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_lshlrev_b32_e32 v0, 1, v0 +; GFX11-NEXT: global_load_u16 v0, v0, s[2:3] ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: v_readfirstlane_b32 s0, v0 ; GFX11-NEXT: ; return to shader part epilog @@ -686,11 +653,8 @@ define amdgpu_ps i16 @extractelement_sgpr_v8i16_sgpr_idx(ptr addrspace(4) inreg ; GFX9: ; %bb.0: ; GFX9-NEXT: s_and_b32 s0, s4, 7 ; GFX9-NEXT: s_lshl_b32 s0, s0, 1 -; GFX9-NEXT: s_ashr_i32 s1, s0, 31 -; GFX9-NEXT: s_add_u32 s0, s2, s0 -; GFX9-NEXT: s_addc_u32 s1, s3, s1 -; GFX9-NEXT: v_mov_b32_e32 v0, 0 -; GFX9-NEXT: global_load_ushort v0, v0, s[0:1] +; GFX9-NEXT: v_mov_b32_e32 v0, s0 +; GFX9-NEXT: global_load_ushort v0, v0, s[2:3] ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_readfirstlane_b32 s0, v0 ; GFX9-NEXT: ; return to shader part epilog @@ -699,9 +663,8 @@ define amdgpu_ps i16 @extractelement_sgpr_v8i16_sgpr_idx(ptr addrspace(4) inreg ; GFX8: ; %bb.0: ; GFX8-NEXT: s_and_b32 s0, s4, 7 ; GFX8-NEXT: s_lshl_b32 s0, s0, 1 -; GFX8-NEXT: s_ashr_i32 s1, s0, 31 ; GFX8-NEXT: s_add_u32 s0, s2, s0 -; GFX8-NEXT: s_addc_u32 s1, s3, s1 +; GFX8-NEXT: s_addc_u32 s1, s3, 0 ; GFX8-NEXT: v_mov_b32_e32 v0, s0 ; GFX8-NEXT: v_mov_b32_e32 v1, s1 ; GFX8-NEXT: flat_load_ushort v0, v[0:1] @@ -714,11 +677,11 @@ define amdgpu_ps i16 @extractelement_sgpr_v8i16_sgpr_idx(ptr addrspace(4) inreg ; GFX7-NEXT: s_mov_b32 s0, s2 ; GFX7-NEXT: s_and_b32 s2, s4, 7 ; GFX7-NEXT: s_lshl_b32 s4, s2, 1 -; GFX7-NEXT: s_ashr_i32 s5, s4, 31 +; GFX7-NEXT: s_mov_b32 s5, 0 ; GFX7-NEXT: v_mov_b32_e32 v0, s4 ; GFX7-NEXT: s_mov_b32 s1, s3 -; GFX7-NEXT: s_mov_b32 s2, 0 ; GFX7-NEXT: s_mov_b32 s3, 0xf000 +; GFX7-NEXT: s_mov_b32 s2, s5 ; GFX7-NEXT: v_mov_b32_e32 v1, s5 ; GFX7-NEXT: buffer_load_ushort v0, v[0:1], s[0:3], 0 addr64 ; GFX7-NEXT: s_waitcnt vmcnt(0) @@ -728,12 +691,9 @@ define amdgpu_ps i16 @extractelement_sgpr_v8i16_sgpr_idx(ptr addrspace(4) inreg ; GFX10-LABEL: extractelement_sgpr_v8i16_sgpr_idx: ; GFX10: ; %bb.0: ; GFX10-NEXT: s_and_b32 s0, s4, 7 -; GFX10-NEXT: v_mov_b32_e32 v0, 0 ; GFX10-NEXT: s_lshl_b32 s0, s0, 1 -; GFX10-NEXT: s_ashr_i32 s1, s0, 31 -; GFX10-NEXT: s_add_u32 s0, s2, s0 -; GFX10-NEXT: s_addc_u32 s1, s3, s1 -; GFX10-NEXT: global_load_ushort v0, v0, s[0:1] +; GFX10-NEXT: v_mov_b32_e32 v0, s0 +; GFX10-NEXT: global_load_ushort v0, v0, s[2:3] ; GFX10-NEXT: s_waitcnt vmcnt(0) ; GFX10-NEXT: v_readfirstlane_b32 s0, v0 ; GFX10-NEXT: ; return to shader part epilog @@ -741,13 +701,10 @@ define amdgpu_ps i16 @extractelement_sgpr_v8i16_sgpr_idx(ptr addrspace(4) inreg ; GFX11-LABEL: extractelement_sgpr_v8i16_sgpr_idx: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_and_b32 s0, s4, 7 -; GFX11-NEXT: v_mov_b32_e32 v0, 0 +; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1) ; GFX11-NEXT: s_lshl_b32 s0, s0, 1 -; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) -; GFX11-NEXT: s_ashr_i32 s1, s0, 31 -; GFX11-NEXT: s_add_u32 s0, s2, s0 -; GFX11-NEXT: s_addc_u32 s1, s3, s1 -; GFX11-NEXT: global_load_u16 v0, v0, s[0:1] +; GFX11-NEXT: v_mov_b32_e32 v0, s0 +; GFX11-NEXT: global_load_u16 v0, v0, s[2:3] ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: v_readfirstlane_b32 s0, v0 ; GFX11-NEXT: ; return to shader part epilog @@ -760,8 +717,8 @@ define amdgpu_ps i16 @extractelement_vgpr_v8i16_sgpr_idx(ptr addrspace(1) %ptr, ; GFX9-LABEL: extractelement_vgpr_v8i16_sgpr_idx: ; GFX9: ; %bb.0: ; GFX9-NEXT: s_and_b32 s0, s2, 7 +; GFX9-NEXT: s_mov_b32 s1, 0 ; GFX9-NEXT: s_lshl_b32 s0, s0, 1 -; GFX9-NEXT: s_ashr_i32 s1, s0, 31 ; GFX9-NEXT: v_mov_b32_e32 v3, s1 ; GFX9-NEXT: v_mov_b32_e32 v2, s0 ; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v0, v2 @@ -774,8 +731,8 @@ define amdgpu_ps i16 @extractelement_vgpr_v8i16_sgpr_idx(ptr addrspace(1) %ptr, ; GFX8-LABEL: extractelement_vgpr_v8i16_sgpr_idx: ; GFX8: ; %bb.0: ; GFX8-NEXT: s_and_b32 s0, s2, 7 +; GFX8-NEXT: s_mov_b32 s1, 0 ; GFX8-NEXT: s_lshl_b32 s0, s0, 1 -; GFX8-NEXT: s_ashr_i32 s1, s0, 31 ; GFX8-NEXT: v_mov_b32_e32 v3, s1 ; GFX8-NEXT: v_mov_b32_e32 v2, s0 ; GFX8-NEXT: v_add_u32_e32 v0, vcc, v0, v2 @@ -788,10 +745,10 @@ define amdgpu_ps i16 @extractelement_vgpr_v8i16_sgpr_idx(ptr addrspace(1) %ptr, ; GFX7-LABEL: extractelement_vgpr_v8i16_sgpr_idx: ; GFX7: ; %bb.0: ; GFX7-NEXT: s_and_b32 s0, s2, 7 +; GFX7-NEXT: s_mov_b32 s1, 0 ; GFX7-NEXT: s_lshl_b32 s0, s0, 1 -; GFX7-NEXT: s_ashr_i32 s1, s0, 31 -; GFX7-NEXT: s_mov_b32 s2, 0 ; GFX7-NEXT: s_mov_b32 s3, 0xf000 +; GFX7-NEXT: s_mov_b32 s2, s1 ; GFX7-NEXT: buffer_load_ushort v0, v[0:1], s[0:3], 0 addr64 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_readfirstlane_b32 s0, v0 @@ -800,8 +757,8 @@ define amdgpu_ps i16 @extractelement_vgpr_v8i16_sgpr_idx(ptr addrspace(1) %ptr, ; GFX10-LABEL: extractelement_vgpr_v8i16_sgpr_idx: ; GFX10: ; %bb.0: ; GFX10-NEXT: s_and_b32 s0, s2, 7 +; GFX10-NEXT: s_mov_b32 s1, 0 ; GFX10-NEXT: s_lshl_b32 s0, s0, 1 -; GFX10-NEXT: s_ashr_i32 s1, s0, 31 ; GFX10-NEXT: v_mov_b32_e32 v3, s1 ; GFX10-NEXT: v_mov_b32_e32 v2, s0 ; GFX10-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 @@ -814,9 +771,8 @@ define amdgpu_ps i16 @extractelement_vgpr_v8i16_sgpr_idx(ptr addrspace(1) %ptr, ; GFX11-LABEL: extractelement_vgpr_v8i16_sgpr_idx: ; GFX11: ; %bb.0: ; GFX11-NEXT: s_and_b32 s0, s2, 7 -; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1) +; GFX11-NEXT: s_mov_b32 s1, 0 ; GFX11-NEXT: s_lshl_b32 s0, s0, 1 -; GFX11-NEXT: s_ashr_i32 s1, s0, 31 ; GFX11-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(VALU_DEP_1) ; GFX11-NEXT: v_dual_mov_b32 v3, s1 :: v_dual_mov_b32 v2, s0 ; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 @@ -837,9 +793,8 @@ define i16 @extractelement_vgpr_v8i16_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx) ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: v_and_b32_e32 v2, 7, v2 ; GFX9-NEXT: v_lshlrev_b32_e32 v2, 1, v2 -; GFX9-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v0, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v3, vcc +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc ; GFX9-NEXT: global_load_ushort v0, v[0:1], off ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -849,9 +804,8 @@ define i16 @extractelement_vgpr_v8i16_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx) ; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX8-NEXT: v_and_b32_e32 v2, 7, v2 ; GFX8-NEXT: v_lshlrev_b32_e32 v2, 1, v2 -; GFX8-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX8-NEXT: v_add_u32_e32 v0, vcc, v0, v2 -; GFX8-NEXT: v_addc_u32_e32 v1, vcc, v1, v3, vcc +; GFX8-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GFX8-NEXT: flat_load_ushort v0, v[0:1] ; GFX8-NEXT: s_waitcnt vmcnt(0) ; GFX8-NEXT: s_setpc_b64 s[30:31] @@ -861,9 +815,8 @@ define i16 @extractelement_vgpr_v8i16_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx) ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX7-NEXT: v_and_b32_e32 v2, 7, v2 ; GFX7-NEXT: v_lshlrev_b32_e32 v2, 1, v2 -; GFX7-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX7-NEXT: v_add_i32_e32 v0, vcc, v0, v2 -; GFX7-NEXT: v_addc_u32_e32 v1, vcc, v1, v3, vcc +; GFX7-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GFX7-NEXT: s_mov_b32 s6, 0 ; GFX7-NEXT: s_mov_b32 s7, 0xf000 ; GFX7-NEXT: s_mov_b64 s[4:5], 0 @@ -876,9 +829,8 @@ define i16 @extractelement_vgpr_v8i16_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx) ; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX10-NEXT: v_and_b32_e32 v2, 7, v2 ; GFX10-NEXT: v_lshlrev_b32_e32 v2, 1, v2 -; GFX10-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX10-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX10-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo +; GFX10-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, 0, v1, vcc_lo ; GFX10-NEXT: global_load_ushort v0, v[0:1], off ; GFX10-NEXT: s_waitcnt vmcnt(0) ; GFX10-NEXT: s_setpc_b64 s[30:31] @@ -889,10 +841,8 @@ define i16 @extractelement_vgpr_v8i16_vgpr_idx(ptr addrspace(1) %ptr, i32 %idx) ; GFX11-NEXT: v_and_b32_e32 v2, 7, v2 ; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) ; GFX11-NEXT: v_lshlrev_b32_e32 v2, 1, v2 -; GFX11-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) -; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo +; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, 0, v1, vcc_lo ; GFX11-NEXT: global_load_u16 v0, v[0:1], off ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: s_setpc_b64 s[30:31] @@ -905,13 +855,8 @@ define amdgpu_ps i16 @extractelement_sgpr_v8i16_vgpr_idx(ptr addrspace(4) inreg ; GFX9-LABEL: extractelement_sgpr_v8i16_vgpr_idx: ; GFX9: ; %bb.0: ; GFX9-NEXT: v_and_b32_e32 v0, 7, v0 -; GFX9-NEXT: v_lshlrev_b32_e32 v2, 1, v0 -; GFX9-NEXT: v_mov_b32_e32 v0, s2 -; GFX9-NEXT: v_ashrrev_i32_e32 v3, 31, v2 -; GFX9-NEXT: v_mov_b32_e32 v1, s3 -; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, v0, v2 -; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, v1, v3, vcc -; GFX9-NEXT: global_load_ushort v0, v[0:1], off +; GFX9-NEXT: v_lshlrev_b32_e32 v0, 1, v0 +; GFX9-NEXT: global_load_ushort v0, v0, s[2:3] ; GFX9-NEXT: s_waitcnt vmcnt(0) ; GFX9-NEXT: v_readfirstlane_b32 s0, v0 ; GFX9-NEXT: ; return to shader part epilog @@ -921,10 +866,9 @@ define amdgpu_ps i16 @extractelement_sgpr_v8i16_vgpr_idx(ptr addrspace(4) inreg ; GFX8-NEXT: v_and_b32_e32 v0, 7, v0 ; GFX8-NEXT: v_lshlrev_b32_e32 v2, 1, v0 ; GFX8-NEXT: v_mov_b32_e32 v0, s2 -; GFX8-NEXT: v_ashrrev_i32_e32 v3, 31, v2 ; GFX8-NEXT: v_mov_b32_e32 v1, s3 ; GFX8-NEXT: v_add_u32_e32 v0, vcc, v0, v2 -; GFX8-NEXT: v_addc_u32_e32 v1, vcc, v1, v3, vcc +; GFX8-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc ; GFX8-NEXT: flat_load_ushort v0, v[0:1] ; GFX8-NEXT: s_waitcnt vmcnt(0) ; GFX8-NEXT: v_readfirstlane_b32 s0, v0 @@ -933,10 +877,10 @@ define amdgpu_ps i16 @extractelement_sgpr_v8i16_vgpr_idx(ptr addrspace(4) inreg ; GFX7-LABEL: extractelement_sgpr_v8i16_vgpr_idx: ; GFX7: ; %bb.0: ; GFX7-NEXT: v_and_b32_e32 v0, 7, v0 -; GFX7-NEXT: v_lshlrev_b32_e32 v0, 1, v0 ; GFX7-NEXT: s_mov_b32 s0, s2 ; GFX7-NEXT: s_mov_b32 s1, s3 -; GFX7-NEXT: v_ashrrev_i32_e32 v1, 31, v0 +; GFX7-NEXT: v_lshlrev_b32_e32 v0, 1, v0 +; GFX7-NEXT: v_mov_b32_e32 v1, 0 ; GFX7-NEXT: s_mov_b32 s2, 0 ; GFX7-NEXT: s_mov_b32 s3, 0xf000 ; GFX7-NEXT: buffer_load_ushort v0, v[0:1], s[0:3], 0 addr64 @@ -947,13 +891,8 @@ define amdgpu_ps i16 @extractelement_sgpr_v8i16_vgpr_idx(ptr addrspace(4) inreg ; GFX10-LABEL: extractelement_sgpr_v8i16_vgpr_idx: ; GFX10: ; %bb.0: ; GFX10-NEXT: v_and_b32_e32 v0, 7, v0 -; GFX10-NEXT: v_lshlrev_b32_e32 v2, 1, v0 -; GFX10-NEXT: v_mov_b32_e32 v0, s2 -; GFX10-NEXT: v_mov_b32_e32 v1, s3 -; GFX10-NEXT: v_ashrrev_i32_e32 v3, 31, v2 -; GFX10-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX10-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo -; GFX10-NEXT: global_load_ushort v0, v[0:1], off +; GFX10-NEXT: v_lshlrev_b32_e32 v0, 1, v0 +; GFX10-NEXT: global_load_ushort v0, v0, s[2:3] ; GFX10-NEXT: s_waitcnt vmcnt(0) ; GFX10-NEXT: v_readfirstlane_b32 s0, v0 ; GFX10-NEXT: ; return to shader part epilog @@ -961,14 +900,9 @@ define amdgpu_ps i16 @extractelement_sgpr_v8i16_vgpr_idx(ptr addrspace(4) inreg ; GFX11-LABEL: extractelement_sgpr_v8i16_vgpr_idx: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_and_b32_e32 v0, 7, v0 -; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2) -; GFX11-NEXT: v_lshlrev_b32_e32 v2, 1, v0 -; GFX11-NEXT: v_dual_mov_b32 v0, s2 :: v_dual_mov_b32 v1, s3 -; GFX11-NEXT: v_ashrrev_i32_e32 v3, 31, v2 -; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) -; GFX11-NEXT: v_add_co_u32 v0, vcc_lo, v0, v2 -; GFX11-NEXT: v_add_co_ci_u32_e32 v1, vcc_lo, v1, v3, vcc_lo -; GFX11-NEXT: global_load_u16 v0, v[0:1], off +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_lshlrev_b32_e32 v0, 1, v0 +; GFX11-NEXT: global_load_u16 v0, v0, s[2:3] ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: v_readfirstlane_b32 s0, v0 ; GFX11-NEXT: ; return to shader part epilog diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ptr-add.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ptr-add.mir index 660746c84287..09e1109c3629 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ptr-add.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ptr-add.mir @@ -205,210 +205,3 @@ body: | %2:_(<2 x p3>) = G_PTR_ADD %0, %1 $vgpr0_vgpr1 = COPY %2 ... - ---- -name: test_gep_global_s16_idx -body: | - bb.0: - liveins: $vgpr0_vgpr1, $vgpr2 - - ; CHECK-LABEL: name: test_gep_global_s16_idx - ; CHECK: liveins: $vgpr0_vgpr1, $vgpr2 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p1) = COPY $vgpr0_vgpr1 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr2 - ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[COPY1]](s32) - ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s64) = G_SEXT_INREG [[ANYEXT]], 16 - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p1) = G_PTR_ADD [[COPY]], [[SEXT_INREG]](s64) - ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[PTR_ADD]](p1) - %0:_(p1) = COPY $vgpr0_vgpr1 - %1:_(s32) = COPY $vgpr2 - %2:_(s16) = G_TRUNC %1 - %3:_(p1) = G_PTR_ADD %0, %2 - $vgpr0_vgpr1 = COPY %3 -... - ---- -name: test_gep_global_s32_idx -body: | - bb.0: - liveins: $vgpr0_vgpr1, $vgpr2 - - ; CHECK-LABEL: name: test_gep_global_s32_idx - ; CHECK: liveins: $vgpr0_vgpr1, $vgpr2 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p1) = COPY $vgpr0_vgpr1 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr2 - ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[COPY1]](s32) - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p1) = G_PTR_ADD [[COPY]], [[SEXT]](s64) - ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[PTR_ADD]](p1) - %0:_(p1) = COPY $vgpr0_vgpr1 - %1:_(s32) = COPY $vgpr2 - %2:_(p1) = G_PTR_ADD %0, %1 - $vgpr0_vgpr1 = COPY %2 -... - ---- -name: test_gep_global_s96_idx -body: | - bb.0: - liveins: $vgpr0_vgpr1, $vgpr2_vgpr3_vgpr4 - - ; CHECK-LABEL: name: test_gep_global_s96_idx - ; CHECK: liveins: $vgpr0_vgpr1, $vgpr2_vgpr3_vgpr4 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p1) = COPY $vgpr0_vgpr1 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s96) = COPY $vgpr2_vgpr3_vgpr4 - ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s64) = G_TRUNC [[COPY1]](s96) - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p1) = G_PTR_ADD [[COPY]], [[TRUNC]](s64) - ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[PTR_ADD]](p1) - %0:_(p1) = COPY $vgpr0_vgpr1 - %1:_(s96) = COPY $vgpr2_vgpr3_vgpr4 - %2:_(p1) = G_PTR_ADD %0, %1 - $vgpr0_vgpr1 = COPY %2 -... - ---- -name: test_gep_local_i16_idx -body: | - bb.0: - liveins: $vgpr0, $vgpr1 - - ; CHECK-LABEL: name: test_gep_local_i16_idx - ; CHECK: liveins: $vgpr0, $vgpr1 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p3) = COPY $vgpr0 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 - ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[COPY1]], 16 - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p3) = G_PTR_ADD [[COPY]], [[SEXT_INREG]](s32) - ; CHECK-NEXT: $vgpr0 = COPY [[PTR_ADD]](p3) - %0:_(p3) = COPY $vgpr0 - %1:_(s32) = COPY $vgpr1 - %2:_(s16) = G_TRUNC %1 - %3:_(p3) = G_PTR_ADD %0, %2 - $vgpr0 = COPY %3 -... - ---- -name: test_gep_local_i64_idx -body: | - bb.0: - liveins: $vgpr0, $vgpr1_vgpr2 - - ; CHECK-LABEL: name: test_gep_local_i64_idx - ; CHECK: liveins: $vgpr0, $vgpr1_vgpr2 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p3) = COPY $vgpr0 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr1_vgpr2 - ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p3) = G_PTR_ADD [[COPY]], [[TRUNC]](s32) - ; CHECK-NEXT: $vgpr0 = COPY [[PTR_ADD]](p3) - %0:_(p3) = COPY $vgpr0 - %1:_(s64) = COPY $vgpr1_vgpr2 - %2:_(p3) = G_PTR_ADD %0, %1 - $vgpr0 = COPY %2 -... - ---- -name: test_gep_v2p1_v2i32 -body: | - bb.0: - liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5 - - ; CHECK-LABEL: name: test_gep_v2p1_v2i32 - ; CHECK: liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x p1>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr4_vgpr5 - ; CHECK-NEXT: [[UV:%[0-9]+]]:_(p1), [[UV1:%[0-9]+]]:_(p1) = G_UNMERGE_VALUES [[COPY]](<2 x p1>) - ; CHECK-NEXT: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) - ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[UV2]](s32) - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p1) = G_PTR_ADD [[UV]], [[SEXT]](s64) - ; CHECK-NEXT: [[SEXT1:%[0-9]+]]:_(s64) = G_SEXT [[UV3]](s32) - ; CHECK-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p1) = G_PTR_ADD [[UV1]], [[SEXT1]](s64) - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x p1>) = G_BUILD_VECTOR [[PTR_ADD]](p1), [[PTR_ADD1]](p1) - ; CHECK-NEXT: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x p1>) - %0:_(<2 x p1>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 - %1:_(<2 x s32>) = COPY $vgpr4_vgpr5 - %2:_(<2 x p1>) = G_PTR_ADD %0, %1 - $vgpr0_vgpr1_vgpr2_vgpr3 = COPY %2 -... - ---- -name: test_gep_v2p1_v2i96 -body: | - bb.0: - liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5_vgpr6, $vgpr7_vgpr8_vgpr9 - - ; CHECK-LABEL: name: test_gep_v2p1_v2i96 - ; CHECK: liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5_vgpr6, $vgpr7_vgpr8_vgpr9 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x p1>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s96) = COPY $vgpr4_vgpr5_vgpr6 - ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s96) = COPY $vgpr7_vgpr8_vgpr9 - ; CHECK-NEXT: [[UV:%[0-9]+]]:_(p1), [[UV1:%[0-9]+]]:_(p1) = G_UNMERGE_VALUES [[COPY]](<2 x p1>) - ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s64) = G_TRUNC [[COPY1]](s96) - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p1) = G_PTR_ADD [[UV]], [[TRUNC]](s64) - ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s64) = G_TRUNC [[COPY2]](s96) - ; CHECK-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p1) = G_PTR_ADD [[UV1]], [[TRUNC1]](s64) - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x p1>) = G_BUILD_VECTOR [[PTR_ADD]](p1), [[PTR_ADD1]](p1) - ; CHECK-NEXT: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x p1>) - %0:_(<2 x p1>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 - %1:_(s96) = COPY $vgpr4_vgpr5_vgpr6 - %2:_(s96) = COPY $vgpr7_vgpr8_vgpr9 - %3:_(<2 x s96>) = G_BUILD_VECTOR %1, %2 - %4:_(<2 x p1>) = G_PTR_ADD %0, %3 - $vgpr0_vgpr1_vgpr2_vgpr3 = COPY %4 -... - ---- -name: test_gep_v2p3_v2s16 -body: | - bb.0: - liveins: $vgpr0_vgpr1, $vgpr2 - - ; CHECK-LABEL: name: test_gep_v2p3_v2s16 - ; CHECK: liveins: $vgpr0_vgpr1, $vgpr2 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x p3>) = COPY $vgpr0_vgpr1 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr2 - ; CHECK-NEXT: [[UV:%[0-9]+]]:_(p3), [[UV1:%[0-9]+]]:_(p3) = G_UNMERGE_VALUES [[COPY]](<2 x p3>) - ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(s32) = G_BITCAST [[COPY1]](<2 x s16>) - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 - ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[BITCAST]], [[C]](s32) - ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[BITCAST]], 16 - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p3) = G_PTR_ADD [[UV]], [[SEXT_INREG]](s32) - ; CHECK-NEXT: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[LSHR]], 16 - ; CHECK-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p3) = G_PTR_ADD [[UV1]], [[SEXT_INREG1]](s32) - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x p3>) = G_BUILD_VECTOR [[PTR_ADD]](p3), [[PTR_ADD1]](p3) - ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x p3>) - %0:_(<2 x p3>) = COPY $vgpr0_vgpr1 - %1:_(<2 x s16>) = COPY $vgpr2 - %2:_(<2 x p3>) = G_PTR_ADD %0, %1 - $vgpr0_vgpr1 = COPY %2 -... - ---- -name: test_gep_v2p3_v2s64 -body: | - bb.0: - liveins: $vgpr0_vgpr1, $vgpr2_vgpr3_vgpr4_vgpr5 - - ; CHECK-LABEL: name: test_gep_v2p3_v2s64 - ; CHECK: liveins: $vgpr0_vgpr1, $vgpr2_vgpr3_vgpr4_vgpr5 - ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x p3>) = COPY $vgpr0_vgpr1 - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr2_vgpr3_vgpr4_vgpr5 - ; CHECK-NEXT: [[UV:%[0-9]+]]:_(p3), [[UV1:%[0-9]+]]:_(p3) = G_UNMERGE_VALUES [[COPY]](<2 x p3>) - ; CHECK-NEXT: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY1]](<2 x s64>) - ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[UV2]](s64) - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p3) = G_PTR_ADD [[UV]], [[TRUNC]](s32) - ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[UV3]](s64) - ; CHECK-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p3) = G_PTR_ADD [[UV1]], [[TRUNC1]](s32) - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x p3>) = G_BUILD_VECTOR [[PTR_ADD]](p3), [[PTR_ADD1]](p3) - ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x p3>) - %0:_(<2 x p3>) = COPY $vgpr0_vgpr1 - %1:_(<2 x s64>) = COPY $vgpr2_vgpr3_vgpr4_vgpr5 - %2:_(<2 x p3>) = G_PTR_ADD %0, %1 - $vgpr0_vgpr1 = COPY %2 -... diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-load-store.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-load-store.mir index c1b1e2282254..044ad60d1ae7 100644 --- a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-load-store.mir +++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-load-store.mir @@ -9,7 +9,6 @@ define void @test_load_store_64_novfp() #1 { ret void } define void @test_gep_s32() { ret void } - define void @test_gep_s16() { ret void } attributes #0 = { "target-features"="+vfp2" } attributes #1 = { "target-features"="-vfp2sp" } @@ -211,30 +210,3 @@ body: | $r0 = COPY %2(p0) BX_RET 14, $noreg, implicit $r0 ... ---- -name: test_gep_s16 -# CHECK-LABEL: name: test_gep_s16 -legalized: false -# CHECK: legalized: true -regBankSelected: false -selected: false -tracksRegLiveness: true -registers: - - { id: 0, class: _ } - - { id: 1, class: _ } - - { id: 2, class: _ } -body: | - bb.0: - liveins: $r0 - - %0(p0) = COPY $r0 - %1(s16) = G_LOAD %0(p0) :: (load (s16)) - - ; CHECK-NOT: G_PTR_ADD {{%[0-9]+}}, {{%[0-9]+}}(s16) - ; CHECK: {{%[0-9]+}}:_(p0) = G_PTR_ADD {{%[0-9]+}}, {{%[0-9]+}}(s32) - ; CHECK-NOT: G_PTR_ADD {{%[0-9]+}}, {{%[0-9]+}}(s16) - %2(p0) = G_PTR_ADD %0, %1(s16) - - $r0 = COPY %2(p0) - BX_RET 14, $noreg, implicit $r0 -... diff --git a/llvm/test/CodeGen/X86/GlobalISel/legalize-ptr-add-32.mir b/llvm/test/CodeGen/X86/GlobalISel/legalize-ptr-add-32.mir new file mode 100644 index 000000000000..584a400996e6 --- /dev/null +++ b/llvm/test/CodeGen/X86/GlobalISel/legalize-ptr-add-32.mir @@ -0,0 +1,55 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=i386-linux-gnu -run-pass=legalizer %s -o - | FileCheck %s --check-prefixes=CHECK + +--- | + define void @test_gep_i32c(ptr %addr) { + %arrayidx = getelementptr i32, ptr undef, i32 5 + ret void + } + define void @test_gep_i32(ptr %addr, i32 %ofs) { + %arrayidx = getelementptr i32, ptr undef, i32 %ofs + ret void + } +... +--- +name: test_gep_i32c +legalized: false +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.1 (%ir-block.0): + ; CHECK-LABEL: name: test_gep_i32c + ; CHECK: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 20 + ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[DEF]], [[C]](s32) + ; CHECK-NEXT: G_STORE [[PTR_ADD]](p0), [[DEF]](p0) :: (store (p0) into %ir.addr) + ; CHECK-NEXT: RET 0 + %0(p0) = IMPLICIT_DEF + %1(s32) = G_CONSTANT i32 20 + %2(p0) = G_PTR_ADD %0, %1(s32) + G_STORE %2, %0 :: (store (p0) into %ir.addr) + RET 0 +... +--- +name: test_gep_i32 +legalized: false +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.1 (%ir-block.0): + ; CHECK-LABEL: name: test_gep_i32 + ; CHECK: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(s32) = IMPLICIT_DEF + ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[DEF]], [[DEF1]](s32) + ; CHECK-NEXT: G_STORE [[PTR_ADD]](p0), [[DEF]](p0) :: (store (p0) into %ir.addr) + ; CHECK-NEXT: RET 0 + %0(p0) = IMPLICIT_DEF + %1(s32) = IMPLICIT_DEF + %2(p0) = G_PTR_ADD %0, %1(s32) + G_STORE %2, %0 :: (store (p0) into %ir.addr) + RET 0 +... diff --git a/llvm/test/CodeGen/X86/GlobalISel/legalize-ptr-add-64.mir b/llvm/test/CodeGen/X86/GlobalISel/legalize-ptr-add-64.mir new file mode 100644 index 000000000000..7826257c21e5 --- /dev/null +++ b/llvm/test/CodeGen/X86/GlobalISel/legalize-ptr-add-64.mir @@ -0,0 +1,55 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=x86_64-linux-gnu -run-pass=legalizer %s -o - | FileCheck %s --check-prefixes=X64 + +--- | + define void @test_gep_i64c(ptr %addr) { + %arrayidx = getelementptr i32, ptr undef, i64 5 + ret void + } + define void @test_gep_i64(ptr %addr, i64 %ofs) { + %arrayidx = getelementptr i32, ptr undef, i64 %ofs + ret void + } +... +--- +name: test_gep_i64c +legalized: false +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.1 (%ir-block.0): + ; X64-LABEL: name: test_gep_i64c + ; X64: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF + ; X64-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 20 + ; X64-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[DEF]], [[C]](s64) + ; X64-NEXT: G_STORE [[PTR_ADD]](p0), [[DEF]](p0) :: (store (p0) into %ir.addr) + ; X64-NEXT: RET 0 + %0(p0) = IMPLICIT_DEF + %1(s64) = G_CONSTANT i64 20 + %2(p0) = G_PTR_ADD %0, %1(s64) + G_STORE %2, %0 :: (store (p0) into %ir.addr) + RET 0 +... +--- +name: test_gep_i64 +legalized: false +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.1 (%ir-block.0): + ; X64-LABEL: name: test_gep_i64 + ; X64: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF + ; X64-NEXT: [[DEF1:%[0-9]+]]:_(s64) = IMPLICIT_DEF + ; X64-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[DEF]], [[DEF1]](s64) + ; X64-NEXT: G_STORE [[PTR_ADD]](p0), [[DEF]](p0) :: (store (p0) into %ir.addr) + ; X64-NEXT: RET 0 + %0(p0) = IMPLICIT_DEF + %1(s64) = IMPLICIT_DEF + %2(p0) = G_PTR_ADD %0, %1(s64) + G_STORE %2, %0 :: (store (p0) into %ir.addr) + RET 0 +... diff --git a/llvm/test/CodeGen/X86/GlobalISel/legalize-ptr-add.mir b/llvm/test/CodeGen/X86/GlobalISel/legalize-ptr-add.mir deleted file mode 100644 index b1beb2e98cc8..000000000000 --- a/llvm/test/CodeGen/X86/GlobalISel/legalize-ptr-add.mir +++ /dev/null @@ -1,224 +0,0 @@ -# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py -# RUN: llc -mtriple=x86_64-linux-gnu -run-pass=legalizer %s -o - | FileCheck %s --check-prefixes=CHECK,X64 -# RUN: llc -mtriple=i386-linux-gnu -run-pass=legalizer %s -o - | FileCheck %s --check-prefixes=CHECK,X86 - ---- | - define void @test_gep_i8c(ptr %addr) { - %arrayidx = getelementptr i32, ptr undef, i8 5 - ret void - } - define void @test_gep_i8(ptr %addr, i8 %ofs) { - %arrayidx = getelementptr i32, ptr undef, i8 %ofs - ret void - } - - define void @test_gep_i16c(ptr %addr) { - %arrayidx = getelementptr i32, ptr undef, i16 5 - ret void - } - define void @test_gep_i16(ptr %addr, i16 %ofs) { - %arrayidx = getelementptr i32, ptr undef, i16 %ofs - ret void - } - - define void @test_gep_i32c(ptr %addr) { - %arrayidx = getelementptr i32, ptr undef, i32 5 - ret void - } - define void @test_gep_i32(ptr %addr, i32 %ofs) { - %arrayidx = getelementptr i32, ptr undef, i32 %ofs - ret void - } - - define void @test_gep_i64c(ptr %addr) { - %arrayidx = getelementptr i32, ptr undef, i64 5 - ret void - } - define void @test_gep_i64(ptr %addr, i64 %ofs) { - %arrayidx = getelementptr i32, ptr undef, i64 %ofs - ret void - } -... ---- -name: test_gep_i8c -legalized: false -registers: - - { id: 0, class: _ } - - { id: 1, class: _ } - - { id: 2, class: _ } -body: | - bb.1 (%ir-block.0): - ; CHECK-LABEL: name: test_gep_i8c - ; CHECK: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 20 - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[DEF]], [[C]](s32) - ; CHECK-NEXT: G_STORE [[PTR_ADD]](p0), [[DEF]](p0) :: (store (p0) into %ir.addr) - ; CHECK-NEXT: RET 0 - %0(p0) = IMPLICIT_DEF - %1(s8) = G_CONSTANT i8 20 - %2(p0) = G_PTR_ADD %0, %1(s8) - G_STORE %2, %0 :: (store (p0) into %ir.addr) - RET 0 -... ---- -name: test_gep_i8 -legalized: false -registers: - - { id: 0, class: _ } - - { id: 1, class: _ } - - { id: 2, class: _ } -body: | - bb.1 (%ir-block.0): - ; CHECK-LABEL: name: test_gep_i8 - ; CHECK: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF - ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(s8) = IMPLICIT_DEF - ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[DEF1]](s8) - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[DEF]], [[SEXT]](s32) - ; CHECK-NEXT: G_STORE [[PTR_ADD]](p0), [[DEF]](p0) :: (store (p0) into %ir.addr) - ; CHECK-NEXT: RET 0 - %0(p0) = IMPLICIT_DEF - %1(s8) = IMPLICIT_DEF - %2(p0) = G_PTR_ADD %0, %1(s8) - G_STORE %2, %0 :: (store (p0) into %ir.addr) - RET 0 -... ---- -name: test_gep_i16c -legalized: false -registers: - - { id: 0, class: _ } - - { id: 1, class: _ } - - { id: 2, class: _ } -body: | - bb.1 (%ir-block.0): - ; CHECK-LABEL: name: test_gep_i16c - ; CHECK: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 20 - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[DEF]], [[C]](s32) - ; CHECK-NEXT: G_STORE [[PTR_ADD]](p0), [[DEF]](p0) :: (store (p0) into %ir.addr) - ; CHECK-NEXT: RET 0 - %0(p0) = IMPLICIT_DEF - %1(s16) = G_CONSTANT i16 20 - %2(p0) = G_PTR_ADD %0, %1(s16) - G_STORE %2, %0 :: (store (p0) into %ir.addr) - RET 0 -... ---- -name: test_gep_i16 -legalized: false -registers: - - { id: 0, class: _ } - - { id: 1, class: _ } - - { id: 2, class: _ } -body: | - bb.1 (%ir-block.0): - ; CHECK-LABEL: name: test_gep_i16 - ; CHECK: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF - ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(s16) = IMPLICIT_DEF - ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[DEF1]](s16) - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[DEF]], [[SEXT]](s32) - ; CHECK-NEXT: G_STORE [[PTR_ADD]](p0), [[DEF]](p0) :: (store (p0) into %ir.addr) - ; CHECK-NEXT: RET 0 - %0(p0) = IMPLICIT_DEF - %1(s16) = IMPLICIT_DEF - %2(p0) = G_PTR_ADD %0, %1(s16) - G_STORE %2, %0 :: (store (p0) into %ir.addr) - RET 0 -... ---- -name: test_gep_i32c -legalized: false -registers: - - { id: 0, class: _ } - - { id: 1, class: _ } - - { id: 2, class: _ } -body: | - bb.1 (%ir-block.0): - ; CHECK-LABEL: name: test_gep_i32c - ; CHECK: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 20 - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[DEF]], [[C]](s32) - ; CHECK-NEXT: G_STORE [[PTR_ADD]](p0), [[DEF]](p0) :: (store (p0) into %ir.addr) - ; CHECK-NEXT: RET 0 - %0(p0) = IMPLICIT_DEF - %1(s32) = G_CONSTANT i32 20 - %2(p0) = G_PTR_ADD %0, %1(s32) - G_STORE %2, %0 :: (store (p0) into %ir.addr) - RET 0 -... ---- -name: test_gep_i32 -legalized: false -registers: - - { id: 0, class: _ } - - { id: 1, class: _ } - - { id: 2, class: _ } -body: | - bb.1 (%ir-block.0): - ; CHECK-LABEL: name: test_gep_i32 - ; CHECK: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF - ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(s32) = IMPLICIT_DEF - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[DEF]], [[DEF1]](s32) - ; CHECK-NEXT: G_STORE [[PTR_ADD]](p0), [[DEF]](p0) :: (store (p0) into %ir.addr) - ; CHECK-NEXT: RET 0 - %0(p0) = IMPLICIT_DEF - %1(s32) = IMPLICIT_DEF - %2(p0) = G_PTR_ADD %0, %1(s32) - G_STORE %2, %0 :: (store (p0) into %ir.addr) - RET 0 -... ---- -name: test_gep_i64c -legalized: false -registers: - - { id: 0, class: _ } - - { id: 1, class: _ } - - { id: 2, class: _ } -body: | - bb.1 (%ir-block.0): - ; X64-LABEL: name: test_gep_i64c - ; X64: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF - ; X64-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 20 - ; X64-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[DEF]], [[C]](s64) - ; X64-NEXT: G_STORE [[PTR_ADD]](p0), [[DEF]](p0) :: (store (p0) into %ir.addr) - ; X64-NEXT: RET 0 - ; X86-LABEL: name: test_gep_i64c - ; X86: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF - ; X86-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 20 - ; X86-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[DEF]], [[C]](s32) - ; X86-NEXT: G_STORE [[PTR_ADD]](p0), [[DEF]](p0) :: (store (p0) into %ir.addr) - ; X86-NEXT: RET 0 - %0(p0) = IMPLICIT_DEF - %1(s64) = G_CONSTANT i64 20 - %2(p0) = G_PTR_ADD %0, %1(s64) - G_STORE %2, %0 :: (store (p0) into %ir.addr) - RET 0 -... ---- -name: test_gep_i64 -legalized: false -registers: - - { id: 0, class: _ } - - { id: 1, class: _ } - - { id: 2, class: _ } -body: | - bb.1 (%ir-block.0): - ; X64-LABEL: name: test_gep_i64 - ; X64: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF - ; X64-NEXT: [[DEF1:%[0-9]+]]:_(s64) = IMPLICIT_DEF - ; X64-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[DEF]], [[DEF1]](s64) - ; X64-NEXT: G_STORE [[PTR_ADD]](p0), [[DEF]](p0) :: (store (p0) into %ir.addr) - ; X64-NEXT: RET 0 - ; X86-LABEL: name: test_gep_i64 - ; X86: [[DEF:%[0-9]+]]:_(p0) = IMPLICIT_DEF - ; X86-NEXT: [[DEF1:%[0-9]+]]:_(s64) = IMPLICIT_DEF - ; X86-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[DEF1]](s64) - ; X86-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[DEF]], [[TRUNC]](s32) - ; X86-NEXT: G_STORE [[PTR_ADD]](p0), [[DEF]](p0) :: (store (p0) into %ir.addr) - ; X86-NEXT: RET 0 - %0(p0) = IMPLICIT_DEF - %1(s64) = IMPLICIT_DEF - %2(p0) = G_PTR_ADD %0, %1(s64) - G_STORE %2, %0 :: (store (p0) into %ir.addr) - RET 0 -... diff --git a/llvm/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir b/llvm/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir index c2dcf3035924..03d4c7dd3281 100644 --- a/llvm/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir +++ b/llvm/test/CodeGen/X86/GlobalISel/regbankselect-X86_64.mir @@ -1380,23 +1380,18 @@ body: | bb.0 (%ir-block.0): ; FAST-LABEL: name: test_gep ; FAST: [[DEF:%[0-9]+]]:gpr(p0) = G_IMPLICIT_DEF - ; FAST: [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 20 - ; FAST: [[PTR_ADD:%[0-9]+]]:gpr(p0) = G_PTR_ADD [[DEF]], [[C]](s32) - ; FAST: [[C1:%[0-9]+]]:gpr(s64) = G_CONSTANT i64 20 - ; FAST: [[PTR_ADD1:%[0-9]+]]:gpr(p0) = G_PTR_ADD [[DEF]], [[C1]](s64) + ; FAST: [[C:%[0-9]+]]:gpr(s64) = G_CONSTANT i64 20 + ; FAST: [[PTR_ADD:%[0-9]+]]:gpr(p0) = G_PTR_ADD [[DEF]], [[C]](s64) ; FAST: RET 0 + ; ; GREEDY-LABEL: name: test_gep ; GREEDY: [[DEF:%[0-9]+]]:gpr(p0) = G_IMPLICIT_DEF - ; GREEDY: [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 20 - ; GREEDY: [[PTR_ADD:%[0-9]+]]:gpr(p0) = G_PTR_ADD [[DEF]], [[C]](s32) - ; GREEDY: [[C1:%[0-9]+]]:gpr(s64) = G_CONSTANT i64 20 - ; GREEDY: [[PTR_ADD1:%[0-9]+]]:gpr(p0) = G_PTR_ADD [[DEF]], [[C1]](s64) + ; GREEDY: [[C:%[0-9]+]]:gpr(s64) = G_CONSTANT i64 20 + ; GREEDY: [[PTR_ADD:%[0-9]+]]:gpr(p0) = G_PTR_ADD [[DEF]], [[C]](s64) ; GREEDY: RET 0 %0(p0) = G_IMPLICIT_DEF - %1(s32) = G_CONSTANT i32 20 - %2(p0) = G_PTR_ADD %0, %1(s32) - %3(s64) = G_CONSTANT i64 20 - %4(p0) = G_PTR_ADD %0, %3(s64) + %1(s64) = G_CONSTANT i64 20 + %2(p0) = G_PTR_ADD %0, %1(s64) RET 0 ... diff --git a/llvm/test/MachineVerifier/test_g_ptr_add.mir b/llvm/test/MachineVerifier/test_g_ptr_add.mir index 07fe6266701d..7d1373586c8e 100644 --- a/llvm/test/MachineVerifier/test_g_ptr_add.mir +++ b/llvm/test/MachineVerifier/test_g_ptr_add.mir @@ -1,4 +1,4 @@ -#RUN: not --crash llc -o - -mtriple=arm64 -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s +# RUN: not --crash llc -o - -mtriple=arm64 -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s # REQUIRES: aarch64-registered-target --- @@ -29,4 +29,8 @@ body: | ; CHECK: Bad machine code: gep first operand must be a pointer %6:_(s64) = G_PTR_ADD %1, %1 + %7:_(s32) = G_IMPLICIT_DEF + + ; CHECK: Bad machine code: gep offset operand must match index size for address space + %8:_(p0) = G_PTR_ADD %0, %7 ... -- GitLab From 10aed27e9c8966cd11d98a61982b95607ab6e08c Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Sat, 9 Mar 2024 11:21:47 +0100 Subject: [PATCH 005/953] [libc++] Simplify the std::pair constructor overload set (#81448) This depends on enabling extensions in the implementation. --- libcxx/include/__utility/pair.h | 96 ++++++++++----------------------- 1 file changed, 27 insertions(+), 69 deletions(-) diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h index 8af23668a815..b488a9829c38 100644 --- a/libcxx/include/__utility/pair.h +++ b/libcxx/include/__utility/pair.h @@ -120,14 +120,13 @@ struct _LIBCPP_TEMPLATE_VIS pair #else struct _CheckArgs { template - static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_explicit_default() { - return is_default_constructible<_T1>::value && is_default_constructible<_T2>::value && - !__enable_implicit_default<>(); + static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_implicit_default() { + return __is_implicitly_default_constructible<_T1>::value && __is_implicitly_default_constructible<_T2>::value; } template - static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_implicit_default() { - return __is_implicitly_default_constructible<_T1>::value && __is_implicitly_default_constructible<_T2>::value; + static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_default() { + return is_default_constructible<_T1>::value && is_default_constructible<_T2>::value; } template @@ -139,58 +138,25 @@ struct _LIBCPP_TEMPLATE_VIS pair static _LIBCPP_HIDE_FROM_ABI constexpr bool __is_implicit() { return is_convertible<_U1, first_type>::value && is_convertible<_U2, second_type>::value; } - - template - static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_explicit() { - return __is_pair_constructible<_U1, _U2>() && !__is_implicit<_U1, _U2>(); - } - - template - static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_implicit() { - return __is_pair_constructible<_U1, _U2>() && __is_implicit<_U1, _U2>(); - } }; template using _CheckArgsDep _LIBCPP_NODEBUG = typename conditional< _MaybeEnable, _CheckArgs, __check_tuple_constructor_fail>::type; - template ::__enable_explicit_default(), int> = 0> - explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair() _NOEXCEPT_( - is_nothrow_default_constructible::value&& is_nothrow_default_constructible::value) - : first(), second() {} - - template ::__enable_implicit_default(), int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair() _NOEXCEPT_( - is_nothrow_default_constructible::value&& is_nothrow_default_constructible::value) + template ::__enable_default(), int> = 0> + explicit(!_CheckArgsDep<_Dummy>::__enable_implicit_default()) _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair() + _NOEXCEPT_( + is_nothrow_default_constructible::value&& is_nothrow_default_constructible::value) : first(), second() {} - template ::template __enable_explicit<_T1 const&, _T2 const&>(), int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(_T1 const& __t1, _T2 const& __t2) + template ::template __is_pair_constructible<_T1 const&, _T2 const&>(), int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit( + !_CheckArgsDep<_Dummy>::template __is_implicit<_T1 const&, _T2 const&>()) pair(_T1 const& __t1, _T2 const& __t2) _NOEXCEPT_(is_nothrow_copy_constructible::value&& is_nothrow_copy_constructible::value) : first(__t1), second(__t2) {} - template ::template __enable_implicit<_T1 const&, _T2 const&>(), int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(_T1 const& __t1, _T2 const& __t2) - _NOEXCEPT_(is_nothrow_copy_constructible::value&& is_nothrow_copy_constructible::value) - : first(__t1), second(__t2) {} - - template < -# if _LIBCPP_STD_VER >= 23 // http://wg21.link/P1951 - class _U1 = _T1, - class _U2 = _T2, -# else - class _U1, - class _U2, -# endif - __enable_if_t<_CheckArgs::template __enable_explicit<_U1, _U2>(), int> = 0 > - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(_U1&& __u1, _U2&& __u2) - _NOEXCEPT_(is_nothrow_constructible::value&& is_nothrow_constructible::value) - : first(std::forward<_U1>(__u1)), second(std::forward<_U2>(__u2)) { - } - template < # if _LIBCPP_STD_VER >= 23 // http://wg21.link/P1951 class _U1 = _T1, @@ -199,9 +165,11 @@ struct _LIBCPP_TEMPLATE_VIS pair class _U1, class _U2, # endif - __enable_if_t<_CheckArgs::template __enable_implicit<_U1, _U2>(), int> = 0 > - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(_U1&& __u1, _U2&& __u2) - _NOEXCEPT_(is_nothrow_constructible::value&& is_nothrow_constructible::value) + __enable_if_t<_CheckArgs::template __is_pair_constructible<_U1, _U2>(), int> = 0 > + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_CheckArgs::template __is_implicit<_U1, _U2>()) + pair(_U1&& __u1, _U2&& __u2) + _NOEXCEPT_((is_nothrow_constructible::value && + is_nothrow_constructible::value)) : first(std::forward<_U1>(__u1)), second(std::forward<_U2>(__u2)) { } @@ -215,28 +183,18 @@ struct _LIBCPP_TEMPLATE_VIS pair template (), int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(pair<_U1, _U2> const& __p) - _NOEXCEPT_(is_nothrow_constructible::value&& - is_nothrow_constructible::value) - : first(__p.first), second(__p.second) {} - - template (), int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(pair<_U1, _U2> const& __p) - _NOEXCEPT_(is_nothrow_constructible::value&& - is_nothrow_constructible::value) + __enable_if_t<_CheckArgs::template __is_pair_constructible<_U1 const&, _U2 const&>(), int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit( + !_CheckArgs::template __is_implicit<_U1 const&, _U2 const&>()) pair(pair<_U1, _U2> const& __p) + _NOEXCEPT_((is_nothrow_constructible::value && + is_nothrow_constructible::value)) : first(__p.first), second(__p.second) {} - template (), int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(pair<_U1, _U2>&& __p) _NOEXCEPT_( - is_nothrow_constructible::value&& is_nothrow_constructible::value) - : first(std::forward<_U1>(__p.first)), second(std::forward<_U2>(__p.second)) {} - - template (), int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(pair<_U1, _U2>&& __p) _NOEXCEPT_( - is_nothrow_constructible::value&& is_nothrow_constructible::value) + template (), int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_CheckArgs::template __is_implicit<_U1, _U2>()) + pair(pair<_U1, _U2>&& __p) + _NOEXCEPT_((is_nothrow_constructible::value && + is_nothrow_constructible::value)) : first(std::forward<_U1>(__p.first)), second(std::forward<_U2>(__p.second)) {} # if _LIBCPP_STD_VER >= 23 -- GitLab From 1c7607e8ee6ec4ca3abce1561dd39a98d4efac96 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 9 Mar 2024 02:31:58 -0800 Subject: [PATCH 006/953] [libc++][test] Fix MSVC warning C4127 in `array.cons/initialization.pass.cpp` (#79793) This fixes MSVC warning C4127: conditional expression is constant. Testing `TEST_STD_AT_LEAST_20_OR_RUNTIME_EVALUATED` by itself doesn't emit this warning, but the condition here is more complicated. I'm expanding the macro and mechanically simplifying the resulting code. (Yeah, this warning is often annoying, and I introduced `TEST_STD_AT_LEAST_20_OR_RUNTIME_EVALUATED` to avoid this warning elsewhere, so it's disappointing that it doesn't make the compiler happy here. If this change is undesirable, I can replace it with `ADDITIONAL_COMPILE_FLAGS(cl-style-warnings)`, but ideally I'd like to avoid having to suppress it.) --------- Co-authored-by: Louis Dionne --- .../array/array.cons/initialization.pass.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libcxx/test/std/containers/sequences/array/array.cons/initialization.pass.cpp b/libcxx/test/std/containers/sequences/array/array.cons/initialization.pass.cpp index 7991d4738d96..a23211f5464d 100644 --- a/libcxx/test/std/containers/sequences/array/array.cons/initialization.pass.cpp +++ b/libcxx/test/std/containers/sequences/array/array.cons/initialization.pass.cpp @@ -28,10 +28,16 @@ struct test_initialization { // Before C++20, default initialization doesn't work inside constexpr for // trivially default constructible types. This only apply to non-empty arrays, // since empty arrays don't hold an element of type T. - if (TEST_STD_AT_LEAST_20_OR_RUNTIME_EVALUATED || !std::is_trivially_default_constructible::value) { - std::array a1; (void)a1; - std::array a2; (void)a2; - std::array a3; (void)a3; +#if TEST_STD_VER < 20 + if (!(TEST_IS_CONSTANT_EVALUATED && std::is_trivially_default_constructible::value)) +#endif + { + std::array a1; + (void)a1; + std::array a2; + (void)a2; + std::array a3; + (void)a3; } std::array nodefault; (void)nodefault; -- GitLab From a116f0ebaf0304e73b26098a7141c4ab836b7dc9 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Sat, 9 Mar 2024 11:59:37 +0100 Subject: [PATCH 007/953] [bazel] Port test parts of cb6ff746e0c7b9218b6f5c11db44162cacd623a4 --- utils/bazel/llvm-project-overlay/mlir/BUILD.bazel | 3 ++- .../llvm-project-overlay/mlir/test/BUILD.bazel | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index 8da2b51ffc99..28a69c7ffea1 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -1933,7 +1933,7 @@ cc_library( cc_library( name = "ArmNeonTransforms", - srcs = ["lib/Dialect/ArmNeon/Transforms/LowerVectorToArmNeon.cpp"], + srcs = glob(["lib/Dialect/ArmNeon/Transforms/*.cpp"]), hdrs = ["include/mlir/Dialect/ArmNeon/Transforms.h"], includes = ["include"], deps = [ @@ -9334,6 +9334,7 @@ cc_binary( "//mlir/test:TestAffine", "//mlir/test:TestAnalysis", "//mlir/test:TestArith", + "//mlir/test:TestArmNeon", "//mlir/test:TestArmSME", "//mlir/test:TestBufferization", "//mlir/test:TestControlFlow", diff --git a/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel index 16881b296823..91706af935ac 100644 --- a/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel @@ -889,6 +889,21 @@ cc_library( ], ) +cc_library( + name = "TestArmNeon", + srcs = glob(["lib/Dialect/ArmNeon/*.cpp"]), + includes = ["lib/Dialect/Test"], + deps = [ + "//mlir:ArmNeonDialect", + "//mlir:ArmNeonTransforms", + "//mlir:FuncDialect", + "//mlir:IR", + "//mlir:Pass", + "//mlir:Support", + "//mlir:Transforms", + ], +) + cc_library( name = "TestArmSME", srcs = glob(["lib/Dialect/ArmSME/*.cpp"]), -- GitLab From 9df719407f808d71d3bf02867da2b01617ef3d55 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Sat, 9 Mar 2024 12:05:25 +0100 Subject: [PATCH 008/953] [ArmNeon] Make header self-contained. NFC. --- mlir/include/mlir/Dialect/ArmNeon/Transforms.h | 1 + 1 file changed, 1 insertion(+) diff --git a/mlir/include/mlir/Dialect/ArmNeon/Transforms.h b/mlir/include/mlir/Dialect/ArmNeon/Transforms.h index 49cad22defec..52ebea2d0ffd 100644 --- a/mlir/include/mlir/Dialect/ArmNeon/Transforms.h +++ b/mlir/include/mlir/Dialect/ArmNeon/Transforms.h @@ -10,6 +10,7 @@ #define MLIR_DIALECT_ARMNEON_TRANSFORMS_H namespace mlir { +class RewritePatternSet; namespace arm_neon { void populateLowerContractionToSMMLAPatternPatterns( -- GitLab From 2b5f68a5f63d2342a056bf9f86bd116c100fd81a Mon Sep 17 00:00:00 2001 From: Sirraide Date: Sat, 9 Mar 2024 12:07:16 +0100 Subject: [PATCH 009/953] [Clang][C++23] Implement P1774R8: Portable assumptions (#81014) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This implements the C++23 `[[assume]]` attribute. Assumption information is lowered to a call to `@llvm.assume`, unless the expression has side-effects, in which case it is discarded and a warning is issued to tell the user that the assumption doesn’t do anything. A failed assumption at compile time is an error (unless we are in `MSVCCompat` mode, in which case we don’t check assumptions at compile time). Due to performance regressions in LLVM, assumptions can be disabled with the `-fno-assumptions` flag. With it, assumptions will still be parsed and checked, but no calls to `@llvm.assume` will be emitted and assumptions will not be checked at compile time. --- clang/docs/ReleaseNotes.rst | 1 + clang/include/clang/Basic/Attr.td | 11 +- clang/include/clang/Basic/AttrDocs.td | 30 +++- .../include/clang/Basic/DiagnosticASTKinds.td | 2 + clang/include/clang/Basic/DiagnosticGroups.td | 4 +- .../clang/Basic/DiagnosticParseKinds.td | 3 + .../clang/Basic/DiagnosticSemaKinds.td | 9 +- clang/include/clang/Basic/LangOptions.def | 2 + clang/include/clang/Driver/Options.td | 6 + clang/include/clang/Parse/Parser.h | 7 + clang/include/clang/Sema/Sema.h | 10 +- clang/lib/AST/ExprConstant.cpp | 23 ++++ clang/lib/CodeGen/CGCall.cpp | 8 +- clang/lib/CodeGen/CGStmt.cpp | 12 +- clang/lib/Driver/ToolChains/Clang.cpp | 5 + clang/lib/Parse/ParseDeclCXX.cpp | 62 ++++++++- clang/lib/Parse/ParseExpr.cpp | 13 ++ clang/lib/Sema/SemaDeclAttr.cpp | 19 +-- clang/lib/Sema/SemaOpenMP.cpp | 6 +- clang/lib/Sema/SemaStmtAttr.cpp | 55 ++++++++ clang/lib/Sema/SemaTemplateInstantiate.cpp | 16 +++ clang/test/CodeGenCXX/cxx23-assume.cpp | 50 +++++++ ...a-attribute-supported-attributes-list.test | 2 +- clang/test/Parser/cxx23-assume.cpp | 18 +++ clang/test/SemaCXX/cxx23-assume-disabled.cpp | 14 ++ clang/test/SemaCXX/cxx23-assume-print.cpp | 13 ++ clang/test/SemaCXX/cxx23-assume.cpp | 128 ++++++++++++++++++ clang/www/cxx_status.html | 2 +- 28 files changed, 502 insertions(+), 29 deletions(-) create mode 100644 clang/test/CodeGenCXX/cxx23-assume.cpp create mode 100644 clang/test/Parser/cxx23-assume.cpp create mode 100644 clang/test/SemaCXX/cxx23-assume-disabled.cpp create mode 100644 clang/test/SemaCXX/cxx23-assume-print.cpp create mode 100644 clang/test/SemaCXX/cxx23-assume.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 690fc7ed271a..f61dca9bbc84 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -100,6 +100,7 @@ C++23 Feature Support - Implemented `P2718R0: Lifetime extension in range-based for loops `_. Also materialize temporary object which is a prvalue in discarded-value expression. +- Implemented `P1774R8: Portable assumptions `_. - Implemented `P2448R2: Relaxing some constexpr restrictions `_. diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index ebb616fbe253..fd7970d0451a 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1580,6 +1580,13 @@ def Unlikely : StmtAttr { } def : MutualExclusions<[Likely, Unlikely]>; +def CXXAssume : StmtAttr { + let Spellings = [CXX11<"", "assume", 202207>]; + let Subjects = SubjectList<[NullStmt], ErrorDiag, "empty statements">; + let Args = [ExprArgument<"Assumption">]; + let Documentation = [CXXAssumeDocs]; +} + def NoMerge : DeclOrStmtAttr { let Spellings = [Clang<"nomerge">]; let Documentation = [NoMergeDocs]; @@ -4151,11 +4158,11 @@ def OMPDeclareVariant : InheritableAttr { }]; } -def Assumption : InheritableAttr { +def OMPAssume : InheritableAttr { let Spellings = [Clang<"assume">]; let Subjects = SubjectList<[Function, ObjCMethod]>; let InheritEvenIfAlreadyPresent = 1; - let Documentation = [AssumptionDocs]; + let Documentation = [OMPAssumeDocs]; let Args = [StringArgument<"Assumption">]; } diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index b96fbddd5115..2c07cd09b0d5 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -1996,6 +1996,34 @@ Here is an example: }]; } +def CXXAssumeDocs : Documentation { + let Category = DocCatStmt; + let Heading = "assume"; + let Content = [{ +The ``assume`` attribute is used to indicate to the optimizer that a +certain condition is assumed to be true at a certain point in the +program. If this condition is violated at runtime, the behavior is +undefined. ``assume`` can only be applied to a null statement. + +Different optimisers are likely to react differently to the presence of +this attribute; in some cases, adding ``assume`` may affect performance +negatively. It should be used with parsimony and care. + +Note that `clang::assume` is a different attribute. Always write ``assume`` +without a namespace if you intend to use the standard C++ attribute. + +Example: + +.. code-block:: c++ + + int f(int x, int y) { + [[assume(x == 27)]]; + [[assume(x == y)]]; + return y + 1; // May be optimised to `return 28`. + } + }]; +} + def LikelihoodDocs : Documentation { let Category = DocCatStmt; let Heading = "likely and unlikely"; @@ -4629,7 +4657,7 @@ For more information see }]; } -def AssumptionDocs : Documentation { +def OMPAssumeDocs : Documentation { let Category = DocCatFunction; let Heading = "assume"; let Content = [{ diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index c81d17ed6410..a024f9b2a9f8 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -399,6 +399,8 @@ def note_constexpr_unsupported_flexible_array : Note< "flexible array initialization is not yet supported">; def note_constexpr_non_const_vectorelements : Note< "cannot determine number of elements for sizeless vectors in a constant expression">; +def note_constexpr_assumption_failed : Note< + "assumption evaluated to false">; def err_experimental_clang_interp_failed : Error< "the experimental clang interpreter failed to evaluate an expression">; diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 0791a0002319..ba1d4b2352e3 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1133,9 +1133,11 @@ def NonGCC : DiagGroup<"non-gcc", def CXX14Attrs : DiagGroup<"c++14-attribute-extensions">; def CXX17Attrs : DiagGroup<"c++17-attribute-extensions">; def CXX20Attrs : DiagGroup<"c++20-attribute-extensions">; +def CXX23Attrs : DiagGroup<"c++23-attribute-extensions">; def FutureAttrs : DiagGroup<"future-attribute-extensions", [CXX14Attrs, CXX17Attrs, - CXX20Attrs]>; + CXX20Attrs, + CXX23Attrs]>; def CXX23AttrsOnLambda : DiagGroup<"c++23-lambda-attributes">; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index c0dbc25a0c32..816c3ff5f8b2 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -786,6 +786,9 @@ def err_ms_property_expected_comma_or_rparen : Error< def err_ms_property_initializer : Error< "property declaration cannot have a default member initializer">; +def err_assume_attr_expects_cond_expr : Error< + "use of this expression in an %0 attribute requires parentheses">; + def warn_cxx20_compat_explicit_bool : Warning< "this expression will be parsed as explicit(bool) in C++20">, InGroup, DefaultIgnore; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6da49facd27e..9b5245695153 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -855,10 +855,10 @@ def note_strncat_wrong_size : Note< def warn_assume_side_effects : Warning< "the argument to %0 has side effects that will be discarded">, InGroup>; -def warn_assume_attribute_string_unknown : Warning< +def warn_omp_assume_attribute_string_unknown : Warning< "unknown assumption string '%0'; attribute is potentially ignored">, InGroup; -def warn_assume_attribute_string_unknown_suggested : Warning< +def warn_omp_assume_attribute_string_unknown_suggested : Warning< "unknown assumption string '%0' may be misspelled; attribute is potentially " "ignored, did you mean '%1'?">, InGroup; @@ -9115,6 +9115,8 @@ def ext_cxx17_attr : Extension< "use of the %0 attribute is a C++17 extension">, InGroup; def ext_cxx20_attr : Extension< "use of the %0 attribute is a C++20 extension">, InGroup; +def ext_cxx23_attr : Extension< + "use of the %0 attribute is a C++23 extension">, InGroup; def warn_unused_comparison : Warning< "%select{equality|inequality|relational|three-way}0 comparison result unused">, @@ -10169,6 +10171,9 @@ def err_fallthrough_attr_outside_switch : Error< def err_fallthrough_attr_invalid_placement : Error< "fallthrough annotation does not directly precede switch label">; +def err_assume_attr_args : Error< + "attribute '%0' requires a single expression argument">; + def warn_unreachable_default : Warning< "default label in switch which covers all enumeration values">, InGroup, DefaultIgnore; diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 2b42b521a303..472fd9f093a7 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -450,6 +450,8 @@ LANGOPT(RegCall4, 1, 0, "Set __regcall4 as a default calling convention to respe LANGOPT(MatrixTypes, 1, 0, "Enable or disable the builtin matrix type") +LANGOPT(CXXAssumptions, 1, 1, "Enable or disable codegen and compile-time checks for C++23's [[assume]] attribute") + ENUM_LANGOPT(StrictFlexArraysLevel, StrictFlexArraysLevelKind, 2, StrictFlexArraysLevelKind::Default, "Rely on strict definition of flexible arrays") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 5b3d366dbcf9..d5eed152d150 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3789,6 +3789,12 @@ def foptimization_record_passes_EQ : Joined<["-"], "foptimization-record-passes= HelpText<"Only include passes which match a specified regular expression in the generated optimization record (by default, include all passes)">, MetaVarName<"">; +defm assumptions : BoolFOption<"assumptions", + LangOpts<"CXXAssumptions">, DefaultTrue, + NegFlag, + PosFlag>; + def fvectorize : Flag<["-"], "fvectorize">, Group, HelpText<"Enable the loop vectorization passes">; def fno_vectorize : Flag<["-"], "fno-vectorize">, Group; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 071520f535bc..64e031d5094c 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1803,6 +1803,7 @@ public: ExprResult ParseConstraintLogicalOrExpression(bool IsTrailingRequiresClause); // Expr that doesn't include commas. ExprResult ParseAssignmentExpression(TypeCastState isTypeCast = NotTypeCast); + ExprResult ParseConditionalExpression(); ExprResult ParseMSAsmIdentifier(llvm::SmallVectorImpl &LineToks, unsigned &NumLineToksConsumed, @@ -2955,6 +2956,12 @@ private: SourceLocation ScopeLoc, CachedTokens &OpenMPTokens); + /// Parse a C++23 assume() attribute. Returns true on error. + bool ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs, + IdentifierInfo *AttrName, + SourceLocation AttrNameLoc, + SourceLocation *EndLoc); + IdentifierInfo *TryParseCXX11AttributeIdentifier( SourceLocation &Loc, Sema::AttributeCompletion Completion = Sema::AttributeCompletion::None, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index cfc1c3b34947..00b3f53f5c1c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9011,6 +9011,12 @@ public: void ProcessStmtAttributes(Stmt *Stmt, const ParsedAttributes &InAttrs, SmallVectorImpl &OutAttrs); + ExprResult ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A, + SourceRange Range); + ExprResult BuildCXXAssumeExpr(Expr *Assumption, + const IdentifierInfo *AttrName, + SourceRange Range); + ///@} // @@ -14716,10 +14722,10 @@ private: SmallVector OMPDeclareVariantScopes; /// The current `omp begin/end assumes` scopes. - SmallVector OMPAssumeScoped; + SmallVector OMPAssumeScoped; /// All `omp assumes` we encountered so far. - SmallVector OMPAssumeGlobal; + SmallVector OMPAssumeGlobal; /// OMPD_loop is mapped to OMPD_for, OMPD_distribute or OMPD_simd depending /// on the parameter of the bind clause. In the methods for the diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 4a7c7755e1d6..726415cfbde0 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -5582,6 +5582,29 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, MSConstexprContextRAII ConstexprContext( *Info.CurrentCall, hasSpecificAttr(AS->getAttrs()) && isa(SS)); + + auto LO = Info.getCtx().getLangOpts(); + if (LO.CXXAssumptions && !LO.MSVCCompat) { + for (auto *Attr : AS->getAttrs()) { + auto *AA = dyn_cast(Attr); + if (!AA) + continue; + + auto *Assumption = AA->getAssumption(); + if (Assumption->isValueDependent()) + return ESR_Failed; + + bool Value; + if (!EvaluateAsBooleanCondition(Assumption, Value, Info)) + return ESR_Failed; + if (!Value) { + Info.CCEDiag(Assumption->getExprLoc(), + diag::note_constexpr_assumption_failed); + return ESR_Failed; + } + } + } + return EvaluateStmt(Result, Info, SS, Case); } diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 13f68237b464..a28d7888715d 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1796,14 +1796,14 @@ static void AddAttributesFromFunctionProtoType(ASTContext &Ctx, FuncAttrs.addAttribute("aarch64_inout_zt0"); } -static void AddAttributesFromAssumes(llvm::AttrBuilder &FuncAttrs, - const Decl *Callee) { +static void AddAttributesFromOMPAssumes(llvm::AttrBuilder &FuncAttrs, + const Decl *Callee) { if (!Callee) return; SmallVector Attrs; - for (const AssumptionAttr *AA : Callee->specific_attrs()) + for (const OMPAssumeAttr *AA : Callee->specific_attrs()) AA->getAssumption().split(Attrs, ","); if (!Attrs.empty()) @@ -2344,7 +2344,7 @@ void CodeGenModule::ConstructAttributeList(StringRef Name, // Attach assumption attributes to the declaration. If this is a call // site, attach assumptions from the caller to the call as well. - AddAttributesFromAssumes(FuncAttrs, TargetDecl); + AddAttributesFromOMPAssumes(FuncAttrs, TargetDecl); bool HasOptnone = false; // The NoBuiltinAttr attached to the target FunctionDecl. diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index d0a3a716ad75..8898e3f22a7d 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -728,11 +728,19 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) { case attr::AlwaysInline: alwaysinline = true; break; - case attr::MustTail: + case attr::MustTail: { const Stmt *Sub = S.getSubStmt(); const ReturnStmt *R = cast(Sub); musttail = cast(R->getRetValue()->IgnoreParens()); - break; + } break; + case attr::CXXAssume: { + const Expr *Assumption = cast(A)->getAssumption(); + if (getLangOpts().CXXAssumptions && + !Assumption->HasSideEffects(getContext())) { + llvm::Value *AssumptionVal = EvaluateExprAsBool(Assumption); + Builder.CreateAssumption(AssumptionVal); + } + } break; } } SaveAndRestore save_nomerge(InNoMergeAttributedStmt, nomerge); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index fa17f6295d6e..678e24eae883 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -6982,6 +6982,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, (!IsWindowsMSVC || IsMSVC2015Compatible))) CmdArgs.push_back("-fno-threadsafe-statics"); + // Add -fno-assumptions, if it was specified. + if (!Args.hasFlag(options::OPT_fassumptions, options::OPT_fno_assumptions, + true)) + CmdArgs.push_back("-fno-assumptions"); + // -fgnu-keywords default varies depending on language; only pass if // specified. Args.AddLastArg(CmdArgs, options::OPT_fgnu_keywords, diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 62632b2d7979..bdca10c4c7c0 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -4528,6 +4528,61 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, } } +/// Parse the argument to C++23's [[assume()]] attribute. +bool Parser::ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs, + IdentifierInfo *AttrName, + SourceLocation AttrNameLoc, + SourceLocation *EndLoc) { + assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list"); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + + // [dcl.attr.assume]: The expression is potentially evaluated. + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); + + TentativeParsingAction TPA(*this); + ExprResult Res( + Actions.CorrectDelayedTyposInExpr(ParseConditionalExpression())); + if (Res.isInvalid()) { + TPA.Commit(); + SkipUntil(tok::r_paren, tok::r_square, StopAtSemi | StopBeforeMatch); + if (Tok.is(tok::r_paren)) + T.consumeClose(); + return true; + } + + if (!Tok.isOneOf(tok::r_paren, tok::r_square)) { + // Emit a better diagnostic if this is an otherwise valid expression that + // is not allowed here. + TPA.Revert(); + Res = ParseExpression(); + if (!Res.isInvalid()) { + auto *E = Res.get(); + Diag(E->getExprLoc(), diag::err_assume_attr_expects_cond_expr) + << AttrName << FixItHint::CreateInsertion(E->getBeginLoc(), "(") + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(E->getEndLoc()), + ")") + << E->getSourceRange(); + } + + T.consumeClose(); + return true; + } + + TPA.Commit(); + ArgsUnion Assumption = Res.get(); + auto RParen = Tok.getLocation(); + T.consumeClose(); + Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), nullptr, + SourceLocation(), &Assumption, 1, ParsedAttr::Form::CXX11()); + + if (EndLoc) + *EndLoc = RParen; + + return false; +} + /// ParseCXX11AttributeArgs -- Parse a C++11 attribute-argument-clause. /// /// [C++11] attribute-argument-clause: @@ -4596,7 +4651,12 @@ bool Parser::ParseCXX11AttributeArgs( if (ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang"))) NumArgs = ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Form); - else + // So does C++23's assume() attribute. + else if (!ScopeName && AttrName->isStr("assume")) { + if (ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc)) + return true; + NumArgs = 1; + } else NumArgs = ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Form); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 1f07eddb0fb3..88c3a1469e8e 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -179,6 +179,19 @@ ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) { return ParseRHSOfBinaryExpression(LHS, prec::Assignment); } +ExprResult Parser::ParseConditionalExpression() { + if (Tok.is(tok::code_completion)) { + cutOffParsing(); + Actions.CodeCompleteExpression(getCurScope(), + PreferredType.get(Tok.getLocation())); + return ExprError(); + } + + ExprResult LHS = ParseCastExpression( + AnyCastExpr, /*isAddressOfOperand=*/false, NotTypeCast); + return ParseRHSOfBinaryExpression(LHS, prec::Conditional); +} + /// Parse an assignment expression where part of an Objective-C message /// send has already been parsed. /// diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index e6943efb345c..c00120b59d39 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1771,8 +1771,8 @@ void Sema::AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI, } /// Check if \p AssumptionStr is a known assumption and warn if not. -static void checkAssumptionAttr(Sema &S, SourceLocation Loc, - StringRef AssumptionStr) { +static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, + StringRef AssumptionStr) { if (llvm::KnownAssumptionStrings.count(AssumptionStr)) return; @@ -1788,22 +1788,23 @@ static void checkAssumptionAttr(Sema &S, SourceLocation Loc, } if (!Suggestion.empty()) - S.Diag(Loc, diag::warn_assume_attribute_string_unknown_suggested) + S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested) << AssumptionStr << Suggestion; else - S.Diag(Loc, diag::warn_assume_attribute_string_unknown) << AssumptionStr; + S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown) + << AssumptionStr; } -static void handleAssumumptionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { +static void handleOMPAssumeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Handle the case where the attribute has a text message. StringRef Str; SourceLocation AttrStrLoc; if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc)) return; - checkAssumptionAttr(S, AttrStrLoc, Str); + checkOMPAssumeAttr(S, AttrStrLoc, Str); - D->addAttr(::new (S.Context) AssumptionAttr(S.Context, AL, Str)); + D->addAttr(::new (S.Context) OMPAssumeAttr(S.Context, AL, Str)); } /// Normalize the attribute, __foo__ becomes foo. @@ -9491,8 +9492,8 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_Unavailable: handleAttrWithMessage(S, D, AL); break; - case ParsedAttr::AT_Assumption: - handleAssumumptionAttr(S, D, AL); + case ParsedAttr::AT_OMPAssume: + handleOMPAssumeAttr(S, D, AL); break; case ParsedAttr::AT_ObjCDirect: handleObjCDirectAttr(S, D, AL); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index afffd371c58d..0cc0cbacb375 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -3496,7 +3496,7 @@ void Sema::ActOnOpenMPAssumesDirective(SourceLocation Loc, << llvm::omp::getAllAssumeClauseOptions() << llvm::omp::getOpenMPDirectiveName(DKind); - auto *AA = AssumptionAttr::Create(Context, llvm::join(Assumptions, ","), Loc); + auto *AA = OMPAssumeAttr::Create(Context, llvm::join(Assumptions, ","), Loc); if (DKind == llvm::omp::Directive::OMPD_begin_assumes) { OMPAssumeScoped.push_back(AA); return; @@ -7275,10 +7275,10 @@ void Sema::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) { // only global ones. We apply scoped assumption to the template definition // though. if (!inTemplateInstantiation()) { - for (AssumptionAttr *AA : OMPAssumeScoped) + for (OMPAssumeAttr *AA : OMPAssumeScoped) FD->addAttr(AA); } - for (AssumptionAttr *AA : OMPAssumeGlobal) + for (OMPAssumeAttr *AA : OMPAssumeGlobal) FD->addAttr(AA); } diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index e6a4d3e63e4a..691857e88beb 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -303,6 +303,15 @@ static Attr *handleAlwaysInlineAttr(Sema &S, Stmt *St, const ParsedAttr &A, return ::new (S.Context) AlwaysInlineAttr(S.Context, A); } +static Attr *handleCXXAssumeAttr(Sema &S, Stmt *St, const ParsedAttr &A, + SourceRange Range) { + ExprResult Res = S.ActOnCXXAssumeAttr(St, A, Range); + if (!Res.isUsable()) + return nullptr; + + return ::new (S.Context) CXXAssumeAttr(S.Context, A, Res.get()); +} + static Attr *handleMustTailAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range) { // Validation is in Sema::ActOnAttributedStmt(). @@ -594,6 +603,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, switch (A.getKind()) { case ParsedAttr::AT_AlwaysInline: return handleAlwaysInlineAttr(S, St, A, Range); + case ParsedAttr::AT_CXXAssume: + return handleCXXAssumeAttr(S, St, A, Range); case ParsedAttr::AT_FallThrough: return handleFallThroughAttr(S, St, A, Range); case ParsedAttr::AT_LoopHint: @@ -641,3 +652,47 @@ bool Sema::CheckRebuiltStmtAttributes(ArrayRef Attrs) { CheckForDuplicateLoopAttrs(*this, Attrs); return false; } + +ExprResult Sema::ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A, + SourceRange Range) { + if (A.getNumArgs() != 1 || !A.getArgAsExpr(0)) { + Diag(A.getLoc(), diag::err_assume_attr_args) << A.getAttrName() << Range; + return ExprError(); + } + + auto *Assumption = A.getArgAsExpr(0); + if (Assumption->getDependence() == ExprDependence::None) { + ExprResult Res = BuildCXXAssumeExpr(Assumption, A.getAttrName(), Range); + if (Res.isInvalid()) + return ExprError(); + Assumption = Res.get(); + } + + if (!getLangOpts().CPlusPlus23) + Diag(A.getLoc(), diag::ext_cxx23_attr) << A << Range; + + return Assumption; +} + +ExprResult Sema::BuildCXXAssumeExpr(Expr *Assumption, + const IdentifierInfo *AttrName, + SourceRange Range) { + ExprResult Res = CorrectDelayedTyposInExpr(Assumption); + if (Res.isInvalid()) + return ExprError(); + + Res = CheckPlaceholderExpr(Res.get()); + if (Res.isInvalid()) + return ExprError(); + + Res = PerformContextuallyConvertToBool(Res.get()); + if (Res.isInvalid()) + return ExprError(); + + Assumption = Res.get(); + if (Assumption->HasSideEffects(Context)) + Diag(Assumption->getBeginLoc(), diag::warn_assume_side_effects) + << AttrName << Range; + + return Assumption; +} diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index d9994d7fd37a..1a0c88703aca 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1411,6 +1411,7 @@ namespace { NamedDecl *FirstQualifierInScope = nullptr, bool AllowInjectedClassName = false); + const CXXAssumeAttr *TransformCXXAssumeAttr(const CXXAssumeAttr *AA); const LoopHintAttr *TransformLoopHintAttr(const LoopHintAttr *LH); const NoInlineAttr *TransformStmtNoInlineAttr(const Stmt *OrigS, const Stmt *InstS, @@ -1980,6 +1981,21 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, Arg, PackIndex); } +const CXXAssumeAttr * +TemplateInstantiator::TransformCXXAssumeAttr(const CXXAssumeAttr *AA) { + ExprResult Res = getDerived().TransformExpr(AA->getAssumption()); + if (!Res.isUsable()) + return AA; + + Res = getSema().BuildCXXAssumeExpr(Res.get(), AA->getAttrName(), + AA->getRange()); + if (!Res.isUsable()) + return AA; + + return CXXAssumeAttr::CreateImplicit(getSema().Context, Res.get(), + AA->getRange()); +} + const LoopHintAttr * TemplateInstantiator::TransformLoopHintAttr(const LoopHintAttr *LH) { Expr *TransformedExpr = getDerived().TransformExpr(LH->getValue()).get(); diff --git a/clang/test/CodeGenCXX/cxx23-assume.cpp b/clang/test/CodeGenCXX/cxx23-assume.cpp new file mode 100644 index 000000000000..a1fa6b30b2f0 --- /dev/null +++ b/clang/test/CodeGenCXX/cxx23-assume.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++23 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++23 -fno-assumptions %s -emit-llvm -o - | FileCheck %s --check-prefix=DISABLED + +// DISABLED-NOT: @llvm.assume + +bool f(); + +template +void f2() { + [[assume(sizeof(T) == sizeof(int))]]; +} + +// CHECK: @_Z1gii(i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) +// CHECK-NEXT: entry: +// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32 +// CHECK-NEXT: [[Y_ADDR:%.*]] = alloca i32 +// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]] +// CHECK-NEXT: store i32 [[Y]], ptr [[Y_ADDR]] +void g(int x, int y) { + // Not emitted because it has side-effects. + [[assume(f())]]; + + // CHECK-NEXT: call void @llvm.assume(i1 true) + [[assume((1, 2))]]; + + // CHECK-NEXT: [[X1:%.*]] = load i32, ptr [[X_ADDR]] + // CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[X1]], 27 + // CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]]) + [[assume(x != 27)]]; + + // CHECK-NEXT: [[X2:%.*]] = load i32, ptr [[X_ADDR]] + // CHECK-NEXT: [[Y2:%.*]] = load i32, ptr [[Y_ADDR]] + // CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[X2]], [[Y2]] + // CHECK-NEXT: call void @llvm.assume(i1 [[CMP2]]) + [[assume(x == y)]]; + + // CHECK-NEXT: call void @_Z2f2IiEvv() + f2(); + + // CHECK-NEXT: call void @_Z2f2IdEvv() + f2(); +} + +// CHECK: void @_Z2f2IiEvv() +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.assume(i1 true) + +// CHECK: void @_Z2f2IdEvv() +// CHECK-NEXT: entry: +// CHECK-NEXT: call void @llvm.assume(i1 false) diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 1528388e3298..ec84ebdc6abe 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -19,7 +19,6 @@ // CHECK-NEXT: ArcWeakrefUnavailable (SubjectMatchRule_objc_interface) // CHECK-NEXT: ArmBuiltinAlias (SubjectMatchRule_function) // CHECK-NEXT: AssumeAligned (SubjectMatchRule_objc_method, SubjectMatchRule_function) -// CHECK-NEXT: Assumption (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: Availability ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_implementation, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable)) // CHECK-NEXT: AvailableOnlyInDefaultEvalMethod (SubjectMatchRule_type_alias) // CHECK-NEXT: BPFPreserveAccessIndex (SubjectMatchRule_record) @@ -127,6 +126,7 @@ // CHECK-NEXT: NoThrow (SubjectMatchRule_hasType_functionType) // CHECK-NEXT: NoUwtable (SubjectMatchRule_hasType_functionType) // CHECK-NEXT: NotTailCalled (SubjectMatchRule_function) +// CHECK-NEXT: OMPAssume (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: OSConsumed (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: OSReturnsNotRetained (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: OSReturnsRetained (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_variable_is_parameter) diff --git a/clang/test/Parser/cxx23-assume.cpp b/clang/test/Parser/cxx23-assume.cpp new file mode 100644 index 000000000000..269fb7e59944 --- /dev/null +++ b/clang/test/Parser/cxx23-assume.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++23 -x c++ %s -verify + +void f(int x, int y) { + [[assume(true)]]; + [[assume(1)]]; + [[assume(1.0)]]; + [[assume(1 + 2 == 3)]]; + [[assume(x ? 1 : 2)]]; + [[assume(x && y)]]; + [[assume(true)]] [[assume(true)]]; + + [[assume]]; // expected-error {{takes one argument}} + [[assume(]]; // expected-error {{expected expression}} + [[assume()]]; // expected-error {{expected expression}} + [[assume(2]]; // expected-error {{expected ')'}} expected-note {{to match this '('}} + [[assume(x = 2)]]; // expected-error {{requires parentheses}} + [[assume(2, 3)]]; // expected-error {{requires parentheses}} expected-warning {{has no effect}} +} diff --git a/clang/test/SemaCXX/cxx23-assume-disabled.cpp b/clang/test/SemaCXX/cxx23-assume-disabled.cpp new file mode 100644 index 000000000000..4233a2f7f433 --- /dev/null +++ b/clang/test/SemaCXX/cxx23-assume-disabled.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++23 -x c++ %s -fno-assumptions -verify +// RUN: %clang_cc1 -std=c++23 -x c++ %s -fms-compatibility -verify +// expected-no-diagnostics + +// We don't check assumptions at compile time if '-fno-assumptions' is passed, +// or if we're in MSVCCompat mode + +constexpr bool f(bool x) { + [[assume(x)]]; + return true; +} + +static_assert(f(false)); + diff --git a/clang/test/SemaCXX/cxx23-assume-print.cpp b/clang/test/SemaCXX/cxx23-assume-print.cpp new file mode 100644 index 000000000000..37db015fcc39 --- /dev/null +++ b/clang/test/SemaCXX/cxx23-assume-print.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++23 -ast-print %s | FileCheck %s + +// CHECK: void f(int x, int y) { +void f(int x, int y) { + // CHECK-NEXT: {{\[}}[assume(true)]] + [[assume(true)]]; + + // CHECK-NEXT: {{\[}}[assume(2 + 4)]] + [[assume(2 + 4)]]; + + // CHECK-NEXT: {{\[}}[assume(x == y)]] + [[assume(x == y)]]; +} diff --git a/clang/test/SemaCXX/cxx23-assume.cpp b/clang/test/SemaCXX/cxx23-assume.cpp new file mode 100644 index 000000000000..2b99cbd3e788 --- /dev/null +++ b/clang/test/SemaCXX/cxx23-assume.cpp @@ -0,0 +1,128 @@ +// RUN: %clang_cc1 -std=c++23 -x c++ %s -verify +// RUN: %clang_cc1 -std=c++20 -pedantic -x c++ %s -verify=ext,expected + +struct A{}; +struct B{ explicit operator bool() { return true; } }; + +template +void f() { + [[assume(cond)]]; // ext-warning {{C++23 extension}} +} + +template +struct S { + void f() { + [[assume(cond)]]; // ext-warning {{C++23 extension}} + } + + template + constexpr bool g() { + [[assume(cond == sizeof(T))]]; // expected-note {{assumption evaluated to false}} ext-warning {{C++23 extension}} + return true; + } +}; + +bool f2(); + +template +constexpr void f3() { + [[assume(T{})]]; // expected-error {{not contextually convertible to 'bool'}} expected-warning {{has side effects that will be discarded}} ext-warning {{C++23 extension}} +} + +void g(int x) { + f(); + f(); + S{}.f(); + S{}.f(); + S{}.g(); + S{}.g(); + [[assume(f2())]]; // expected-warning {{side effects that will be discarded}} ext-warning {{C++23 extension}} + + [[assume((x = 3))]]; // expected-warning {{has side effects that will be discarded}} // ext-warning {{C++23 extension}} + [[assume(x++)]]; // expected-warning {{has side effects that will be discarded}} // ext-warning {{C++23 extension}} + [[assume(++x)]]; // expected-warning {{has side effects that will be discarded}} // ext-warning {{C++23 extension}} + [[assume([]{ return true; }())]]; // expected-warning {{has side effects that will be discarded}} // ext-warning {{C++23 extension}} + [[assume(B{})]]; // expected-warning {{has side effects that will be discarded}} // ext-warning {{C++23 extension}} + [[assume((1, 2))]]; // expected-warning {{has no effect}} // ext-warning {{C++23 extension}} + + f3(); // expected-note {{in instantiation of}} + f3(); // expected-note {{in instantiation of}} + [[assume]]; // expected-error {{takes one argument}} + [[assume(z)]]; // expected-error {{undeclared identifier}} + [[assume(A{})]]; // expected-error {{not contextually convertible to 'bool'}} + [[assume(true)]] if (true) {} // expected-error {{only applies to empty statements}} + [[assume(true)]] {} // expected-error {{only applies to empty statements}} + [[assume(true)]] for (;false;) {} // expected-error {{only applies to empty statements}} + [[assume(true)]] while (false) {} // expected-error {{only applies to empty statements}} + [[assume(true)]] label:; // expected-error {{cannot be applied to a declaration}} + [[assume(true)]] goto label; // expected-error {{only applies to empty statements}} +} + +// Check that 'x' is ODR-used here. +constexpr int h(int x) { return sizeof([=] { [[assume(x)]]; }); } // ext-warning {{C++23 extension}} +static_assert(h(4) == sizeof(int)); + +static_assert(__has_cpp_attribute(assume) == 202207L); +static_assert(__has_attribute(assume)); + +constexpr bool i() { // expected-error {{never produces a constant expression}} + [[assume(false)]]; // expected-note {{assumption evaluated to false}} expected-note {{assumption evaluated to false}} ext-warning {{C++23 extension}} + return true; +} + +constexpr bool j(bool b) { + [[assume(b)]]; // expected-note {{assumption evaluated to false}} ext-warning {{C++23 extension}} + return true; +} + +static_assert(i()); // expected-error {{not an integral constant expression}} expected-note {{in call to}} +static_assert(j(true)); +static_assert(j(false)); // expected-error {{not an integral constant expression}} expected-note {{in call to}} +static_assert(S{}.g()); +static_assert(S{}.g()); // expected-error {{not an integral constant expression}} expected-note {{in call to}} + + +template +constexpr bool f4() { + [[assume(!T{})]]; // expected-error {{invalid argument type 'D'}} // expected-warning 2 {{side effects}} ext-warning {{C++23 extension}} + return sizeof(T) == sizeof(int); +} + +template +concept C = f4(); // expected-note 3 {{in instantiation of}} + // expected-note@-1 3 {{while substituting}} + // expected-error@-2 2 {{resulted in a non-constant expression}} + +struct D { + int x; +}; + +struct E { + int x; + constexpr explicit operator bool() { return false; } +}; + +struct F { + int x; + int y; + constexpr explicit operator bool() { return false; } +}; + +template +constexpr int f5() requires C { return 1; } // expected-note {{while checking the satisfaction}} + // expected-note@-1 {{while substituting template arguments}} + // expected-note@-2 {{candidate template ignored}} + +template +constexpr int f5() requires (!C) { return 2; } // expected-note 4 {{while checking the satisfaction}} + // expected-note@-1 4 {{while substituting template arguments}} + // expected-note@-2 {{candidate template ignored}} + +static_assert(f5() == 1); +static_assert(f5() == 1); // expected-note 3 {{while checking constraint satisfaction}} + // expected-note@-1 3 {{in instantiation of}} + // expected-error@-2 {{no matching function for call}} + +static_assert(f5() == 2); +static_assert(f5() == 1); // expected-note {{while checking constraint satisfaction}} expected-note {{in instantiation of}} +static_assert(f5() == 2); // expected-note {{while checking constraint satisfaction}} expected-note {{in instantiation of}} diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index a3090adb5d47..66a2b11ee34f 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -381,7 +381,7 @@ C++23, informally referred to as C++26.

Portable assumptions
P1774R8 - No + Clang 19 Support for UTF-8 as a portable source file encoding -- GitLab From ceaf4a0aab86f10199e16a825c1bdabe59d07eb3 Mon Sep 17 00:00:00 2001 From: cor3ntin Date: Sat, 9 Mar 2024 12:22:40 +0100 Subject: [PATCH 010/953] [Clang] Fix status of P1774 Portable assumptions --- clang/www/cxx_status.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 66a2b11ee34f..1e36b90356c3 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -381,7 +381,7 @@ C++23, informally referred to as C++26.

Portable assumptions P1774R8 - Clang 19 + Clang 19 Support for UTF-8 as a portable source file encoding -- GitLab From 914f75487673033a6d8d5b9eb15c339a2a4df842 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Sat, 9 Mar 2024 12:32:57 +0100 Subject: [PATCH 011/953] [libc++][format] Update LWG3701 status. (#80545) The issue has been resolved in https://reviews.llvm.org/D121138 since it was needed to implement format. This updates the status of the LWG-issue filed for this review. Marks as complete: - LWG3701 Make formatter, charT> requirement explicit --- libcxx/docs/Status/Cxx23Issues.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index 70480b338205..c2af29281cce 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -169,7 +169,7 @@ "`3683 `__","``operator==`` for ``polymorphic_allocator`` cannot deduce template argument in common cases","July 2022","","" "`3687 `__","``expected`` move constructor should move","July 2022","|Complete|","16.0" "`3692 `__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","July 2022","","","|ranges| |spaceship|" -"`3701 `__","Make ``formatter, charT>`` requirement explicit","July 2022","","","|format|" +"`3701 `__","Make ``formatter, charT>`` requirement explicit","July 2022","|Complete|","15.0","|format|" "`3702 `__","Should ``zip_transform_view::iterator`` remove ``operator<``","July 2022","","","|ranges| |spaceship|" "`3703 `__","Missing requirements for ``expected`` requires ``is_void``","July 2022","|Complete|","16.0" "`3704 `__","LWG 2059 added overloads that might be ill-formed for sets","July 2022","","" -- GitLab From e1da74d916e58f3c7748c21757cba1922aecbc52 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Sat, 9 Mar 2024 12:35:26 +0100 Subject: [PATCH 012/953] [libc++][format] Updates LWG3462 status. (#80550) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The specifications of format had a contradiction, libc++ always implemented the code as-if LWG3462 has been done; the contradiction was a bit hard to spot. Marks as nothing to do: - LWG3462 §[formatter.requirements]: Formatter requirements forbid use of fc.arg() --- libcxx/docs/Status/Cxx23Issues.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index c2af29281cce..e00345533b86 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -65,7 +65,7 @@ `2997 `__,"LWG 491 and the specification of ``{forward_,}list::unique``","June 2021","","" `3410 `__,"``lexicographical_compare_three_way`` is overspecified","June 2021","|Complete|","17.0","|spaceship|" `3430 `__,"``std::fstream`` & co. should be constructible from string_view","June 2021","","" -`3462 `__,"§[formatter.requirements]: Formatter requirements forbid use of ``fc.arg()``","June 2021","","","|format|" +`3462 `__,"§[formatter.requirements]: Formatter requirements forbid use of ``fc.arg()``","June 2021","|Nothing To Do|","","|format|" `3481 `__,"``viewable_range`` mishandles lvalue move-only views","June 2021","Superseded by `P2415R2 `__","","|ranges|" `3506 `__,"Missing allocator-extended constructors for ``priority_queue``","June 2021","|Complete|","14.0" `3517 `__,"``join_view::iterator``'s ``iter_swap`` is underconstrained","June 2021","|Complete|","14.0","|ranges|" -- GitLab From 5630dc66369ccec925f27151b495c9f9818638f1 Mon Sep 17 00:00:00 2001 From: Sirraide Date: Sat, 9 Mar 2024 12:39:55 +0100 Subject: [PATCH 013/953] [Clang] Only check for error in C++20 mode (#84624) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a test that was added in #81014 and which caused buildbots to fail. Only check for the ‘never produces a constant expression error’ in C++20 mode. This fixes #84623. --- clang/test/SemaCXX/cxx23-assume.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/SemaCXX/cxx23-assume.cpp b/clang/test/SemaCXX/cxx23-assume.cpp index 2b99cbd3e788..2d7c9b174d90 100644 --- a/clang/test/SemaCXX/cxx23-assume.cpp +++ b/clang/test/SemaCXX/cxx23-assume.cpp @@ -65,8 +65,8 @@ static_assert(h(4) == sizeof(int)); static_assert(__has_cpp_attribute(assume) == 202207L); static_assert(__has_attribute(assume)); -constexpr bool i() { // expected-error {{never produces a constant expression}} - [[assume(false)]]; // expected-note {{assumption evaluated to false}} expected-note {{assumption evaluated to false}} ext-warning {{C++23 extension}} +constexpr bool i() { // ext-error {{never produces a constant expression}} + [[assume(false)]]; // ext-note {{assumption evaluated to false}} expected-note {{assumption evaluated to false}} ext-warning {{C++23 extension}} return true; } -- GitLab From 11cd2a33f1a80c1b8ad1968c1316204b172e4937 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sat, 9 Mar 2024 11:45:07 +0000 Subject: [PATCH 014/953] [openmp] porting affinity feature to netbsd. (#84618) netbsd supports the portable hwloc's layer as well. for a hardware with 4 cpus, a cpu set is 4 and maxcpus is 256. --- openmp/runtime/src/kmp.h | 2 +- openmp/runtime/src/kmp_affinity.cpp | 8 +++++--- openmp/runtime/src/kmp_affinity.h | 11 +++++++---- openmp/runtime/src/kmp_os.h | 3 ++- openmp/runtime/src/kmp_runtime.cpp | 4 ++-- openmp/runtime/src/z_Linux_util.cpp | 12 +++++++++--- 6 files changed, 26 insertions(+), 14 deletions(-) diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index 121e7e959129..1fc31779a217 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -3912,7 +3912,7 @@ extern void __kmp_balanced_affinity(kmp_info_t *th, int team_size); #if KMP_WEIGHTED_ITERATIONS_SUPPORTED extern int __kmp_get_first_osid_with_ecore(void); #endif -#if KMP_OS_LINUX || KMP_OS_FREEBSD +#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD extern int kmp_set_thread_affinity_mask_initial(void); #endif static inline void __kmp_assign_root_init_mask() { diff --git a/openmp/runtime/src/kmp_affinity.cpp b/openmp/runtime/src/kmp_affinity.cpp index 6a41d34b0237..f40215429417 100644 --- a/openmp/runtime/src/kmp_affinity.cpp +++ b/openmp/runtime/src/kmp_affinity.cpp @@ -2828,7 +2828,8 @@ static void __kmp_dispatch_set_hierarchy_values() { __kmp_hier_max_units[kmp_hier_layer_e::LAYER_THREAD + 1] = nPackages * nCoresPerPkg * __kmp_nThreadsPerCore; __kmp_hier_max_units[kmp_hier_layer_e::LAYER_L1 + 1] = __kmp_ncores; -#if KMP_ARCH_X86_64 && (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_WINDOWS) && \ +#if KMP_ARCH_X86_64 && \ + (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_WINDOWS) && \ KMP_MIC_SUPPORTED if (__kmp_mic_type >= mic3) __kmp_hier_max_units[kmp_hier_layer_e::LAYER_L2 + 1] = __kmp_ncores / 2; @@ -2843,7 +2844,8 @@ static void __kmp_dispatch_set_hierarchy_values() { __kmp_hier_threads_per[kmp_hier_layer_e::LAYER_THREAD + 1] = 1; __kmp_hier_threads_per[kmp_hier_layer_e::LAYER_L1 + 1] = __kmp_nThreadsPerCore; -#if KMP_ARCH_X86_64 && (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_WINDOWS) && \ +#if KMP_ARCH_X86_64 && \ + (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_WINDOWS) && \ KMP_MIC_SUPPORTED if (__kmp_mic_type >= mic3) __kmp_hier_threads_per[kmp_hier_layer_e::LAYER_L2 + 1] = @@ -5557,7 +5559,7 @@ void __kmp_balanced_affinity(kmp_info_t *th, int nthreads) { } } -#if KMP_OS_LINUX || KMP_OS_FREEBSD +#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD // We don't need this entry for Windows because // there is GetProcessAffinityMask() api // diff --git a/openmp/runtime/src/kmp_affinity.h b/openmp/runtime/src/kmp_affinity.h index 5464259784e2..a58a6f0e7c03 100644 --- a/openmp/runtime/src/kmp_affinity.h +++ b/openmp/runtime/src/kmp_affinity.h @@ -191,7 +191,7 @@ public: }; #endif /* KMP_USE_HWLOC */ -#if KMP_OS_LINUX || KMP_OS_FREEBSD +#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD #if KMP_OS_LINUX /* On some of the older OS's that we build on, these constants aren't present in #included from . They must be the same on @@ -314,6 +314,9 @@ public: #elif KMP_OS_FREEBSD #include #include +#elif KMP_OS_NETBSD +#include +#include #endif class KMPNativeAffinity : public KMPAffinity { class Mask : public KMPAffinity::Mask { @@ -407,7 +410,7 @@ class KMPNativeAffinity : public KMPAffinity { #if KMP_OS_LINUX long retval = syscall(__NR_sched_getaffinity, 0, __kmp_affin_mask_size, mask); -#elif KMP_OS_FREEBSD +#elif KMP_OS_FREEBSD || KMP_OS_NETBSD int r = pthread_getaffinity_np(pthread_self(), __kmp_affin_mask_size, reinterpret_cast(mask)); int retval = (r == 0 ? 0 : -1); @@ -428,7 +431,7 @@ class KMPNativeAffinity : public KMPAffinity { #if KMP_OS_LINUX long retval = syscall(__NR_sched_setaffinity, 0, __kmp_affin_mask_size, mask); -#elif KMP_OS_FREEBSD +#elif KMP_OS_FREEBSD || KMP_OS_NETBSD int r = pthread_setaffinity_np(pthread_self(), __kmp_affin_mask_size, reinterpret_cast(mask)); int retval = (r == 0 ? 0 : -1); @@ -471,7 +474,7 @@ class KMPNativeAffinity : public KMPAffinity { } api_type get_api_type() const override { return NATIVE_OS; } }; -#endif /* KMP_OS_LINUX || KMP_OS_FREEBSD */ +#endif /* KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD */ #if KMP_OS_WINDOWS class KMPNativeAffinity : public KMPAffinity { diff --git a/openmp/runtime/src/kmp_os.h b/openmp/runtime/src/kmp_os.h index 954fd93c0877..627d44fb7595 100644 --- a/openmp/runtime/src/kmp_os.h +++ b/openmp/runtime/src/kmp_os.h @@ -75,7 +75,8 @@ #error Unknown compiler #endif -#if (KMP_OS_LINUX || KMP_OS_WINDOWS || KMP_OS_FREEBSD) && !KMP_OS_WASI +#if (KMP_OS_LINUX || KMP_OS_WINDOWS || KMP_OS_FREEBSD || KMP_OS_NETBSD) && \ + !KMP_OS_WASI #define KMP_AFFINITY_SUPPORTED 1 #if KMP_OS_WINDOWS && KMP_ARCH_X86_64 #define KMP_GROUP_AFFINITY 1 diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp index 7edb0b440acc..4016e6daf3f6 100644 --- a/openmp/runtime/src/kmp_runtime.cpp +++ b/openmp/runtime/src/kmp_runtime.cpp @@ -5376,7 +5376,7 @@ __kmp_allocate_team(kmp_root_t *root, int new_nproc, int max_nproc, __kmp_reinitialize_team(team, new_icvs, NULL); } -#if (KMP_OS_LINUX || KMP_OS_FREEBSD) && KMP_AFFINITY_SUPPORTED +#if (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD) && KMP_AFFINITY_SUPPORTED /* Temporarily set full mask for primary thread before creation of workers. The reason is that workers inherit the affinity from the primary thread, so if a lot of workers are created on the single @@ -5412,7 +5412,7 @@ __kmp_allocate_team(kmp_root_t *root, int new_nproc, int max_nproc, } } -#if (KMP_OS_LINUX || KMP_OS_FREEBSD) && KMP_AFFINITY_SUPPORTED +#if (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD) && KMP_AFFINITY_SUPPORTED /* Restore initial primary thread's affinity mask */ new_temp_affinity.restore(); #endif diff --git a/openmp/runtime/src/z_Linux_util.cpp b/openmp/runtime/src/z_Linux_util.cpp index a8e5a9e6bbb0..ee08ea90213f 100644 --- a/openmp/runtime/src/z_Linux_util.cpp +++ b/openmp/runtime/src/z_Linux_util.cpp @@ -65,6 +65,9 @@ #elif KMP_OS_NETBSD || KMP_OS_OPENBSD #include #include +#if KMP_OS_NETBSD +#include +#endif #elif KMP_OS_SOLARIS #include #include @@ -122,7 +125,8 @@ static void __kmp_print_cond(char *buffer, kmp_cond_align_t *cond) { } #endif -#if ((KMP_OS_LINUX || KMP_OS_FREEBSD) && KMP_AFFINITY_SUPPORTED) +#if ((KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD) && \ + KMP_AFFINITY_SUPPORTED) /* Affinity support */ @@ -149,6 +153,8 @@ void __kmp_affinity_determine_capable(const char *env_var) { #define KMP_CPU_SET_TRY_SIZE CACHE_LINE #elif KMP_OS_FREEBSD #define KMP_CPU_SET_SIZE_LIMIT (sizeof(cpuset_t)) +#elif KMP_OS_NETBSD +#define KMP_CPU_SET_SIZE_LIMIT (256) #endif int verbose = __kmp_affinity.flags.verbose; @@ -236,7 +242,7 @@ void __kmp_affinity_determine_capable(const char *env_var) { KMP_INTERNAL_FREE(buf); return; } -#elif KMP_OS_FREEBSD +#elif KMP_OS_FREEBSD || KMP_OS_NETBSD long gCode; unsigned char *buf; buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT); @@ -1262,7 +1268,7 @@ static void __kmp_atfork_child(void) { ++__kmp_fork_count; #if KMP_AFFINITY_SUPPORTED -#if KMP_OS_LINUX || KMP_OS_FREEBSD +#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD // reset the affinity in the child to the initial thread // affinity in the parent kmp_set_thread_affinity_mask_initial(); -- GitLab From 40282674e9808baeb9b88afdd3cbd7da46825544 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Sat, 9 Mar 2024 12:47:43 +0100 Subject: [PATCH 015/953] Reapply [IR] Add new Range attribute using new ConstantRange Attribute type (#84617) The only change from https://github.com/llvm/llvm-project/pull/83171 is the change of the allocator so the destructor is called for ConstantRangeAttributeImpl. reverts https://github.com/llvm/llvm-project/pull/84549 --- llvm/docs/LangRef.rst | 16 ++++ llvm/include/llvm/ADT/FoldingSet.h | 7 ++ llvm/include/llvm/AsmParser/LLParser.h | 1 + llvm/include/llvm/Bitcode/LLVMBitCodes.h | 1 + llvm/include/llvm/IR/Attributes.h | 23 ++++++ llvm/include/llvm/IR/Attributes.td | 6 ++ llvm/lib/AsmParser/LLParser.cpp | 43 ++++++++++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 41 ++++++++++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 61 +++++++++----- llvm/lib/IR/AttributeImpl.h | 28 ++++++- llvm/lib/IR/Attributes.cpp | 81 ++++++++++++++++++- llvm/lib/IR/LLVMContextImpl.h | 3 + llvm/lib/IR/Verifier.cpp | 5 ++ llvm/lib/Transforms/Utils/CodeExtractor.cpp | 1 + .../range-attribute-invalid-range.ll | 6 ++ .../Assembler/range-attribute-invalid-type.ll | 6 ++ llvm/test/Bitcode/attributes.ll | 10 +++ llvm/test/Verifier/range-attr.ll | 19 +++++ llvm/utils/TableGen/Attributes.cpp | 9 ++- 19 files changed, 341 insertions(+), 26 deletions(-) create mode 100644 llvm/test/Assembler/range-attribute-invalid-range.ll create mode 100644 llvm/test/Assembler/range-attribute-invalid-type.ll create mode 100644 llvm/test/Verifier/range-attr.ll diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index a7b77d6f776a..b70220dec926 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -1635,6 +1635,22 @@ Currently, only the following parameter attributes are defined: This attribute cannot be applied to return values. +``range( , )`` + This attribute expresses the possible range of the parameter or return value. + If the value is not in the specified range, it is converted to poison. + The arguments passed to ``range`` have the following properties: + + - The type must match the scalar type of the parameter or return value. + - The pair ``a,b`` represents the range ``[a,b)``. + - Both ``a`` and ``b`` are constants. + - The range is allowed to wrap. + - The range should not represent the full or empty set. That is, ``a!=b``. + + This attribute may only be applied to parameters or return values with integer + or vector of integer types. + + For vector-typed parameters, the range is applied element-wise. + .. _gc: Garbage Collector Strategy Names diff --git a/llvm/include/llvm/ADT/FoldingSet.h b/llvm/include/llvm/ADT/FoldingSet.h index f82eabd5044b..ddc3e52255d6 100644 --- a/llvm/include/llvm/ADT/FoldingSet.h +++ b/llvm/include/llvm/ADT/FoldingSet.h @@ -16,6 +16,7 @@ #ifndef LLVM_ADT_FOLDINGSET_H #define LLVM_ADT_FOLDINGSET_H +#include "llvm/ADT/APInt.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallVector.h" @@ -354,6 +355,12 @@ public: AddInteger(unsigned(I)); AddInteger(unsigned(I >> 32)); } + void AddInteger(const APInt &Int) { + const auto *Parts = Int.getRawData(); + for (int i = 0, N = Int.getNumWords(); i < N; ++i) { + AddInteger(Parts[i]); + } + } void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); } void AddString(StringRef String); diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h index e5e1ade8b38b..e85728aa3c0d 100644 --- a/llvm/include/llvm/AsmParser/LLParser.h +++ b/llvm/include/llvm/AsmParser/LLParser.h @@ -369,6 +369,7 @@ namespace llvm { bool parseFnAttributeValuePairs(AttrBuilder &B, std::vector &FwdRefAttrGrps, bool inAttrGrp, LocTy &BuiltinLoc); + bool parseRangeAttr(AttrBuilder &B); bool parseRequiredTypeAttr(AttrBuilder &B, lltok::Kind AttrToken, Attribute::AttrKind AttrKind); diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index c6f0ddf29a6d..c0a52d64a101 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -724,6 +724,7 @@ enum AttributeKindCodes { ATTR_KIND_WRITABLE = 89, ATTR_KIND_CORO_ONLY_DESTROY_WHEN_COMPLETE = 90, ATTR_KIND_DEAD_ON_UNWIND = 91, + ATTR_KIND_RANGE = 92, }; enum ComdatSelectionKindCodes { diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h index a4ebe5d732f5..0c2a02514ba0 100644 --- a/llvm/include/llvm/IR/Attributes.h +++ b/llvm/include/llvm/IR/Attributes.h @@ -37,6 +37,7 @@ class AttributeMask; class AttributeImpl; class AttributeListImpl; class AttributeSetNode; +class ConstantRange; class FoldingSetNodeID; class Function; class LLVMContext; @@ -103,6 +104,9 @@ public: static bool isTypeAttrKind(AttrKind Kind) { return Kind >= FirstTypeAttr && Kind <= LastTypeAttr; } + static bool isConstantRangeAttrKind(AttrKind Kind) { + return Kind >= FirstConstantRangeAttr && Kind <= LastConstantRangeAttr; + } static bool canUseAsFnAttr(AttrKind Kind); static bool canUseAsParamAttr(AttrKind Kind); @@ -125,6 +129,8 @@ public: static Attribute get(LLVMContext &Context, StringRef Kind, StringRef Val = StringRef()); static Attribute get(LLVMContext &Context, AttrKind Kind, Type *Ty); + static Attribute get(LLVMContext &Context, AttrKind Kind, + const ConstantRange &CR); /// Return a uniquified Attribute object that has the specific /// alignment set. @@ -180,6 +186,9 @@ public: /// Return true if the attribute is a type attribute. bool isTypeAttribute() const; + /// Return true if the attribute is a ConstantRange attribute. + bool isConstantRangeAttribute() const; + /// Return true if the attribute is any kind of attribute. bool isValid() const { return pImpl; } @@ -213,6 +222,10 @@ public: /// a type attribute. Type *getValueAsType() const; + /// Return the attribute's value as a ConstantRange. This requires the + /// attribute to be a ConstantRange attribute. + ConstantRange getValueAsConstantRange() const; + /// Returns the alignment field of an attribute as a byte alignment /// value. MaybeAlign getAlignment() const; @@ -251,6 +264,9 @@ public: /// Return the FPClassTest for nofpclass FPClassTest getNoFPClass() const; + /// Returns the value of the range attribute. + ConstantRange getRange() const; + /// The Attribute is converted to a string of equivalent mnemonic. This /// is, presumably, for writing out the mnemonics for the assembly writer. std::string getAsString(bool InAttrGrp = false) const; @@ -1189,6 +1205,13 @@ public: // Add nofpclass attribute AttrBuilder &addNoFPClassAttr(FPClassTest NoFPClassMask); + /// Add a ConstantRange attribute with the given range. + AttrBuilder &addConstantRangeAttr(Attribute::AttrKind Kind, + const ConstantRange &CR); + + /// Add range attribute. + AttrBuilder &addRangeAttr(const ConstantRange &CR); + ArrayRef attrs() const { return Attrs; } bool operator==(const AttrBuilder &B) const; diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td index 08afecf32015..cef8b17769f0 100644 --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -44,6 +44,9 @@ class StrBoolAttr : Attr; /// Arbitrary string attribute. class ComplexStrAttr P> : Attr; +/// ConstantRange attribute. +class ConstantRangeAttr P> : Attr; + /// Target-independent enum attributes. /// Alignment of parameter (5 bits) stored as log2 of alignment with +1 bias. @@ -218,6 +221,9 @@ def OptimizeNone : EnumAttr<"optnone", [FnAttr]>; /// Similar to byval but without a copy. def Preallocated : TypeAttr<"preallocated", [FnAttr, ParamAttr]>; +/// Parameter or return value is within the specified range. +def Range : ConstantRangeAttr<"range", [ParamAttr, RetAttr]>; + /// Function does not access memory. def ReadNone : EnumAttr<"readnone", [ParamAttr]>; diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index e140c9419520..78bcd94e23fa 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -1596,6 +1596,8 @@ bool LLParser::parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B, return true; } + case Attribute::Range: + return parseRangeAttr(B); default: B.addAttribute(Attr); Lex.Lex(); @@ -3008,6 +3010,47 @@ bool LLParser::parseRequiredTypeAttr(AttrBuilder &B, lltok::Kind AttrToken, return false; } +/// parseRangeAttr +/// ::= range( ,) +bool LLParser::parseRangeAttr(AttrBuilder &B) { + Lex.Lex(); + + APInt Lower; + APInt Upper; + Type *Ty = nullptr; + LocTy TyLoc; + + auto ParseAPSInt = [&](unsigned BitWidth, APInt &Val) { + if (Lex.getKind() != lltok::APSInt) + return tokError("expected integer"); + if (Lex.getAPSIntVal().getBitWidth() > BitWidth) + return tokError( + "integer is too large for the bit width of specified type"); + Val = Lex.getAPSIntVal().extend(BitWidth); + Lex.Lex(); + return false; + }; + + if (parseToken(lltok::lparen, "expected '('") || parseType(Ty, TyLoc)) + return true; + if (!Ty->isIntegerTy()) + return error(TyLoc, "the range must have integer type!"); + + unsigned BitWidth = Ty->getPrimitiveSizeInBits(); + + if (ParseAPSInt(BitWidth, Lower) || + parseToken(lltok::comma, "expected ','") || ParseAPSInt(BitWidth, Upper)) + return true; + if (Lower == Upper) + return tokError("the range should not represent the full or empty set!"); + + if (parseToken(lltok::rparen, "expected ')'")) + return true; + + B.addRangeAttr(ConstantRange(Lower, Upper)); + return false; +} + /// parseOptionalOperandBundles /// ::= /*empty*/ /// ::= '[' OperandBundle [, OperandBundle ]* ']' diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 832907a3f53f..9c63116114f3 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -815,6 +815,30 @@ private: return getFnValueByID(ValNo, Ty, TyID, ConstExprInsertBB); } + Expected readConstantRange(ArrayRef Record, + unsigned &OpNum) { + if (Record.size() - OpNum < 3) + return error("Too few records for range"); + unsigned BitWidth = Record[OpNum++]; + if (BitWidth > 64) { + unsigned LowerActiveWords = Record[OpNum]; + unsigned UpperActiveWords = Record[OpNum++] >> 32; + if (Record.size() - OpNum < LowerActiveWords + UpperActiveWords) + return error("Too few records for range"); + APInt Lower = + readWideAPInt(ArrayRef(&Record[OpNum], LowerActiveWords), BitWidth); + OpNum += LowerActiveWords; + APInt Upper = + readWideAPInt(ArrayRef(&Record[OpNum], UpperActiveWords), BitWidth); + OpNum += UpperActiveWords; + return ConstantRange(Lower, Upper); + } else { + int64_t Start = BitcodeReader::decodeSignRotatedValue(Record[OpNum++]); + int64_t End = BitcodeReader::decodeSignRotatedValue(Record[OpNum++]); + return ConstantRange(APInt(BitWidth, Start), APInt(BitWidth, End)); + } + } + /// Upgrades old-style typeless byval/sret/inalloca attributes by adding the /// corresponding argument's pointee type. Also upgrades intrinsics that now /// require an elementtype attribute. @@ -2103,6 +2127,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { return Attribute::CoroDestroyOnlyWhenComplete; case bitc::ATTR_KIND_DEAD_ON_UNWIND: return Attribute::DeadOnUnwind; + case bitc::ATTR_KIND_RANGE: + return Attribute::Range; } } @@ -2272,6 +2298,21 @@ Error BitcodeReader::parseAttributeGroupBlock() { return error("Not a type attribute"); B.addTypeAttr(Kind, HasType ? getTypeByID(Record[++i]) : nullptr); + } else if (Record[i] == 7) { + Attribute::AttrKind Kind; + + i++; + if (Error Err = parseAttrKind(Record[i++], &Kind)) + return Err; + if (!Attribute::isConstantRangeAttrKind(Kind)) + return error("Not a ConstantRange attribute"); + + Expected MaybeCR = readConstantRange(Record, i); + if (!MaybeCR) + return MaybeCR.takeError(); + i--; + + B.addConstantRangeAttr(Kind, MaybeCR.get()); } else { return error("Invalid attribute group entry"); } diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 656f2a6ce870..597f49332fad 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -844,6 +844,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_CORO_ONLY_DESTROY_WHEN_COMPLETE; case Attribute::DeadOnUnwind: return bitc::ATTR_KIND_DEAD_ON_UNWIND; + case Attribute::Range: + return bitc::ATTR_KIND_RANGE; case Attribute::EndAttrKinds: llvm_unreachable("Can not encode end-attribute kinds marker."); case Attribute::None: @@ -856,6 +858,39 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { llvm_unreachable("Trying to encode unknown attribute"); } +static void emitSignedInt64(SmallVectorImpl &Vals, uint64_t V) { + if ((int64_t)V >= 0) + Vals.push_back(V << 1); + else + Vals.push_back((-V << 1) | 1); +} + +static void emitWideAPInt(SmallVectorImpl &Vals, const APInt &A) { + // We have an arbitrary precision integer value to write whose + // bit width is > 64. However, in canonical unsigned integer + // format it is likely that the high bits are going to be zero. + // So, we only write the number of active words. + unsigned NumWords = A.getActiveWords(); + const uint64_t *RawData = A.getRawData(); + for (unsigned i = 0; i < NumWords; i++) + emitSignedInt64(Vals, RawData[i]); +} + +static void emitConstantRange(SmallVectorImpl &Record, + const ConstantRange &CR) { + unsigned BitWidth = CR.getBitWidth(); + Record.push_back(BitWidth); + if (BitWidth > 64) { + Record.push_back(CR.getLower().getActiveWords() | + (uint64_t(CR.getUpper().getActiveWords()) << 32)); + emitWideAPInt(Record, CR.getLower()); + emitWideAPInt(Record, CR.getUpper()); + } else { + emitSignedInt64(Record, CR.getLower().getSExtValue()); + emitSignedInt64(Record, CR.getUpper().getSExtValue()); + } +} + void ModuleBitcodeWriter::writeAttributeGroupTable() { const std::vector &AttrGrps = VE.getAttributeGroups(); @@ -889,13 +924,17 @@ void ModuleBitcodeWriter::writeAttributeGroupTable() { Record.append(Val.begin(), Val.end()); Record.push_back(0); } - } else { - assert(Attr.isTypeAttribute()); + } else if (Attr.isTypeAttribute()) { Type *Ty = Attr.getValueAsType(); Record.push_back(Ty ? 6 : 5); Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); if (Ty) Record.push_back(VE.getTypeID(Attr.getValueAsType())); + } else { + assert(Attr.isConstantRangeAttribute()); + Record.push_back(7); + Record.push_back(getAttrKindEncoding(Attr.getKindAsEnum())); + emitConstantRange(Record, Attr.getValueAsConstantRange()); } } @@ -1716,24 +1755,6 @@ void ModuleBitcodeWriter::writeDIGenericSubrange( Record.clear(); } -static void emitSignedInt64(SmallVectorImpl &Vals, uint64_t V) { - if ((int64_t)V >= 0) - Vals.push_back(V << 1); - else - Vals.push_back((-V << 1) | 1); -} - -static void emitWideAPInt(SmallVectorImpl &Vals, const APInt &A) { - // We have an arbitrary precision integer value to write whose - // bit width is > 64. However, in canonical unsigned integer - // format it is likely that the high bits are going to be zero. - // So, we only write the number of active words. - unsigned NumWords = A.getActiveWords(); - const uint64_t *RawData = A.getRawData(); - for (unsigned i = 0; i < NumWords; i++) - emitSignedInt64(Vals, RawData[i]); -} - void ModuleBitcodeWriter::writeDIEnumerator(const DIEnumerator *N, SmallVectorImpl &Record, unsigned Abbrev) { diff --git a/llvm/lib/IR/AttributeImpl.h b/llvm/lib/IR/AttributeImpl.h index 78496786b0ae..9a6427bbc3d5 100644 --- a/llvm/lib/IR/AttributeImpl.h +++ b/llvm/lib/IR/AttributeImpl.h @@ -20,6 +20,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/Attributes.h" +#include "llvm/IR/ConstantRange.h" #include "llvm/Support/TrailingObjects.h" #include #include @@ -46,6 +47,7 @@ protected: IntAttrEntry, StringAttrEntry, TypeAttrEntry, + ConstantRangeAttrEntry, }; AttributeImpl(AttrEntryKind KindID) : KindID(KindID) {} @@ -59,6 +61,9 @@ public: bool isIntAttribute() const { return KindID == IntAttrEntry; } bool isStringAttribute() const { return KindID == StringAttrEntry; } bool isTypeAttribute() const { return KindID == TypeAttrEntry; } + bool isConstantRangeAttribute() const { + return KindID == ConstantRangeAttrEntry; + } bool hasAttribute(Attribute::AttrKind A) const; bool hasAttribute(StringRef Kind) const; @@ -72,6 +77,8 @@ public: Type *getValueAsType() const; + ConstantRange getValueAsConstantRange() const; + /// Used when sorting the attributes. bool operator<(const AttributeImpl &AI) const; @@ -82,8 +89,10 @@ public: Profile(ID, getKindAsEnum(), getValueAsInt()); else if (isStringAttribute()) Profile(ID, getKindAsString(), getValueAsString()); - else + else if (isTypeAttribute()) Profile(ID, getKindAsEnum(), getValueAsType()); + else + Profile(ID, getKindAsEnum(), getValueAsConstantRange()); } static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind) { @@ -108,6 +117,13 @@ public: ID.AddInteger(Kind); ID.AddPointer(Ty); } + + static void Profile(FoldingSetNodeID &ID, Attribute::AttrKind Kind, + const ConstantRange &CR) { + ID.AddInteger(Kind); + ID.AddInteger(CR.getLower()); + ID.AddInteger(CR.getUpper()); + } }; static_assert(std::is_trivially_destructible::value, @@ -196,6 +212,16 @@ public: Type *getTypeValue() const { return Ty; } }; +class ConstantRangeAttributeImpl : public EnumAttributeImpl { + ConstantRange CR; + +public: + ConstantRangeAttributeImpl(Attribute::AttrKind Kind, const ConstantRange &CR) + : EnumAttributeImpl(ConstantRangeAttrEntry, Kind), CR(CR) {} + + ConstantRange getConstantRangeValue() const { return CR; } +}; + class AttributeBitSet { /// Bitset with a bit for each available attribute Attribute::AttrKind. uint8_t AvailableAttrs[12] = {}; diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index 00acbbe7989d..b2d9992cdc02 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -24,6 +24,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/AttributeMask.h" +#include "llvm/IR/ConstantRange.h" #include "llvm/IR/Function.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Type.h" @@ -165,6 +166,31 @@ Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, return Attribute(PA); } +Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, + const ConstantRange &CR) { + assert(Attribute::isConstantRangeAttrKind(Kind) && + "Not a ConstantRange attribute"); + LLVMContextImpl *pImpl = Context.pImpl; + FoldingSetNodeID ID; + ID.AddInteger(Kind); + ID.AddInteger(CR.getLower()); + ID.AddInteger(CR.getUpper()); + + void *InsertPoint; + AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); + + if (!PA) { + // If we didn't find any existing attributes of the same shape then create a + // new one and insert it. + PA = new (pImpl->ConstantRangeAttributeAlloc.Allocate()) + ConstantRangeAttributeImpl(Kind, CR); + pImpl->AttrsSet.InsertNode(PA, InsertPoint); + } + + // Return the Attribute that we found or created. + return Attribute(PA); +} + Attribute Attribute::getWithAlignment(LLVMContext &Context, Align A) { assert(A <= llvm::Value::MaximumAlignment && "Alignment too large."); return get(Context, Alignment, A.value()); @@ -287,9 +313,14 @@ bool Attribute::isTypeAttribute() const { return pImpl && pImpl->isTypeAttribute(); } +bool Attribute::isConstantRangeAttribute() const { + return pImpl && pImpl->isConstantRangeAttribute(); +} + Attribute::AttrKind Attribute::getKindAsEnum() const { if (!pImpl) return None; - assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) && + assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute() || + isConstantRangeAttribute()) && "Invalid attribute type to get the kind as an enum!"); return pImpl->getKindAsEnum(); } @@ -329,6 +360,11 @@ Type *Attribute::getValueAsType() const { return pImpl->getValueAsType(); } +ConstantRange Attribute::getValueAsConstantRange() const { + assert(isConstantRangeAttribute() && + "Invalid attribute type to get the value as a ConstantRange!"); + return pImpl->getValueAsConstantRange(); +} bool Attribute::hasAttribute(AttrKind Kind) const { return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None); @@ -408,6 +444,12 @@ FPClassTest Attribute::getNoFPClass() const { return static_cast(pImpl->getValueAsInt()); } +ConstantRange Attribute::getRange() const { + assert(hasAttribute(Attribute::Range) && + "Trying to get range args from non-range attribute"); + return pImpl->getValueAsConstantRange(); +} + static const char *getModRefStr(ModRefInfo MR) { switch (MR) { case ModRefInfo::NoModRef: @@ -562,6 +604,18 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return Result; } + if (hasAttribute(Attribute::Range)) { + std::string Result; + raw_string_ostream OS(Result); + ConstantRange CR = getValueAsConstantRange(); + OS << "range("; + OS << "i" << CR.getBitWidth() << " "; + OS << CR.getLower() << ", " << CR.getUpper(); + OS << ")"; + OS.flush(); + return Result; + } + // Convert target-dependent attributes to strings of the form: // // "kind" @@ -651,7 +705,8 @@ bool AttributeImpl::hasAttribute(StringRef Kind) const { } Attribute::AttrKind AttributeImpl::getKindAsEnum() const { - assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute()); + assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute() || + isConstantRangeAttribute()); return static_cast(this)->getEnumKind(); } @@ -680,6 +735,12 @@ Type *AttributeImpl::getValueAsType() const { return static_cast(this)->getTypeValue(); } +ConstantRange AttributeImpl::getValueAsConstantRange() const { + assert(isConstantRangeAttribute()); + return static_cast(this) + ->getConstantRangeValue(); +} + bool AttributeImpl::operator<(const AttributeImpl &AI) const { if (this == &AI) return false; @@ -693,6 +754,7 @@ bool AttributeImpl::operator<(const AttributeImpl &AI) const { return getKindAsEnum() < AI.getKindAsEnum(); assert(!AI.isEnumAttribute() && "Non-unique attribute"); assert(!AI.isTypeAttribute() && "Comparison of types would be unstable"); + assert(!AI.isConstantRangeAttribute() && "Unclear how to compare ranges"); // TODO: Is this actually needed? assert(AI.isIntAttribute() && "Only possibility left"); return getValueAsInt() < AI.getValueAsInt(); @@ -1881,6 +1943,15 @@ AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) { return addTypeAttr(Attribute::InAlloca, Ty); } +AttrBuilder &AttrBuilder::addConstantRangeAttr(Attribute::AttrKind Kind, + const ConstantRange &CR) { + return addAttribute(Attribute::get(Ctx, Kind, CR)); +} + +AttrBuilder &AttrBuilder::addRangeAttr(const ConstantRange &CR) { + return addConstantRangeAttr(Attribute::Range, CR); +} + AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { // TODO: Could make this O(n) as we're merging two sorted lists. for (const auto &I : B.attrs()) @@ -1952,6 +2023,12 @@ AttributeMask AttributeFuncs::typeIncompatible(Type *Ty, Incompatible.addAttribute(Attribute::SExt).addAttribute(Attribute::ZExt); } + if (!Ty->isIntOrIntVectorTy()) { + // Attributes that only apply to integers or vector of integers. + if (ASK & ASK_SAFE_TO_DROP) + Incompatible.addAttribute(Attribute::Range); + } + if (!Ty->isPointerTy()) { // Attributes that only apply to pointers. if (ASK & ASK_SAFE_TO_DROP) diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 2ee1080a1ffa..547a02a6490e 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -56,6 +56,7 @@ class AttributeImpl; class AttributeListImpl; class AttributeSetNode; class BasicBlock; +class ConstantRangeAttributeImpl; struct DiagnosticHandler; class DPMarker; class ElementCount; @@ -1562,6 +1563,8 @@ public: BumpPtrAllocator Alloc; UniqueStringSaver Saver{Alloc}; + SpecificBumpPtrAllocator + ConstantRangeAttributeAlloc; DenseMap IntegerTypes; diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index fd5f7d57c258..3cf5e81efb3b 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -2039,6 +2039,11 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty, Check((Val & ~static_cast(fcAllFlags)) == 0, "Invalid value for 'nofpclass' test mask", V); } + if (Attrs.hasAttribute(Attribute::Range)) { + auto CR = Attrs.getAttribute(Attribute::Range).getValueAsConstantRange(); + Check(Ty->isIntOrIntVectorTy(CR.getBitWidth()), + "Range bit width must match type bit width!", V); + } } void Verifier::checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr, diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 3071ec0c9113..ab2d25c3f17c 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -999,6 +999,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs, case Attribute::WriteOnly: case Attribute::Writable: case Attribute::DeadOnUnwind: + case Attribute::Range: // These are not really attributes. case Attribute::None: case Attribute::EndAttrKinds: diff --git a/llvm/test/Assembler/range-attribute-invalid-range.ll b/llvm/test/Assembler/range-attribute-invalid-range.ll new file mode 100644 index 000000000000..cf6d3f080183 --- /dev/null +++ b/llvm/test/Assembler/range-attribute-invalid-range.ll @@ -0,0 +1,6 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s + +; CHECK: the range should not represent the full or empty set! +define void @range_empty(i8 range(i8 0, 0) %a) { + ret void +} diff --git a/llvm/test/Assembler/range-attribute-invalid-type.ll b/llvm/test/Assembler/range-attribute-invalid-type.ll new file mode 100644 index 000000000000..cc09149a94dc --- /dev/null +++ b/llvm/test/Assembler/range-attribute-invalid-type.ll @@ -0,0 +1,6 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s + +; CHECK: the range must have integer type! +define void @range_vector_type(i8 range(<4 x i32> 0, 0) %a) { + ret void +} diff --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll index 6921f11a352d..26163b4d38c8 100644 --- a/llvm/test/Bitcode/attributes.ll +++ b/llvm/test/Bitcode/attributes.ll @@ -526,6 +526,16 @@ define void @f91(ptr dead_on_unwind %p) { ret void } +; CHECK: define range(i32 -1, 42) i32 @range_attribute(<4 x i32> range(i32 -1, 42) %a) +define range(i32 -1, 42) i32 @range_attribute(<4 x i32> range(i32 -1, 42) %a) { + ret i32 0 +} + +; CHECK: define void @wide_range_attribute(i128 range(i128 618970019642690137449562111, 618970019642690137449562114) %a) +define void @wide_range_attribute(i128 range(i128 618970019642690137449562111, 618970019642690137449562114) %a) { + ret void +} + ; CHECK: attributes #0 = { noreturn } ; CHECK: attributes #1 = { nounwind } ; CHECK: attributes #2 = { memory(none) } diff --git a/llvm/test/Verifier/range-attr.ll b/llvm/test/Verifier/range-attr.ll new file mode 100644 index 000000000000..f985ab696eac --- /dev/null +++ b/llvm/test/Verifier/range-attr.ll @@ -0,0 +1,19 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +; CHECK: Range bit width must match type bit width! +; CHECK-NEXT: ptr @bit_widths_do_not_match +define void @bit_widths_do_not_match(i32 range(i8 1, 0) %a) { + ret void +} + +; CHECK: Range bit width must match type bit width! +; CHECK-NEXT: ptr @bit_widths_do_not_match_vector +define void @bit_widths_do_not_match_vector(<4 x i32> range(i8 1, 0) %a) { + ret void +} + +; CHECK: Attribute 'range(i8 1, 0)' applied to incompatible type! +; CHECK-NEXT: ptr @not-integer-type +define void @not-integer-type(ptr range(i8 1, 0) %a) { + ret void +} diff --git a/llvm/utils/TableGen/Attributes.cpp b/llvm/utils/TableGen/Attributes.cpp index db3c4decccb4..d9fc7834416c 100644 --- a/llvm/utils/TableGen/Attributes.cpp +++ b/llvm/utils/TableGen/Attributes.cpp @@ -53,7 +53,8 @@ void Attributes::emitTargetIndependentNames(raw_ostream &OS) { }; // Emit attribute enums in the same order llvm::Attribute::operator< expects. - Emit({"EnumAttr", "TypeAttr", "IntAttr"}, "ATTRIBUTE_ENUM"); + Emit({"EnumAttr", "TypeAttr", "IntAttr", "ConstantRangeAttr"}, + "ATTRIBUTE_ENUM"); Emit({"StrBoolAttr"}, "ATTRIBUTE_STRBOOL"); Emit({"ComplexStrAttr"}, "ATTRIBUTE_COMPLEXSTR"); @@ -63,7 +64,8 @@ void Attributes::emitTargetIndependentNames(raw_ostream &OS) { OS << "#ifdef GET_ATTR_ENUM\n"; OS << "#undef GET_ATTR_ENUM\n"; unsigned Value = 1; // Leave zero for AttrKind::None. - for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr"}) { + for (StringRef KindName : + {"EnumAttr", "TypeAttr", "IntAttr", "ConstantRangeAttr"}) { OS << "First" << KindName << " = " << Value << ",\n"; for (auto *A : Records.getAllDerivedDefinitions(KindName)) { OS << A->getName() << " = " << Value << ",\n"; @@ -117,7 +119,8 @@ void Attributes::emitAttributeProperties(raw_ostream &OS) { OS << "#ifdef GET_ATTR_PROP_TABLE\n"; OS << "#undef GET_ATTR_PROP_TABLE\n"; OS << "static const uint8_t AttrPropTable[] = {\n"; - for (StringRef KindName : {"EnumAttr", "TypeAttr", "IntAttr"}) { + for (StringRef KindName : + {"EnumAttr", "TypeAttr", "IntAttr", "ConstantRangeAttr"}) { for (auto *A : Records.getAllDerivedDefinitions(KindName)) { OS << "0"; for (Init *P : *A->getValueAsListInit("Properties")) -- GitLab From ee22e255648ee9b056280484b4b70d4542bc807e Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Sat, 9 Mar 2024 12:49:36 +0100 Subject: [PATCH 016/953] [libc++] Remove include from (#83742) This reduces the include time of `` from 122ms to 78ms. --- libcxx/include/__fwd/array.h | 6 ++++++ libcxx/include/span | 16 ++++++++-------- libcxx/test/libcxx/transitive_includes/cxx23.csv | 1 - libcxx/test/libcxx/transitive_includes/cxx26.csv | 1 - .../range.subrange/operator.pair_like.pass.cpp | 1 + 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/libcxx/include/__fwd/array.h b/libcxx/include/__fwd/array.h index ff3a3eeeefc7..b429d0c5a954 100644 --- a/libcxx/include/__fwd/array.h +++ b/libcxx/include/__fwd/array.h @@ -35,6 +35,12 @@ template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp&& get(const array<_Tp, _Size>&&) _NOEXCEPT; #endif +template +struct __is_std_array : false_type {}; + +template +struct __is_std_array > : true_type {}; + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___FWD_ARRAY_H diff --git a/libcxx/include/span b/libcxx/include/span index cfeef35d2d80..c0fe25ddb4be 100644 --- a/libcxx/include/span +++ b/libcxx/include/span @@ -130,10 +130,12 @@ template #include <__assert> #include <__config> +#include <__fwd/array.h> #include <__fwd/span.h> #include <__iterator/bounded_iter.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> +#include <__iterator/reverse_iterator.h> #include <__iterator/wrap_iter.h> #include <__memory/pointer_traits.h> #include <__ranges/concepts.h> @@ -141,13 +143,16 @@ template #include <__ranges/enable_borrowed_range.h> #include <__ranges/enable_view.h> #include <__ranges/size.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_const.h> #include <__type_traits/is_convertible.h> +#include <__type_traits/remove_cv.h> #include <__type_traits/remove_cvref.h> #include <__type_traits/remove_reference.h> #include <__type_traits/type_identity.h> #include <__utility/forward.h> -#include // for array -#include // for byte +#include // for byte +#include #include #include @@ -171,12 +176,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 -template -struct __is_std_array : false_type {}; - -template -struct __is_std_array> : true_type {}; - template struct __is_std_span : false_type {}; @@ -586,6 +585,7 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include # include # include # include diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv index 64ff9261820a..043d23d551c5 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx23.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv @@ -509,7 +509,6 @@ shared_mutex string shared_mutex version source_location cstdint source_location version -span array span cstddef span initializer_list span limits diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv index 64ff9261820a..043d23d551c5 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx26.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv @@ -509,7 +509,6 @@ shared_mutex string shared_mutex version source_location cstdint source_location version -span array span cstddef span initializer_list span limits diff --git a/libcxx/test/std/ranges/range.utility/range.subrange/operator.pair_like.pass.cpp b/libcxx/test/std/ranges/range.utility/range.subrange/operator.pair_like.pass.cpp index 1d0dfd05b3f7..2641a9ad94ea 100644 --- a/libcxx/test/std/ranges/range.utility/range.subrange/operator.pair_like.pass.cpp +++ b/libcxx/test/std/ranges/range.utility/range.subrange/operator.pair_like.pass.cpp @@ -13,6 +13,7 @@ // requires pair-like-convertible-from // constexpr operator PairLike() const; +#include #include #include #include -- GitLab From 5b5c21d772d20320fd876edddfc204cca93fae0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 9 Mar 2024 12:57:20 +0200 Subject: [PATCH 017/953] Revert "[SLP]Improve minbitwidth analysis." This reverts commit 2bd369b48dbf0bc3128becb7ef8f8a1b82514b87. That commit triggered failed assertions: $ cat repro.c short *a; int b; void h() { short *c = a; b = 0; for (; b < 4; b++) { unsigned d = a[b] + a[b + 4 * 2], e = a[b] - a[b + 4 * 2], f = (a[b + 4] >> 1) - a[b + 4 * 3], g = a[b + 4] + (a[b + 4 * 3] >> 1); c[b] = g; c[b + 4] = e + f; c[b + 4 * 2] = e - f; c[b + 4 * 3] = d - g; } } $ clang -target aarch64-linux-gnu -c -O2 repro.c clang: ../lib/Transforms/Vectorize/SLPVectorizer.cpp:12503: llvm::Value* llvm::slpvectorizer::BoUpSLP::vectorizeTree(llvm::slpvectorizer::BoUpSLP::TreeEntry*, bool): Assertion `(MinBWs.contains(getOperandEntry(E, 0)) || MinBWs.contains(getOperandEntry(E, 1))) && "Expected item in MinBWs."' failed. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 676 +++++------------- .../SLPVectorizer/AArch64/ext-trunc.ll | 9 +- .../SLPVectorizer/AArch64/getelementptr2.ll | 4 +- .../SLPVectorizer/AArch64/reduce-add-i64.ll | 20 +- .../SLPVectorizer/RISCV/reductions.ll | 7 +- .../Transforms/SLPVectorizer/X86/PR35777.ll | 9 +- .../X86/int-bitcast-minbitwidth.ll | 2 +- ...minbitwidth-multiuse-with-insertelement.ll | 17 +- .../X86/minbitwidth-transformed-operand.ll | 21 +- .../SLPVectorizer/X86/minimum-sizes.ll | 43 +- .../SLPVectorizer/X86/phi-undef-input.ll | 24 +- .../Transforms/SLPVectorizer/X86/resched.ll | 32 +- .../X86/reused-reductions-with-minbitwidth.ll | 10 +- .../X86/store-insertelement-minbitwidth.ll | 22 +- .../SLPVectorizer/alt-cmp-vectorize.ll | 4 +- 15 files changed, 306 insertions(+), 594 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index a5c34bfbf9b4..36dc9094538a 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -1085,9 +1085,6 @@ public: BS->clear(); } MinBWs.clear(); - ReductionBitWidth = 0; - CastMaxMinBWSizes.reset(); - TruncNodes.clear(); InstrElementSize.clear(); UserIgnoreList = nullptr; PostponedGathers.clear(); @@ -2290,7 +2287,6 @@ public: void clearReductionData() { AnalyzedReductionsRoots.clear(); AnalyzedReductionVals.clear(); - AnalyzedMinBWVals.clear(); } /// Checks if the given value is gathered in one of the nodes. bool isAnyGathered(const SmallDenseSet &Vals) const { @@ -2311,11 +2307,9 @@ private: /// constant and to be demoted. Required to correctly identify constant nodes /// to be demoted. bool collectValuesToDemote( - Value *V, bool IsProfitableToDemoteRoot, unsigned &BitWidth, - SmallVectorImpl &ToDemote, + Value *V, SmallVectorImpl &ToDemote, DenseMap> &DemotedConsts, - DenseSet &Visited, unsigned &MaxDepthLevel, - bool &IsProfitableToDemote) const; + SmallVectorImpl &Roots, DenseSet &Visited) const; /// Check if the operands on the edges \p Edges of the \p UserTE allows /// reordering (i.e. the operands can be reordered because they have only one @@ -2381,10 +2375,6 @@ private: /// \ returns the graph entry for the \p Idx operand of the \p E entry. const TreeEntry *getOperandEntry(const TreeEntry *E, unsigned Idx) const; - /// \returns Cast context for the given graph node. - TargetTransformInfo::CastContextHint - getCastContextHint(const TreeEntry &TE) const; - /// \returns the cost of the vectorizable entry. InstructionCost getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, @@ -2935,18 +2925,11 @@ private: } assert(!BundleMember && "Bundle and VL out of sync"); } else { + MustGather.insert(VL.begin(), VL.end()); // Build a map for gathered scalars to the nodes where they are used. - bool AllConstsOrCasts = true; for (Value *V : VL) - if (!isConstant(V)) { - auto *I = dyn_cast(V); - AllConstsOrCasts &= I && I->getType()->isIntegerTy(); + if (!isConstant(V)) ValueToGatherNodes.try_emplace(V).first->getSecond().insert(Last); - } - if (AllConstsOrCasts) - CastMaxMinBWSizes = - std::make_pair(std::numeric_limits::max(), 1); - MustGather.insert(VL.begin(), VL.end()); } if (UserTreeIdx.UserTE) @@ -3071,10 +3054,6 @@ private: /// Set of hashes for the list of reduction values already being analyzed. DenseSet AnalyzedReductionVals; - /// Values, already been analyzed for mininmal bitwidth and found to be - /// non-profitable. - DenseSet AnalyzedMinBWVals; - /// A list of values that need to extracted out of the tree. /// This list holds pairs of (Internal Scalar : External User). External User /// can be nullptr, it means that this Internal Scalar will be used later, @@ -3650,18 +3629,6 @@ private: /// value must be signed-extended, rather than zero-extended, back to its /// original width. DenseMap> MinBWs; - - /// Final size of the reduced vector, if the current graph represents the - /// input for the reduction and it was possible to narrow the size of the - /// reduction. - unsigned ReductionBitWidth = 0; - - /// If the tree contains any zext/sext/trunc nodes, contains max-min pair of - /// type sizes, used in the tree. - std::optional> CastMaxMinBWSizes; - - /// Indices of the vectorized trunc nodes. - DenseSet TruncNodes; }; } // end namespace slpvectorizer @@ -6572,29 +6539,8 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth, case Instruction::Trunc: case Instruction::FPTrunc: case Instruction::BitCast: { - auto [PrevMaxBW, PrevMinBW] = CastMaxMinBWSizes.value_or( - std::make_pair(std::numeric_limits::min(), - std::numeric_limits::max())); - if (ShuffleOrOp == Instruction::ZExt || - ShuffleOrOp == Instruction::SExt) { - CastMaxMinBWSizes = std::make_pair( - std::max(DL->getTypeSizeInBits(VL0->getType()), - PrevMaxBW), - std::min( - DL->getTypeSizeInBits(VL0->getOperand(0)->getType()), - PrevMinBW)); - } else if (ShuffleOrOp == Instruction::Trunc) { - CastMaxMinBWSizes = std::make_pair( - std::max( - DL->getTypeSizeInBits(VL0->getOperand(0)->getType()), - PrevMaxBW), - std::min(DL->getTypeSizeInBits(VL0->getType()), - PrevMinBW)); - TruncNodes.insert(VectorizableTree.size()); - } TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, ReuseShuffleIndicies); - LLVM_DEBUG(dbgs() << "SLP: added a vector of casts.\n"); TE->setOperandsInOrder(); @@ -8416,22 +8362,6 @@ const BoUpSLP::TreeEntry *BoUpSLP::getOperandEntry(const TreeEntry *E, return It->get(); } -TTI::CastContextHint BoUpSLP::getCastContextHint(const TreeEntry &TE) const { - if (TE.State == TreeEntry::ScatterVectorize || - TE.State == TreeEntry::StridedVectorize) - return TTI::CastContextHint::GatherScatter; - if (TE.State == TreeEntry::Vectorize && TE.getOpcode() == Instruction::Load && - !TE.isAltShuffle()) { - if (TE.ReorderIndices.empty()) - return TTI::CastContextHint::Normal; - SmallVector Mask; - inversePermutation(TE.ReorderIndices, Mask); - if (ShuffleVectorInst::isReverseMask(Mask, Mask.size())) - return TTI::CastContextHint::Reversed; - } - return TTI::CastContextHint::None; -} - InstructionCost BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, SmallPtrSetImpl &CheckedExtracts) { @@ -8454,7 +8384,6 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, // If we have computed a smaller type for the expression, update VecTy so // that the costs will be accurate. auto It = MinBWs.find(E); - Type *OrigScalarTy = ScalarTy; if (It != MinBWs.end()) { ScalarTy = IntegerType::get(F->getContext(), It->second.first); VecTy = FixedVectorType::get(ScalarTy, VL.size()); @@ -8512,11 +8441,24 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, UsedScalars.set(I); } auto GetCastContextHint = [&](Value *V) { - if (const TreeEntry *OpTE = getTreeEntry(V)) - return getCastContextHint(*OpTE); - InstructionsState SrcState = getSameOpcode(E->getOperand(0), *TLI); - if (SrcState.getOpcode() == Instruction::Load && !SrcState.isAltShuffle()) - return TTI::CastContextHint::GatherScatter; + if (const TreeEntry *OpTE = getTreeEntry(V)) { + if (OpTE->State == TreeEntry::ScatterVectorize || + OpTE->State == TreeEntry::StridedVectorize) + return TTI::CastContextHint::GatherScatter; + if (OpTE->State == TreeEntry::Vectorize && + OpTE->getOpcode() == Instruction::Load && !OpTE->isAltShuffle()) { + if (OpTE->ReorderIndices.empty()) + return TTI::CastContextHint::Normal; + SmallVector Mask; + inversePermutation(OpTE->ReorderIndices, Mask); + if (ShuffleVectorInst::isReverseMask(Mask, Mask.size())) + return TTI::CastContextHint::Reversed; + } + } else { + InstructionsState SrcState = getSameOpcode(E->getOperand(0), *TLI); + if (SrcState.getOpcode() == Instruction::Load && !SrcState.isAltShuffle()) + return TTI::CastContextHint::GatherScatter; + } return TTI::CastContextHint::None; }; auto GetCostDiff = @@ -8565,6 +8507,8 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, TTI::CastContextHint CCH = GetCastContextHint(VL0); VecCost += TTI->getCastInstrCost(VecOpcode, UserVecTy, VecTy, CCH, CostKind); + ScalarCost += Sz * TTI->getCastInstrCost(VecOpcode, UserScalarTy, + ScalarTy, CCH, CostKind); } } } @@ -8581,7 +8525,7 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, InstructionCost ScalarCost = 0; InstructionCost VecCost = 0; std::tie(ScalarCost, VecCost) = getGEPCosts( - *TTI, Ptrs, BasePtr, E->getOpcode(), CostKind, OrigScalarTy, VecTy); + *TTI, Ptrs, BasePtr, E->getOpcode(), CostKind, ScalarTy, VecTy); LLVM_DEBUG(dumpTreeCosts(E, 0, VecCost, ScalarCost, "Calculated GEPs cost for Tree")); @@ -8628,7 +8572,7 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, NumElts = ATy->getNumElements(); else NumElts = AggregateTy->getStructNumElements(); - SrcVecTy = FixedVectorType::get(OrigScalarTy, NumElts); + SrcVecTy = FixedVectorType::get(ScalarTy, NumElts); } if (I->hasOneUse()) { Instruction *Ext = I->user_back(); @@ -8796,7 +8740,13 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, } } auto GetScalarCost = [&](unsigned Idx) -> InstructionCost { - auto *VI = cast(UniqueValues[Idx]); + // Do not count cost here if minimum bitwidth is in effect and it is just + // a bitcast (here it is just a noop). + if (VecOpcode != Opcode && VecOpcode == Instruction::BitCast) + return TTI::TCC_Free; + auto *VI = VL0->getOpcode() == Opcode + ? cast(UniqueValues[Idx]) + : nullptr; return TTI->getCastInstrCost(Opcode, VL0->getType(), VL0->getOperand(0)->getType(), TTI::getCastContextHint(VI), CostKind, VI); @@ -8839,7 +8789,7 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, ? CmpInst::BAD_FCMP_PREDICATE : CmpInst::BAD_ICMP_PREDICATE; - return TTI->getCmpSelInstrCost(E->getOpcode(), OrigScalarTy, + return TTI->getCmpSelInstrCost(E->getOpcode(), ScalarTy, Builder.getInt1Ty(), CurrentPred, CostKind, VI); }; @@ -8894,7 +8844,7 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, TTI::OperandValueInfo Op2Info = TTI::getOperandInfo(VI->getOperand(OpIdx)); SmallVector Operands(VI->operand_values()); - return TTI->getArithmeticInstrCost(ShuffleOrOp, OrigScalarTy, CostKind, + return TTI->getArithmeticInstrCost(ShuffleOrOp, ScalarTy, CostKind, Op1Info, Op2Info, Operands, VI); }; auto GetVectorCost = [=](InstructionCost CommonCost) { @@ -8913,9 +8863,9 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, case Instruction::Load: { auto GetScalarCost = [&](unsigned Idx) { auto *VI = cast(UniqueValues[Idx]); - return TTI->getMemoryOpCost(Instruction::Load, OrigScalarTy, - VI->getAlign(), VI->getPointerAddressSpace(), - CostKind, TTI::OperandValueInfo(), VI); + return TTI->getMemoryOpCost(Instruction::Load, ScalarTy, VI->getAlign(), + VI->getPointerAddressSpace(), CostKind, + TTI::OperandValueInfo(), VI); }; auto *LI0 = cast(VL0); auto GetVectorCost = [&](InstructionCost CommonCost) { @@ -8958,9 +8908,9 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef VectorizedVals, auto GetScalarCost = [=](unsigned Idx) { auto *VI = cast(VL[Idx]); TTI::OperandValueInfo OpInfo = TTI::getOperandInfo(VI->getValueOperand()); - return TTI->getMemoryOpCost(Instruction::Store, OrigScalarTy, - VI->getAlign(), VI->getPointerAddressSpace(), - CostKind, OpInfo, VI); + return TTI->getMemoryOpCost(Instruction::Store, ScalarTy, VI->getAlign(), + VI->getPointerAddressSpace(), CostKind, + OpInfo, VI); }; auto *BaseSI = cast(IsReorder ? VL[E->ReorderIndices.front()] : VL0); @@ -9822,44 +9772,6 @@ InstructionCost BoUpSLP::getTreeCost(ArrayRef VectorizedVals) { Cost -= InsertCost; } - // Add the cost for reduced value resize (if required). - if (ReductionBitWidth != 0) { - assert(UserIgnoreList && "Expected reduction tree."); - const TreeEntry &E = *VectorizableTree.front().get(); - auto It = MinBWs.find(&E); - if (It != MinBWs.end() && It->second.first != ReductionBitWidth) { - unsigned SrcSize = It->second.first; - unsigned DstSize = ReductionBitWidth; - unsigned Opcode = Instruction::Trunc; - if (SrcSize < DstSize) - Opcode = It->second.second ? Instruction::SExt : Instruction::ZExt; - auto *SrcVecTy = - FixedVectorType::get(Builder.getIntNTy(SrcSize), E.getVectorFactor()); - auto *DstVecTy = - FixedVectorType::get(Builder.getIntNTy(DstSize), E.getVectorFactor()); - TTI::CastContextHint CCH = getCastContextHint(E); - InstructionCost CastCost; - switch (E.getOpcode()) { - case Instruction::SExt: - case Instruction::ZExt: - case Instruction::Trunc: { - const TreeEntry *OpTE = getOperandEntry(&E, 0); - CCH = getCastContextHint(*OpTE); - break; - } - default: - break; - } - CastCost += TTI->getCastInstrCost(Opcode, DstVecTy, SrcVecTy, CCH, - TTI::TCK_RecipThroughput); - Cost += CastCost; - LLVM_DEBUG(dbgs() << "SLP: Adding cost " << CastCost - << " for final resize for reduction from " << SrcVecTy - << " to " << DstVecTy << "\n"; - dbgs() << "SLP: Current total cost = " << Cost << "\n"); - } - } - #ifndef NDEBUG SmallString<256> Str; { @@ -10130,7 +10042,7 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry( continue; VTE = *It->getSecond().begin(); // Iterate through all vectorized nodes. - auto *MIt = find_if(It->getSecond(), [&](const TreeEntry *MTE) { + auto *MIt = find_if(It->getSecond(), [](const TreeEntry *MTE) { return MTE->State == TreeEntry::Vectorize; }); if (MIt == It->getSecond().end()) @@ -10141,6 +10053,11 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry( Instruction &LastBundleInst = getLastInstructionInBundle(VTE); if (&LastBundleInst == TEInsertPt || !CheckOrdering(&LastBundleInst)) continue; + auto It = MinBWs.find(VTE); + // If vectorize node is demoted - do not match. + if (It != MinBWs.end() && + It->second.first != DL->getTypeSizeInBits(V->getType())) + continue; VToTEs.insert(VTE); } if (VToTEs.empty()) @@ -10188,57 +10105,6 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry( return std::nullopt; } - // Filter out entries with larger bitwidth of elements. - Type *ScalarTy = VL.front()->getType(); - unsigned BitWidth = 0; - if (ScalarTy->isIntegerTy()) { - // Check if the used TEs supposed to be resized and choose the best - // candidates. - BitWidth = DL->getTypeStoreSize(ScalarTy); - if (TEUseEI.UserTE->getOpcode() != Instruction::Select || - TEUseEI.EdgeIdx != 0) { - auto UserIt = MinBWs.find(TEUseEI.UserTE); - if (UserIt != MinBWs.end()) - BitWidth = UserIt->second.second; - } - // Check if the used TEs supposed to be resized and choose the best - // candidates. - unsigned NodesBitWidth = 0; - auto CheckBitwidth = [&](const TreeEntry &TE) { - unsigned TEBitWidth = BitWidth; - auto UserIt = MinBWs.find(TEUseEI.UserTE); - if (UserIt != MinBWs.end()) - TEBitWidth = UserIt->second.second; - if (BitWidth <= TEBitWidth) { - if (NodesBitWidth == 0) - NodesBitWidth = TEBitWidth; - return NodesBitWidth == TEBitWidth; - } - return false; - }; - for (auto [Idx, Set] : enumerate(UsedTEs)) { - DenseSet ForRemoval; - for (const TreeEntry *TE : Set) { - if (!CheckBitwidth(*TE)) - ForRemoval.insert(TE); - } - // All elements must be removed - remove the whole container. - if (ForRemoval.size() == Set.size()) { - Set.clear(); - continue; - } - for (const TreeEntry *TE : ForRemoval) - Set.erase(TE); - } - for (auto *It = UsedTEs.begin(); It != UsedTEs.end();) { - if (It->empty()) { - UsedTEs.erase(It); - continue; - } - std::advance(It, 1); - } - } - unsigned VF = 0; if (UsedTEs.size() == 1) { // Keep the order to avoid non-determinism. @@ -13063,21 +12929,7 @@ Value *BoUpSLP::vectorizeTree( Builder.ClearInsertionPoint(); InstrElementSize.clear(); - const TreeEntry &RootTE = *VectorizableTree.front().get(); - Value *Vec = RootTE.VectorizedValue; - if (auto It = MinBWs.find(&RootTE); ReductionBitWidth != 0 && - It != MinBWs.end() && - ReductionBitWidth != It->second.first) { - IRBuilder<>::InsertPointGuard Guard(Builder); - Builder.SetInsertPoint(ReductionRoot->getParent(), - ReductionRoot->getIterator()); - Vec = Builder.CreateIntCast( - Vec, - VectorType::get(Builder.getIntNTy(ReductionBitWidth), - cast(Vec->getType())->getElementCount()), - It->second.second); - } - return Vec; + return VectorizableTree[0]->VectorizedValue; } void BoUpSLP::optimizeGatherSequence() { @@ -13897,48 +13749,23 @@ unsigned BoUpSLP::getVectorElementSize(Value *V) { // smaller type with a truncation. We collect the values that will be demoted // in ToDemote and additional roots that require investigating in Roots. bool BoUpSLP::collectValuesToDemote( - Value *V, bool IsProfitableToDemoteRoot, unsigned &BitWidth, - SmallVectorImpl &ToDemote, + Value *V, SmallVectorImpl &ToDemote, DenseMap> &DemotedConsts, - DenseSet &Visited, unsigned &MaxDepthLevel, - bool &IsProfitableToDemote) const { + SmallVectorImpl &Roots, DenseSet &Visited) const { // We can always demote constants. - if (isa(V)) { - MaxDepthLevel = 1; + if (isa(V)) return true; - } - - if (DL->getTypeSizeInBits(V->getType()) == BitWidth) { - MaxDepthLevel = 1; - return true; - } // If the value is not a vectorized instruction in the expression and not used // by the insertelement instruction and not used in multiple vector nodes, it // cannot be demoted. - // TODO: improve handling of gathered values and others. auto *I = dyn_cast(V); - const TreeEntry *ITE = I ? getTreeEntry(I) : nullptr; - if (!ITE || !Visited.insert(I).second || MultiNodeScalars.contains(I) || - all_of(I->users(), [&](User *U) { + if (!I || !getTreeEntry(I) || MultiNodeScalars.contains(I) || + !Visited.insert(I).second || all_of(I->users(), [&](User *U) { return isa(U) && !getTreeEntry(U); })) return false; - auto IsPotentiallyTruncated = [&](Value *V, unsigned &BitWidth) -> bool { - if (MultiNodeScalars.contains(V)) - return false; - uint32_t OrigBitWidth = DL->getTypeSizeInBits(V->getType()); - APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, BitWidth); - if (MaskedValueIsZero(V, Mask, SimplifyQuery(*DL))) - return true; - auto NumSignBits = ComputeNumSignBits(V, *DL, 0, AC, nullptr, DT); - unsigned BitWidth1 = OrigBitWidth - NumSignBits; - if (!isKnownNonNegative(V, SimplifyQuery(*DL))) - ++BitWidth1; - BitWidth = std::max(BitWidth, BitWidth1); - return BitWidth > 0 && OrigBitWidth >= (BitWidth * 2); - }; unsigned Start = 0; unsigned End = I->getNumOperands(); switch (I->getOpcode()) { @@ -13946,14 +13773,12 @@ bool BoUpSLP::collectValuesToDemote( // We can always demote truncations and extensions. Since truncations can // seed additional demotion, we save the truncated value. case Instruction::Trunc: - MaxDepthLevel = 1; - if (IsProfitableToDemoteRoot) - IsProfitableToDemote = true; + Roots.push_back(I->getOperand(0)); break; case Instruction::ZExt: case Instruction::SExt: - MaxDepthLevel = 1; - IsProfitableToDemote = true; + if (isa(I->getOperand(0))) + return false; break; // We can demote certain binary operations if we can demote both of their @@ -13963,36 +13788,23 @@ bool BoUpSLP::collectValuesToDemote( case Instruction::Mul: case Instruction::And: case Instruction::Or: - case Instruction::Xor: { - unsigned Level1, Level2; - if ((ITE->UserTreeIndices.size() > 1 && - !IsPotentiallyTruncated(I, BitWidth)) || - !collectValuesToDemote(I->getOperand(0), IsProfitableToDemoteRoot, - BitWidth, ToDemote, DemotedConsts, Visited, - Level1, IsProfitableToDemote) || - !collectValuesToDemote(I->getOperand(1), IsProfitableToDemoteRoot, - BitWidth, ToDemote, DemotedConsts, Visited, - Level2, IsProfitableToDemote)) + case Instruction::Xor: + if (!collectValuesToDemote(I->getOperand(0), ToDemote, DemotedConsts, Roots, + Visited) || + !collectValuesToDemote(I->getOperand(1), ToDemote, DemotedConsts, Roots, + Visited)) return false; - MaxDepthLevel = std::max(Level1, Level2); break; - } // We can demote selects if we can demote their true and false values. case Instruction::Select: { Start = 1; - unsigned Level1, Level2; SelectInst *SI = cast(I); - if ((ITE->UserTreeIndices.size() > 1 && - !IsPotentiallyTruncated(I, BitWidth)) || - !collectValuesToDemote(SI->getTrueValue(), IsProfitableToDemoteRoot, - BitWidth, ToDemote, DemotedConsts, Visited, - Level1, IsProfitableToDemote) || - !collectValuesToDemote(SI->getFalseValue(), IsProfitableToDemoteRoot, - BitWidth, ToDemote, DemotedConsts, Visited, - Level2, IsProfitableToDemote)) + if (!collectValuesToDemote(SI->getTrueValue(), ToDemote, DemotedConsts, + Roots, Visited) || + !collectValuesToDemote(SI->getFalseValue(), ToDemote, DemotedConsts, + Roots, Visited)) return false; - MaxDepthLevel = std::max(Level1, Level2); break; } @@ -14000,270 +13812,172 @@ bool BoUpSLP::collectValuesToDemote( // we don't need to worry about cycles since we ensure single use above. case Instruction::PHI: { PHINode *PN = cast(I); - MaxDepthLevel = 0; - if (ITE->UserTreeIndices.size() > 1 && !IsPotentiallyTruncated(I, BitWidth)) - return false; - for (Value *IncValue : PN->incoming_values()) { - unsigned Level; - if (!collectValuesToDemote(IncValue, IsProfitableToDemoteRoot, BitWidth, - ToDemote, DemotedConsts, Visited, Level, - IsProfitableToDemote)) + for (Value *IncValue : PN->incoming_values()) + if (!collectValuesToDemote(IncValue, ToDemote, DemotedConsts, Roots, + Visited)) return false; - MaxDepthLevel = std::max(MaxDepthLevel, Level); - } break; } // Otherwise, conservatively give up. default: - MaxDepthLevel = 1; - return IsProfitableToDemote && IsPotentiallyTruncated(I, BitWidth); + return false; } - ++MaxDepthLevel; // Gather demoted constant operands. for (unsigned Idx : seq(Start, End)) if (isa(I->getOperand(Idx))) DemotedConsts.try_emplace(I).first->getSecond().push_back(Idx); // Record the value that we can demote. ToDemote.push_back(V); - return IsProfitableToDemote; + return true; } void BoUpSLP::computeMinimumValueSizes() { // We only attempt to truncate integer expressions. - bool IsStoreOrInsertElt = - VectorizableTree.front()->getOpcode() == Instruction::Store || - VectorizableTree.front()->getOpcode() == Instruction::InsertElement; - if ((IsStoreOrInsertElt || UserIgnoreList) && TruncNodes.size() <= 1 && - (!CastMaxMinBWSizes || CastMaxMinBWSizes->second == 0 || - CastMaxMinBWSizes->first / CastMaxMinBWSizes->second <= 2)) + auto &TreeRoot = VectorizableTree[0]->Scalars; + auto *TreeRootIT = dyn_cast(TreeRoot[0]->getType()); + if (!TreeRootIT || VectorizableTree.front()->State == TreeEntry::NeedToGather) return; - unsigned NodeIdx = 0; - if (IsStoreOrInsertElt && - VectorizableTree.front()->State != TreeEntry::NeedToGather) - NodeIdx = 1; - // Ensure the roots of the vectorizable tree don't form a cycle. - if (VectorizableTree[NodeIdx]->State == TreeEntry::NeedToGather || - (NodeIdx == 0 && !VectorizableTree[NodeIdx]->UserTreeIndices.empty()) || - (NodeIdx != 0 && any_of(VectorizableTree[NodeIdx]->UserTreeIndices, - [NodeIdx](const EdgeInfo &EI) { - return EI.UserTE->Idx > - static_cast(NodeIdx); - }))) - return; - - // The first value node for store/insertelement is sext/zext/trunc? Skip it, - // resize to the final type. - bool IsProfitableToDemoteRoot = !IsStoreOrInsertElt; - if (NodeIdx != 0 && - VectorizableTree[NodeIdx]->State == TreeEntry::Vectorize && - (VectorizableTree[NodeIdx]->getOpcode() == Instruction::ZExt || - VectorizableTree[NodeIdx]->getOpcode() == Instruction::SExt || - VectorizableTree[NodeIdx]->getOpcode() == Instruction::Trunc)) { - assert(IsStoreOrInsertElt && "Expected store/insertelement seeded graph."); - ++NodeIdx; - IsProfitableToDemoteRoot = true; - } - - // Analyzed in reduction already and not profitable - exit. - if (AnalyzedMinBWVals.contains(VectorizableTree[NodeIdx]->Scalars.front())) + if (!VectorizableTree.front()->UserTreeIndices.empty()) return; - SmallVector ToDemote; + // Conservatively determine if we can actually truncate the roots of the + // expression. Collect the values that can be demoted in ToDemote and + // additional roots that require investigating in Roots. + SmallVector ToDemote; DenseMap> DemotedConsts; - auto ComputeMaxBitWidth = [&](ArrayRef TreeRoot, unsigned VF, - bool IsTopRoot, bool IsProfitableToDemoteRoot, - unsigned Opcode, unsigned Limit) { - ToDemote.clear(); - auto *TreeRootIT = dyn_cast(TreeRoot[0]->getType()); - if (!TreeRootIT || !Opcode) - return 0u; - - if (AnalyzedMinBWVals.contains(TreeRoot.front())) - return 0u; - - unsigned NumParts = TTI->getNumberOfParts( - FixedVectorType::get(TreeRoot.front()->getType(), VF)); - - // The maximum bit width required to represent all the values that can be - // demoted without loss of precision. It would be safe to truncate the roots - // of the expression to this width. - unsigned MaxBitWidth = 1u; - - // True if the roots can be zero-extended back to their original type, - // rather than sign-extended. We know that if the leading bits are not - // demanded, we can safely zero-extend. So we initialize IsKnownPositive to - // True. + SmallVector Roots; + for (auto *Root : TreeRoot) { + DenseSet Visited; + if (!collectValuesToDemote(Root, ToDemote, DemotedConsts, Roots, Visited)) + return; + } + + // The maximum bit width required to represent all the values that can be + // demoted without loss of precision. It would be safe to truncate the roots + // of the expression to this width. + auto MaxBitWidth = 1u; + + // We first check if all the bits of the roots are demanded. If they're not, + // we can truncate the roots to this narrower type. + for (auto *Root : TreeRoot) { + auto Mask = DB->getDemandedBits(cast(Root)); + MaxBitWidth = std::max(Mask.getBitWidth() - Mask.countl_zero(), + MaxBitWidth); + } + + // True if the roots can be zero-extended back to their original type, rather + // than sign-extended. We know that if the leading bits are not demanded, we + // can safely zero-extend. So we initialize IsKnownPositive to True. + bool IsKnownPositive = true; + + // If all the bits of the roots are demanded, we can try a little harder to + // compute a narrower type. This can happen, for example, if the roots are + // getelementptr indices. InstCombine promotes these indices to the pointer + // width. Thus, all their bits are technically demanded even though the + // address computation might be vectorized in a smaller type. + // + // We start by looking at each entry that can be demoted. We compute the + // maximum bit width required to store the scalar by using ValueTracking to + // compute the number of high-order bits we can truncate. + if (MaxBitWidth == DL->getTypeSizeInBits(TreeRoot[0]->getType()) && + all_of(TreeRoot, [](Value *V) { + return all_of(V->users(), + [](User *U) { return isa(U); }); + })) { + MaxBitWidth = 8u; + // Determine if the sign bit of all the roots is known to be zero. If not, // IsKnownPositive is set to False. - bool IsKnownPositive = all_of(TreeRoot, [&](Value *R) { + IsKnownPositive = llvm::all_of(TreeRoot, [&](Value *R) { KnownBits Known = computeKnownBits(R, *DL); return Known.isNonNegative(); }); - // We first check if all the bits of the roots are demanded. If they're not, - // we can truncate the roots to this narrower type. - for (auto *Root : TreeRoot) { - unsigned NumSignBits = ComputeNumSignBits(Root, *DL, 0, AC, nullptr, DT); - TypeSize NumTypeBits = DL->getTypeSizeInBits(Root->getType()); - unsigned BitWidth1 = NumTypeBits - NumSignBits; - // If we can't prove that the sign bit is zero, we must add one to the - // maximum bit width to account for the unknown sign bit. This preserves - // the existing sign bit so we can safely sign-extend the root back to the - // original type. Otherwise, if we know the sign bit is zero, we will - // zero-extend the root instead. - // - // FIXME: This is somewhat suboptimal, as there will be cases where adding - // one to the maximum bit width will yield a larger-than-necessary - // type. In general, we need to add an extra bit only if we can't - // prove that the upper bit of the original type is equal to the - // upper bit of the proposed smaller type. If these two bits are - // the same (either zero or one) we know that sign-extending from - // the smaller type will result in the same value. Here, since we - // can't yet prove this, we are just making the proposed smaller - // type larger to ensure correctness. - if (!IsKnownPositive) - ++BitWidth1; - - APInt Mask = DB->getDemandedBits(cast(Root)); - unsigned BitWidth2 = Mask.getBitWidth() - Mask.countl_zero(); - MaxBitWidth = - std::max(std::min(BitWidth1, BitWidth2), MaxBitWidth); - } - - if (MaxBitWidth < 8 && MaxBitWidth > 1) - MaxBitWidth = 8; - - // If the original type is large, but reduced type does not improve the reg - // use - ignore it. - if (NumParts > 1 && - NumParts == - TTI->getNumberOfParts(FixedVectorType::get( - IntegerType::get(F->getContext(), bit_ceil(MaxBitWidth)), VF))) - return 0u; - - bool IsProfitableToDemote = Opcode == Instruction::Trunc || - Opcode == Instruction::SExt || - Opcode == Instruction::ZExt || NumParts > 1; - // Conservatively determine if we can actually truncate the roots of the - // expression. Collect the values that can be demoted in ToDemote and - // additional roots that require investigating in Roots. - for (auto *Root : TreeRoot) { - DenseSet Visited; - unsigned MaxDepthLevel = 0; - bool NeedToDemote = IsProfitableToDemote; - - if (!collectValuesToDemote(Root, IsProfitableToDemoteRoot, MaxBitWidth, - ToDemote, DemotedConsts, Visited, - MaxDepthLevel, NeedToDemote) || - (MaxDepthLevel <= Limit && - !(((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) && - (!IsTopRoot || !(IsStoreOrInsertElt || UserIgnoreList) || - DL->getTypeSizeInBits(Root->getType()) / - DL->getTypeSizeInBits( - cast(Root)->getOperand(0)->getType()) > - 2)) || - (Opcode == Instruction::Trunc && - (!IsTopRoot || !(IsStoreOrInsertElt || UserIgnoreList) || - DL->getTypeSizeInBits( - cast(Root)->getOperand(0)->getType()) / - DL->getTypeSizeInBits(Root->getType()) > - 2))))) - return 0u; - } - // Round MaxBitWidth up to the next power-of-two. - MaxBitWidth = bit_ceil(MaxBitWidth); - - return MaxBitWidth; - }; + // Determine the maximum number of bits required to store the scalar + // values. + for (auto *Scalar : ToDemote) { + auto NumSignBits = ComputeNumSignBits(Scalar, *DL, 0, AC, nullptr, DT); + auto NumTypeBits = DL->getTypeSizeInBits(Scalar->getType()); + MaxBitWidth = std::max(NumTypeBits - NumSignBits, MaxBitWidth); + } + + // If we can't prove that the sign bit is zero, we must add one to the + // maximum bit width to account for the unknown sign bit. This preserves + // the existing sign bit so we can safely sign-extend the root back to the + // original type. Otherwise, if we know the sign bit is zero, we will + // zero-extend the root instead. + // + // FIXME: This is somewhat suboptimal, as there will be cases where adding + // one to the maximum bit width will yield a larger-than-necessary + // type. In general, we need to add an extra bit only if we can't + // prove that the upper bit of the original type is equal to the + // upper bit of the proposed smaller type. If these two bits are the + // same (either zero or one) we know that sign-extending from the + // smaller type will result in the same value. Here, since we can't + // yet prove this, we are just making the proposed smaller type + // larger to ensure correctness. + if (!IsKnownPositive) + ++MaxBitWidth; + } + + // Round MaxBitWidth up to the next power-of-two. + MaxBitWidth = llvm::bit_ceil(MaxBitWidth); + + // If the maximum bit width we compute is less than the with of the roots' + // type, we can proceed with the narrowing. Otherwise, do nothing. + if (MaxBitWidth >= TreeRootIT->getBitWidth()) + return; // If we can truncate the root, we must collect additional values that might // be demoted as a result. That is, those seeded by truncations we will // modify. - // Add reduction ops sizes, if any. - if (UserIgnoreList && - isa(VectorizableTree.front()->Scalars.front()->getType())) { - for (Value *V : *UserIgnoreList) { - auto NumSignBits = ComputeNumSignBits(V, *DL, 0, AC, nullptr, DT); - auto NumTypeBits = DL->getTypeSizeInBits(V->getType()); - unsigned BitWidth1 = NumTypeBits - NumSignBits; - if (!isKnownNonNegative(V, SimplifyQuery(*DL))) - ++BitWidth1; - auto Mask = DB->getDemandedBits(cast(V)); - unsigned BitWidth2 = Mask.getBitWidth() - Mask.countl_zero(); - ReductionBitWidth = - std::max(std::min(BitWidth1, BitWidth2), ReductionBitWidth); - } - if (ReductionBitWidth < 8 && ReductionBitWidth > 1) - ReductionBitWidth = 8; - - ReductionBitWidth = bit_ceil(ReductionBitWidth); - } - bool IsTopRoot = NodeIdx == 0; - while (NodeIdx < VectorizableTree.size() && - VectorizableTree[NodeIdx]->State == TreeEntry::Vectorize && - VectorizableTree[NodeIdx]->getOpcode() == Instruction::Trunc) - ++NodeIdx; - while (NodeIdx < VectorizableTree.size()) { - ArrayRef TreeRoot = VectorizableTree[NodeIdx]->Scalars; - unsigned Limit = 2; - unsigned Opcode = VectorizableTree[NodeIdx]->getOpcode(); - if (IsTopRoot && - ReductionBitWidth == - DL->getTypeSizeInBits( - VectorizableTree.front()->Scalars.front()->getType())) - Limit = 3; - unsigned MaxBitWidth = ComputeMaxBitWidth( - TreeRoot, VectorizableTree[NodeIdx]->getVectorFactor(), IsTopRoot, - IsProfitableToDemoteRoot, Opcode, Limit); - IsTopRoot = false; - IsProfitableToDemoteRoot = true; - - if (TruncNodes.empty()) { - NodeIdx = VectorizableTree.size(); - } else { - NodeIdx = *TruncNodes.begin() + 1; - TruncNodes.erase(TruncNodes.begin()); - } - - // If the maximum bit width we compute is less than the with of the roots' - // type, we can proceed with the narrowing. Otherwise, do nothing. - if (MaxBitWidth == 0 || - MaxBitWidth >= - cast(TreeRoot.front()->getType())->getBitWidth()) { - if (UserIgnoreList) - AnalyzedMinBWVals.insert(TreeRoot.begin(), TreeRoot.end()); + while (!Roots.empty()) { + DenseSet Visited; + collectValuesToDemote(Roots.pop_back_val(), ToDemote, DemotedConsts, Roots, + Visited); + } + + // Check that all users are marked for demotion. + DenseSet Demoted(ToDemote.begin(), ToDemote.end()); + DenseSet Visited; + for (Value *V: ToDemote) { + const TreeEntry *TE = getTreeEntry(V); + assert(TE && "Expected vectorized scalar."); + if (!Visited.insert(TE).second) continue; - } - - // Finally, map the values we can demote to the maximum bit with we - // computed. - for (Value *Scalar : ToDemote) { - TreeEntry *TE = getTreeEntry(Scalar); - assert(TE && "Expected vectorized scalar."); - if (MinBWs.contains(TE)) - continue; - bool IsSigned = any_of(TE->Scalars, [&](Value *R) { - return !isKnownNonNegative(R, SimplifyQuery(*DL)); - }); - MinBWs.try_emplace(TE, MaxBitWidth, IsSigned); - const auto *I = cast(Scalar); - auto DCIt = DemotedConsts.find(I); - if (DCIt != DemotedConsts.end()) { - for (unsigned Idx : DCIt->getSecond()) { - // Check that all instructions operands are demoted. + if (!all_of(TE->UserTreeIndices, [&](const EdgeInfo &EI) { + return all_of(EI.UserTE->Scalars, + [&](Value *V) { return Demoted.contains(V); }); + })) + return; + } + // Finally, map the values we can demote to the maximum bit with we computed. + for (auto *Scalar : ToDemote) { + auto *TE = getTreeEntry(Scalar); + assert(TE && "Expected vectorized scalar."); + if (MinBWs.contains(TE)) + continue; + bool IsSigned = any_of(TE->Scalars, [&](Value *R) { + KnownBits Known = computeKnownBits(R, *DL); + return !Known.isNonNegative(); + }); + MinBWs.try_emplace(TE, MaxBitWidth, IsSigned); + const auto *I = cast(Scalar); + auto DCIt = DemotedConsts.find(I); + if (DCIt != DemotedConsts.end()) { + for (unsigned Idx : DCIt->getSecond()) { + // Check that all instructions operands are demoted. + if (all_of(TE->Scalars, [&](Value *V) { + auto SIt = DemotedConsts.find(cast(V)); + return SIt != DemotedConsts.end() && + is_contained(SIt->getSecond(), Idx); + })) { const TreeEntry *CTE = getOperandEntry(TE, Idx); - if (all_of(TE->Scalars, - [&](Value *V) { - auto SIt = DemotedConsts.find(cast(V)); - return SIt != DemotedConsts.end() && - is_contained(SIt->getSecond(), Idx); - }) || - all_of(CTE->Scalars, Constant::classof)) - MinBWs.try_emplace(CTE, MaxBitWidth, IsSigned); + MinBWs.try_emplace(CTE, MaxBitWidth, IsSigned); } } } diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/ext-trunc.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/ext-trunc.ll index 5e3fd156666f..cef791633655 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/ext-trunc.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/ext-trunc.ll @@ -17,13 +17,12 @@ define void @test1(<4 x i16> %a, <4 x i16> %b, ptr %p) { ; CHECK-NEXT: [[GEP0:%.*]] = getelementptr inbounds i64, ptr [[P:%.*]], i64 [[S0]] ; CHECK-NEXT: [[LOAD0:%.*]] = load i64, ptr [[GEP0]], align 4 ; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <4 x i32> [[SUB0]], <4 x i32> poison, <2 x i32> -; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x i32> [[TMP0]], i32 0 -; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64 +; CHECK-NEXT: [[TMP1:%.*]] = sext <2 x i32> [[TMP0]] to <2 x i64> +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x i64> [[TMP1]], i32 0 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i64, ptr [[P]], i64 [[TMP2]] ; CHECK-NEXT: [[LOAD1:%.*]] = load i64, ptr [[GEP1]], align 4 -; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x i32> [[TMP0]], i32 1 -; CHECK-NEXT: [[TMP4:%.*]] = sext i32 [[TMP3]] to i64 -; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i64, ptr [[P]], i64 [[TMP4]] +; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x i64> [[TMP1]], i32 1 +; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i64, ptr [[P]], i64 [[TMP3]] ; CHECK-NEXT: [[LOAD2:%.*]] = load i64, ptr [[GEP2]], align 4 ; CHECK-NEXT: [[E3:%.*]] = extractelement <4 x i32> [[SUB0]], i32 3 ; CHECK-NEXT: [[S3:%.*]] = sext i32 [[E3]] to i64 diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr2.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr2.ll index 1cce52060c47..47485e514ec2 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr2.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr2.ll @@ -1,8 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ;test_i16_extend NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -mtriple=aarch64--linux-gnu -passes=slp-vectorizer,dce,instcombine -slp-threshold=-5 -pass-remarks-output=%t < %s | FileCheck %s +; RUN: opt -S -mtriple=aarch64--linux-gnu -passes=slp-vectorizer,dce,instcombine -slp-threshold=-7 -pass-remarks-output=%t < %s | FileCheck %s ; RUN: cat %t | FileCheck -check-prefix=YAML %s -; RUN: opt -S -mtriple=aarch64--linux-gnu -passes='slp-vectorizer,dce,instcombine' -slp-threshold=-5 -pass-remarks-output=%t < %s | FileCheck %s +; RUN: opt -S -mtriple=aarch64--linux-gnu -passes='slp-vectorizer,dce,instcombine' -slp-threshold=-7 -pass-remarks-output=%t < %s | FileCheck %s ; RUN: cat %t | FileCheck -check-prefix=YAML %s diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-i64.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-i64.ll index a7a7f642ced5..d67fdc1cd6aa 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-i64.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-i64.ll @@ -28,11 +28,21 @@ entry: define i64 @red_zext_ld_4xi64(ptr %ptr) { ; CHECK-LABEL: @red_zext_ld_4xi64( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i8>, ptr [[PTR:%.*]], align 1 -; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i16> -; CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> [[TMP1]]) -; CHECK-NEXT: [[TMP3:%.*]] = zext i16 [[TMP2]] to i64 -; CHECK-NEXT: ret i64 [[TMP3]] +; CHECK-NEXT: [[LD0:%.*]] = load i8, ptr [[PTR:%.*]], align 1 +; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[LD0]] to i64 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 1 +; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[GEP]], align 1 +; CHECK-NEXT: [[ZEXT_1:%.*]] = zext i8 [[LD1]] to i64 +; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i64 [[ZEXT]], [[ZEXT_1]] +; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 2 +; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[GEP_1]], align 1 +; CHECK-NEXT: [[ZEXT_2:%.*]] = zext i8 [[LD2]] to i64 +; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i64 [[ADD_1]], [[ZEXT_2]] +; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 3 +; CHECK-NEXT: [[LD3:%.*]] = load i8, ptr [[GEP_2]], align 1 +; CHECK-NEXT: [[ZEXT_3:%.*]] = zext i8 [[LD3]] to i64 +; CHECK-NEXT: [[ADD_3:%.*]] = add nuw nsw i64 [[ADD_2]], [[ZEXT_3]] +; CHECK-NEXT: ret i64 [[ADD_3]] ; entry: %ld0 = load i8, ptr %ptr diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/reductions.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/reductions.ll index 500f10659f04..000e7a56df37 100644 --- a/llvm/test/Transforms/SLPVectorizer/RISCV/reductions.ll +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/reductions.ll @@ -802,10 +802,9 @@ define i64 @red_zext_ld_4xi64(ptr %ptr) { ; CHECK-LABEL: @red_zext_ld_4xi64( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i8>, ptr [[PTR:%.*]], align 1 -; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i16> -; CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> [[TMP1]]) -; CHECK-NEXT: [[TMP3:%.*]] = zext i16 [[TMP2]] to i64 -; CHECK-NEXT: ret i64 [[TMP3]] +; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i64> +; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vector.reduce.add.v4i64(<4 x i64> [[TMP1]]) +; CHECK-NEXT: ret i64 [[TMP2]] ; entry: %ld0 = load i8, ptr %ptr diff --git a/llvm/test/Transforms/SLPVectorizer/X86/PR35777.ll b/llvm/test/Transforms/SLPVectorizer/X86/PR35777.ll index 05511f843a68..4565d4928ba4 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/PR35777.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/PR35777.ll @@ -15,12 +15,11 @@ define { i64, i64 } @patatino(double %arg) { ; CHECK-NEXT: [[TMP6:%.*]] = load <2 x double>, ptr getelementptr inbounds ([6 x double], ptr @global, i64 0, i64 4), align 16 ; CHECK-NEXT: [[TMP7:%.*]] = fadd <2 x double> [[TMP6]], [[TMP5]] ; CHECK-NEXT: [[TMP8:%.*]] = fptosi <2 x double> [[TMP7]] to <2 x i32> -; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x i32> [[TMP8]], i32 0 -; CHECK-NEXT: [[TMP10:%.*]] = sext i32 [[TMP9]] to i64 +; CHECK-NEXT: [[TMP9:%.*]] = sext <2 x i32> [[TMP8]] to <2 x i64> +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i64> [[TMP9]], i32 0 ; CHECK-NEXT: [[T16:%.*]] = insertvalue { i64, i64 } undef, i64 [[TMP10]], 0 -; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i32> [[TMP8]], i32 1 -; CHECK-NEXT: [[TMP12:%.*]] = sext i32 [[TMP11]] to i64 -; CHECK-NEXT: [[T17:%.*]] = insertvalue { i64, i64 } [[T16]], i64 [[TMP12]], 1 +; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i64> [[TMP9]], i32 1 +; CHECK-NEXT: [[T17:%.*]] = insertvalue { i64, i64 } [[T16]], i64 [[TMP11]], 1 ; CHECK-NEXT: ret { i64, i64 } [[T17]] ; bb: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/int-bitcast-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/int-bitcast-minbitwidth.ll index 5ee801607653..a0af8e36b36c 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/int-bitcast-minbitwidth.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/int-bitcast-minbitwidth.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 -; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -slp-threshold=-6 < %s | FileCheck %s +; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -slp-threshold=-3 < %s | FileCheck %s define void @t(i64 %v) { ; CHECK-LABEL: define void @t( diff --git a/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-multiuse-with-insertelement.ll b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-multiuse-with-insertelement.ll index 6051638562b5..6e512fcbb739 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-multiuse-with-insertelement.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-multiuse-with-insertelement.ll @@ -6,17 +6,18 @@ define void @test(i8 %0) { ; CHECK-SAME: i8 [[TMP0:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> , i8 [[TMP0]], i32 1 -; CHECK-NEXT: [[TMP2:%.*]] = sext <2 x i8> [[TMP1]] to <2 x i32> -; CHECK-NEXT: [[TMP3:%.*]] = mul <2 x i8> [[TMP1]], zeroinitializer -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x i8> [[TMP3]], i32 0 -; CHECK-NEXT: [[TMP5:%.*]] = zext i8 [[TMP4]] to i32 -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i8> [[TMP3]], i32 1 -; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 -; CHECK-NEXT: [[ADD:%.*]] = or i32 [[TMP5]], [[TMP7]] +; CHECK-NEXT: [[TMP2:%.*]] = sext <2 x i8> [[TMP1]] to <2 x i16> +; CHECK-NEXT: [[TMP3:%.*]] = sext <2 x i16> [[TMP2]] to <2 x i32> +; CHECK-NEXT: [[TMP4:%.*]] = mul <2 x i16> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i16> [[TMP4]], i32 0 +; CHECK-NEXT: [[TMP6:%.*]] = zext i16 [[TMP5]] to i32 +; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x i16> [[TMP4]], i32 1 +; CHECK-NEXT: [[TMP8:%.*]] = zext i16 [[TMP7]] to i32 +; CHECK-NEXT: [[ADD:%.*]] = or i32 [[TMP6]], [[TMP8]] ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[ADD]], 1 ; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SHR]] to i8 ; CHECK-NEXT: store i8 [[CONV9]], ptr null, align 1 -; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <2 x i32> [[TMP2]], <2 x i32> poison, <8 x i32> +; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <2 x i32> [[TMP3]], <2 x i32> poison, <8 x i32> ; CHECK-NEXT: ret void ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-transformed-operand.ll b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-transformed-operand.ll index 4acd63078b82..2c834616becc 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-transformed-operand.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-transformed-operand.ll @@ -6,20 +6,15 @@ define void @test(i64 %d.promoted.i) { ; CHECK-SAME: i64 [[D_PROMOTED_I:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[AND_1_I:%.*]] = and i64 0, [[D_PROMOTED_I]] -; CHECK-NEXT: [[TMP0:%.*]] = insertelement <8 x i64> , i64 [[AND_1_I]], i32 1 -; CHECK-NEXT: [[TMP1:%.*]] = trunc <8 x i64> [[TMP0]] to <8 x i1> -; CHECK-NEXT: [[TMP2:%.*]] = mul <8 x i1> [[TMP1]], zeroinitializer ; CHECK-NEXT: [[AND_1_I_1:%.*]] = and i64 0, 0 -; CHECK-NEXT: [[TMP3:%.*]] = insertelement <8 x i64> , i64 [[AND_1_I_1]], i32 1 -; CHECK-NEXT: [[TMP4:%.*]] = trunc <8 x i64> [[TMP3]] to <8 x i1> -; CHECK-NEXT: [[TMP5:%.*]] = mul <8 x i1> [[TMP4]], zeroinitializer -; CHECK-NEXT: [[TMP6:%.*]] = call i1 @llvm.vector.reduce.or.v8i1(<8 x i1> [[TMP5]]) -; CHECK-NEXT: [[TMP7:%.*]] = zext i1 [[TMP6]] to i32 -; CHECK-NEXT: [[TMP8:%.*]] = call i1 @llvm.vector.reduce.or.v8i1(<8 x i1> [[TMP2]]) -; CHECK-NEXT: [[TMP9:%.*]] = zext i1 [[TMP8]] to i32 -; CHECK-NEXT: [[OP_RDX:%.*]] = or i32 [[TMP7]], [[TMP9]] -; CHECK-NEXT: [[TMP10:%.*]] = and i32 [[OP_RDX]], 0 -; CHECK-NEXT: store i32 [[TMP10]], ptr null, align 4 +; CHECK-NEXT: [[TMP0:%.*]] = insertelement <16 x i64> , i64 [[AND_1_I_1]], i32 1 +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <16 x i64> [[TMP0]], i64 [[AND_1_I]], i32 9 +; CHECK-NEXT: [[TMP2:%.*]] = trunc <16 x i64> [[TMP1]] to <16 x i1> +; CHECK-NEXT: [[TMP3:%.*]] = mul <16 x i1> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = call i1 @llvm.vector.reduce.or.v16i1(<16 x i1> [[TMP3]]) +; CHECK-NEXT: [[TMP5:%.*]] = zext i1 [[TMP4]] to i32 +; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP5]], 0 +; CHECK-NEXT: store i32 [[TMP6]], ptr null, align 4 ; CHECK-NEXT: ret void ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/minimum-sizes.ll b/llvm/test/Transforms/SLPVectorizer/X86/minimum-sizes.ll index a316415dcc6b..651631de2c35 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/minimum-sizes.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/minimum-sizes.ll @@ -17,15 +17,12 @@ target triple = "x86_64-unknown-linux-gnu" define i8 @PR31243_zext(i8 %v0, i8 %v1, i8 %v2, i8 %v3, ptr %ptr) { ; SSE-LABEL: @PR31243_zext( ; SSE-NEXT: entry: -; SSE-NEXT: [[TMP0:%.*]] = insertelement <2 x i8> poison, i8 [[V0:%.*]], i64 0 -; SSE-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> [[TMP0]], i8 [[V1:%.*]], i64 1 -; SSE-NEXT: [[TMP2:%.*]] = or <2 x i8> [[TMP1]], -; SSE-NEXT: [[TMP3:%.*]] = extractelement <2 x i8> [[TMP2]], i64 0 -; SSE-NEXT: [[TMP4:%.*]] = zext i8 [[TMP3]] to i64 -; SSE-NEXT: [[T4:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[TMP4]] -; SSE-NEXT: [[TMP5:%.*]] = extractelement <2 x i8> [[TMP2]], i64 1 -; SSE-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i64 -; SSE-NEXT: [[T5:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[TMP6]] +; SSE-NEXT: [[TMP0:%.*]] = or i8 [[V0:%.*]], 1 +; SSE-NEXT: [[TMP1:%.*]] = or i8 [[V1:%.*]], 1 +; SSE-NEXT: [[TMP2:%.*]] = zext i8 [[TMP0]] to i64 +; SSE-NEXT: [[T4:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[TMP2]] +; SSE-NEXT: [[TMP3:%.*]] = zext i8 [[TMP1]] to i64 +; SSE-NEXT: [[T5:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[TMP3]] ; SSE-NEXT: [[T6:%.*]] = load i8, ptr [[T4]], align 1 ; SSE-NEXT: [[T7:%.*]] = load i8, ptr [[T5]], align 1 ; SSE-NEXT: [[T8:%.*]] = add i8 [[T6]], [[T7]] @@ -76,15 +73,12 @@ entry: define i8 @PR31243_sext(i8 %v0, i8 %v1, i8 %v2, i8 %v3, ptr %ptr) { ; SSE-LABEL: @PR31243_sext( ; SSE-NEXT: entry: -; SSE-NEXT: [[TMP0:%.*]] = insertelement <2 x i8> poison, i8 [[V0:%.*]], i64 0 -; SSE-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> [[TMP0]], i8 [[V1:%.*]], i64 1 -; SSE-NEXT: [[TMP2:%.*]] = or <2 x i8> [[TMP1]], -; SSE-NEXT: [[TMP3:%.*]] = extractelement <2 x i8> [[TMP2]], i64 0 -; SSE-NEXT: [[TMP4:%.*]] = sext i8 [[TMP3]] to i64 -; SSE-NEXT: [[T4:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[TMP4]] -; SSE-NEXT: [[TMP5:%.*]] = extractelement <2 x i8> [[TMP2]], i64 1 -; SSE-NEXT: [[TMP6:%.*]] = sext i8 [[TMP5]] to i64 -; SSE-NEXT: [[T5:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[TMP6]] +; SSE-NEXT: [[TMP0:%.*]] = or i8 [[V0:%.*]], 1 +; SSE-NEXT: [[TMP1:%.*]] = or i8 [[V1:%.*]], 1 +; SSE-NEXT: [[TMP2:%.*]] = sext i8 [[TMP0]] to i64 +; SSE-NEXT: [[T4:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[TMP2]] +; SSE-NEXT: [[TMP3:%.*]] = sext i8 [[TMP1]] to i64 +; SSE-NEXT: [[T5:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[TMP3]] ; SSE-NEXT: [[T6:%.*]] = load i8, ptr [[T4]], align 1 ; SSE-NEXT: [[T7:%.*]] = load i8, ptr [[T5]], align 1 ; SSE-NEXT: [[T8:%.*]] = add i8 [[T6]], [[T7]] @@ -95,12 +89,13 @@ define i8 @PR31243_sext(i8 %v0, i8 %v1, i8 %v2, i8 %v3, ptr %ptr) { ; AVX-NEXT: [[TMP0:%.*]] = insertelement <2 x i8> poison, i8 [[V0:%.*]], i64 0 ; AVX-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> [[TMP0]], i8 [[V1:%.*]], i64 1 ; AVX-NEXT: [[TMP2:%.*]] = or <2 x i8> [[TMP1]], -; AVX-NEXT: [[TMP3:%.*]] = extractelement <2 x i8> [[TMP2]], i64 0 -; AVX-NEXT: [[TMP4:%.*]] = sext i8 [[TMP3]] to i64 -; AVX-NEXT: [[T4:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[TMP4]] -; AVX-NEXT: [[TMP5:%.*]] = extractelement <2 x i8> [[TMP2]], i64 1 -; AVX-NEXT: [[TMP6:%.*]] = sext i8 [[TMP5]] to i64 -; AVX-NEXT: [[T5:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[TMP6]] +; AVX-NEXT: [[TMP3:%.*]] = sext <2 x i8> [[TMP2]] to <2 x i16> +; AVX-NEXT: [[TMP4:%.*]] = extractelement <2 x i16> [[TMP3]], i64 0 +; AVX-NEXT: [[TMP5:%.*]] = sext i16 [[TMP4]] to i64 +; AVX-NEXT: [[T4:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[TMP5]] +; AVX-NEXT: [[TMP6:%.*]] = extractelement <2 x i16> [[TMP3]], i64 1 +; AVX-NEXT: [[TMP7:%.*]] = sext i16 [[TMP6]] to i64 +; AVX-NEXT: [[T5:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[TMP7]] ; AVX-NEXT: [[T6:%.*]] = load i8, ptr [[T4]], align 1 ; AVX-NEXT: [[T7:%.*]] = load i8, ptr [[T5]], align 1 ; AVX-NEXT: [[T8:%.*]] = add i8 [[T6]], [[T7]] diff --git a/llvm/test/Transforms/SLPVectorizer/X86/phi-undef-input.ll b/llvm/test/Transforms/SLPVectorizer/X86/phi-undef-input.ll index 3cc32c1fc7b2..88f75c37846e 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/phi-undef-input.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/phi-undef-input.ll @@ -15,8 +15,8 @@ define i32 @phi3UndefInput(i1 %cond, i8 %arg0, i8 %arg1, i8 %arg2, i8 %arg3) { ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP4:%.*]] = phi <4 x i8> [ [[TMP3]], [[BB2]] ], [ , [[ENTRY:%.*]] ] -; CHECK-NEXT: [[TMP5:%.*]] = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> [[TMP4]]) -; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 +; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i8> [[TMP4]] to <4 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP5]]) ; CHECK-NEXT: ret i32 [[TMP6]] ; entry: @@ -52,8 +52,8 @@ define i32 @phi2UndefInput(i1 %cond, i8 %arg0, i8 %arg1, i8 %arg2, i8 %arg3) { ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP4:%.*]] = phi <4 x i8> [ [[TMP3]], [[BB2]] ], [ , [[ENTRY:%.*]] ] -; CHECK-NEXT: [[TMP5:%.*]] = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> [[TMP4]]) -; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 +; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i8> [[TMP4]] to <4 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP5]]) ; CHECK-NEXT: ret i32 [[TMP6]] ; entry: @@ -89,8 +89,8 @@ define i32 @phi1UndefInput(i1 %cond, i8 %arg0, i8 %arg1, i8 %arg2, i8 %arg3) { ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP4:%.*]] = phi <4 x i8> [ [[TMP3]], [[BB2]] ], [ , [[ENTRY:%.*]] ] -; CHECK-NEXT: [[TMP5:%.*]] = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> [[TMP4]]) -; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 +; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i8> [[TMP4]] to <4 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP5]]) ; CHECK-NEXT: ret i32 [[TMP6]] ; entry: @@ -127,8 +127,8 @@ define i32 @phi1Undef1PoisonInput(i1 %cond, i8 %arg0, i8 %arg1, i8 %arg2, i8 %ar ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP4:%.*]] = phi <4 x i8> [ [[TMP3]], [[BB2]] ], [ , [[ENTRY:%.*]] ] -; CHECK-NEXT: [[TMP5:%.*]] = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> [[TMP4]]) -; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 +; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i8> [[TMP4]] to <4 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP5]]) ; CHECK-NEXT: ret i32 [[TMP6]] ; entry: @@ -165,8 +165,8 @@ define i32 @phi1Undef2PoisonInputs(i1 %cond, i8 %arg0, i8 %arg1, i8 %arg2, i8 %a ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP4:%.*]] = phi <4 x i8> [ [[TMP3]], [[BB2]] ], [ , [[ENTRY:%.*]] ] -; CHECK-NEXT: [[TMP5:%.*]] = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> [[TMP4]]) -; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 +; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i8> [[TMP4]] to <4 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP5]]) ; CHECK-NEXT: ret i32 [[TMP6]] ; entry: @@ -202,8 +202,8 @@ define i32 @phi1Undef1PoisonGapInput(i1 %cond, i8 %arg0, i8 %arg1, i8 %arg2, i8 ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP4:%.*]] = phi <4 x i8> [ [[TMP3]], [[BB2]] ], [ , [[ENTRY:%.*]] ] -; CHECK-NEXT: [[TMP5:%.*]] = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> [[TMP4]]) -; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 +; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i8> [[TMP4]] to <4 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP5]]) ; CHECK-NEXT: ret i32 [[TMP6]] ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/resched.ll b/llvm/test/Transforms/SLPVectorizer/X86/resched.ll index b7237cbb02bb..78c6d9516a3d 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/resched.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/resched.ll @@ -11,26 +11,26 @@ define fastcc void @_ZN12_GLOBAL__N_127PolynomialMultiplyRecognize9recognizeEv() ; CHECK: if.then22.i: ; CHECK-NEXT: [[SUB_I:%.*]] = add nsw i32 undef, -1 ; CHECK-NEXT: [[CONV31_I:%.*]] = and i32 undef, [[SUB_I]] -; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x i32> poison, i32 [[CONV31_I]], i32 0 -; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[TMP0]], <4 x i32> poison, <4 x i32> zeroinitializer -; CHECK-NEXT: [[TMP2:%.*]] = lshr <4 x i32> [[TMP1]], +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i32> poison, i32 [[CONV31_I]], i32 0 +; CHECK-NEXT: [[SHUFFLE1:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = lshr <4 x i32> [[SHUFFLE1]], ; CHECK-NEXT: [[SHR_4_I_I:%.*]] = lshr i32 [[CONV31_I]], 5 ; CHECK-NEXT: [[SHR_5_I_I:%.*]] = lshr i32 [[CONV31_I]], 6 ; CHECK-NEXT: [[SHR_6_I_I:%.*]] = lshr i32 [[CONV31_I]], 7 ; CHECK-NEXT: [[TMP3:%.*]] = insertelement <8 x i32> poison, i32 [[CONV31_I]], i32 0 -; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <8 x i32> [[TMP3]], <8 x i32> poison, <8 x i32> zeroinitializer -; CHECK-NEXT: [[TMP5:%.*]] = lshr <8 x i32> [[TMP4]], -; CHECK-NEXT: [[TMP6:%.*]] = insertelement <16 x i32> poison, i32 [[SUB_I]], i32 0 -; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <4 x i32> [[TMP2]], <4 x i32> poison, <16 x i32> -; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <16 x i32> [[TMP6]], <16 x i32> [[TMP7]], <16 x i32> -; CHECK-NEXT: [[TMP9:%.*]] = insertelement <16 x i32> [[TMP8]], i32 [[SHR_4_I_I]], i32 5 -; CHECK-NEXT: [[TMP10:%.*]] = insertelement <16 x i32> [[TMP9]], i32 [[SHR_5_I_I]], i32 6 -; CHECK-NEXT: [[TMP11:%.*]] = insertelement <16 x i32> [[TMP10]], i32 [[SHR_6_I_I]], i32 7 -; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <8 x i32> [[TMP5]], <8 x i32> poison, <16 x i32> -; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <16 x i32> [[TMP11]], <16 x i32> [[TMP12]], <16 x i32> -; CHECK-NEXT: [[TMP14:%.*]] = trunc <16 x i32> [[TMP13]] to <16 x i8> -; CHECK-NEXT: [[TMP15:%.*]] = and <16 x i8> [[TMP14]], -; CHECK-NEXT: store <16 x i8> [[TMP15]], ptr undef, align 1 +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <8 x i32> [[TMP3]], <8 x i32> poison, <8 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = lshr <8 x i32> [[SHUFFLE]], +; CHECK-NEXT: [[TMP5:%.*]] = insertelement <16 x i32> poison, i32 [[SUB_I]], i32 0 +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <4 x i32> [[TMP2]], <4 x i32> poison, <16 x i32> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <16 x i32> [[TMP5]], <16 x i32> [[TMP6]], <16 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = insertelement <16 x i32> [[TMP7]], i32 [[SHR_4_I_I]], i32 5 +; CHECK-NEXT: [[TMP9:%.*]] = insertelement <16 x i32> [[TMP8]], i32 [[SHR_5_I_I]], i32 6 +; CHECK-NEXT: [[TMP10:%.*]] = insertelement <16 x i32> [[TMP9]], i32 [[SHR_6_I_I]], i32 7 +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <8 x i32> [[TMP4]], <8 x i32> poison, <16 x i32> +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <16 x i32> [[TMP10]], <16 x i32> [[TMP11]], <16 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = trunc <16 x i32> [[TMP12]] to <16 x i8> +; CHECK-NEXT: [[TMP14:%.*]] = and <16 x i8> [[TMP13]], +; CHECK-NEXT: store <16 x i8> [[TMP14]], ptr undef, align 1 ; CHECK-NEXT: unreachable ; CHECK: if.end50.i: ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/SLPVectorizer/X86/reused-reductions-with-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/reused-reductions-with-minbitwidth.ll index 1d1fcec2a7ae..5d22b5a4873b 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/reused-reductions-with-minbitwidth.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/reused-reductions-with-minbitwidth.ll @@ -7,10 +7,12 @@ define i1 @test(i1 %cmp5.not.31) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x i1> , i1 [[CMP5_NOT_31]], i32 0 ; CHECK-NEXT: [[TMP1:%.*]] = select <4 x i1> [[TMP0]], <4 x i32> zeroinitializer, <4 x i32> zeroinitializer -; CHECK-NEXT: [[TMP2:%.*]] = mul <4 x i32> [[TMP1]], -; CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[TMP2]]) -; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP3]], 0 -; CHECK-NEXT: [[CMP_NOT_I_I:%.*]] = icmp eq i32 [[TMP4]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = trunc <4 x i32> [[TMP1]] to <4 x i1> +; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i1> [[TMP2]] to <4 x i32> +; CHECK-NEXT: [[TMP4:%.*]] = mul <4 x i32> [[TMP3]], +; CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[TMP4]]) +; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP5]], 0 +; CHECK-NEXT: [[CMP_NOT_I_I:%.*]] = icmp eq i32 [[TMP6]], 0 ; CHECK-NEXT: ret i1 [[CMP_NOT_I_I]] ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/store-insertelement-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/store-insertelement-minbitwidth.ll index 2f6868d8dfd6..c1dd90d0e9a7 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/store-insertelement-minbitwidth.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/store-insertelement-minbitwidth.ll @@ -8,18 +8,17 @@ ; YAML-NEXT: Function: stores ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'Stores SLP vectorized with cost ' -; YAML-NEXT: - Cost: '-7' +; YAML-NEXT: - Cost: '-3' ; YAML-NEXT: - String: ' and with tree size ' ; YAML-NEXT: - TreeSize: '6' define void @stores(ptr noalias %in, ptr noalias %inn, ptr noalias %out) { ; CHECK-LABEL: @stores( ; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i8>, ptr [[IN:%.*]], align 1 ; CHECK-NEXT: [[TMP2:%.*]] = load <4 x i8>, ptr [[INN:%.*]], align 1 -; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i16> -; CHECK-NEXT: [[TMP4:%.*]] = zext <4 x i8> [[TMP2]] to <4 x i16> -; CHECK-NEXT: [[TMP5:%.*]] = add <4 x i16> [[TMP3]], [[TMP4]] -; CHECK-NEXT: [[TMP6:%.*]] = zext <4 x i16> [[TMP5]] to <4 x i64> -; CHECK-NEXT: store <4 x i64> [[TMP6]], ptr [[OUT:%.*]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i64> +; CHECK-NEXT: [[TMP4:%.*]] = zext <4 x i8> [[TMP2]] to <4 x i64> +; CHECK-NEXT: [[TMP5:%.*]] = add <4 x i64> [[TMP3]], [[TMP4]] +; CHECK-NEXT: store <4 x i64> [[TMP5]], ptr [[OUT:%.*]], align 4 ; CHECK-NEXT: ret void ; %load.1 = load i8, ptr %in, align 1 @@ -64,18 +63,17 @@ define void @stores(ptr noalias %in, ptr noalias %inn, ptr noalias %out) { ; YAML-NEXT: Function: insertelems ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'SLP vectorized with cost ' -; YAML-NEXT: - Cost: '-9' +; YAML-NEXT: - Cost: '-5' ; YAML-NEXT: - String: ' and with tree size ' ; YAML-NEXT: - TreeSize: '6' define <4 x i64> @insertelems(ptr noalias %in, ptr noalias %inn) { ; CHECK-LABEL: @insertelems( ; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i8>, ptr [[IN:%.*]], align 1 ; CHECK-NEXT: [[TMP2:%.*]] = load <4 x i8>, ptr [[INN:%.*]], align 1 -; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i16> -; CHECK-NEXT: [[TMP4:%.*]] = zext <4 x i8> [[TMP2]] to <4 x i16> -; CHECK-NEXT: [[TMP5:%.*]] = add <4 x i16> [[TMP3]], [[TMP4]] -; CHECK-NEXT: [[TMP6:%.*]] = zext <4 x i16> [[TMP5]] to <4 x i64> -; CHECK-NEXT: ret <4 x i64> [[TMP6]] +; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i64> +; CHECK-NEXT: [[TMP4:%.*]] = zext <4 x i8> [[TMP2]] to <4 x i64> +; CHECK-NEXT: [[TMP5:%.*]] = add <4 x i64> [[TMP3]], [[TMP4]] +; CHECK-NEXT: ret <4 x i64> [[TMP5]] ; %load.1 = load i8, ptr %in, align 1 %gep.1 = getelementptr inbounds i8, ptr %in, i64 1 diff --git a/llvm/test/Transforms/SLPVectorizer/alt-cmp-vectorize.ll b/llvm/test/Transforms/SLPVectorizer/alt-cmp-vectorize.ll index ff6f0bdd3db8..061fbdb45a13 100644 --- a/llvm/test/Transforms/SLPVectorizer/alt-cmp-vectorize.ll +++ b/llvm/test/Transforms/SLPVectorizer/alt-cmp-vectorize.ll @@ -10,8 +10,8 @@ define i32 @alt_cmp(i16 %call46) { ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult <4 x i16> [[TMP0]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = icmp ugt <4 x i16> [[TMP0]], [[TMP1]] ; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <4 x i1> [[TMP2]], <4 x i1> [[TMP3]], <4 x i32> -; CHECK-NEXT: [[TMP5:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP4]]) -; CHECK-NEXT: [[TMP6:%.*]] = zext i1 [[TMP5]] to i16 +; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i1> [[TMP4]] to <4 x i16> +; CHECK-NEXT: [[TMP6:%.*]] = call i16 @llvm.vector.reduce.or.v4i16(<4 x i16> [[TMP5]]) ; CHECK-NEXT: [[OP_RDX:%.*]] = or i16 [[TMP6]], 0 ; CHECK-NEXT: [[EXT:%.*]] = zext i16 [[OP_RDX]] to i32 ; CHECK-NEXT: ret i32 [[EXT]] -- GitLab From 83fe0b13824bc419092bad47727aa1c8ca69330a Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Sat, 9 Mar 2024 20:26:10 +0800 Subject: [PATCH 018/953] [clang] Fix -Wunused-lambda-capture in TokenAnnotator.cpp (NFC) llvm-project/clang/lib/Format/TokenAnnotator.cpp:2707:43: error: lambda capture 'this' is not used [-Werror,-Wunused-lambda-capture] auto IsQualifiedPointerOrReference = [this](FormatToken *T) { ^~~~ 1 error generated. --- clang/lib/Format/TokenAnnotator.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 3a5510661200..d7b84e309e09 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2707,6 +2707,7 @@ private: auto IsQualifiedPointerOrReference = [this](FormatToken *T) { // This is used to handle cases such as x = (foo *const)&y; assert(!T->isTypeName(IsCpp) && "Should have already been checked"); + (void)IsCpp; // Avoid -Wunused-lambda-capture when assertion is disabled. // Strip trailing qualifiers such as const or volatile when checking // whether the parens could be a cast to a pointer/reference type. while (T) { -- GitLab From 124d0b787b5d1ff4aa06bbd61a98d3fc344d0cc6 Mon Sep 17 00:00:00 2001 From: "Yaxun (Sam) Liu" Date: Sat, 9 Mar 2024 09:45:48 -0500 Subject: [PATCH 019/953] [HIP] add --offload-compression-level= option (#83605) Added --offload-compression-level= option to clang and -compression-level= option to clang-offload-bundler for controlling compression level. Added support of long distance matching (LDM) for llvm::zstd which is off by default. Enable it for clang-offload-bundler by default since it improves compression rate in general. Change default compression level to 3 for zstd for clang-offload-bundler since it works well for bundle entry size from 1KB to 32MB, which should cover most of the clang-offload-bundler usage. Users can still specify compression level by -compression-level= option if necessary. --- clang/include/clang/Driver/OffloadBundler.h | 6 +- clang/include/clang/Driver/Options.td | 4 + clang/lib/Driver/OffloadBundler.cpp | 111 ++++++++++++++---- clang/lib/Driver/ToolChains/Clang.cpp | 11 +- clang/lib/Driver/ToolChains/CommonArgs.cpp | 12 ++ clang/lib/Driver/ToolChains/CommonArgs.h | 2 + clang/lib/Driver/ToolChains/HIPUtility.cpp | 7 +- .../test/Driver/clang-offload-bundler-zlib.c | 21 +++- .../test/Driver/clang-offload-bundler-zstd.c | 19 ++- .../test/Driver/hip-offload-compress-zlib.hip | 7 +- .../test/Driver/hip-offload-compress-zstd.hip | 5 +- clang/test/Driver/linker-wrapper.c | 5 +- .../ClangLinkerWrapper.cpp | 3 + .../clang-linker-wrapper/LinkerWrapperOpts.td | 2 + .../ClangOffloadBundler.cpp | 5 + llvm/include/llvm/Support/Compression.h | 5 +- llvm/lib/Support/Compression.cpp | 43 +++++-- 17 files changed, 204 insertions(+), 64 deletions(-) diff --git a/clang/include/clang/Driver/OffloadBundler.h b/clang/include/clang/Driver/OffloadBundler.h index 84349abe185f..65d33bfbd282 100644 --- a/clang/include/clang/Driver/OffloadBundler.h +++ b/clang/include/clang/Driver/OffloadBundler.h @@ -17,6 +17,7 @@ #ifndef LLVM_CLANG_DRIVER_OFFLOADBUNDLER_H #define LLVM_CLANG_DRIVER_OFFLOADBUNDLER_H +#include "llvm/Support/Compression.h" #include "llvm/Support/Error.h" #include "llvm/TargetParser/Triple.h" #include @@ -36,6 +37,8 @@ public: bool HipOpenmpCompatible = false; bool Compress = false; bool Verbose = false; + llvm::compression::Format CompressionFormat; + int CompressionLevel; unsigned BundleAlignment = 1; unsigned HostInputIndex = ~0u; @@ -116,7 +119,8 @@ private: public: static llvm::Expected> - compress(const llvm::MemoryBuffer &Input, bool Verbose = false); + compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input, + bool Verbose = false); static llvm::Expected> decompress(const llvm::MemoryBuffer &Input, bool Verbose = false); }; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index d5eed152d150..aca8c9b0d548 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1264,6 +1264,10 @@ def fno_gpu_sanitize : Flag<["-"], "fno-gpu-sanitize">, Group; def offload_compress : Flag<["--"], "offload-compress">, HelpText<"Compress offload device binaries (HIP only)">; def no_offload_compress : Flag<["--"], "no-offload-compress">; + +def offload_compression_level_EQ : Joined<["--"], "offload-compression-level=">, + Flags<[HelpHidden]>, + HelpText<"Compression level for offload device binaries (HIP only)">; } // CUDA options diff --git a/clang/lib/Driver/OffloadBundler.cpp b/clang/lib/Driver/OffloadBundler.cpp index f9eadfaec88d..77c89356bc76 100644 --- a/clang/lib/Driver/OffloadBundler.cpp +++ b/clang/lib/Driver/OffloadBundler.cpp @@ -924,6 +924,17 @@ CreateFileHandler(MemoryBuffer &FirstInput, } OffloadBundlerConfig::OffloadBundlerConfig() { + if (llvm::compression::zstd::isAvailable()) { + CompressionFormat = llvm::compression::Format::Zstd; + // Compression level 3 is usually sufficient for zstd since long distance + // matching is enabled. + CompressionLevel = 3; + } else if (llvm::compression::zlib::isAvailable()) { + CompressionFormat = llvm::compression::Format::Zlib; + // Use default level for zlib since higher level does not have significant + // improvement. + CompressionLevel = llvm::compression::zlib::DefaultCompression; + } auto IgnoreEnvVarOpt = llvm::sys::Process::GetEnv("OFFLOAD_BUNDLER_IGNORE_ENV_VAR"); if (IgnoreEnvVarOpt.has_value() && IgnoreEnvVarOpt.value() == "1") @@ -937,11 +948,41 @@ OffloadBundlerConfig::OffloadBundlerConfig() { llvm::sys::Process::GetEnv("OFFLOAD_BUNDLER_COMPRESS"); if (CompressEnvVarOpt.has_value()) Compress = CompressEnvVarOpt.value() == "1"; + + auto CompressionLevelEnvVarOpt = + llvm::sys::Process::GetEnv("OFFLOAD_BUNDLER_COMPRESSION_LEVEL"); + if (CompressionLevelEnvVarOpt.has_value()) { + llvm::StringRef CompressionLevelStr = CompressionLevelEnvVarOpt.value(); + int Level; + if (!CompressionLevelStr.getAsInteger(10, Level)) + CompressionLevel = Level; + else + llvm::errs() + << "Warning: Invalid value for OFFLOAD_BUNDLER_COMPRESSION_LEVEL: " + << CompressionLevelStr.str() << ". Ignoring it.\n"; + } +} + +// Utility function to format numbers with commas +static std::string formatWithCommas(unsigned long long Value) { + std::string Num = std::to_string(Value); + int InsertPosition = Num.length() - 3; + while (InsertPosition > 0) { + Num.insert(InsertPosition, ","); + InsertPosition -= 3; + } + return Num; } llvm::Expected> -CompressedOffloadBundle::compress(const llvm::MemoryBuffer &Input, +CompressedOffloadBundle::compress(llvm::compression::Params P, + const llvm::MemoryBuffer &Input, bool Verbose) { + if (!llvm::compression::zstd::isAvailable() && + !llvm::compression::zlib::isAvailable()) + return createStringError(llvm::inconvertibleErrorCode(), + "Compression not supported"); + llvm::Timer HashTimer("Hash Calculation Timer", "Hash calculation time", ClangOffloadBundlerTimerGroup); if (Verbose) @@ -959,25 +1000,15 @@ CompressedOffloadBundle::compress(const llvm::MemoryBuffer &Input, reinterpret_cast(Input.getBuffer().data()), Input.getBuffer().size()); - llvm::compression::Format CompressionFormat; - - if (llvm::compression::zstd::isAvailable()) - CompressionFormat = llvm::compression::Format::Zstd; - else if (llvm::compression::zlib::isAvailable()) - CompressionFormat = llvm::compression::Format::Zlib; - else - return createStringError(llvm::inconvertibleErrorCode(), - "Compression not supported"); - llvm::Timer CompressTimer("Compression Timer", "Compression time", ClangOffloadBundlerTimerGroup); if (Verbose) CompressTimer.startTimer(); - llvm::compression::compress(CompressionFormat, BufferUint8, CompressedBuffer); + llvm::compression::compress(P, BufferUint8, CompressedBuffer); if (Verbose) CompressTimer.stopTimer(); - uint16_t CompressionMethod = static_cast(CompressionFormat); + uint16_t CompressionMethod = static_cast(P.format); uint32_t UncompressedSize = Input.getBuffer().size(); SmallVector FinalBuffer; @@ -995,17 +1026,29 @@ CompressedOffloadBundle::compress(const llvm::MemoryBuffer &Input, if (Verbose) { auto MethodUsed = - CompressionFormat == llvm::compression::Format::Zstd ? "zstd" : "zlib"; + P.format == llvm::compression::Format::Zstd ? "zstd" : "zlib"; + double CompressionRate = + static_cast(UncompressedSize) / CompressedBuffer.size(); + double CompressionTimeSeconds = CompressTimer.getTotalTime().getWallTime(); + double CompressionSpeedMBs = + (UncompressedSize / (1024.0 * 1024.0)) / CompressionTimeSeconds; + llvm::errs() << "Compressed bundle format version: " << Version << "\n" << "Compression method used: " << MethodUsed << "\n" - << "Binary size before compression: " << UncompressedSize - << " bytes\n" - << "Binary size after compression: " << CompressedBuffer.size() - << " bytes\n" + << "Compression level: " << P.level << "\n" + << "Binary size before compression: " + << formatWithCommas(UncompressedSize) << " bytes\n" + << "Binary size after compression: " + << formatWithCommas(CompressedBuffer.size()) << " bytes\n" + << "Compression rate: " + << llvm::format("%.2lf", CompressionRate) << "\n" + << "Compression ratio: " + << llvm::format("%.2lf%%", 100.0 / CompressionRate) << "\n" + << "Compression speed: " + << llvm::format("%.2lf MB/s", CompressionSpeedMBs) << "\n" << "Truncated MD5 hash: " << llvm::format_hex(TruncatedHash, 16) << "\n"; } - return llvm::MemoryBuffer::getMemBufferCopy( llvm::StringRef(FinalBuffer.data(), FinalBuffer.size())); } @@ -1070,7 +1113,10 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input, if (Verbose) { DecompressTimer.stopTimer(); - // Recalculate MD5 hash + double DecompressionTimeSeconds = + DecompressTimer.getTotalTime().getWallTime(); + + // Recalculate MD5 hash for integrity check llvm::Timer HashRecalcTimer("Hash Recalculation Timer", "Hash recalculation time", ClangOffloadBundlerTimerGroup); @@ -1084,16 +1130,27 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input, HashRecalcTimer.stopTimer(); bool HashMatch = (StoredHash == RecalculatedHash); + double CompressionRate = + static_cast(UncompressedSize) / CompressedData.size(); + double DecompressionSpeedMBs = + (UncompressedSize / (1024.0 * 1024.0)) / DecompressionTimeSeconds; + llvm::errs() << "Compressed bundle format version: " << ThisVersion << "\n" << "Decompression method: " << (CompressionFormat == llvm::compression::Format::Zlib ? "zlib" : "zstd") << "\n" - << "Size before decompression: " << CompressedData.size() - << " bytes\n" - << "Size after decompression: " << UncompressedSize - << " bytes\n" + << "Size before decompression: " + << formatWithCommas(CompressedData.size()) << " bytes\n" + << "Size after decompression: " + << formatWithCommas(UncompressedSize) << " bytes\n" + << "Compression rate: " + << llvm::format("%.2lf", CompressionRate) << "\n" + << "Compression ratio: " + << llvm::format("%.2lf%%", 100.0 / CompressionRate) << "\n" + << "Decompression speed: " + << llvm::format("%.2lf MB/s", DecompressionSpeedMBs) << "\n" << "Stored hash: " << llvm::format_hex(StoredHash, 16) << "\n" << "Recalculated hash: " << llvm::format_hex(RecalculatedHash, 16) << "\n" @@ -1287,8 +1344,10 @@ Error OffloadBundler::BundleFiles() { std::unique_ptr BufferMemory = llvm::MemoryBuffer::getMemBufferCopy( llvm::StringRef(Buffer.data(), Buffer.size())); - auto CompressionResult = - CompressedOffloadBundle::compress(*BufferMemory, BundlerConfig.Verbose); + auto CompressionResult = CompressedOffloadBundle::compress( + {BundlerConfig.CompressionFormat, BundlerConfig.CompressionLevel, + /*zstdEnableLdm=*/true}, + *BufferMemory, BundlerConfig.Verbose); if (auto Error = CompressionResult.takeError()) return Error; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 678e24eae883..cc568b9a715b 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -8529,7 +8529,6 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, } // Begin OffloadBundler - void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -8627,11 +8626,7 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA, } CmdArgs.push_back(TCArgs.MakeArgString(UB)); } - if (TCArgs.hasFlag(options::OPT_offload_compress, - options::OPT_no_offload_compress, false)) - CmdArgs.push_back("-compress"); - if (TCArgs.hasArg(options::OPT_v)) - CmdArgs.push_back("-verbose"); + addOffloadCompressArgs(TCArgs, CmdArgs); // All the inputs are encoded as commands. C.addCommand(std::make_unique( JA, *this, ResponseFileSupport::None(), @@ -8900,9 +8895,7 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, for (const char *LinkArg : LinkCommand->getArguments()) CmdArgs.push_back(LinkArg); - if (Args.hasFlag(options::OPT_offload_compress, - options::OPT_no_offload_compress, false)) - CmdArgs.push_back("--compress"); + addOffloadCompressArgs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("clang-linker-wrapper")); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 7f0f78b41e79..100e71245394 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -2863,3 +2863,15 @@ void tools::addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC, CmdArgs.push_back("+outline-atomics"); } } + +void tools::addOffloadCompressArgs(const llvm::opt::ArgList &TCArgs, + llvm::opt::ArgStringList &CmdArgs) { + if (TCArgs.hasFlag(options::OPT_offload_compress, + options::OPT_no_offload_compress, false)) + CmdArgs.push_back("-compress"); + if (TCArgs.hasArg(options::OPT_v)) + CmdArgs.push_back("-verbose"); + if (auto *Arg = TCArgs.getLastArg(options::OPT_offload_compression_level_EQ)) + CmdArgs.push_back( + TCArgs.MakeArgString(Twine("-compression-level=") + Arg->getValue())); +} diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index b8f649aab4bd..bb37be4bd6ea 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -221,6 +221,8 @@ void addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const llvm::Triple &Triple); +void addOffloadCompressArgs(const llvm::opt::ArgList &TCArgs, + llvm::opt::ArgStringList &CmdArgs); } // end namespace tools } // end namespace driver diff --git a/clang/lib/Driver/ToolChains/HIPUtility.cpp b/clang/lib/Driver/ToolChains/HIPUtility.cpp index fcecf2e1313b..08c647dfcb6f 100644 --- a/clang/lib/Driver/ToolChains/HIPUtility.cpp +++ b/clang/lib/Driver/ToolChains/HIPUtility.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "HIPUtility.h" +#include "Clang.h" #include "CommonArgs.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Options.h" @@ -258,11 +259,7 @@ void HIP::constructHIPFatbinCommand(Compilation &C, const JobAction &JA, Args.MakeArgString(std::string("-output=").append(Output)); BundlerArgs.push_back(BundlerOutputArg); - if (Args.hasFlag(options::OPT_offload_compress, - options::OPT_no_offload_compress, false)) - BundlerArgs.push_back("-compress"); - if (Args.hasArg(options::OPT_v)) - BundlerArgs.push_back("-verbose"); + addOffloadCompressArgs(Args, BundlerArgs); const char *Bundler = Args.MakeArgString( T.getToolChain().GetProgramPath("clang-offload-bundler")); diff --git a/clang/test/Driver/clang-offload-bundler-zlib.c b/clang/test/Driver/clang-offload-bundler-zlib.c index a57ee6da9a86..15b60341a8db 100644 --- a/clang/test/Driver/clang-offload-bundler-zlib.c +++ b/clang/test/Driver/clang-offload-bundler-zlib.c @@ -1,4 +1,4 @@ -// REQUIRES: zlib +// REQUIRES: zlib && !zstd // REQUIRES: x86-registered-target // UNSUPPORTED: target={{.*}}-darwin{{.*}}, target={{.*}}-aix{{.*}} @@ -34,13 +34,28 @@ // RUN: diff %t.tgt2 %t.res.tgt2 // -// COMPRESS: Compression method used: -// DECOMPRESS: Decompression method: +// COMPRESS: Compression method used: zlib +// COMPRESS: Compression level: 6 +// DECOMPRESS: Decompression method: zlib +// DECOMPRESS: Hashes match: Yes // NOHOST-NOT: host- // NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx900 // NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx906 // +// Check -compression-level= option + +// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ +// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip.bundle.bc -compress -verbose -compression-level=9 2>&1 | \ +// RUN: FileCheck -check-prefix=LEVEL %s +// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ +// RUN: -output=%t.res.tgt1 -output=%t.res.tgt2 -input=%t.hip.bundle.bc -unbundle +// RUN: diff %t.tgt1 %t.res.tgt1 +// RUN: diff %t.tgt2 %t.res.tgt2 +// +// LEVEL: Compression method used: zlib +// LEVEL: Compression level: 9 + // // Check -bundle-align option. // diff --git a/clang/test/Driver/clang-offload-bundler-zstd.c b/clang/test/Driver/clang-offload-bundler-zstd.c index 3b577d4d166a..c1eb3f6e7ebd 100644 --- a/clang/test/Driver/clang-offload-bundler-zstd.c +++ b/clang/test/Driver/clang-offload-bundler-zstd.c @@ -31,13 +31,28 @@ // RUN: diff %t.tgt1 %t.res.tgt1 // RUN: diff %t.tgt2 %t.res.tgt2 // -// COMPRESS: Compression method used -// DECOMPRESS: Decompression method +// COMPRESS: Compression method used: zstd +// COMPRESS: Compression level: 20 +// DECOMPRESS: Decompression method: zstd +// DECOMPRESS: Hashes match: Yes // NOHOST-NOT: host- // NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx900 // NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx906 // +// Check -compression-level= option + +// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ +// RUN: -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip.bundle.bc -compress -verbose -compression-level=9 2>&1 | \ +// RUN: FileCheck -check-prefix=LEVEL %s +// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \ +// RUN: -output=%t.res.tgt1 -output=%t.res.tgt2 -input=%t.hip.bundle.bc -unbundle +// RUN: diff %t.tgt1 %t.res.tgt1 +// RUN: diff %t.tgt2 %t.res.tgt2 +// +// LEVEL: Compression method used: zstd +// LEVEL: Compression level: 9 + // // Check -bundle-align option. // diff --git a/clang/test/Driver/hip-offload-compress-zlib.hip b/clang/test/Driver/hip-offload-compress-zlib.hip index 7a269c566bb9..c1566c5f192c 100644 --- a/clang/test/Driver/hip-offload-compress-zlib.hip +++ b/clang/test/Driver/hip-offload-compress-zlib.hip @@ -1,4 +1,4 @@ -// REQUIRES: zlib +// REQUIRES: zlib && !zstd // REQUIRES: x86-registered-target // REQUIRES: amdgpu-registered-target @@ -9,13 +9,14 @@ // RUN: -x hip --offload-arch=gfx1100 --offload-arch=gfx1101 \ // RUN: --no-offload-new-driver -fgpu-rdc -nogpuinc -nogpulib \ // RUN: %S/Inputs/hip_multiple_inputs/a.cu \ -// RUN: --offload-compress --offload-device-only --gpu-bundle-output \ +// RUN: --offload-compress --offload-compression-level=9 \ +// RUN: --offload-device-only --gpu-bundle-output \ // RUN: -o %t.bc \ // RUN: 2>&1 | FileCheck %s // CHECK: clang-offload-bundler{{.*}} -type=bc // CHECK-SAME: -targets={{.*}}hip-amdgcn-amd-amdhsa-gfx1100,hip-amdgcn-amd-amdhsa-gfx1101 -// CHECK-SAME: -compress -verbose +// CHECK-SAME: -compress -verbose -compression-level=9 // CHECK: Compressed bundle format // Test uncompress of bundled bitcode. diff --git a/clang/test/Driver/hip-offload-compress-zstd.hip b/clang/test/Driver/hip-offload-compress-zstd.hip index fa7fb3b6d5b5..ede7d59f113c 100644 --- a/clang/test/Driver/hip-offload-compress-zstd.hip +++ b/clang/test/Driver/hip-offload-compress-zstd.hip @@ -9,13 +9,14 @@ // RUN: -x hip --offload-arch=gfx1100 --offload-arch=gfx1101 \ // RUN: --no-offload-new-driver -fgpu-rdc -nogpuinc -nogpulib \ // RUN: %S/Inputs/hip_multiple_inputs/a.cu \ -// RUN: --offload-compress --offload-device-only --gpu-bundle-output \ +// RUN: --offload-compress --offload-compression-level=9 \ +// RUN: --offload-device-only --gpu-bundle-output \ // RUN: -o %t.bc \ // RUN: 2>&1 | FileCheck %s // CHECK: clang-offload-bundler{{.*}} -type=bc // CHECK-SAME: -targets={{.*}}hip-amdgcn-amd-amdhsa-gfx1100,hip-amdgcn-amd-amdhsa-gfx1101 -// CHECK-SAME: -compress -verbose +// CHECK-SAME: -compress -verbose -compression-level=9 // CHECK: Compressed bundle format // Test uncompress of bundled bitcode. diff --git a/clang/test/Driver/linker-wrapper.c b/clang/test/Driver/linker-wrapper.c index 0e6fd80b4298..cbf24d4ce3a8 100644 --- a/clang/test/Driver/linker-wrapper.c +++ b/clang/test/Driver/linker-wrapper.c @@ -114,12 +114,13 @@ __attribute__((visibility("protected"), used)) int x; // RUN: --image=file=%t.elf.o,kind=hip,triple=amdgcn-amd-amdhsa,arch=gfx908 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o \ // RUN: -fembed-offload-object=%t.out -// RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu --compress \ +// RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu \ +// RUN: --compress --compression-level=6 \ // RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=HIP // HIP: clang{{.*}} -o [[IMG_GFX908:.+]] --target=amdgcn-amd-amdhsa -mcpu=gfx908 // HIP: clang{{.*}} -o [[IMG_GFX90A:.+]] --target=amdgcn-amd-amdhsa -mcpu=gfx90a -// HIP: clang-offload-bundler{{.*}}-type=o -bundle-align=4096 -compress -targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx90a,hipv4-amdgcn-amd-amdhsa--gfx908 -input=/dev/null -input=[[IMG_GFX90A]] -input=[[IMG_GFX908]] -output={{.*}}.hipfb +// HIP: clang-offload-bundler{{.*}}-type=o -bundle-align=4096 -compress -compression-level=6 -targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx90a,hipv4-amdgcn-amd-amdhsa--gfx908 -input=/dev/null -input=[[IMG_GFX90A]] -input=[[IMG_GFX908]] -output={{.*}}.hipfb // RUN: clang-offload-packager -o %t.out \ // RUN: --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx908 \ diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 7e6e289c50d8..535ef42c78c4 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -407,6 +407,9 @@ fatbinary(ArrayRef> InputFiles, if (Args.hasArg(OPT_compress)) CmdArgs.push_back("-compress"); + if (auto *Arg = Args.getLastArg(OPT_compression_level_eq)) + CmdArgs.push_back( + Args.MakeArgString(Twine("-compression-level=") + Arg->getValue())); SmallVector Targets = {"-targets=host-x86_64-unknown-linux"}; for (const auto &[File, Arch] : InputFiles) diff --git a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td index 473fb19d9223..0a8bd541c452 100644 --- a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td +++ b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td @@ -60,6 +60,8 @@ def save_temps : Flag<["--"], "save-temps">, Flags<[WrapperOnlyOption]>, HelpText<"Save intermediate results">; def compress : Flag<["--"], "compress">, Flags<[WrapperOnlyOption]>, HelpText<"Compress bundled files">; +def compression_level_eq : Joined<["--"], "compression-level=">, + Flags<[WrapperOnlyOption]>, HelpText<"Specify the compression level (integer)">; def wrapper_time_trace_eq : Joined<["--"], "wrapper-time-trace=">, Flags<[WrapperOnlyOption]>, MetaVarName<"">, diff --git a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp index ec67e24552e9..e336417586f7 100644 --- a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp +++ b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp @@ -145,6 +145,9 @@ int main(int argc, const char **argv) { cl::init(false), cl::cat(ClangOffloadBundlerCategory)); cl::opt Verbose("verbose", cl::desc("Print debug information.\n"), cl::init(false), cl::cat(ClangOffloadBundlerCategory)); + cl::opt CompressionLevel( + "compression-level", cl::desc("Specify the compression level (integer)"), + cl::value_desc("n"), cl::Optional, cl::cat(ClangOffloadBundlerCategory)); // Process commandline options and report errors sys::PrintStackTraceOnErrorSignal(argv[0]); @@ -178,6 +181,8 @@ int main(int argc, const char **argv) { BundlerConfig.Compress = Compress; if (Verbose.getNumOccurrences() > 0) BundlerConfig.Verbose = Verbose; + if (CompressionLevel.getNumOccurrences() > 0) + BundlerConfig.CompressionLevel = CompressionLevel; BundlerConfig.TargetNames = TargetNames; BundlerConfig.InputFileNames = InputFileNames; diff --git a/llvm/include/llvm/Support/Compression.h b/llvm/include/llvm/Support/Compression.h index c3ba3274d6ed..2a8da9e96d35 100644 --- a/llvm/include/llvm/Support/Compression.h +++ b/llvm/include/llvm/Support/Compression.h @@ -63,7 +63,7 @@ bool isAvailable(); void compress(ArrayRef Input, SmallVectorImpl &CompressedBuffer, - int Level = DefaultCompression); + int Level = DefaultCompression, bool EnableLdm = false); Error decompress(ArrayRef Input, uint8_t *Output, size_t &UncompressedSize); @@ -94,10 +94,13 @@ struct Params { constexpr Params(Format F) : format(F), level(F == Format::Zlib ? zlib::DefaultCompression : zstd::DefaultCompression) {} + constexpr Params(Format F, int L, bool Ldm = false) + : format(F), level(L), zstdEnableLdm(Ldm) {} Params(DebugCompressionType Type) : Params(formatFor(Type)) {} Format format; int level; + bool zstdEnableLdm = false; // Enable zstd long distance matching // This may support multi-threading for zstd in the future. Note that // different threads may produce different output, so be careful if certain // output determinism is desired. diff --git a/llvm/lib/Support/Compression.cpp b/llvm/lib/Support/Compression.cpp index 8e57ba798f52..badaf68ab59c 100644 --- a/llvm/lib/Support/Compression.cpp +++ b/llvm/lib/Support/Compression.cpp @@ -50,7 +50,7 @@ void compression::compress(Params P, ArrayRef Input, zlib::compress(Input, Output, P.level); break; case compression::Format::Zstd: - zstd::compress(Input, Output, P.level); + zstd::compress(Input, Output, P.level, P.zstdEnableLdm); break; } } @@ -163,17 +163,39 @@ Error zlib::decompress(ArrayRef Input, bool zstd::isAvailable() { return true; } +#include // Ensure ZSTD library is included + void zstd::compress(ArrayRef Input, - SmallVectorImpl &CompressedBuffer, int Level) { - unsigned long CompressedBufferSize = ::ZSTD_compressBound(Input.size()); + SmallVectorImpl &CompressedBuffer, int Level, + bool EnableLdm) { + ZSTD_CCtx *Cctx = ZSTD_createCCtx(); + if (!Cctx) + report_bad_alloc_error("Failed to create ZSTD_CCtx"); + + if (ZSTD_isError(ZSTD_CCtx_setParameter( + Cctx, ZSTD_c_enableLongDistanceMatching, EnableLdm ? 1 : 0))) { + ZSTD_freeCCtx(Cctx); + report_bad_alloc_error("Failed to set ZSTD_c_enableLongDistanceMatching"); + } + + if (ZSTD_isError( + ZSTD_CCtx_setParameter(Cctx, ZSTD_c_compressionLevel, Level))) { + ZSTD_freeCCtx(Cctx); + report_bad_alloc_error("Failed to set ZSTD_c_compressionLevel"); + } + + unsigned long CompressedBufferSize = ZSTD_compressBound(Input.size()); CompressedBuffer.resize_for_overwrite(CompressedBufferSize); - unsigned long CompressedSize = - ::ZSTD_compress((char *)CompressedBuffer.data(), CompressedBufferSize, - (const char *)Input.data(), Input.size(), Level); + + size_t const CompressedSize = + ZSTD_compress2(Cctx, CompressedBuffer.data(), CompressedBufferSize, + Input.data(), Input.size()); + + ZSTD_freeCCtx(Cctx); + if (ZSTD_isError(CompressedSize)) - report_bad_alloc_error("Allocation failed"); - // Tell MemorySanitizer that zstd output buffer is fully initialized. - // This avoids a false report when running LLVM with uninstrumented ZLib. + report_bad_alloc_error("Compression failed"); + __msan_unpoison(CompressedBuffer.data(), CompressedSize); if (CompressedSize < CompressedBuffer.size()) CompressedBuffer.truncate(CompressedSize); @@ -205,7 +227,8 @@ Error zstd::decompress(ArrayRef Input, #else bool zstd::isAvailable() { return false; } void zstd::compress(ArrayRef Input, - SmallVectorImpl &CompressedBuffer, int Level) { + SmallVectorImpl &CompressedBuffer, int Level, + bool EnableLdm) { llvm_unreachable("zstd::compress is unavailable"); } Error zstd::decompress(ArrayRef Input, uint8_t *Output, -- GitLab From e733d7e23f6553c55c85edd55511b133d2064677 Mon Sep 17 00:00:00 2001 From: "Yaxun (Sam) Liu" Date: Sat, 9 Mar 2024 10:07:38 -0500 Subject: [PATCH 020/953] Fix test clang-offload-bundler-zstd.c --- clang/test/Driver/clang-offload-bundler-zstd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/Driver/clang-offload-bundler-zstd.c b/clang/test/Driver/clang-offload-bundler-zstd.c index c1eb3f6e7ebd..4485e57309bb 100644 --- a/clang/test/Driver/clang-offload-bundler-zstd.c +++ b/clang/test/Driver/clang-offload-bundler-zstd.c @@ -32,7 +32,7 @@ // RUN: diff %t.tgt2 %t.res.tgt2 // // COMPRESS: Compression method used: zstd -// COMPRESS: Compression level: 20 +// COMPRESS: Compression level: 3 // DECOMPRESS: Decompression method: zstd // DECOMPRESS: Hashes match: Yes // NOHOST-NOT: host- -- GitLab From 4fdf10faf2b45f4bbbd2ddfb07272d19a47cc531 Mon Sep 17 00:00:00 2001 From: Congcong Cai Date: Sat, 9 Mar 2024 23:08:51 +0800 Subject: [PATCH 021/953] [clang-tidy]avoid bugprone-unused-return-value false positive for assignment operator overloading (#84489) --- .../bugprone/UnusedReturnValueCheck.cpp | 33 +++++++++++++------ clang-tools-extra/docs/ReleaseNotes.rst | 4 +-- .../checks/bugprone/unused-return-value.rst | 2 ++ .../unused-return-value-avoid-assignment.cpp | 30 +++++++++++++++++ 4 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp index 1252b2f23805..243fe47c2036 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp @@ -11,6 +11,8 @@ #include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Basic/OperatorKinds.h" using namespace clang::ast_matchers; using namespace clang::ast_matchers::internal; @@ -28,6 +30,11 @@ AST_MATCHER_P(FunctionDecl, isInstantiatedFrom, Matcher, return InnerMatcher.matches(InstantiatedFrom ? *InstantiatedFrom : Node, Finder, Builder); } + +AST_MATCHER_P(CXXMethodDecl, isOperatorOverloading, + llvm::SmallVector, Kinds) { + return llvm::is_contained(Kinds, Node.getOverloadedOperator()); +} } // namespace UnusedReturnValueCheck::UnusedReturnValueCheck(llvm::StringRef Name, @@ -157,16 +164,22 @@ void UnusedReturnValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { } void UnusedReturnValueCheck::registerMatchers(MatchFinder *Finder) { - auto MatchedDirectCallExpr = - expr(callExpr(callee(functionDecl( - // Don't match void overloads of checked functions. - unless(returns(voidType())), - anyOf(isInstantiatedFrom(matchers::matchesAnyListedName( - CheckedFunctions)), - returns(hasCanonicalType(hasDeclaration( - namedDecl(matchers::matchesAnyListedName( - CheckedReturnTypes))))))))) - .bind("match")); + auto MatchedDirectCallExpr = expr( + callExpr( + callee(functionDecl( + // Don't match void overloads of checked functions. + unless(returns(voidType())), + // Don't match copy or move assignment operator. + unless(cxxMethodDecl(isOperatorOverloading( + {OO_Equal, OO_PlusEqual, OO_MinusEqual, OO_StarEqual, + OO_SlashEqual, OO_PercentEqual, OO_CaretEqual, OO_AmpEqual, + OO_PipeEqual, OO_LessLessEqual, OO_GreaterGreaterEqual}))), + anyOf( + isInstantiatedFrom( + matchers::matchesAnyListedName(CheckedFunctions)), + returns(hasCanonicalType(hasDeclaration(namedDecl( + matchers::matchesAnyListedName(CheckedReturnTypes))))))))) + .bind("match")); auto CheckCastToVoid = AllowCastToVoid ? castExpr(unless(hasCastKind(CK_ToVoid))) : castExpr(); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index a005adf76b8b..44680f79de6f 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -152,9 +152,9 @@ Changes in existing checks - Improved :doc:`bugprone-unused-return-value ` check by updating the - parameter `CheckedFunctions` to support regexp and avoiding false postive for + parameter `CheckedFunctions` to support regexp, avoiding false positive for function with the same prefix as the default argument, e.g. ``std::unique_ptr`` - and ``std::unique``. + and ``std::unique``, avoiding false positive for assignment operator overloading. - Improved :doc:`bugprone-use-after-move ` check to also handle diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-return-value.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-return-value.rst index 9c01ef50b538..9205ba98729c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-return-value.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-return-value.rst @@ -5,6 +5,8 @@ bugprone-unused-return-value Warns on unused function return values. The checked functions can be configured. +Operator overloading with assignment semantics are ignored. + Options ------- diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp new file mode 100644 index 000000000000..b4a41004adf8 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp @@ -0,0 +1,30 @@ +// RUN: %check_clang_tidy %s bugprone-unused-return-value %t \ +// RUN: -config='{CheckOptions: \ +// RUN: {bugprone-unused-return-value.CheckedFunctions: "::*"}}' \ +// RUN: -- + +struct S { + S(){}; + S(S const &); + S(S &&); + S &operator=(S const &); + S &operator=(S &&); + S &operator+=(S); +}; + +S returnValue(); +S const &returnRef(); + +void bar() { + returnValue(); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors + + S a{}; + a = returnValue(); + a.operator=(returnValue()); + + a = returnRef(); + a.operator=(returnRef()); + + a += returnRef(); +} -- GitLab From 92d7aca441e09c85ab9355f99f93f3dbc35924a0 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sat, 9 Mar 2024 16:21:25 +0000 Subject: [PATCH 022/953] [X86] Add missing immediate qualifier to the (V)CMPSS/D instructions (#84496) Matches (V)CMPPS/D and makes it easier to algorithmically recreate the instruction name in various analysis scripts I'm working on --- .../X86/MCTargetDesc/X86ATTInstPrinter.cpp | 112 +++++++++--------- .../MCTargetDesc/X86EncodingOptimization.cpp | 4 +- .../X86/MCTargetDesc/X86InstPrinterCommon.cpp | 40 +++---- .../X86/MCTargetDesc/X86IntelInstPrinter.cpp | 112 +++++++++--------- llvm/lib/Target/X86/X86FastISel.cpp | 8 +- llvm/lib/Target/X86/X86InstrAVX512.td | 98 +++++++-------- llvm/lib/Target/X86/X86InstrInfo.cpp | 40 +++---- llvm/lib/Target/X86/X86InstrSSE.td | 46 +++---- llvm/lib/Target/X86/X86SchedSapphireRapids.td | 8 +- .../CodeGen/X86/apx/kmov-domain-assignment.ll | 8 +- llvm/test/CodeGen/X86/domain-reassignment.mir | 12 +- llvm/test/CodeGen/X86/sqrt-fastmath-mir.ll | 8 +- llvm/test/TableGen/x86-fold-tables.inc | 34 +++--- 13 files changed, 265 insertions(+), 265 deletions(-) diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp index e96f9279826b..33104524c5a8 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp @@ -89,12 +89,12 @@ bool X86ATTInstPrinter::printVecCompareInstr(const MCInst *MI, // Custom print the vector compare instructions to get the immediate // translated into the mnemonic. switch (MI->getOpcode()) { - case X86::CMPPDrmi: case X86::CMPPDrri: - case X86::CMPPSrmi: case X86::CMPPSrri: - case X86::CMPSDrm: case X86::CMPSDrr: - case X86::CMPSDrm_Int: case X86::CMPSDrr_Int: - case X86::CMPSSrm: case X86::CMPSSrr: - case X86::CMPSSrm_Int: case X86::CMPSSrr_Int: + case X86::CMPPDrmi: case X86::CMPPDrri: + case X86::CMPPSrmi: case X86::CMPPSrri: + case X86::CMPSDrmi: case X86::CMPSDrri: + case X86::CMPSDrmi_Int: case X86::CMPSDrri_Int: + case X86::CMPSSrmi: case X86::CMPSSrri: + case X86::CMPSSrmi_Int: case X86::CMPSSrri_Int: if (Imm >= 0 && Imm <= 7) { OS << '\t'; printCMPMnemonic(MI, /*IsVCMP*/false, OS); @@ -117,56 +117,56 @@ bool X86ATTInstPrinter::printVecCompareInstr(const MCInst *MI, } break; - case X86::VCMPPDrmi: case X86::VCMPPDrri: - case X86::VCMPPDYrmi: case X86::VCMPPDYrri: - case X86::VCMPPDZ128rmi: case X86::VCMPPDZ128rri: - case X86::VCMPPDZ256rmi: case X86::VCMPPDZ256rri: - case X86::VCMPPDZrmi: case X86::VCMPPDZrri: - case X86::VCMPPSrmi: case X86::VCMPPSrri: - case X86::VCMPPSYrmi: case X86::VCMPPSYrri: - case X86::VCMPPSZ128rmi: case X86::VCMPPSZ128rri: - case X86::VCMPPSZ256rmi: case X86::VCMPPSZ256rri: - case X86::VCMPPSZrmi: case X86::VCMPPSZrri: - case X86::VCMPSDrm: case X86::VCMPSDrr: - case X86::VCMPSDZrm: case X86::VCMPSDZrr: - case X86::VCMPSDrm_Int: case X86::VCMPSDrr_Int: - case X86::VCMPSDZrm_Int: case X86::VCMPSDZrr_Int: - case X86::VCMPSSrm: case X86::VCMPSSrr: - case X86::VCMPSSZrm: case X86::VCMPSSZrr: - case X86::VCMPSSrm_Int: case X86::VCMPSSrr_Int: - case X86::VCMPSSZrm_Int: case X86::VCMPSSZrr_Int: - case X86::VCMPPDZ128rmik: case X86::VCMPPDZ128rrik: - case X86::VCMPPDZ256rmik: case X86::VCMPPDZ256rrik: - case X86::VCMPPDZrmik: case X86::VCMPPDZrrik: - case X86::VCMPPSZ128rmik: case X86::VCMPPSZ128rrik: - case X86::VCMPPSZ256rmik: case X86::VCMPPSZ256rrik: - case X86::VCMPPSZrmik: case X86::VCMPPSZrrik: - case X86::VCMPSDZrm_Intk: case X86::VCMPSDZrr_Intk: - case X86::VCMPSSZrm_Intk: case X86::VCMPSSZrr_Intk: - case X86::VCMPPDZ128rmbi: case X86::VCMPPDZ128rmbik: - case X86::VCMPPDZ256rmbi: case X86::VCMPPDZ256rmbik: - case X86::VCMPPDZrmbi: case X86::VCMPPDZrmbik: - case X86::VCMPPSZ128rmbi: case X86::VCMPPSZ128rmbik: - case X86::VCMPPSZ256rmbi: case X86::VCMPPSZ256rmbik: - case X86::VCMPPSZrmbi: case X86::VCMPPSZrmbik: - case X86::VCMPPDZrrib: case X86::VCMPPDZrribk: - case X86::VCMPPSZrrib: case X86::VCMPPSZrribk: - case X86::VCMPSDZrrb_Int: case X86::VCMPSDZrrb_Intk: - case X86::VCMPSSZrrb_Int: case X86::VCMPSSZrrb_Intk: - case X86::VCMPPHZ128rmi: case X86::VCMPPHZ128rri: - case X86::VCMPPHZ256rmi: case X86::VCMPPHZ256rri: - case X86::VCMPPHZrmi: case X86::VCMPPHZrri: - case X86::VCMPSHZrm: case X86::VCMPSHZrr: - case X86::VCMPSHZrm_Int: case X86::VCMPSHZrr_Int: - case X86::VCMPPHZ128rmik: case X86::VCMPPHZ128rrik: - case X86::VCMPPHZ256rmik: case X86::VCMPPHZ256rrik: - case X86::VCMPPHZrmik: case X86::VCMPPHZrrik: - case X86::VCMPSHZrm_Intk: case X86::VCMPSHZrr_Intk: - case X86::VCMPPHZ128rmbi: case X86::VCMPPHZ128rmbik: - case X86::VCMPPHZ256rmbi: case X86::VCMPPHZ256rmbik: - case X86::VCMPPHZrmbi: case X86::VCMPPHZrmbik: - case X86::VCMPPHZrrib: case X86::VCMPPHZrribk: - case X86::VCMPSHZrrb_Int: case X86::VCMPSHZrrb_Intk: + case X86::VCMPPDrmi: case X86::VCMPPDrri: + case X86::VCMPPDYrmi: case X86::VCMPPDYrri: + case X86::VCMPPDZ128rmi: case X86::VCMPPDZ128rri: + case X86::VCMPPDZ256rmi: case X86::VCMPPDZ256rri: + case X86::VCMPPDZrmi: case X86::VCMPPDZrri: + case X86::VCMPPSrmi: case X86::VCMPPSrri: + case X86::VCMPPSYrmi: case X86::VCMPPSYrri: + case X86::VCMPPSZ128rmi: case X86::VCMPPSZ128rri: + case X86::VCMPPSZ256rmi: case X86::VCMPPSZ256rri: + case X86::VCMPPSZrmi: case X86::VCMPPSZrri: + case X86::VCMPSDrmi: case X86::VCMPSDrri: + case X86::VCMPSDZrmi: case X86::VCMPSDZrri: + case X86::VCMPSDrmi_Int: case X86::VCMPSDrri_Int: + case X86::VCMPSDZrmi_Int: case X86::VCMPSDZrri_Int: + case X86::VCMPSSrmi: case X86::VCMPSSrri: + case X86::VCMPSSZrmi: case X86::VCMPSSZrri: + case X86::VCMPSSrmi_Int: case X86::VCMPSSrri_Int: + case X86::VCMPSSZrmi_Int: case X86::VCMPSSZrri_Int: + case X86::VCMPPDZ128rmik: case X86::VCMPPDZ128rrik: + case X86::VCMPPDZ256rmik: case X86::VCMPPDZ256rrik: + case X86::VCMPPDZrmik: case X86::VCMPPDZrrik: + case X86::VCMPPSZ128rmik: case X86::VCMPPSZ128rrik: + case X86::VCMPPSZ256rmik: case X86::VCMPPSZ256rrik: + case X86::VCMPPSZrmik: case X86::VCMPPSZrrik: + case X86::VCMPSDZrmi_Intk: case X86::VCMPSDZrri_Intk: + case X86::VCMPSSZrmi_Intk: case X86::VCMPSSZrri_Intk: + case X86::VCMPPDZ128rmbi: case X86::VCMPPDZ128rmbik: + case X86::VCMPPDZ256rmbi: case X86::VCMPPDZ256rmbik: + case X86::VCMPPDZrmbi: case X86::VCMPPDZrmbik: + case X86::VCMPPSZ128rmbi: case X86::VCMPPSZ128rmbik: + case X86::VCMPPSZ256rmbi: case X86::VCMPPSZ256rmbik: + case X86::VCMPPSZrmbi: case X86::VCMPPSZrmbik: + case X86::VCMPPDZrrib: case X86::VCMPPDZrribk: + case X86::VCMPPSZrrib: case X86::VCMPPSZrribk: + case X86::VCMPSDZrrib_Int: case X86::VCMPSDZrrib_Intk: + case X86::VCMPSSZrrib_Int: case X86::VCMPSSZrrib_Intk: + case X86::VCMPPHZ128rmi: case X86::VCMPPHZ128rri: + case X86::VCMPPHZ256rmi: case X86::VCMPPHZ256rri: + case X86::VCMPPHZrmi: case X86::VCMPPHZrri: + case X86::VCMPSHZrmi: case X86::VCMPSHZrri: + case X86::VCMPSHZrmi_Int: case X86::VCMPSHZrri_Int: + case X86::VCMPPHZ128rmik: case X86::VCMPPHZ128rrik: + case X86::VCMPPHZ256rmik: case X86::VCMPPHZ256rrik: + case X86::VCMPPHZrmik: case X86::VCMPPHZrrik: + case X86::VCMPSHZrmi_Intk: case X86::VCMPSHZrri_Intk: + case X86::VCMPPHZ128rmbi: case X86::VCMPPHZ128rmbik: + case X86::VCMPPHZ256rmbi: case X86::VCMPPHZ256rmbik: + case X86::VCMPPHZrmbi: case X86::VCMPPHZrmbik: + case X86::VCMPPHZrrib: case X86::VCMPPHZrribk: + case X86::VCMPSHZrrib_Int: case X86::VCMPSHZrrib_Intk: if (Imm >= 0 && Imm <= 31) { OS << '\t'; printCMPMnemonic(MI, /*IsVCMP*/true, OS); diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.cpp index 134206466c54..001a9d4d4d3c 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86EncodingOptimization.cpp @@ -52,8 +52,8 @@ bool X86::optimizeInstFromVEX3ToVEX2(MCInst &MI, const MCInstrDesc &Desc) { case X86::VCMPPDYrri: case X86::VCMPPSrri: case X86::VCMPPSYrri: - case X86::VCMPSDrr: - case X86::VCMPSSrr: { + case X86::VCMPSDrri: + case X86::VCMPSSrri: { switch (MI.getOperand(3).getImm() & 0x7) { default: return false; diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp index fd46e4e1df82..29a1866bf01a 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp @@ -272,24 +272,24 @@ void X86InstPrinterCommon::printCMPMnemonic(const MCInst *MI, bool IsVCmp, case X86::VCMPPSZrrib: case X86::VCMPPSZrribk: OS << "ps\t"; break; - case X86::CMPSDrm: case X86::CMPSDrr: - case X86::CMPSDrm_Int: case X86::CMPSDrr_Int: - case X86::VCMPSDrm: case X86::VCMPSDrr: - case X86::VCMPSDrm_Int: case X86::VCMPSDrr_Int: - case X86::VCMPSDZrm: case X86::VCMPSDZrr: - case X86::VCMPSDZrm_Int: case X86::VCMPSDZrr_Int: - case X86::VCMPSDZrm_Intk: case X86::VCMPSDZrr_Intk: - case X86::VCMPSDZrrb_Int: case X86::VCMPSDZrrb_Intk: + case X86::CMPSDrmi: case X86::CMPSDrri: + case X86::CMPSDrmi_Int: case X86::CMPSDrri_Int: + case X86::VCMPSDrmi: case X86::VCMPSDrri: + case X86::VCMPSDrmi_Int: case X86::VCMPSDrri_Int: + case X86::VCMPSDZrmi: case X86::VCMPSDZrri: + case X86::VCMPSDZrmi_Int: case X86::VCMPSDZrri_Int: + case X86::VCMPSDZrmi_Intk: case X86::VCMPSDZrri_Intk: + case X86::VCMPSDZrrib_Int: case X86::VCMPSDZrrib_Intk: OS << "sd\t"; break; - case X86::CMPSSrm: case X86::CMPSSrr: - case X86::CMPSSrm_Int: case X86::CMPSSrr_Int: - case X86::VCMPSSrm: case X86::VCMPSSrr: - case X86::VCMPSSrm_Int: case X86::VCMPSSrr_Int: - case X86::VCMPSSZrm: case X86::VCMPSSZrr: - case X86::VCMPSSZrm_Int: case X86::VCMPSSZrr_Int: - case X86::VCMPSSZrm_Intk: case X86::VCMPSSZrr_Intk: - case X86::VCMPSSZrrb_Int: case X86::VCMPSSZrrb_Intk: + case X86::CMPSSrmi: case X86::CMPSSrri: + case X86::CMPSSrmi_Int: case X86::CMPSSrri_Int: + case X86::VCMPSSrmi: case X86::VCMPSSrri: + case X86::VCMPSSrmi_Int: case X86::VCMPSSrri_Int: + case X86::VCMPSSZrmi: case X86::VCMPSSZrri: + case X86::VCMPSSZrmi_Int: case X86::VCMPSSZrri_Int: + case X86::VCMPSSZrmi_Intk: case X86::VCMPSSZrri_Intk: + case X86::VCMPSSZrrib_Int: case X86::VCMPSSZrrib_Intk: OS << "ss\t"; break; case X86::VCMPPHZ128rmi: case X86::VCMPPHZ128rri: @@ -304,10 +304,10 @@ void X86InstPrinterCommon::printCMPMnemonic(const MCInst *MI, bool IsVCmp, case X86::VCMPPHZrrib: case X86::VCMPPHZrribk: OS << "ph\t"; break; - case X86::VCMPSHZrm: case X86::VCMPSHZrr: - case X86::VCMPSHZrm_Int: case X86::VCMPSHZrr_Int: - case X86::VCMPSHZrrb_Int: case X86::VCMPSHZrrb_Intk: - case X86::VCMPSHZrm_Intk: case X86::VCMPSHZrr_Intk: + case X86::VCMPSHZrmi: case X86::VCMPSHZrri: + case X86::VCMPSHZrmi_Int: case X86::VCMPSHZrri_Int: + case X86::VCMPSHZrrib_Int: case X86::VCMPSHZrrib_Intk: + case X86::VCMPSHZrmi_Intk: case X86::VCMPSHZrri_Intk: OS << "sh\t"; break; } diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp index 0705700c7817..7c8459a54651 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86IntelInstPrinter.cpp @@ -69,12 +69,12 @@ bool X86IntelInstPrinter::printVecCompareInstr(const MCInst *MI, raw_ostream &OS // Custom print the vector compare instructions to get the immediate // translated into the mnemonic. switch (MI->getOpcode()) { - case X86::CMPPDrmi: case X86::CMPPDrri: - case X86::CMPPSrmi: case X86::CMPPSrri: - case X86::CMPSDrm: case X86::CMPSDrr: - case X86::CMPSDrm_Int: case X86::CMPSDrr_Int: - case X86::CMPSSrm: case X86::CMPSSrr: - case X86::CMPSSrm_Int: case X86::CMPSSrr_Int: + case X86::CMPPDrmi: case X86::CMPPDrri: + case X86::CMPPSrmi: case X86::CMPPSrri: + case X86::CMPSDrmi: case X86::CMPSDrri: + case X86::CMPSDrmi_Int: case X86::CMPSDrri_Int: + case X86::CMPSSrmi: case X86::CMPSSrri: + case X86::CMPSSrmi_Int: case X86::CMPSSrri_Int: if (Imm >= 0 && Imm <= 7) { OS << '\t'; printCMPMnemonic(MI, /*IsVCMP*/false, OS); @@ -96,56 +96,56 @@ bool X86IntelInstPrinter::printVecCompareInstr(const MCInst *MI, raw_ostream &OS } break; - case X86::VCMPPDrmi: case X86::VCMPPDrri: - case X86::VCMPPDYrmi: case X86::VCMPPDYrri: - case X86::VCMPPDZ128rmi: case X86::VCMPPDZ128rri: - case X86::VCMPPDZ256rmi: case X86::VCMPPDZ256rri: - case X86::VCMPPDZrmi: case X86::VCMPPDZrri: - case X86::VCMPPSrmi: case X86::VCMPPSrri: - case X86::VCMPPSYrmi: case X86::VCMPPSYrri: - case X86::VCMPPSZ128rmi: case X86::VCMPPSZ128rri: - case X86::VCMPPSZ256rmi: case X86::VCMPPSZ256rri: - case X86::VCMPPSZrmi: case X86::VCMPPSZrri: - case X86::VCMPSDrm: case X86::VCMPSDrr: - case X86::VCMPSDZrm: case X86::VCMPSDZrr: - case X86::VCMPSDrm_Int: case X86::VCMPSDrr_Int: - case X86::VCMPSDZrm_Int: case X86::VCMPSDZrr_Int: - case X86::VCMPSSrm: case X86::VCMPSSrr: - case X86::VCMPSSZrm: case X86::VCMPSSZrr: - case X86::VCMPSSrm_Int: case X86::VCMPSSrr_Int: - case X86::VCMPSSZrm_Int: case X86::VCMPSSZrr_Int: - case X86::VCMPPDZ128rmik: case X86::VCMPPDZ128rrik: - case X86::VCMPPDZ256rmik: case X86::VCMPPDZ256rrik: - case X86::VCMPPDZrmik: case X86::VCMPPDZrrik: - case X86::VCMPPSZ128rmik: case X86::VCMPPSZ128rrik: - case X86::VCMPPSZ256rmik: case X86::VCMPPSZ256rrik: - case X86::VCMPPSZrmik: case X86::VCMPPSZrrik: - case X86::VCMPSDZrm_Intk: case X86::VCMPSDZrr_Intk: - case X86::VCMPSSZrm_Intk: case X86::VCMPSSZrr_Intk: - case X86::VCMPPDZ128rmbi: case X86::VCMPPDZ128rmbik: - case X86::VCMPPDZ256rmbi: case X86::VCMPPDZ256rmbik: - case X86::VCMPPDZrmbi: case X86::VCMPPDZrmbik: - case X86::VCMPPSZ128rmbi: case X86::VCMPPSZ128rmbik: - case X86::VCMPPSZ256rmbi: case X86::VCMPPSZ256rmbik: - case X86::VCMPPSZrmbi: case X86::VCMPPSZrmbik: - case X86::VCMPPDZrrib: case X86::VCMPPDZrribk: - case X86::VCMPPSZrrib: case X86::VCMPPSZrribk: - case X86::VCMPSDZrrb_Int: case X86::VCMPSDZrrb_Intk: - case X86::VCMPSSZrrb_Int: case X86::VCMPSSZrrb_Intk: - case X86::VCMPPHZ128rmi: case X86::VCMPPHZ128rri: - case X86::VCMPPHZ256rmi: case X86::VCMPPHZ256rri: - case X86::VCMPPHZrmi: case X86::VCMPPHZrri: - case X86::VCMPSHZrm: case X86::VCMPSHZrr: - case X86::VCMPSHZrm_Int: case X86::VCMPSHZrr_Int: - case X86::VCMPPHZ128rmik: case X86::VCMPPHZ128rrik: - case X86::VCMPPHZ256rmik: case X86::VCMPPHZ256rrik: - case X86::VCMPPHZrmik: case X86::VCMPPHZrrik: - case X86::VCMPSHZrm_Intk: case X86::VCMPSHZrr_Intk: - case X86::VCMPPHZ128rmbi: case X86::VCMPPHZ128rmbik: - case X86::VCMPPHZ256rmbi: case X86::VCMPPHZ256rmbik: - case X86::VCMPPHZrmbi: case X86::VCMPPHZrmbik: - case X86::VCMPPHZrrib: case X86::VCMPPHZrribk: - case X86::VCMPSHZrrb_Int: case X86::VCMPSHZrrb_Intk: + case X86::VCMPPDrmi: case X86::VCMPPDrri: + case X86::VCMPPDYrmi: case X86::VCMPPDYrri: + case X86::VCMPPDZ128rmi: case X86::VCMPPDZ128rri: + case X86::VCMPPDZ256rmi: case X86::VCMPPDZ256rri: + case X86::VCMPPDZrmi: case X86::VCMPPDZrri: + case X86::VCMPPSrmi: case X86::VCMPPSrri: + case X86::VCMPPSYrmi: case X86::VCMPPSYrri: + case X86::VCMPPSZ128rmi: case X86::VCMPPSZ128rri: + case X86::VCMPPSZ256rmi: case X86::VCMPPSZ256rri: + case X86::VCMPPSZrmi: case X86::VCMPPSZrri: + case X86::VCMPSDrmi: case X86::VCMPSDrri: + case X86::VCMPSDZrmi: case X86::VCMPSDZrri: + case X86::VCMPSDrmi_Int: case X86::VCMPSDrri_Int: + case X86::VCMPSDZrmi_Int: case X86::VCMPSDZrri_Int: + case X86::VCMPSSrmi: case X86::VCMPSSrri: + case X86::VCMPSSZrmi: case X86::VCMPSSZrri: + case X86::VCMPSSrmi_Int: case X86::VCMPSSrri_Int: + case X86::VCMPSSZrmi_Int: case X86::VCMPSSZrri_Int: + case X86::VCMPPDZ128rmik: case X86::VCMPPDZ128rrik: + case X86::VCMPPDZ256rmik: case X86::VCMPPDZ256rrik: + case X86::VCMPPDZrmik: case X86::VCMPPDZrrik: + case X86::VCMPPSZ128rmik: case X86::VCMPPSZ128rrik: + case X86::VCMPPSZ256rmik: case X86::VCMPPSZ256rrik: + case X86::VCMPPSZrmik: case X86::VCMPPSZrrik: + case X86::VCMPSDZrmi_Intk: case X86::VCMPSDZrri_Intk: + case X86::VCMPSSZrmi_Intk: case X86::VCMPSSZrri_Intk: + case X86::VCMPPDZ128rmbi: case X86::VCMPPDZ128rmbik: + case X86::VCMPPDZ256rmbi: case X86::VCMPPDZ256rmbik: + case X86::VCMPPDZrmbi: case X86::VCMPPDZrmbik: + case X86::VCMPPSZ128rmbi: case X86::VCMPPSZ128rmbik: + case X86::VCMPPSZ256rmbi: case X86::VCMPPSZ256rmbik: + case X86::VCMPPSZrmbi: case X86::VCMPPSZrmbik: + case X86::VCMPPDZrrib: case X86::VCMPPDZrribk: + case X86::VCMPPSZrrib: case X86::VCMPPSZrribk: + case X86::VCMPSDZrrib_Int: case X86::VCMPSDZrrib_Intk: + case X86::VCMPSSZrrib_Int: case X86::VCMPSSZrrib_Intk: + case X86::VCMPPHZ128rmi: case X86::VCMPPHZ128rri: + case X86::VCMPPHZ256rmi: case X86::VCMPPHZ256rri: + case X86::VCMPPHZrmi: case X86::VCMPPHZrri: + case X86::VCMPSHZrmi: case X86::VCMPSHZrri: + case X86::VCMPSHZrmi_Int: case X86::VCMPSHZrri_Int: + case X86::VCMPPHZ128rmik: case X86::VCMPPHZ128rrik: + case X86::VCMPPHZ256rmik: case X86::VCMPPHZ256rrik: + case X86::VCMPPHZrmik: case X86::VCMPPHZrrik: + case X86::VCMPSHZrmi_Intk: case X86::VCMPSHZrri_Intk: + case X86::VCMPPHZ128rmbi: case X86::VCMPPHZ128rmbik: + case X86::VCMPPHZ256rmbi: case X86::VCMPPHZ256rmbik: + case X86::VCMPPHZrmbi: case X86::VCMPPHZrmbik: + case X86::VCMPPHZrrib: case X86::VCMPPHZrribk: + case X86::VCMPSHZrrib_Int: case X86::VCMPSHZrrib_Intk: if (Imm >= 0 && Imm <= 31) { OS << '\t'; printCMPMnemonic(MI, /*IsVCMP*/true, OS); diff --git a/llvm/lib/Target/X86/X86FastISel.cpp b/llvm/lib/Target/X86/X86FastISel.cpp index 9368de62817b..9f0b5f32df20 100644 --- a/llvm/lib/Target/X86/X86FastISel.cpp +++ b/llvm/lib/Target/X86/X86FastISel.cpp @@ -2198,7 +2198,7 @@ bool X86FastISel::X86FastEmitSSESelect(MVT RetVT, const Instruction *I) { const TargetRegisterClass *VK1 = &X86::VK1RegClass; unsigned CmpOpcode = - (RetVT == MVT::f32) ? X86::VCMPSSZrr : X86::VCMPSDZrr; + (RetVT == MVT::f32) ? X86::VCMPSSZrri : X86::VCMPSDZrri; Register CmpReg = fastEmitInst_rri(CmpOpcode, VK1, CmpLHSReg, CmpRHSReg, CC); @@ -2228,7 +2228,7 @@ bool X86FastISel::X86FastEmitSSESelect(MVT RetVT, const Instruction *I) { // instructions as the AND/ANDN/OR sequence due to register moves, so // don't bother. unsigned CmpOpcode = - (RetVT == MVT::f32) ? X86::VCMPSSrr : X86::VCMPSDrr; + (RetVT == MVT::f32) ? X86::VCMPSSrri : X86::VCMPSDrri; unsigned BlendOpcode = (RetVT == MVT::f32) ? X86::VBLENDVPSrr : X86::VBLENDVPDrr; @@ -2242,8 +2242,8 @@ bool X86FastISel::X86FastEmitSSESelect(MVT RetVT, const Instruction *I) { } else { // Choose the SSE instruction sequence based on data type (float or double). static const uint16_t OpcTable[2][4] = { - { X86::CMPSSrr, X86::ANDPSrr, X86::ANDNPSrr, X86::ORPSrr }, - { X86::CMPSDrr, X86::ANDPDrr, X86::ANDNPDrr, X86::ORPDrr } + { X86::CMPSSrri, X86::ANDPSrr, X86::ANDNPSrr, X86::ORPSrr }, + { X86::CMPSDrri, X86::ANDPDrr, X86::ANDNPDrr, X86::ORPDrr } }; const uint16_t *Opc = nullptr; diff --git a/llvm/lib/Target/X86/X86InstrAVX512.td b/llvm/lib/Target/X86/X86InstrAVX512.td index a76561f092c3..43a40f5e691e 100644 --- a/llvm/lib/Target/X86/X86InstrAVX512.td +++ b/llvm/lib/Target/X86/X86InstrAVX512.td @@ -1937,58 +1937,58 @@ defm VPBLENDMW : blendmask_bw<0x66, "vpblendmw", SchedWriteVarBlend, multiclass avx512_cmp_scalar { - defm rr_Int : AVX512_maskable_cmp<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.RC:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, $src2, $src1", "$src1, $src2, $cc", - (OpNode (_.VT _.RC:$src1), (_.VT _.RC:$src2), timm:$cc), - (OpNode_su (_.VT _.RC:$src1), (_.VT _.RC:$src2), - timm:$cc)>, EVEX, VVVV, VEX_LIG, Sched<[sched]>, SIMD_EXC; + defm rri_Int : AVX512_maskable_cmp<0xC2, MRMSrcReg, _, + (outs _.KRC:$dst), + (ins _.RC:$src1, _.RC:$src2, u8imm:$cc), + "vcmp"#_.Suffix, + "$cc, $src2, $src1", "$src1, $src2, $cc", + (OpNode (_.VT _.RC:$src1), (_.VT _.RC:$src2), timm:$cc), + (OpNode_su (_.VT _.RC:$src1), (_.VT _.RC:$src2), timm:$cc)>, + EVEX, VVVV, VEX_LIG, Sched<[sched]>, SIMD_EXC; let mayLoad = 1 in - defm rm_Int : AVX512_maskable_cmp<0xC2, MRMSrcMem, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.IntScalarMemOp:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, $src2, $src1", "$src1, $src2, $cc", - (OpNode (_.VT _.RC:$src1), (_.ScalarIntMemFrags addr:$src2), - timm:$cc), - (OpNode_su (_.VT _.RC:$src1), (_.ScalarIntMemFrags addr:$src2), - timm:$cc)>, EVEX, VVVV, VEX_LIG, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[sched.Folded, sched.ReadAfterFold]>, SIMD_EXC; + defm rmi_Int : AVX512_maskable_cmp<0xC2, MRMSrcMem, _, + (outs _.KRC:$dst), + (ins _.RC:$src1, _.IntScalarMemOp:$src2, u8imm:$cc), + "vcmp"#_.Suffix, + "$cc, $src2, $src1", "$src1, $src2, $cc", + (OpNode (_.VT _.RC:$src1), (_.ScalarIntMemFrags addr:$src2), + timm:$cc), + (OpNode_su (_.VT _.RC:$src1), (_.ScalarIntMemFrags addr:$src2), + timm:$cc)>, EVEX, VVVV, VEX_LIG, EVEX_CD8<_.EltSize, CD8VT1>, + Sched<[sched.Folded, sched.ReadAfterFold]>, SIMD_EXC; let Uses = [MXCSR] in - defm rrb_Int : AVX512_maskable_cmp<0xC2, MRMSrcReg, _, - (outs _.KRC:$dst), - (ins _.RC:$src1, _.RC:$src2, u8imm:$cc), - "vcmp"#_.Suffix, - "$cc, {sae}, $src2, $src1","$src1, $src2, {sae}, $cc", - (OpNodeSAE (_.VT _.RC:$src1), (_.VT _.RC:$src2), - timm:$cc), - (OpNodeSAE_su (_.VT _.RC:$src1), (_.VT _.RC:$src2), - timm:$cc)>, - EVEX, VVVV, VEX_LIG, EVEX_B, Sched<[sched]>; + defm rrib_Int : AVX512_maskable_cmp<0xC2, MRMSrcReg, _, + (outs _.KRC:$dst), + (ins _.RC:$src1, _.RC:$src2, u8imm:$cc), + "vcmp"#_.Suffix, + "$cc, {sae}, $src2, $src1","$src1, $src2, {sae}, $cc", + (OpNodeSAE (_.VT _.RC:$src1), (_.VT _.RC:$src2), + timm:$cc), + (OpNodeSAE_su (_.VT _.RC:$src1), (_.VT _.RC:$src2), + timm:$cc)>, + EVEX, VVVV, VEX_LIG, EVEX_B, Sched<[sched]>; let isCodeGenOnly = 1 in { let isCommutable = 1 in - def rr : AVX512Ii8<0xC2, MRMSrcReg, - (outs _.KRC:$dst), (ins _.FRC:$src1, _.FRC:$src2, u8imm:$cc), - !strconcat("vcmp", _.Suffix, - "\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}"), - [(set _.KRC:$dst, (OpNode _.FRC:$src1, - _.FRC:$src2, - timm:$cc))]>, - EVEX, VVVV, VEX_LIG, Sched<[sched]>, SIMD_EXC; - def rm : AVX512Ii8<0xC2, MRMSrcMem, - (outs _.KRC:$dst), - (ins _.FRC:$src1, _.ScalarMemOp:$src2, u8imm:$cc), - !strconcat("vcmp", _.Suffix, - "\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}"), - [(set _.KRC:$dst, (OpNode _.FRC:$src1, - (_.ScalarLdFrag addr:$src2), - timm:$cc))]>, - EVEX, VVVV, VEX_LIG, EVEX_CD8<_.EltSize, CD8VT1>, - Sched<[sched.Folded, sched.ReadAfterFold]>, SIMD_EXC; + def rri : AVX512Ii8<0xC2, MRMSrcReg, + (outs _.KRC:$dst), (ins _.FRC:$src1, _.FRC:$src2, u8imm:$cc), + !strconcat("vcmp", _.Suffix, + "\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}"), + [(set _.KRC:$dst, (OpNode _.FRC:$src1, + _.FRC:$src2, + timm:$cc))]>, + EVEX, VVVV, VEX_LIG, Sched<[sched]>, SIMD_EXC; + def rmi : AVX512Ii8<0xC2, MRMSrcMem, + (outs _.KRC:$dst), + (ins _.FRC:$src1, _.ScalarMemOp:$src2, u8imm:$cc), + !strconcat("vcmp", _.Suffix, + "\t{$cc, $src2, $src1, $dst|$dst, $src1, $src2, $cc}"), + [(set _.KRC:$dst, (OpNode _.FRC:$src1, + (_.ScalarLdFrag addr:$src2), + timm:$cc))]>, + EVEX, VVVV, VEX_LIG, EVEX_CD8<_.EltSize, CD8VT1>, + Sched<[sched.Folded, sched.ReadAfterFold]>, SIMD_EXC; } } @@ -2437,15 +2437,15 @@ defm VCMPPH : avx512_vcmp, // Patterns to select fp compares with load as first operand. let Predicates = [HasAVX512] in { def : Pat<(v1i1 (X86cmpms (loadf64 addr:$src2), FR64X:$src1, timm:$cc)), - (VCMPSDZrm FR64X:$src1, addr:$src2, (X86cmpm_imm_commute timm:$cc))>; + (VCMPSDZrmi FR64X:$src1, addr:$src2, (X86cmpm_imm_commute timm:$cc))>; def : Pat<(v1i1 (X86cmpms (loadf32 addr:$src2), FR32X:$src1, timm:$cc)), - (VCMPSSZrm FR32X:$src1, addr:$src2, (X86cmpm_imm_commute timm:$cc))>; + (VCMPSSZrmi FR32X:$src1, addr:$src2, (X86cmpm_imm_commute timm:$cc))>; } let Predicates = [HasFP16] in { def : Pat<(v1i1 (X86cmpms (loadf16 addr:$src2), FR16X:$src1, timm:$cc)), - (VCMPSHZrm FR16X:$src1, addr:$src2, (X86cmpm_imm_commute timm:$cc))>; + (VCMPSHZrmi FR16X:$src1, addr:$src2, (X86cmpm_imm_commute timm:$cc))>; } // ---------------------------------------------------------------- diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index 3f0557e651f8..af0ed071c29a 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -2573,11 +2573,11 @@ MachineInstr *X86InstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI, WorkingMI->getOperand(3).setImm( X86::getSwappedVPCOMImm(MI.getOperand(3).getImm() & 0x7)); break; - case X86::VCMPSDZrr: - case X86::VCMPSSZrr: + case X86::VCMPSDZrri: + case X86::VCMPSSZrri: case X86::VCMPPDZrri: case X86::VCMPPSZrri: - case X86::VCMPSHZrr: + case X86::VCMPSHZrri: case X86::VCMPPHZrri: case X86::VCMPPHZ128rri: case X86::VCMPPHZ256rri: @@ -2820,21 +2820,21 @@ bool X86InstrInfo::findCommutedOpIndices(const MachineInstr &MI, return false; switch (MI.getOpcode()) { - case X86::CMPSDrr: - case X86::CMPSSrr: + case X86::CMPSDrri: + case X86::CMPSSrri: case X86::CMPPDrri: case X86::CMPPSrri: - case X86::VCMPSDrr: - case X86::VCMPSSrr: + case X86::VCMPSDrri: + case X86::VCMPSSrri: case X86::VCMPPDrri: case X86::VCMPPSrri: case X86::VCMPPDYrri: case X86::VCMPPSYrri: - case X86::VCMPSDZrr: - case X86::VCMPSSZrr: + case X86::VCMPSDZrri: + case X86::VCMPSSZrri: case X86::VCMPPDZrri: case X86::VCMPPSZrri: - case X86::VCMPSHZrr: + case X86::VCMPSHZrri: case X86::VCMPPHZrri: case X86::VCMPPHZ128rri: case X86::VCMPPHZ256rri: @@ -7510,9 +7510,9 @@ static bool isNonFoldablePartialRegisterLoad(const MachineInstr &LoadMI, case X86::ADDSSrr_Int: case X86::VADDSSrr_Int: case X86::VADDSSZrr_Int: - case X86::CMPSSrr_Int: - case X86::VCMPSSrr_Int: - case X86::VCMPSSZrr_Int: + case X86::CMPSSrri_Int: + case X86::VCMPSSrri_Int: + case X86::VCMPSSZrri_Int: case X86::DIVSSrr_Int: case X86::VDIVSSrr_Int: case X86::VDIVSSZrr_Int: @@ -7533,7 +7533,7 @@ static bool isNonFoldablePartialRegisterLoad(const MachineInstr &LoadMI, case X86::VSUBSSZrr_Int: case X86::VADDSSZrr_Intk: case X86::VADDSSZrr_Intkz: - case X86::VCMPSSZrr_Intk: + case X86::VCMPSSZrri_Intk: case X86::VDIVSSZrr_Intk: case X86::VDIVSSZrr_Intkz: case X86::VMAXSSZrr_Intk: @@ -7679,9 +7679,9 @@ static bool isNonFoldablePartialRegisterLoad(const MachineInstr &LoadMI, case X86::ADDSDrr_Int: case X86::VADDSDrr_Int: case X86::VADDSDZrr_Int: - case X86::CMPSDrr_Int: - case X86::VCMPSDrr_Int: - case X86::VCMPSDZrr_Int: + case X86::CMPSDrri_Int: + case X86::VCMPSDrri_Int: + case X86::VCMPSDZrri_Int: case X86::DIVSDrr_Int: case X86::VDIVSDrr_Int: case X86::VDIVSDZrr_Int: @@ -7702,7 +7702,7 @@ static bool isNonFoldablePartialRegisterLoad(const MachineInstr &LoadMI, case X86::VSUBSDZrr_Int: case X86::VADDSDZrr_Intk: case X86::VADDSDZrr_Intkz: - case X86::VCMPSDZrr_Intk: + case X86::VCMPSDZrri_Intk: case X86::VDIVSDZrr_Intk: case X86::VDIVSDZrr_Intkz: case X86::VMAXSDZrr_Intk: @@ -7814,7 +7814,7 @@ static bool isNonFoldablePartialRegisterLoad(const MachineInstr &LoadMI, // instruction isn't scalar (SH). switch (UserOpc) { case X86::VADDSHZrr_Int: - case X86::VCMPSHZrr_Int: + case X86::VCMPSHZrri_Int: case X86::VDIVSHZrr_Int: case X86::VMAXSHZrr_Int: case X86::VMINSHZrr_Int: @@ -7822,7 +7822,7 @@ static bool isNonFoldablePartialRegisterLoad(const MachineInstr &LoadMI, case X86::VSUBSHZrr_Int: case X86::VADDSHZrr_Intk: case X86::VADDSHZrr_Intkz: - case X86::VCMPSHZrr_Intk: + case X86::VCMPSHZrri_Intk: case X86::VDIVSHZrr_Intk: case X86::VDIVSHZrr_Intkz: case X86::VMAXSHZrr_Intk: diff --git a/llvm/lib/Target/X86/X86InstrSSE.td b/llvm/lib/Target/X86/X86InstrSSE.td index 459b5b03507c..fd20090fe097 100644 --- a/llvm/lib/Target/X86/X86InstrSSE.td +++ b/llvm/lib/Target/X86/X86InstrSSE.td @@ -1830,29 +1830,29 @@ multiclass sse12_cmp_scalar { - def rr_Int : SIi8<0xC2, MRMSrcReg, (outs VR128:$dst), - (ins VR128:$src1, VR128:$src2, u8imm:$cc), asm, - [(set VR128:$dst, (OpNode (VT VR128:$src1), - VR128:$src2, timm:$cc))]>, - Sched<[sched]>, SIMD_EXC; + def rri_Int : SIi8<0xC2, MRMSrcReg, (outs VR128:$dst), + (ins VR128:$src1, VR128:$src2, u8imm:$cc), asm, + [(set VR128:$dst, (OpNode (VT VR128:$src1), + VR128:$src2, timm:$cc))]>, + Sched<[sched]>, SIMD_EXC; let mayLoad = 1 in - def rm_Int : SIi8<0xC2, MRMSrcMem, (outs VR128:$dst), - (ins VR128:$src1, memop:$src2, u8imm:$cc), asm, - [(set VR128:$dst, (OpNode (VT VR128:$src1), - (mem_frags addr:$src2), timm:$cc))]>, - Sched<[sched.Folded, sched.ReadAfterFold]>, SIMD_EXC; + def rmi_Int : SIi8<0xC2, MRMSrcMem, (outs VR128:$dst), + (ins VR128:$src1, memop:$src2, u8imm:$cc), asm, + [(set VR128:$dst, (OpNode (VT VR128:$src1), + (mem_frags addr:$src2), timm:$cc))]>, + Sched<[sched.Folded, sched.ReadAfterFold]>, SIMD_EXC; let isCodeGenOnly = 1 in { let isCommutable = 1 in - def rr : SIi8<0xC2, MRMSrcReg, - (outs RC:$dst), (ins RC:$src1, RC:$src2, u8imm:$cc), asm, - [(set RC:$dst, (OpNode RC:$src1, RC:$src2, timm:$cc))]>, - Sched<[sched]>, SIMD_EXC; - def rm : SIi8<0xC2, MRMSrcMem, - (outs RC:$dst), (ins RC:$src1, x86memop:$src2, u8imm:$cc), asm, - [(set RC:$dst, (OpNode RC:$src1, - (ld_frag addr:$src2), timm:$cc))]>, - Sched<[sched.Folded, sched.ReadAfterFold]>, SIMD_EXC; + def rri : SIi8<0xC2, MRMSrcReg, + (outs RC:$dst), (ins RC:$src1, RC:$src2, u8imm:$cc), asm, + [(set RC:$dst, (OpNode RC:$src1, RC:$src2, timm:$cc))]>, + Sched<[sched]>, SIMD_EXC; + def rmi : SIi8<0xC2, MRMSrcMem, + (outs RC:$dst), (ins RC:$src1, x86memop:$src2, u8imm:$cc), asm, + [(set RC:$dst, (OpNode RC:$src1, + (ld_frag addr:$src2), timm:$cc))]>, + Sched<[sched.Folded, sched.ReadAfterFold]>, SIMD_EXC; } } @@ -2023,11 +2023,11 @@ let Predicates = [HasAVX] in { def : Pat<(f64 (X86cmps (loadf64 addr:$src2), FR64:$src1, CommutableCMPCC:$cc)), - (VCMPSDrm FR64:$src1, addr:$src2, timm:$cc)>; + (VCMPSDrmi FR64:$src1, addr:$src2, timm:$cc)>; def : Pat<(f32 (X86cmps (loadf32 addr:$src2), FR32:$src1, CommutableCMPCC:$cc)), - (VCMPSSrm FR32:$src1, addr:$src2, timm:$cc)>; + (VCMPSSrmi FR32:$src1, addr:$src2, timm:$cc)>; } let Predicates = [UseSSE2] in { @@ -2037,7 +2037,7 @@ let Predicates = [UseSSE2] in { def : Pat<(f64 (X86cmps (loadf64 addr:$src2), FR64:$src1, CommutableCMPCC:$cc)), - (CMPSDrm FR64:$src1, addr:$src2, timm:$cc)>; + (CMPSDrmi FR64:$src1, addr:$src2, timm:$cc)>; } let Predicates = [UseSSE1] in { @@ -2047,7 +2047,7 @@ let Predicates = [UseSSE1] in { def : Pat<(f32 (X86cmps (loadf32 addr:$src2), FR32:$src1, CommutableCMPCC:$cc)), - (CMPSSrm FR32:$src1, addr:$src2, timm:$cc)>; + (CMPSSrmi FR32:$src1, addr:$src2, timm:$cc)>; } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/X86/X86SchedSapphireRapids.td b/llvm/lib/Target/X86/X86SchedSapphireRapids.td index bf9e4b7dc6d9..78c5994ee964 100644 --- a/llvm/lib/Target/X86/X86SchedSapphireRapids.td +++ b/llvm/lib/Target/X86/X86SchedSapphireRapids.td @@ -663,8 +663,8 @@ def : InstRW<[SPRWriteResGroup12], (instregex "^ADD_F(P?)rST0$", "^SUB(R?)_FST0r$", "^VALIGN(D|Q)Z256rri((k|kz)?)$", "^VCMPP(D|H|S)Z(128|256)rri(k?)$", - "^VCMPS(D|H|S)Zrr$", - "^VCMPS(D|H|S)Zrr(b?)_Int(k?)$", + "^VCMPS(D|H|S)Zrri$", + "^VCMPS(D|H|S)Zrr(b?)i_Int(k?)$", "^VFPCLASSP(D|H|S)Z(128|256)rr(k?)$", "^VFPCLASSS(D|H|S)Zrr(k?)$", "^VPACK(S|U)S(DW|WB)Yrr$", @@ -2739,8 +2739,8 @@ def : InstRW<[SPRWriteResGroup263, ReadAfterVecYLd], (instregex "^VCMPP(D|H|S)Z( "^VPCMPUDZ((256)?)rmib(k?)$", "^VPTEST(N?)M(B|D|Q|W)Z((256)?)rm(k?)$", "^VPTEST(N?)M(D|Q)Z((256)?)rmb(k?)$")>; -def : InstRW<[SPRWriteResGroup263, ReadAfterVecLd], (instregex "^VCMPS(D|H|S)Zrm$", - "^VCMPS(D|H|S)Zrm_Int(k?)$", +def : InstRW<[SPRWriteResGroup263, ReadAfterVecLd], (instregex "^VCMPS(D|H|S)Zrmi$", + "^VCMPS(D|H|S)Zrmi_Int(k?)$", "^VFPCLASSS(D|H|S)Zrmk$")>; def SPRWriteResGroup264 : SchedWriteRes<[SPRPort00, SPRPort02_03_11]> { diff --git a/llvm/test/CodeGen/X86/apx/kmov-domain-assignment.ll b/llvm/test/CodeGen/X86/apx/kmov-domain-assignment.ll index b09a14cee957..e70e5ff80d95 100644 --- a/llvm/test/CodeGen/X86/apx/kmov-domain-assignment.ll +++ b/llvm/test/CodeGen/X86/apx/kmov-domain-assignment.ll @@ -21,8 +21,8 @@ define void @test_fcmp_storei1(i1 %cond, ptr %fptr, ptr %iptr, float %f1, float ; CHECK-NEXT: bb.1.if: ; CHECK-NEXT: successors: %bb.3(0x80000000) ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[VCMPSSZrr:%[0-9]+]]:vk1 = nofpexcept VCMPSSZrr [[COPY3]], [[COPY2]], 0, implicit $mxcsr - ; CHECK-NEXT: [[COPY7:%[0-9]+]]:vk16 = COPY [[VCMPSSZrr]] + ; CHECK-NEXT: [[VCMPSSZrri:%[0-9]+]]:vk1 = nofpexcept VCMPSSZrri [[COPY3]], [[COPY2]], 0, implicit $mxcsr + ; CHECK-NEXT: [[COPY7:%[0-9]+]]:vk16 = COPY [[VCMPSSZrri]] ; CHECK-NEXT: [[COPY8:%[0-9]+]]:vk32 = COPY [[COPY7]] ; CHECK-NEXT: [[COPY9:%[0-9]+]]:vk8 = COPY [[COPY8]] ; CHECK-NEXT: JMP_1 %bb.3 @@ -30,8 +30,8 @@ define void @test_fcmp_storei1(i1 %cond, ptr %fptr, ptr %iptr, float %f1, float ; CHECK-NEXT: bb.2.else: ; CHECK-NEXT: successors: %bb.3(0x80000000) ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[VCMPSSZrr1:%[0-9]+]]:vk1 = nofpexcept VCMPSSZrr [[COPY1]], [[COPY]], 0, implicit $mxcsr - ; CHECK-NEXT: [[COPY10:%[0-9]+]]:vk16 = COPY [[VCMPSSZrr1]] + ; CHECK-NEXT: [[VCMPSSZrri1:%[0-9]+]]:vk1 = nofpexcept VCMPSSZrri [[COPY1]], [[COPY]], 0, implicit $mxcsr + ; CHECK-NEXT: [[COPY10:%[0-9]+]]:vk16 = COPY [[VCMPSSZrri1]] ; CHECK-NEXT: [[COPY11:%[0-9]+]]:vk32 = COPY [[COPY10]] ; CHECK-NEXT: [[COPY12:%[0-9]+]]:vk8 = COPY [[COPY11]] ; CHECK-NEXT: {{ $}} diff --git a/llvm/test/CodeGen/X86/domain-reassignment.mir b/llvm/test/CodeGen/X86/domain-reassignment.mir index 8b2fbe04d14a..dcd435619990 100644 --- a/llvm/test/CodeGen/X86/domain-reassignment.mir +++ b/llvm/test/CodeGen/X86/domain-reassignment.mir @@ -133,14 +133,14 @@ body: | ; CHECK: JMP_1 %bb.1 ; CHECK: bb.1.if: ; CHECK: successors: %bb.3(0x80000000) - ; CHECK: [[VCMPSSZrr:%[0-9]+]]:vk1 = VCMPSSZrr [[COPY3]], [[COPY2]], 0 - ; CHECK: [[COPY9:%[0-9]+]]:vk32 = COPY [[VCMPSSZrr]] + ; CHECK: [[VCMPSSZrri:%[0-9]+]]:vk1 = VCMPSSZrri [[COPY3]], [[COPY2]], 0 + ; CHECK: [[COPY9:%[0-9]+]]:vk32 = COPY [[VCMPSSZrri]] ; CHECK: [[COPY10:%[0-9]+]]:vk8 = COPY [[COPY9]] ; CHECK: JMP_1 %bb.3 ; CHECK: bb.2.else: ; CHECK: successors: %bb.3(0x80000000) - ; CHECK: [[VCMPSSZrr1:%[0-9]+]]:vk1 = VCMPSSZrr [[COPY1]], [[COPY]], 0 - ; CHECK: [[COPY11:%[0-9]+]]:vk32 = COPY [[VCMPSSZrr1]] + ; CHECK: [[VCMPSSZrri1:%[0-9]+]]:vk1 = VCMPSSZrri [[COPY1]], [[COPY]], 0 + ; CHECK: [[COPY11:%[0-9]+]]:vk32 = COPY [[VCMPSSZrri1]] ; CHECK: [[COPY12:%[0-9]+]]:vk8 = COPY [[COPY11]] ; CHECK: bb.3.exit: ; CHECK: [[PHI:%[0-9]+]]:vk8 = PHI [[COPY12]], %bb.2, [[COPY10]], %bb.1 @@ -173,7 +173,7 @@ body: | bb.1.if: successors: %bb.3(0x80000000) - %14 = VCMPSSZrr %7, %8, 0, implicit $mxcsr + %14 = VCMPSSZrri %7, %8, 0, implicit $mxcsr ; check that cross domain copies are replaced with same domain copies. @@ -183,7 +183,7 @@ body: | bb.2.else: successors: %bb.3(0x80000000) - %12 = VCMPSSZrr %9, %10, 0, implicit $mxcsr + %12 = VCMPSSZrri %9, %10, 0, implicit $mxcsr ; check that cross domain copies are replaced with same domain copies. diff --git a/llvm/test/CodeGen/X86/sqrt-fastmath-mir.ll b/llvm/test/CodeGen/X86/sqrt-fastmath-mir.ll index 8a7fea78702d..2c7da100344b 100644 --- a/llvm/test/CodeGen/X86/sqrt-fastmath-mir.ll +++ b/llvm/test/CodeGen/X86/sqrt-fastmath-mir.ll @@ -40,8 +40,8 @@ define float @sqrt_ieee_ninf(float %f) #0 { ; CHECK-NEXT: [[VPBROADCASTDrm:%[0-9]+]]:vr128 = VPBROADCASTDrm $rip, 1, $noreg, %const.2, $noreg :: (load (s32) from constant-pool) ; CHECK-NEXT: [[VPANDrr:%[0-9]+]]:vr128 = VPANDrr killed [[COPY2]], killed [[VPBROADCASTDrm]] ; CHECK-NEXT: [[COPY3:%[0-9]+]]:fr32 = COPY [[VPANDrr]] - ; CHECK-NEXT: [[VCMPSSrm:%[0-9]+]]:fr32 = nofpexcept VCMPSSrm killed [[COPY3]], $rip, 1, $noreg, %const.3, $noreg, 1, implicit $mxcsr :: (load (s32) from constant-pool) - ; CHECK-NEXT: [[COPY4:%[0-9]+]]:vr128 = COPY [[VCMPSSrm]] + ; CHECK-NEXT: [[VCMPSSrmi:%[0-9]+]]:fr32 = nofpexcept VCMPSSrmi killed [[COPY3]], $rip, 1, $noreg, %const.3, $noreg, 1, implicit $mxcsr :: (load (s32) from constant-pool) + ; CHECK-NEXT: [[COPY4:%[0-9]+]]:vr128 = COPY [[VCMPSSrmi]] ; CHECK-NEXT: [[VPANDNrr:%[0-9]+]]:vr128 = VPANDNrr killed [[COPY4]], killed [[COPY1]] ; CHECK-NEXT: [[COPY5:%[0-9]+]]:fr32 = COPY [[VPANDNrr]] ; CHECK-NEXT: $xmm0 = COPY [[COPY5]] @@ -84,8 +84,8 @@ define float @sqrt_daz_ninf(float %f) #1 { ; CHECK-NEXT: [[VMULSSrr5:%[0-9]+]]:fr32 = ninf afn nofpexcept VMULSSrr killed [[VMULSSrr4]], killed [[VFMADD213SSr1]], implicit $mxcsr ; CHECK-NEXT: [[COPY1:%[0-9]+]]:vr128 = COPY [[VMULSSrr5]] ; CHECK-NEXT: [[FsFLD0SS:%[0-9]+]]:fr32 = FsFLD0SS - ; CHECK-NEXT: [[VCMPSSrr:%[0-9]+]]:fr32 = nofpexcept VCMPSSrr [[COPY]], killed [[FsFLD0SS]], 0, implicit $mxcsr - ; CHECK-NEXT: [[COPY2:%[0-9]+]]:vr128 = COPY [[VCMPSSrr]] + ; CHECK-NEXT: [[VCMPSSrri:%[0-9]+]]:fr32 = nofpexcept VCMPSSrri [[COPY]], killed [[FsFLD0SS]], 0, implicit $mxcsr + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:vr128 = COPY [[VCMPSSrri]] ; CHECK-NEXT: [[VPANDNrr:%[0-9]+]]:vr128 = VPANDNrr killed [[COPY2]], killed [[COPY1]] ; CHECK-NEXT: [[COPY3:%[0-9]+]]:fr32 = COPY [[VPANDNrr]] ; CHECK-NEXT: $xmm0 = COPY [[COPY3]] diff --git a/llvm/test/TableGen/x86-fold-tables.inc b/llvm/test/TableGen/x86-fold-tables.inc index c35f22ff36de..d0ae2c474e85 100644 --- a/llvm/test/TableGen/x86-fold-tables.inc +++ b/llvm/test/TableGen/x86-fold-tables.inc @@ -1941,10 +1941,10 @@ static const X86FoldTableEntry Table2[] = { {X86::CMOV64rr, X86::CMOV64rm, 0}, {X86::CMPPDrri, X86::CMPPDrmi, TB_ALIGN_16}, {X86::CMPPSrri, X86::CMPPSrmi, TB_ALIGN_16}, - {X86::CMPSDrr, X86::CMPSDrm, 0}, - {X86::CMPSDrr_Int, X86::CMPSDrm_Int, TB_NO_REVERSE}, - {X86::CMPSSrr, X86::CMPSSrm, 0}, - {X86::CMPSSrr_Int, X86::CMPSSrm_Int, TB_NO_REVERSE}, + {X86::CMPSDrri, X86::CMPSDrmi, 0}, + {X86::CMPSDrri_Int, X86::CMPSDrmi_Int, TB_NO_REVERSE}, + {X86::CMPSSrri, X86::CMPSSrmi, 0}, + {X86::CMPSSrri_Int, X86::CMPSSrmi_Int, TB_NO_REVERSE}, {X86::CRC32r32r16, X86::CRC32r32m16, 0}, {X86::CRC32r32r16_EVEX, X86::CRC32r32m16_EVEX, 0}, {X86::CRC32r32r32, X86::CRC32r32m32, 0}, @@ -2390,16 +2390,16 @@ static const X86FoldTableEntry Table2[] = { {X86::VCMPPSZ256rri, X86::VCMPPSZ256rmi, 0}, {X86::VCMPPSZrri, X86::VCMPPSZrmi, 0}, {X86::VCMPPSrri, X86::VCMPPSrmi, 0}, - {X86::VCMPSDZrr, X86::VCMPSDZrm, 0}, - {X86::VCMPSDZrr_Int, X86::VCMPSDZrm_Int, TB_NO_REVERSE}, - {X86::VCMPSDrr, X86::VCMPSDrm, 0}, - {X86::VCMPSDrr_Int, X86::VCMPSDrm_Int, TB_NO_REVERSE}, - {X86::VCMPSHZrr, X86::VCMPSHZrm, 0}, - {X86::VCMPSHZrr_Int, X86::VCMPSHZrm_Int, TB_NO_REVERSE}, - {X86::VCMPSSZrr, X86::VCMPSSZrm, 0}, - {X86::VCMPSSZrr_Int, X86::VCMPSSZrm_Int, TB_NO_REVERSE}, - {X86::VCMPSSrr, X86::VCMPSSrm, 0}, - {X86::VCMPSSrr_Int, X86::VCMPSSrm_Int, TB_NO_REVERSE}, + {X86::VCMPSDZrri, X86::VCMPSDZrmi, 0}, + {X86::VCMPSDZrri_Int, X86::VCMPSDZrmi_Int, TB_NO_REVERSE}, + {X86::VCMPSDrri, X86::VCMPSDrmi, 0}, + {X86::VCMPSDrri_Int, X86::VCMPSDrmi_Int, TB_NO_REVERSE}, + {X86::VCMPSHZrri, X86::VCMPSHZrmi, 0}, + {X86::VCMPSHZrri_Int, X86::VCMPSHZrmi_Int, TB_NO_REVERSE}, + {X86::VCMPSSZrri, X86::VCMPSSZrmi, 0}, + {X86::VCMPSSZrri_Int, X86::VCMPSSZrmi_Int, TB_NO_REVERSE}, + {X86::VCMPSSrri, X86::VCMPSSrmi, 0}, + {X86::VCMPSSrri_Int, X86::VCMPSSrmi_Int, TB_NO_REVERSE}, {X86::VCVTDQ2PDZ128rrkz, X86::VCVTDQ2PDZ128rmkz, TB_NO_REVERSE}, {X86::VCVTDQ2PDZ256rrkz, X86::VCVTDQ2PDZ256rmkz, 0}, {X86::VCVTDQ2PDZrrkz, X86::VCVTDQ2PDZrmkz, 0}, @@ -3973,9 +3973,9 @@ static const X86FoldTableEntry Table3[] = { {X86::VCMPPSZ128rrik, X86::VCMPPSZ128rmik, 0}, {X86::VCMPPSZ256rrik, X86::VCMPPSZ256rmik, 0}, {X86::VCMPPSZrrik, X86::VCMPPSZrmik, 0}, - {X86::VCMPSDZrr_Intk, X86::VCMPSDZrm_Intk, TB_NO_REVERSE}, - {X86::VCMPSHZrr_Intk, X86::VCMPSHZrm_Intk, TB_NO_REVERSE}, - {X86::VCMPSSZrr_Intk, X86::VCMPSSZrm_Intk, TB_NO_REVERSE}, + {X86::VCMPSDZrri_Intk, X86::VCMPSDZrmi_Intk, TB_NO_REVERSE}, + {X86::VCMPSHZrri_Intk, X86::VCMPSHZrmi_Intk, TB_NO_REVERSE}, + {X86::VCMPSSZrri_Intk, X86::VCMPSSZrmi_Intk, TB_NO_REVERSE}, {X86::VCVTDQ2PDZ128rrk, X86::VCVTDQ2PDZ128rmk, TB_NO_REVERSE}, {X86::VCVTDQ2PDZ256rrk, X86::VCVTDQ2PDZ256rmk, 0}, {X86::VCVTDQ2PDZrrk, X86::VCVTDQ2PDZrmk, 0}, -- GitLab From 99f5e9634b6921ebb6dad9bef1c76ade83adc847 Mon Sep 17 00:00:00 2001 From: lntue <35648136+lntue@users.noreply.github.com> Date: Sat, 9 Mar 2024 11:47:22 -0500 Subject: [PATCH 023/953] [libc][math][c23] Add modff128 C23 math function. (#84532) --- libc/config/linux/aarch64/entrypoints.txt | 1 + libc/config/linux/riscv/entrypoints.txt | 1 + libc/config/linux/x86_64/entrypoints.txt | 1 + libc/docs/math/index.rst | 2 ++ libc/spec/spec.td | 1 + libc/spec/stdc.td | 1 + libc/src/math/CMakeLists.txt | 1 + libc/src/math/generic/CMakeLists.txt | 19 ++++++++++++++++--- libc/src/math/generic/modff128.cpp | 19 +++++++++++++++++++ libc/src/math/modff128.h | 20 ++++++++++++++++++++ libc/test/src/math/smoke/CMakeLists.txt | 19 +++++++++++++++---- libc/test/src/math/smoke/ModfTest.h | 6 ++++-- libc/test/src/math/smoke/modff128_test.cpp | 13 +++++++++++++ 13 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 libc/src/math/generic/modff128.cpp create mode 100644 libc/src/math/modff128.h create mode 100644 libc/test/src/math/smoke/modff128_test.cpp diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index fa15ddd17aef..c24703840183 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -434,6 +434,7 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.llroundf128 libc.src.math.lrintf128 libc.src.math.lroundf128 + libc.src.math.modff128 libc.src.math.rintf128 libc.src.math.roundf128 libc.src.math.sqrtf128 diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 924cf2f1d68b..f7a65615115f 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -442,6 +442,7 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.llroundf128 libc.src.math.lrintf128 libc.src.math.lroundf128 + libc.src.math.modff128 libc.src.math.rintf128 libc.src.math.roundf128 libc.src.math.sqrtf128 diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 0880c372b373..a7894af4b9ca 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -472,6 +472,7 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.llroundf128 libc.src.math.lrintf128 libc.src.math.lroundf128 + libc.src.math.modff128 libc.src.math.rintf128 libc.src.math.roundf128 libc.src.math.sqrtf128 diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst index 81d95d9b6cfa..7f2a1b2f3e28 100644 --- a/libc/docs/math/index.rst +++ b/libc/docs/math/index.rst @@ -249,6 +249,8 @@ Basic Operations +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | modfl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| modff128 | |check| | |check| | | |check| | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | nan | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | nanf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | diff --git a/libc/spec/spec.td b/libc/spec/spec.td index 998f37fb26de..a44a7ae131b5 100644 --- a/libc/spec/spec.td +++ b/libc/spec/spec.td @@ -111,6 +111,7 @@ def IntPtr : PtrType; def RestrictedIntPtr : RestrictedPtrType; def FloatPtr : PtrType; def DoublePtr : PtrType; +def Float128Ptr : PtrType; def UnsignedCharPtr : PtrType; def SigHandlerT : NamedType<"__sighandler_t">; diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index cc845a93a333..766668c51e3e 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -451,6 +451,7 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"modf", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"modff", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"modfl", RetValSpec, [ArgSpec, ArgSpec]>, + GuardedFunctionSpec<"modff128", RetValSpec, [ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"cos", RetValSpec, [ArgSpec]>, FunctionSpec<"cosf", RetValSpec, [ArgSpec]>, diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index 035eefd82d36..6c06d383ec2b 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -183,6 +183,7 @@ add_math_entrypoint_object(lroundf128) add_math_entrypoint_object(modf) add_math_entrypoint_object(modff) add_math_entrypoint_object(modfl) +add_math_entrypoint_object(modff128) add_math_entrypoint_object(nan) add_math_entrypoint_object(nanf) diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index a7b7065980b1..933a05dad157 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -1407,7 +1407,7 @@ add_entrypoint_object( DEPENDS libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( @@ -1419,7 +1419,7 @@ add_entrypoint_object( DEPENDS libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( @@ -1431,7 +1431,20 @@ add_entrypoint_object( DEPENDS libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 +) + +add_entrypoint_object( + modff128 + SRCS + modff128.cpp + HDRS + ../modff128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 ) add_entrypoint_object( diff --git a/libc/src/math/generic/modff128.cpp b/libc/src/math/generic/modff128.cpp new file mode 100644 index 000000000000..6aef5f510a95 --- /dev/null +++ b/libc/src/math/generic/modff128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of modff128 function -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/math/modff128.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, modff128, (float128 x, float128 *iptr)) { + return fputil::modf(x, *iptr); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/modff128.h b/libc/src/math/modff128.h new file mode 100644 index 000000000000..48e614be95b9 --- /dev/null +++ b/libc/src/math/modff128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for modff128 -----------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_MATH_MODFF128_H +#define LLVM_LIBC_SRC_MATH_MODFF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 modff128(float128 x, float128 *iptr); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_MODFF128_H diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index 63faaa9d4e4c..8d3871dd427a 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -1078,8 +1078,6 @@ add_fp_unittest( libc.src.math.modf libc.src.__support.FPUtil.basic_operations libc.src.__support.FPUtil.nearest_integer_operations - # Requires C++ limits. - UNIT_TEST_ONLY ) add_fp_unittest( @@ -1095,8 +1093,6 @@ add_fp_unittest( libc.src.math.modff libc.src.__support.FPUtil.basic_operations libc.src.__support.FPUtil.nearest_integer_operations - # Requires C++ limits. - UNIT_TEST_ONLY ) add_fp_unittest( @@ -1114,6 +1110,21 @@ add_fp_unittest( libc.src.__support.FPUtil.nearest_integer_operations ) +add_fp_unittest( + modff128_test + SUITE + libc-math-smoke-tests + SRCS + modff128_test.cpp + HDRS + ModfTest.h + DEPENDS + libc.include.math + libc.src.math.modff128 + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.nearest_integer_operations +) + add_fp_unittest( fdimf_test SUITE diff --git a/libc/test/src/math/smoke/ModfTest.h b/libc/test/src/math/smoke/ModfTest.h index a73e5ae4298f..d7e15a7ed682 100644 --- a/libc/test/src/math/smoke/ModfTest.h +++ b/libc/test/src/math/smoke/ModfTest.h @@ -84,10 +84,12 @@ public: constexpr StorageType COUNT = 100'000; constexpr StorageType STEP = STORAGE_MAX / COUNT; for (StorageType i = 0, v = 0; i <= COUNT; ++i, v += STEP) { - T x = FPBits(v).get_val(); - if (isnan(x) || isinf(x) || x == T(0.0)) + FPBits x_bits = FPBits(v); + if (x_bits.is_zero() || x_bits.is_inf_or_nan()) continue; + T x = x_bits.get_val(); + T integral; T frac = func(x, &integral); ASSERT_TRUE(LIBC_NAMESPACE::fputil::abs(frac) < 1.0l); diff --git a/libc/test/src/math/smoke/modff128_test.cpp b/libc/test/src/math/smoke/modff128_test.cpp new file mode 100644 index 000000000000..062d40138e72 --- /dev/null +++ b/libc/test/src/math/smoke/modff128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for modff128 --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ModfTest.h" + +#include "src/math/modff128.h" + +LIST_MODF_TESTS(float128, LIBC_NAMESPACE::modff128) -- GitLab From e19e8600cf743690e1a23fb8a2b0dfbe2dafe559 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Sat, 9 Mar 2024 18:03:52 +0100 Subject: [PATCH 024/953] [RFC][libc++] Reworks clang-tidy selection. (#81362) The current selection is done in the test scripts which gives the user no control where to find clang-tidy. The version selection itself is hard-coded and not based on the version of clang used. This moves the selection to configuration time and tries to find a better match. - Mixing the version of clang-tidy and the clang libraries causes ODR violations. This results in practice in crashes or incorrect results. - Mixing the version of clang-tidy and the clang binary sometimes causes issues with supported diagnostic flags. For example, flags tested against clang 17 may not be available in clang-tidy 16. Currently clang-tidy 18.1 can be used, it tests against the clang libraries version 18. This is caused by the new LLVM version numbering scheme. The new selection tries to match the clang version or the version of the HEAD and the last 3 releases. (During the release period libc++ supports 4 versions instead of the typical 3 versions.) --- libcxx/test/tools/CMakeLists.txt | 5 +++ .../tools/clang_tidy_checks/CMakeLists.txt | 8 ++-- libcxx/utils/libcxx/test/features.py | 31 ------------- libcxx/utils/libcxx/test/params.py | 43 ++++++++++++++++++- 4 files changed, 51 insertions(+), 36 deletions(-) diff --git a/libcxx/test/tools/CMakeLists.txt b/libcxx/test/tools/CMakeLists.txt index 10be63e8b50a..e30ad6cdd820 100644 --- a/libcxx/test/tools/CMakeLists.txt +++ b/libcxx/test/tools/CMakeLists.txt @@ -3,5 +3,10 @@ set(LIBCXX_TEST_TOOLS_PATH ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE) # TODO: Remove LIBCXX_ENABLE_CLANG_TIDY if(LIBCXX_ENABLE_CLANG_TIDY) + if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + message(STATUS "Clang-tidy can only be used when building libc++ with " + "a clang compiler.") + return() + endif() add_subdirectory(clang_tidy_checks) endif() diff --git a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt index 978e70952165..74905a0c3ed1 100644 --- a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt +++ b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt @@ -5,10 +5,10 @@ set(LLVM_DIR_SAVE ${LLVM_DIR}) set(Clang_DIR_SAVE ${Clang_DIR}) -find_package(Clang 18) -if (NOT Clang_FOUND) - find_package(Clang 17) -endif() +# Since the Clang C++ ABI is not stable the Clang libraries and clang-tidy +# versions must match. Otherwise there likely will be ODR-violations. This had +# led to crashes and incorrect output of the clang-tidy based checks. +find_package(Clang ${CMAKE_CXX_COMPILER_VERSION}) set(SOURCES abi_tag_on_virtual.cpp diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py index 6ef40755c59d..3f0dc0c50a0d 100644 --- a/libcxx/utils/libcxx/test/features.py +++ b/libcxx/utils/libcxx/test/features.py @@ -23,30 +23,6 @@ _isClExe = lambda cfg: not _isAnyClangOrGCC(cfg) _isMSVC = lambda cfg: "_MSC_VER" in compilerMacros(cfg) _msvcVersion = lambda cfg: (int(compilerMacros(cfg)["_MSC_VER"]) // 100, int(compilerMacros(cfg)["_MSC_VER"]) % 100) - -def _getSuitableClangTidy(cfg): - try: - # If we didn't build the libcxx-tidy plugin via CMake, we can't run the clang-tidy tests. - if runScriptExitCode(cfg, ["stat %{test-tools-dir}/clang_tidy_checks/libcxx-tidy.plugin"]) != 0: - return None - - # TODO MODULES require ToT due module specific fixes. - if runScriptExitCode(cfg, ['clang-tidy-18 --version']) == 0: - return 'clang-tidy-18' - - # TODO This should be the last stable release. - # LLVM RELEASE bump to latest stable version - if runScriptExitCode(cfg, ["clang-tidy-16 --version"]) == 0: - return "clang-tidy-16" - - # LLVM RELEASE bump version - if int(re.search("[0-9]+", commandOutput(cfg, ["clang-tidy --version"])).group()) >= 16: - return "clang-tidy" - - except ConfigurationRuntimeError: - return None - - def _getAndroidDeviceApi(cfg): return int( programOutput( @@ -297,13 +273,6 @@ DEFAULT_FEATURES = [ name="executor-has-no-bash", when=lambda cfg: runScriptExitCode(cfg, ["%{exec} bash -c 'bash --version'"]) != 0, ), - Feature( - name="has-clang-tidy", - when=lambda cfg: _getSuitableClangTidy(cfg) is not None, - actions=[ - AddSubstitution("%{clang-tidy}", lambda cfg: _getSuitableClangTidy(cfg)) - ], - ), # Whether module support for the platform is available. Feature( name="has-no-cxx-module-support", diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py index 89d9f22e9dc6..695e01115aa4 100644 --- a/libcxx/utils/libcxx/test/params.py +++ b/libcxx/utils/libcxx/test/params.py @@ -110,6 +110,37 @@ def getSizeOptimizationFlag(cfg): ) +def testClangTidy(cfg, version, executable): + try: + if version in commandOutput(cfg, [f"{executable} --version"]): + return executable + except ConfigurationRuntimeError: + return None + + +def getSuitableClangTidy(cfg): + # If we didn't build the libcxx-tidy plugin via CMake, we can't run the clang-tidy tests. + if ( + runScriptExitCode( + cfg, ["stat %{test-tools-dir}/clang_tidy_checks/libcxx-tidy.plugin"] + ) + != 0 + ): + return None + + version = "{__clang_major__}.{__clang_minor__}.{__clang_patchlevel__}".format( + **compilerMacros(cfg) + ) + exe = testClangTidy( + cfg, version, "clang-tidy-{__clang_major__}".format(**compilerMacros(cfg)) + ) + + if not exe: + exe = testClangTidy(cfg, version, "clang-tidy") + + return exe + + # fmt: off DEFAULT_PARAMETERS = [ Parameter( @@ -366,6 +397,16 @@ DEFAULT_PARAMETERS = [ default=f"{shlex.quote(sys.executable)} {shlex.quote(str(Path(__file__).resolve().parent.parent.parent / 'run.py'))}", help="Custom executor to use instead of the configured default.", actions=lambda executor: [AddSubstitution("%{executor}", executor)], - ) + ), + Parameter( + name='clang-tidy-executable', + type=str, + default=lambda cfg: getSuitableClangTidy(cfg), + help="Selects the clang-tidy executable to use.", + actions=lambda exe: [] if exe is None else [ + AddFeature('has-clang-tidy'), + AddSubstitution('%{clang-tidy}', exe), + ] + ), ] # fmt: on -- GitLab From 938b9204684222d192a3f817da0c33076ed813e2 Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Thu, 7 Mar 2024 14:32:07 -0600 Subject: [PATCH 025/953] [InstCombine] Add more tests for transforming `(binop (uitofp), -C)`; NFC --- llvm/test/Transforms/InstCombine/binop-itofp.ll | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/binop-itofp.ll b/llvm/test/Transforms/InstCombine/binop-itofp.ll index ffa893745791..c91cef717afb 100644 --- a/llvm/test/Transforms/InstCombine/binop-itofp.ll +++ b/llvm/test/Transforms/InstCombine/binop-itofp.ll @@ -996,3 +996,16 @@ define half @test_ui_si_i12_mul_nsw(i12 noundef %x_in, i12 noundef %y_in) { %r = fmul half %xf, %yf ret half %r } + +define float @test_ui_add_with_signed_constant(i32 %shr.i) { +; CHECK-LABEL: @test_ui_add_with_signed_constant( +; CHECK-NEXT: [[AND_I:%.*]] = and i32 [[SHR_I:%.*]], 32767 +; CHECK-NEXT: [[SUB:%.*]] = uitofp i32 [[AND_I]] to float +; CHECK-NEXT: [[ADD:%.*]] = fadd float [[SUB]], -1.638300e+04 +; CHECK-NEXT: ret float [[ADD]] +; + %and.i = and i32 %shr.i, 32767 + %sub = uitofp i32 %and.i to float + %add = fadd float %sub, -16383.0 + ret float %add +} -- GitLab From 8d976c7f20fe8d92fe6f54af411594e15fac25ae Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Thu, 7 Mar 2024 16:19:22 -0600 Subject: [PATCH 026/953] [InstCombine] Make `(binop ({s|u}itofp),({s|u}itofp))` transform more flexible to mismatched signs Instead of taking the sign of the cast operation as the required since for the transform, only force a sign if an operation is maybe negative. This gives us more flexability when checking if the floats are safely converable to integers. Closes #84389 --- .../InstCombine/InstCombineInternal.h | 4 + .../InstCombine/InstructionCombining.cpp | 81 +++++++++++-------- .../test/Transforms/InstCombine/add-sitofp.ll | 10 +-- .../Transforms/InstCombine/binop-itofp.ll | 45 +++++------ 4 files changed, 78 insertions(+), 62 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h index 57148d719d9b..6a1ef6edeb40 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -380,6 +380,10 @@ private: Instruction *foldBitcastExtElt(ExtractElementInst &ExtElt); Instruction *foldCastedBitwiseLogic(BinaryOperator &I); Instruction *foldFBinOpOfIntCasts(BinaryOperator &I); + // Should only be called by `foldFBinOpOfIntCasts`. + Instruction *foldFBinOpOfIntCastsFromSign( + BinaryOperator &BO, bool OpsFromSigned, std::array IntOps, + Constant *Op1FpC, SmallVectorImpl> &OpsKnown); Instruction *foldBinopOfSextBoolToSelect(BinaryOperator &I); Instruction *narrowBinOp(TruncInst &Trunc); Instruction *narrowMaskedBinOp(BinaryOperator &And); diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index f3a740c1b161..1a831805dc72 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1406,41 +1406,27 @@ Value *InstCombinerImpl::dyn_castNegVal(Value *V) const { // -> ({s|u}itofp (int_binop x, y)) // 2) (fp_binop ({s|u}itofp x), FpC) // -> ({s|u}itofp (int_binop x, (fpto{s|u}i FpC))) -Instruction *InstCombinerImpl::foldFBinOpOfIntCasts(BinaryOperator &BO) { - Value *IntOps[2] = {nullptr, nullptr}; - Constant *Op1FpC = nullptr; - - // Check for: - // 1) (binop ({s|u}itofp x), ({s|u}itofp y)) - // 2) (binop ({s|u}itofp x), FpC) - if (!match(BO.getOperand(0), m_SIToFP(m_Value(IntOps[0]))) && - !match(BO.getOperand(0), m_UIToFP(m_Value(IntOps[0])))) - return nullptr; - - if (!match(BO.getOperand(1), m_Constant(Op1FpC)) && - !match(BO.getOperand(1), m_SIToFP(m_Value(IntOps[1]))) && - !match(BO.getOperand(1), m_UIToFP(m_Value(IntOps[1])))) - return nullptr; +// +// Assuming the sign of the cast for x/y is `OpsFromSigned`. +Instruction *InstCombinerImpl::foldFBinOpOfIntCastsFromSign( + BinaryOperator &BO, bool OpsFromSigned, std::array IntOps, + Constant *Op1FpC, SmallVectorImpl> &OpsKnown) { Type *FPTy = BO.getType(); Type *IntTy = IntOps[0]->getType(); - // Do we have signed casts? - bool OpsFromSigned = isa(BO.getOperand(0)); - unsigned IntSz = IntTy->getScalarSizeInBits(); // This is the maximum number of inuse bits by the integer where the int -> fp // casts are exact. unsigned MaxRepresentableBits = APFloat::semanticsPrecision(FPTy->getScalarType()->getFltSemantics()); - // Cache KnownBits a bit to potentially save some analysis. - WithCache OpsKnown[2] = {IntOps[0], IntOps[1]}; - // Preserve known number of leading bits. This can allow us to trivial nsw/nuw // checks later on. unsigned NumUsedLeadingBits[2] = {IntSz, IntSz}; + // NB: This only comes up if OpsFromSigned is true, so there is no need to + // cache if between calls to `foldFBinOpOfIntCastsFromSign`. auto IsNonZero = [&](unsigned OpNo) -> bool { if (OpsKnown[OpNo].hasKnownBits() && OpsKnown[OpNo].getKnownBits(SQ).isNonZero()) @@ -1449,14 +1435,19 @@ Instruction *InstCombinerImpl::foldFBinOpOfIntCasts(BinaryOperator &BO) { }; auto IsNonNeg = [&](unsigned OpNo) -> bool { - if (OpsKnown[OpNo].hasKnownBits() && - OpsKnown[OpNo].getKnownBits(SQ).isNonNegative()) - return true; - return isKnownNonNegative(IntOps[OpNo], SQ); + // NB: This matches the impl in ValueTracking, we just try to use cached + // knownbits here. If we ever start supporting WithCache for + // `isKnownNonNegative`, change this to an explicit call. + return OpsKnown[OpNo].getKnownBits(SQ).isNonNegative(); }; // Check if we know for certain that ({s|u}itofp op) is exact. auto IsValidPromotion = [&](unsigned OpNo) -> bool { + // Can we treat this operand as the desired sign? + if (OpsFromSigned != isa(BO.getOperand(OpNo)) && + !IsNonNeg(OpNo)) + return false; + // If fp precision >= bitwidth(op) then its exact. // NB: This is slightly conservative for `sitofp`. For signed conversion, we // can handle `MaxRepresentableBits == IntSz - 1` as the sign bit will be @@ -1509,13 +1500,6 @@ Instruction *InstCombinerImpl::foldFBinOpOfIntCasts(BinaryOperator &BO) { return nullptr; if (Op1FpC == nullptr) { - if (OpsFromSigned != isa(BO.getOperand(1))) { - // If we have a signed + unsigned, see if we can treat both as signed - // (uitofp nneg x) == (sitofp nneg x). - if (OpsFromSigned ? !IsNonNeg(1) : !IsNonNeg(0)) - return nullptr; - OpsFromSigned = true; - } if (!IsValidPromotion(1)) return nullptr; } @@ -1574,6 +1558,39 @@ Instruction *InstCombinerImpl::foldFBinOpOfIntCasts(BinaryOperator &BO) { return new UIToFPInst(IntBinOp, FPTy); } +// Try to fold: +// 1) (fp_binop ({s|u}itofp x), ({s|u}itofp y)) +// -> ({s|u}itofp (int_binop x, y)) +// 2) (fp_binop ({s|u}itofp x), FpC) +// -> ({s|u}itofp (int_binop x, (fpto{s|u}i FpC))) +Instruction *InstCombinerImpl::foldFBinOpOfIntCasts(BinaryOperator &BO) { + std::array IntOps = {nullptr, nullptr}; + Constant *Op1FpC = nullptr; + // Check for: + // 1) (binop ({s|u}itofp x), ({s|u}itofp y)) + // 2) (binop ({s|u}itofp x), FpC) + if (!match(BO.getOperand(0), m_SIToFP(m_Value(IntOps[0]))) && + !match(BO.getOperand(0), m_UIToFP(m_Value(IntOps[0])))) + return nullptr; + + if (!match(BO.getOperand(1), m_Constant(Op1FpC)) && + !match(BO.getOperand(1), m_SIToFP(m_Value(IntOps[1]))) && + !match(BO.getOperand(1), m_UIToFP(m_Value(IntOps[1])))) + return nullptr; + + // Cache KnownBits a bit to potentially save some analysis. + SmallVector, 2> OpsKnown = {IntOps[0], IntOps[1]}; + + // Try treating x/y as coming from both `uitofp` and `sitofp`. There are + // different constraints depending on the sign of the cast. + // NB: `(uitofp nneg X)` == `(sitofp nneg X)`. + if (Instruction *R = foldFBinOpOfIntCastsFromSign(BO, /*OpsFromSigned=*/false, + IntOps, Op1FpC, OpsKnown)) + return R; + return foldFBinOpOfIntCastsFromSign(BO, /*OpsFromSigned=*/true, IntOps, + Op1FpC, OpsKnown); +} + /// A binop with a constant operand and a sign-extended boolean operand may be /// converted into a select of constants by applying the binary operation to /// the constant with the two possible values of the extended boolean (0 or -1). diff --git a/llvm/test/Transforms/InstCombine/add-sitofp.ll b/llvm/test/Transforms/InstCombine/add-sitofp.ll index 049db8c84a52..2bdc808d9771 100644 --- a/llvm/test/Transforms/InstCombine/add-sitofp.ll +++ b/llvm/test/Transforms/InstCombine/add-sitofp.ll @@ -6,7 +6,7 @@ define double @x(i32 %a, i32 %b) { ; CHECK-NEXT: [[M:%.*]] = lshr i32 [[A:%.*]], 24 ; CHECK-NEXT: [[N:%.*]] = and i32 [[M]], [[B:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i32 [[N]], 1 -; CHECK-NEXT: [[P:%.*]] = sitofp i32 [[TMP1]] to double +; CHECK-NEXT: [[P:%.*]] = uitofp i32 [[TMP1]] to double ; CHECK-NEXT: ret double [[P]] ; %m = lshr i32 %a, 24 @@ -20,7 +20,7 @@ define double @test(i32 %a) { ; CHECK-LABEL: @test( ; CHECK-NEXT: [[A_AND:%.*]] = and i32 [[A:%.*]], 1073741823 ; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i32 [[A_AND]], 1 -; CHECK-NEXT: [[RES:%.*]] = sitofp i32 [[TMP1]] to double +; CHECK-NEXT: [[RES:%.*]] = uitofp i32 [[TMP1]] to double ; CHECK-NEXT: ret double [[RES]] ; ; Drop two highest bits to guarantee that %a + 1 doesn't overflow @@ -49,7 +49,7 @@ define double @test_2(i32 %a, i32 %b) { ; CHECK-NEXT: [[A_AND:%.*]] = and i32 [[A:%.*]], 1073741823 ; CHECK-NEXT: [[B_AND:%.*]] = and i32 [[B:%.*]], 1073741823 ; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i32 [[A_AND]], [[B_AND]] -; CHECK-NEXT: [[RES:%.*]] = sitofp i32 [[TMP1]] to double +; CHECK-NEXT: [[RES:%.*]] = uitofp i32 [[TMP1]] to double ; CHECK-NEXT: ret double [[RES]] ; ; Drop two highest bits to guarantee that %a + %b doesn't overflow @@ -89,7 +89,7 @@ define float @test_3(i32 %a, i32 %b) { ; CHECK-NEXT: [[M:%.*]] = lshr i32 [[A:%.*]], 24 ; CHECK-NEXT: [[N:%.*]] = and i32 [[M]], [[B:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i32 [[N]], 1 -; CHECK-NEXT: [[P:%.*]] = sitofp i32 [[TMP1]] to float +; CHECK-NEXT: [[P:%.*]] = uitofp i32 [[TMP1]] to float ; CHECK-NEXT: ret float [[P]] ; %m = lshr i32 %a, 24 @@ -104,7 +104,7 @@ define <4 x double> @test_4(<4 x i32> %a, <4 x i32> %b) { ; CHECK-NEXT: [[A_AND:%.*]] = and <4 x i32> [[A:%.*]], ; CHECK-NEXT: [[B_AND:%.*]] = and <4 x i32> [[B:%.*]], ; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw <4 x i32> [[A_AND]], [[B_AND]] -; CHECK-NEXT: [[RES:%.*]] = sitofp <4 x i32> [[TMP1]] to <4 x double> +; CHECK-NEXT: [[RES:%.*]] = uitofp <4 x i32> [[TMP1]] to <4 x double> ; CHECK-NEXT: ret <4 x double> [[RES]] ; ; Drop two highest bits to guarantee that %a + %b doesn't overflow diff --git a/llvm/test/Transforms/InstCombine/binop-itofp.ll b/llvm/test/Transforms/InstCombine/binop-itofp.ll index c91cef717afb..7d2b872985d5 100644 --- a/llvm/test/Transforms/InstCombine/binop-itofp.ll +++ b/llvm/test/Transforms/InstCombine/binop-itofp.ll @@ -110,7 +110,7 @@ define half @test_ui_si_i8_add(i8 noundef %x_in, i8 noundef %y_in) { ; CHECK-NEXT: [[X:%.*]] = and i8 [[X_IN:%.*]], 63 ; CHECK-NEXT: [[Y:%.*]] = and i8 [[Y_IN:%.*]], 63 ; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i8 [[X]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = sitofp i8 [[TMP1]] to half +; CHECK-NEXT: [[R:%.*]] = uitofp i8 [[TMP1]] to half ; CHECK-NEXT: ret half [[R]] ; %x = and i8 %x_in, 63 @@ -125,9 +125,8 @@ define half @test_ui_si_i8_add_overflow(i8 noundef %x_in, i8 noundef %y_in) { ; CHECK-LABEL: @test_ui_si_i8_add_overflow( ; CHECK-NEXT: [[X:%.*]] = and i8 [[X_IN:%.*]], 63 ; CHECK-NEXT: [[Y:%.*]] = and i8 [[Y_IN:%.*]], 65 -; CHECK-NEXT: [[XF:%.*]] = sitofp i8 [[X]] to half -; CHECK-NEXT: [[YF:%.*]] = uitofp i8 [[Y]] to half -; CHECK-NEXT: [[R:%.*]] = fadd half [[XF]], [[YF]] +; CHECK-NEXT: [[TMP1:%.*]] = add nuw i8 [[X]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = uitofp i8 [[TMP1]] to half ; CHECK-NEXT: ret half [[R]] ; %x = and i8 %x_in, 63 @@ -152,9 +151,8 @@ define half @test_ui_ui_i8_sub_C(i8 noundef %x_in) { define half @test_ui_ui_i8_sub_C_fail_overflow(i8 noundef %x_in) { ; CHECK-LABEL: @test_ui_ui_i8_sub_C_fail_overflow( -; CHECK-NEXT: [[X:%.*]] = and i8 [[X_IN:%.*]], 127 -; CHECK-NEXT: [[XF:%.*]] = uitofp i8 [[X]] to half -; CHECK-NEXT: [[R:%.*]] = fadd half [[XF]], 0xHD800 +; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[X_IN:%.*]], -128 +; CHECK-NEXT: [[R:%.*]] = sitofp i8 [[TMP1]] to half ; CHECK-NEXT: ret half [[R]] ; %x = and i8 %x_in, 127 @@ -212,8 +210,8 @@ define half @test_si_si_i8_sub_C(i8 noundef %x_in) { define half @test_si_si_i8_sub_C_fail_overflow(i8 noundef %x_in) { ; CHECK-LABEL: @test_si_si_i8_sub_C_fail_overflow( ; CHECK-NEXT: [[X:%.*]] = and i8 [[X_IN:%.*]], 65 -; CHECK-NEXT: [[XF:%.*]] = sitofp i8 [[X]] to half -; CHECK-NEXT: [[R:%.*]] = fadd half [[XF]], 0xH5400 +; CHECK-NEXT: [[TMP1:%.*]] = add nuw i8 [[X]], 64 +; CHECK-NEXT: [[R:%.*]] = uitofp i8 [[TMP1]] to half ; CHECK-NEXT: ret half [[R]] ; %x = and i8 %x_in, 65 @@ -242,9 +240,8 @@ define half @test_ui_si_i8_sub_fail_maybe_sign(i8 noundef %x_in, i8 noundef %y_i ; CHECK-LABEL: @test_ui_si_i8_sub_fail_maybe_sign( ; CHECK-NEXT: [[X:%.*]] = or i8 [[X_IN:%.*]], 64 ; CHECK-NEXT: [[Y:%.*]] = and i8 [[Y_IN:%.*]], 63 -; CHECK-NEXT: [[XF:%.*]] = uitofp i8 [[X]] to half -; CHECK-NEXT: [[YF:%.*]] = sitofp i8 [[Y]] to half -; CHECK-NEXT: [[R:%.*]] = fsub half [[XF]], [[YF]] +; CHECK-NEXT: [[TMP1:%.*]] = sub nuw nsw i8 [[X]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = uitofp i8 [[TMP1]] to half ; CHECK-NEXT: ret half [[R]] ; %x = or i8 %x_in, 64 @@ -273,8 +270,8 @@ define half @test_ui_ui_i8_mul(i8 noundef %x_in, i8 noundef %y_in) { define half @test_ui_ui_i8_mul_C(i8 noundef %x_in) { ; CHECK-LABEL: @test_ui_ui_i8_mul_C( -; CHECK-NEXT: [[TMP1:%.*]] = shl i8 [[X_IN:%.*]], 4 -; CHECK-NEXT: [[R:%.*]] = uitofp i8 [[TMP1]] to half +; CHECK-NEXT: [[X:%.*]] = shl i8 [[X_IN:%.*]], 4 +; CHECK-NEXT: [[R:%.*]] = uitofp i8 [[X]] to half ; CHECK-NEXT: ret half [[R]] ; %x = and i8 %x_in, 15 @@ -368,7 +365,7 @@ define half @test_ui_si_i8_mul(i8 noundef %x_in, i8 noundef %y_in) { ; CHECK-NEXT: [[YY:%.*]] = and i8 [[Y_IN:%.*]], 7 ; CHECK-NEXT: [[Y:%.*]] = add nuw nsw i8 [[YY]], 1 ; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i8 [[X]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = sitofp i8 [[TMP1]] to half +; CHECK-NEXT: [[R:%.*]] = uitofp i8 [[TMP1]] to half ; CHECK-NEXT: ret half [[R]] ; %xx = and i8 %x_in, 6 @@ -386,9 +383,8 @@ define half @test_ui_si_i8_mul_fail_maybe_zero(i8 noundef %x_in, i8 noundef %y_i ; CHECK-NEXT: [[XX:%.*]] = and i8 [[X_IN:%.*]], 7 ; CHECK-NEXT: [[X:%.*]] = add nuw nsw i8 [[XX]], 1 ; CHECK-NEXT: [[Y:%.*]] = and i8 [[Y_IN:%.*]], 7 -; CHECK-NEXT: [[XF:%.*]] = sitofp i8 [[X]] to half -; CHECK-NEXT: [[YF:%.*]] = uitofp i8 [[Y]] to half -; CHECK-NEXT: [[R:%.*]] = fmul half [[XF]], [[YF]] +; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i8 [[X]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = uitofp i8 [[TMP1]] to half ; CHECK-NEXT: ret half [[R]] ; %xx = and i8 %x_in, 7 @@ -694,7 +690,7 @@ define half @test_ui_si_i16_mul(i16 noundef %x_in, i16 noundef %y_in) { ; CHECK-NEXT: [[YY:%.*]] = and i16 [[Y_IN:%.*]], 126 ; CHECK-NEXT: [[Y:%.*]] = or disjoint i16 [[YY]], 1 ; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i16 [[X]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = sitofp i16 [[TMP1]] to half +; CHECK-NEXT: [[R:%.*]] = uitofp i16 [[TMP1]] to half ; CHECK-NEXT: ret half [[R]] ; %xx = and i16 %x_in, 126 @@ -807,9 +803,8 @@ define half @test_ui_ui_i12_sub_fail_overflow(i12 noundef %x_in, i12 noundef %y_ ; CHECK-LABEL: @test_ui_ui_i12_sub_fail_overflow( ; CHECK-NEXT: [[X:%.*]] = and i12 [[X_IN:%.*]], 1023 ; CHECK-NEXT: [[Y:%.*]] = and i12 [[Y_IN:%.*]], 2047 -; CHECK-NEXT: [[XF:%.*]] = uitofp i12 [[X]] to half -; CHECK-NEXT: [[YF:%.*]] = uitofp i12 [[Y]] to half -; CHECK-NEXT: [[R:%.*]] = fsub half [[XF]], [[YF]] +; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i12 [[X]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = sitofp i12 [[TMP1]] to half ; CHECK-NEXT: ret half [[R]] ; %x = and i12 %x_in, 1023 @@ -984,7 +979,7 @@ define half @test_ui_si_i12_mul_nsw(i12 noundef %x_in, i12 noundef %y_in) { ; CHECK-NEXT: [[YY:%.*]] = and i12 [[Y_IN:%.*]], 30 ; CHECK-NEXT: [[Y:%.*]] = or disjoint i12 [[YY]], 1 ; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i12 [[X]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = sitofp i12 [[TMP1]] to half +; CHECK-NEXT: [[R:%.*]] = uitofp i12 [[TMP1]] to half ; CHECK-NEXT: ret half [[R]] ; %xx = and i12 %x_in, 31 @@ -1000,8 +995,8 @@ define half @test_ui_si_i12_mul_nsw(i12 noundef %x_in, i12 noundef %y_in) { define float @test_ui_add_with_signed_constant(i32 %shr.i) { ; CHECK-LABEL: @test_ui_add_with_signed_constant( ; CHECK-NEXT: [[AND_I:%.*]] = and i32 [[SHR_I:%.*]], 32767 -; CHECK-NEXT: [[SUB:%.*]] = uitofp i32 [[AND_I]] to float -; CHECK-NEXT: [[ADD:%.*]] = fadd float [[SUB]], -1.638300e+04 +; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[AND_I]], -16383 +; CHECK-NEXT: [[ADD:%.*]] = sitofp i32 [[TMP1]] to float ; CHECK-NEXT: ret float [[ADD]] ; %and.i = and i32 %shr.i, 32767 -- GitLab From 57a2229a2f62746d5616f0bd82a03b23eb459cf3 Mon Sep 17 00:00:00 2001 From: rohit-rao Date: Sat, 9 Mar 2024 12:12:06 -0500 Subject: [PATCH 027/953] [compiler-rt] Adds builtins support for xros. (#83484) Adds support for xros when compiling builtins. This is disabled by default and controlled with COMPILER_RT_ENABLE_XROS, similar to watchOS/tvOS. --- compiler-rt/cmake/base-config-ix.cmake | 1 + compiler-rt/cmake/builtin-config-ix.cmake | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/compiler-rt/cmake/base-config-ix.cmake b/compiler-rt/cmake/base-config-ix.cmake index 908c8a40278c..1e3317de80ac 100644 --- a/compiler-rt/cmake/base-config-ix.cmake +++ b/compiler-rt/cmake/base-config-ix.cmake @@ -156,6 +156,7 @@ if(APPLE) option(COMPILER_RT_ENABLE_WATCHOS "Enable building for watchOS - Experimental" Off) option(COMPILER_RT_ENABLE_TVOS "Enable building for tvOS - Experimental" Off) + option(COMPILER_RT_ENABLE_XROS "Enable building for xrOS - Experimental" Off) else() option(COMPILER_RT_DEFAULT_TARGET_ONLY "Build builtins only for the default target" Off) diff --git a/compiler-rt/cmake/builtin-config-ix.cmake b/compiler-rt/cmake/builtin-config-ix.cmake index b17c43bf6a68..d10222b7530a 100644 --- a/compiler-rt/cmake/builtin-config-ix.cmake +++ b/compiler-rt/cmake/builtin-config-ix.cmake @@ -92,6 +92,8 @@ if(APPLE) find_darwin_sdk_dir(DARWIN_watchos_SYSROOT watchos) find_darwin_sdk_dir(DARWIN_tvossim_SYSROOT appletvsimulator) find_darwin_sdk_dir(DARWIN_tvos_SYSROOT appletvos) + find_darwin_sdk_dir(DARWIN_xrossim_SYSROOT xrsimulator) + find_darwin_sdk_dir(DARWIN_xros_SYSROOT xros) # Get supported architecture from SDKSettings. function(sdk_has_arch_support sdk_path os arch has_support) @@ -162,6 +164,11 @@ if(APPLE) list(APPEND DARWIN_tvossim_BUILTIN_ALL_POSSIBLE_ARCHS arm64) endif() endif() + if(COMPILER_RT_ENABLE_XROS) + list(APPEND DARWIN_EMBEDDED_PLATFORMS xros) + set(DARWIN_xros_BUILTIN_ALL_POSSIBLE_ARCHS ${ARM64} ${ARM32}) + set(DARWIN_xrossim_BUILTIN_ALL_POSSIBLE_ARCHS arm64) + endif() set(BUILTIN_SUPPORTED_OS osx) -- GitLab From f5811494b0cde306e98caa339e4dc1c06cb5e8e9 Mon Sep 17 00:00:00 2001 From: Zain Jaffal Date: Sat, 9 Mar 2024 17:15:14 +0000 Subject: [PATCH 028/953] check if operand is div in fold FDivSqrtDivisor (#81970) This patch fixes the issues introduced in https://github.com/llvm/llvm-project/commit/bb5c3899d1936ebdf7ebf5ca4347ee2e057bee7f. I moved the check for the instruction to be div before I check for the fast math flags which resolves the crash in ``` float a, b; double sqrt(); void c() { b = a / sqrt(a); } ``` --------- Co-authored-by: Matt Arsenault --- .../InstCombine/InstCombineMulDivRem.cpp | 31 +++++++++++++++++ llvm/test/Transforms/InstCombine/fdiv-sqrt.ll | 34 ++++++++++++++----- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 3ebf6b3d9bf7..278be6233f4b 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1709,6 +1709,34 @@ static Instruction *foldFDivPowDivisor(BinaryOperator &I, return BinaryOperator::CreateFMulFMF(Op0, Pow, &I); } +/// Convert div to mul if we have an sqrt divisor iff sqrt's operand is a fdiv +/// instruction. +static Instruction *foldFDivSqrtDivisor(BinaryOperator &I, + InstCombiner::BuilderTy &Builder) { + // X / sqrt(Y / Z) --> X * sqrt(Z / Y) + if (!I.hasAllowReassoc() || !I.hasAllowReciprocal()) + return nullptr; + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + auto *II = dyn_cast(Op1); + if (!II || II->getIntrinsicID() != Intrinsic::sqrt || !II->hasOneUse() || + !II->hasAllowReassoc() || !II->hasAllowReciprocal()) + return nullptr; + + Value *Y, *Z; + auto *DivOp = dyn_cast(II->getOperand(0)); + if (!DivOp) + return nullptr; + if (!match(DivOp, m_FDiv(m_Value(Y), m_Value(Z)))) + return nullptr; + if (!DivOp->hasAllowReassoc() || !I.hasAllowReciprocal() || + !DivOp->hasOneUse()) + return nullptr; + Value *SwapDiv = Builder.CreateFDivFMF(Z, Y, DivOp); + Value *NewSqrt = + Builder.CreateUnaryIntrinsic(II->getIntrinsicID(), SwapDiv, II); + return BinaryOperator::CreateFMulFMF(Op0, NewSqrt, &I); +} + Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) { Module *M = I.getModule(); @@ -1816,6 +1844,9 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) { if (Instruction *Mul = foldFDivPowDivisor(I, Builder)) return Mul; + if (Instruction *Mul = foldFDivSqrtDivisor(I, Builder)) + return Mul; + // pow(X, Y) / X --> pow(X, Y-1) if (I.hasAllowReassoc() && match(Op0, m_OneUse(m_Intrinsic(m_Specific(Op1), diff --git a/llvm/test/Transforms/InstCombine/fdiv-sqrt.ll b/llvm/test/Transforms/InstCombine/fdiv-sqrt.ll index 346271be7da7..9f030c5ebf7b 100644 --- a/llvm/test/Transforms/InstCombine/fdiv-sqrt.ll +++ b/llvm/test/Transforms/InstCombine/fdiv-sqrt.ll @@ -6,9 +6,9 @@ declare double @llvm.sqrt.f64(double) define double @sqrt_div_fast(double %x, double %y, double %z) { ; CHECK-LABEL: @sqrt_div_fast( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[DIV:%.*]] = fdiv fast double [[Y:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[SQRT:%.*]] = call fast double @llvm.sqrt.f64(double [[DIV]]) -; CHECK-NEXT: [[DIV1:%.*]] = fdiv fast double [[X:%.*]], [[SQRT]] +; CHECK-NEXT: [[TMP0:%.*]] = fdiv fast double [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = call fast double @llvm.sqrt.f64(double [[TMP0]]) +; CHECK-NEXT: [[DIV1:%.*]] = fmul fast double [[TMP1]], [[X:%.*]] ; CHECK-NEXT: ret double [[DIV1]] ; entry: @@ -36,9 +36,9 @@ entry: define double @sqrt_div_reassoc_arcp(double %x, double %y, double %z) { ; CHECK-LABEL: @sqrt_div_reassoc_arcp( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc arcp double [[Y:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[SQRT:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[DIV]]) -; CHECK-NEXT: [[DIV1:%.*]] = fdiv reassoc arcp double [[X:%.*]], [[SQRT]] +; CHECK-NEXT: [[TMP0:%.*]] = fdiv reassoc arcp double [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[TMP0]]) +; CHECK-NEXT: [[DIV1:%.*]] = fmul reassoc arcp double [[TMP1]], [[X:%.*]] ; CHECK-NEXT: ret double [[DIV1]] ; entry: @@ -96,9 +96,9 @@ entry: define double @sqrt_div_arcp_missing(double %x, double %y, double %z) { ; CHECK-LABEL: @sqrt_div_arcp_missing( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[Y:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[SQRT:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[DIV]]) -; CHECK-NEXT: [[DIV1:%.*]] = fdiv reassoc arcp double [[X:%.*]], [[SQRT]] +; CHECK-NEXT: [[TMP0:%.*]] = fdiv reassoc double [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = call reassoc arcp double @llvm.sqrt.f64(double [[TMP0]]) +; CHECK-NEXT: [[DIV1:%.*]] = fmul reassoc arcp double [[TMP1]], [[X:%.*]] ; CHECK-NEXT: ret double [[DIV1]] ; entry: @@ -173,3 +173,19 @@ entry: ret double %div1 } +define float @sqrt_non_div_operator(float %a) { +; CHECK-LABEL: @sqrt_non_div_operator( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CONV:%.*]] = fpext float [[A:%.*]] to double +; CHECK-NEXT: [[SQRT:%.*]] = call fast double @llvm.sqrt.f64(double [[CONV]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv fast double [[CONV]], [[SQRT]] +; CHECK-NEXT: [[CONV2:%.*]] = fptrunc double [[DIV]] to float +; CHECK-NEXT: ret float [[CONV2]] +; +entry: + %conv = fpext float %a to double + %sqrt = call fast double @llvm.sqrt.f64(double %conv) + %div = fdiv fast double %conv, %sqrt + %conv2 = fptrunc double %div to float + ret float %conv2 +} -- GitLab From b4001e32b1aa4df07dc6babefba19f2b77f487c6 Mon Sep 17 00:00:00 2001 From: Amirreza Ashouri Date: Sat, 9 Mar 2024 20:47:29 +0330 Subject: [PATCH 029/953] [NFC] Eliminate trailing white space causing CI build failure (#84632) To resolve the following issue in the CI build: ``` *** Checking for trailing whitespace left in Clang source files *** + grep -rnI '[[:blank:]]$' clang/lib clang/include clang/docs clang/docs/ReleaseNotes.rst:412:- PTX is no longer included by default when compiling for CUDA. Using + echo '*** Trailing whitespace has been found in Clang source files as described above ***' *** Trailing whitespace has been found in Clang source files as described above *** + exit 1 ``` --- clang/docs/ReleaseNotes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f61dca9bbc84..3b89d5a87207 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -409,7 +409,7 @@ RISC-V Support CUDA/HIP Language Changes ^^^^^^^^^^^^^^^^^^^^^^^^^ -- PTX is no longer included by default when compiling for CUDA. Using +- PTX is no longer included by default when compiling for CUDA. Using ``--cuda-include-ptx=all`` will return the old behavior. CUDA Support -- GitLab From 110141b37813dc48af33de5e1407231e56acdfc5 Mon Sep 17 00:00:00 2001 From: Vadim Paretsky Date: Sat, 9 Mar 2024 10:47:31 -0800 Subject: [PATCH 030/953] [OpenMP] fix endianness dependent definitions in OMP headers for MSVC (#84540) MSVC does not define __BYTE_ORDER__ making the check for BigEndian erroneously evaluate to true and breaking the struct definitions in MSVC compiled builds correspondingly. The fix adds an additional check for whether __BYTE_ORDER__ is defined by the compiler to fix these. --------- Co-authored-by: Vadim Paretsky --- openmp/runtime/src/kmp.h | 4 ++-- openmp/runtime/src/kmp_lock.h | 3 ++- openmp/runtime/test/tasking/bug_nested_proxy_task.c | 2 +- openmp/runtime/test/tasking/bug_proxy_task_dep_waiting.c | 2 +- openmp/runtime/test/tasking/hidden_helper_task/common.h | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index 1fc31779a217..26dda9e1d018 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -2507,7 +2507,7 @@ typedef struct kmp_depend_info { union { kmp_uint8 flag; // flag as an unsigned char struct { // flag as a set of 8 bits -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) /* Same fields as in the #else branch, but in reverse order */ unsigned all : 1; unsigned unused : 3; @@ -2672,7 +2672,7 @@ typedef struct kmp_task_stack { #endif // BUILD_TIED_TASK_STACK typedef struct kmp_tasking_flags { /* Total struct must be exactly 32 bits */ -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) /* Same fields as in the #else branch, but in reverse order */ #if OMPX_TASKGRAPH unsigned reserved31 : 6; diff --git a/openmp/runtime/src/kmp_lock.h b/openmp/runtime/src/kmp_lock.h index e2a0cda01a97..6202f3d617cc 100644 --- a/openmp/runtime/src/kmp_lock.h +++ b/openmp/runtime/src/kmp_lock.h @@ -120,7 +120,8 @@ extern void __kmp_validate_locks(void); struct kmp_base_tas_lock { // KMP_LOCK_FREE(tas) => unlocked; locked: (gtid+1) of owning thread -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __LP64__ +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) && \ + __LP64__ // Flip the ordering of the high and low 32-bit member to be consistent // with the memory layout of the address in 64-bit big-endian. kmp_int32 depth_locked; // depth locked, for nested locks only diff --git a/openmp/runtime/test/tasking/bug_nested_proxy_task.c b/openmp/runtime/test/tasking/bug_nested_proxy_task.c index 24fe1f3fe760..9e0b412efce6 100644 --- a/openmp/runtime/test/tasking/bug_nested_proxy_task.c +++ b/openmp/runtime/test/tasking/bug_nested_proxy_task.c @@ -50,7 +50,7 @@ typedef struct kmp_depend_info { union { kmp_uint8 flag; // flag as an unsigned char struct { // flag as a set of 8 bits -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) unsigned all : 1; unsigned unused : 3; unsigned set : 1; diff --git a/openmp/runtime/test/tasking/bug_proxy_task_dep_waiting.c b/openmp/runtime/test/tasking/bug_proxy_task_dep_waiting.c index 688860c03572..1e86d574f4f6 100644 --- a/openmp/runtime/test/tasking/bug_proxy_task_dep_waiting.c +++ b/openmp/runtime/test/tasking/bug_proxy_task_dep_waiting.c @@ -47,7 +47,7 @@ typedef struct kmp_depend_info { union { kmp_uint8 flag; // flag as an unsigned char struct { // flag as a set of 8 bits -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) unsigned all : 1; unsigned unused : 3; unsigned set : 1; diff --git a/openmp/runtime/test/tasking/hidden_helper_task/common.h b/openmp/runtime/test/tasking/hidden_helper_task/common.h index ba57656cbac4..68e2b584c877 100644 --- a/openmp/runtime/test/tasking/hidden_helper_task/common.h +++ b/openmp/runtime/test/tasking/hidden_helper_task/common.h @@ -17,7 +17,7 @@ typedef struct kmp_depend_info { union { unsigned char flag; struct { -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) unsigned all : 1; unsigned unused : 3; unsigned set : 1; -- GitLab From 0d6f9bf274c1bc69e71ff7dd740f2cee1a4ca769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 9 Mar 2024 22:39:58 +0200 Subject: [PATCH 031/953] [asan] [test] Mark a new test UNSUPPORTED for MinGW targets This test uses the MSVC/clang-cl specific -EHsc flag. This test was recently added, in ea12c1fa15093e24818785b2ca6e06588372a3bf. --- compiler-rt/test/asan/TestCases/Windows/issue64990.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp b/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp index a5a46b5a81dd..aab66502bd16 100644 --- a/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp @@ -2,6 +2,8 @@ // RUN: %clang_cl_asan %Od %s -EHsc %Fe%t // RUN: not %run %t 2>&1 | FileCheck %s +// UNSUPPORTED: target={{.*-windows-gnu}} + char buff1[6] = "hello"; char buff2[6] = "hello"; -- GitLab From 6f7ebcb71f4e89309c613da9600991850f15f74f Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Sat, 9 Mar 2024 12:49:54 -0800 Subject: [PATCH 032/953] [NFC][compiler-rt] Try to collect more info about crashes on bot --- compiler-rt/lib/lsan/lsan_common.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp index 0ecded8b28cd..568bd65ba467 100644 --- a/compiler-rt/lib/lsan/lsan_common.cpp +++ b/compiler-rt/lib/lsan/lsan_common.cpp @@ -568,6 +568,7 @@ static void ProcessRootRegions(Frontier *frontier) { MemoryMappingLayout proc_maps(/*cache_enabled*/ true); MemoryMappedSegment segment; InternalMmapVector mapped_regions; + CHECK_EQ(mapped_regions.size(), 0ull); while (proc_maps.Next(&segment)) if (segment.IsReadable()) mapped_regions.push_back({segment.start, segment.end}); -- GitLab From 0be1c3b92b64373df4057f52f9676c36567253ef Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Sat, 9 Mar 2024 14:20:15 -0800 Subject: [PATCH 033/953] [workflows] Mention the correct user who makes a /cherry-pick comment (#82680) We were mentioning the creator of the issue with the comment rather than the creator of the comment. Fixes #82580 --- .github/workflows/issue-release-workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/issue-release-workflow.yml b/.github/workflows/issue-release-workflow.yml index 448c1c56f897..eb88ec6e43c5 100644 --- a/.github/workflows/issue-release-workflow.yml +++ b/.github/workflows/issue-release-workflow.yml @@ -65,5 +65,5 @@ jobs: release-workflow \ --branch-repo-token ${{ secrets.RELEASE_WORKFLOW_PUSH_SECRET }} \ --issue-number ${{ github.event.issue.number }} \ - --requested-by ${{ github.event.issue.user.login }} \ + --requested-by ${{ (github.event.action == 'opened' && github.event.issue.user.login) || github.event.comment.user.login }} \ auto -- GitLab From bf8c7cda492f227d7e9a9fbc8e7a39adc7380a0e Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Sat, 9 Mar 2024 14:21:40 -0800 Subject: [PATCH 034/953] Revert "[NFC][compiler-rt] Try to collect more info about crashes on bot" Catches nothing, reported #84654. This reverts commit 6f7ebcb71f4e89309c613da9600991850f15f74f. --- compiler-rt/lib/lsan/lsan_common.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp index 568bd65ba467..0ecded8b28cd 100644 --- a/compiler-rt/lib/lsan/lsan_common.cpp +++ b/compiler-rt/lib/lsan/lsan_common.cpp @@ -568,7 +568,6 @@ static void ProcessRootRegions(Frontier *frontier) { MemoryMappingLayout proc_maps(/*cache_enabled*/ true); MemoryMappedSegment segment; InternalMmapVector mapped_regions; - CHECK_EQ(mapped_regions.size(), 0ull); while (proc_maps.Next(&segment)) if (segment.IsReadable()) mapped_regions.push_back({segment.start, segment.end}); -- GitLab From 15e9478187d594016c2c355d8688be2e0a9b554e Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Sat, 9 Mar 2024 14:31:53 -0800 Subject: [PATCH 035/953] [sanitizer] Disable COMPILER_RT_HAS_TRIVIAL_AUTO_INIT on PowerPC to fix the bot See issue #84654. --- compiler-rt/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index 8a2b138d8d70..d562a6206c00 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -502,7 +502,10 @@ append_list_if(MINGW -fms-extensions SANITIZER_COMMON_CFLAGS) # # Note that this type of issue was discovered with lsan, but can apply to other # sanitizers. -append_list_if(COMPILER_RT_HAS_TRIVIAL_AUTO_INIT -ftrivial-auto-var-init=pattern SANITIZER_COMMON_CFLAGS) +# Disable PowerPC because of https://github.com/llvm/llvm-project/issues/84654. +if(NOT "${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "powerpc") + append_list_if(COMPILER_RT_HAS_TRIVIAL_AUTO_INIT -ftrivial-auto-var-init=pattern SANITIZER_COMMON_CFLAGS) +endif() # Set common link flags. # TODO: We should consider using the same model as libc++, that is use either -- GitLab From c1029b6a9b423320ec8f0d1cde24d8f4d8139f63 Mon Sep 17 00:00:00 2001 From: Matthias Springer Date: Sun, 10 Mar 2024 12:10:53 +0900 Subject: [PATCH 036/953] [mlir][Transform] `apply_conversion_patterns`: Update handles (#83950) Until now, `transform.apply_conversion_patterns` consumed the target handle and potentially invalidated handles. This commit adds tracking functionality similar to `transform.apply_patterns`, such that handles are no longer invalidated, but updated based on op replacements performed by the dialect conversion. This new functionality is hidden behind a `preserve_handles` attribute for now. --- .../Transform/IR/TransformInterfaces.h | 32 +++++++++---- .../mlir/Dialect/Transform/IR/TransformOps.td | 19 ++++++-- .../Transform/IR/TransformInterfaces.cpp | 39 ++++++++-------- .../lib/Dialect/Transform/IR/TransformOps.cpp | 45 ++++++++++++++++--- .../Transform/test-pattern-application.mlir | 30 +++++++++++++ 5 files changed, 130 insertions(+), 35 deletions(-) diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h b/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h index 313cdc27f780..32724ff4b98e 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h +++ b/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h @@ -921,20 +921,36 @@ TransformState::RegionScope TransformState::make_region_scope(Region ®ion) { return RegionScope(*this, region); } +/// A configuration object for customizing a `TrackingListener`. +struct TrackingListenerConfig { + using SkipHandleFn = std::function; + + /// An optional function that returns "true" for handles that do not have to + /// be updated. These are typically dead or consumed handles. + SkipHandleFn skipHandleFn = nullptr; + + /// If set to "true", the name of a replacement op must match the name of the + /// original op. If set to "false", the names of the payload ops tracked in a + /// handle may change as the tracking listener updates the transform state. + bool requireMatchingReplacementOpName = true; + + /// If set to "true", cast ops (that implement the CastOpInterface) are + /// skipped and the replacement op search continues with the operands of the + /// cast op. + bool skipCastOps = true; +}; + /// A listener that updates a TransformState based on IR modifications. This /// listener can be used during a greedy pattern rewrite to keep the transform /// state up-to-date. class TrackingListener : public RewriterBase::Listener, public TransformState::Extension { public: - /// A function that returns "true" for handles that do not have to be updated. - using SkipHandleFn = std::function; - /// Create a new TrackingListener for usage in the specified transform op. /// Optionally, a function can be specified to identify handles that should /// do not have to be updated. TrackingListener(TransformState &state, TransformOpInterface op, - SkipHandleFn skipHandleFn = nullptr); + TrackingListenerConfig config = TrackingListenerConfig()); protected: /// Return a replacement payload op for the given op, which is going to be @@ -959,7 +975,8 @@ protected: /// same computation; e.g., there may be tiled "linalg.generic" inside the /// loop body that represents the original computation. Therefore, the /// TrackingListener is conservative by default: it drops the mapping and - /// triggers the "payload replacement not found" notification. + /// triggers the "payload replacement not found" notification. This default + /// behavior can be customized in `TrackingListenerConfig`. /// /// If no replacement op could be found according to the rules mentioned /// above, this function tries to skip over cast-like ops that implement @@ -1023,9 +1040,8 @@ private: /// The handles that are consumed by the transform op. DenseSet consumedHandles; - /// Handles for which this function evaluates to "true" do not have to be - /// updated. These are typically dead or consumed handles. - SkipHandleFn skipHandleFn; + /// Tracking listener configuration. + TrackingListenerConfig config; }; /// A specialized listener that keeps track of cases in which no replacement diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td b/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td index 9f513822ed0a..1766e4bb875f 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td +++ b/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td @@ -190,11 +190,21 @@ def ApplyConversionPatternsOp : TransformDialectOp<"apply_conversion_patterns", The `legal_ops`, `illegal_ops`, `legal_dialects`, `illegal_dialects` attributes specify the conversion target. - This transform consumes the `target` handle and modifies the payload. It - does not produce any handles. + This transform modifies the payload. By default, it consumes the `target` + handle. It does not produce any handles. + + If the `preserve_handles` attribute is set, this transform does not consume + the `target` handle and instead updates handles based on notifications from + a tracking listener that is attached to the dialect conversion, similar to + `transform.apply_patterns`. Only replacements via `RewriterBase::replaceOp` + or `replaceOpWithNewOp` are considered "payload op replacements". In + contrast to `transform.apply_patterns`, we allow replacement ops even if the + op name has changed. This is because conversion patterns are expected to + lower ops to different ops (from a different dialect). More details can be + found at the documentation site of `TrackingListener`. This transform produces a silenceable failure if the dialect conversion was - unsuccessful. + unsuccessful or the tracking listener failed to find a replacement op. }]; let arguments = (ins TransformHandleTypeInterface:$target, @@ -202,7 +212,8 @@ def ApplyConversionPatternsOp : TransformDialectOp<"apply_conversion_patterns", OptionalAttr:$illegal_ops, OptionalAttr:$legal_dialects, OptionalAttr:$illegal_dialects, - UnitAttr:$partial_conversion); + UnitAttr:$partial_conversion, + UnitAttr:$preserve_handles); let results = (outs); let regions = (region MaxSizedRegion<1>:$patterns, diff --git a/mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp b/mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp index bb9f6fec4529..71a9d61198e3 100644 --- a/mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp +++ b/mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp @@ -918,7 +918,8 @@ transform::TransformState::applyTransform(TransformOpInterface transform) { } // Prepare rewriter and listener. - TrackingListener::SkipHandleFn skipHandleFn = [&](Value handle) { + TrackingListenerConfig config; + config.skipHandleFn = [&](Value handle) { // Skip handle if it is dead. auto scopeIt = llvm::find_if(llvm::reverse(regionStack), [&](RegionScope *scope) { @@ -935,7 +936,7 @@ transform::TransformState::applyTransform(TransformOpInterface transform) { return true; }; transform::ErrorCheckingTrackingListener trackingListener(*this, transform, - skipHandleFn); + config); transform::TransformRewriter rewriter(transform->getContext(), &trackingListener); @@ -1184,9 +1185,8 @@ bool transform::TransformResults::isSet(unsigned resultNumber) const { transform::TrackingListener::TrackingListener(TransformState &state, TransformOpInterface op, - SkipHandleFn skipHandleFn) - : TransformState::Extension(state), transformOp(op), - skipHandleFn(skipHandleFn) { + TrackingListenerConfig config) + : TransformState::Extension(state), transformOp(op), config(config) { if (op) { for (OpOperand *opOperand : transformOp.getConsumedHandleOpOperands()) { consumedHandles.insert(opOperand->get()); @@ -1228,8 +1228,19 @@ DiagnosedSilenceableFailure transform::TrackingListener::findReplacementOp( return diag; } - // If the defining op has the same type, we take it as a replacement. - if (op->getName() == defOp->getName()) { + // Skip through ops that implement CastOpInterface. + if (config.skipCastOps && isa(defOp)) { + values.clear(); + values.assign(defOp->getOperands().begin(), defOp->getOperands().end()); + diag.attachNote(defOp->getLoc()) + << "using output of 'CastOpInterface' op"; + continue; + } + + // If the defining op has the same name or we do not care about the name of + // op replacements at all, we take it as a replacement. + if (!config.requireMatchingReplacementOpName || + op->getName() == defOp->getName()) { result = defOp; return DiagnosedSilenceableFailure::success(); } @@ -1251,14 +1262,6 @@ DiagnosedSilenceableFailure transform::TrackingListener::findReplacementOp( "'FindPayloadReplacementOpInterface'"; continue; } - - // Skip through ops that implement CastOpInterface. - if (isa(defOp)) { - values.assign(defOp->getOperands().begin(), defOp->getOperands().end()); - diag.attachNote(defOp->getLoc()) - << "using output of 'CastOpInterface' op"; - continue; - } } while (!values.empty()); diag.attachNote() << "ran out of suitable replacement values"; @@ -1318,9 +1321,9 @@ void transform::TrackingListener::notifyOperationReplaced( // Check if there are any handles that must be updated. Value aliveHandle; - if (skipHandleFn) { - auto it = - llvm::find_if(opHandles, [&](Value v) { return !skipHandleFn(v); }); + if (config.skipHandleFn) { + auto it = llvm::find_if(opHandles, + [&](Value v) { return !config.skipHandleFn(v); }); if (it != opHandles.end()) aliveHandle = *it; } else if (!opHandles.empty()) { diff --git a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp index 180d11c30e65..ca80899ab073 100644 --- a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp +++ b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp @@ -563,6 +563,17 @@ DiagnosedSilenceableFailure transform::ApplyConversionPatternsOp::apply( } } + // Attach a tracking listener if handles should be preserved. We configure the + // listener to allow op replacements with different names, as conversion + // patterns typically replace ops with replacement ops that have a different + // name. + TrackingListenerConfig trackingConfig; + trackingConfig.requireMatchingReplacementOpName = false; + ErrorCheckingTrackingListener trackingListener(state, *this, trackingConfig); + ConversionConfig conversionConfig; + if (getPreserveHandles()) + conversionConfig.listener = &trackingListener; + FrozenRewritePatternSet frozenPatterns(std::move(patterns)); for (Operation *target : state.getPayloadOps(getTarget())) { // Make sure that this transform is not applied to itself. Modifying the @@ -574,16 +585,36 @@ DiagnosedSilenceableFailure transform::ApplyConversionPatternsOp::apply( LogicalResult status = failure(); if (getPartialConversion()) { - status = applyPartialConversion(target, conversionTarget, frozenPatterns); + status = applyPartialConversion(target, conversionTarget, frozenPatterns, + conversionConfig); } else { - status = applyFullConversion(target, conversionTarget, frozenPatterns); + status = applyFullConversion(target, conversionTarget, frozenPatterns, + conversionConfig); } + // Check dialect conversion state. + DiagnosedSilenceableFailure diag = DiagnosedSilenceableFailure::success(); if (failed(status)) { - auto diag = emitSilenceableError() << "dialect conversion failed"; + diag = emitSilenceableError() << "dialect conversion failed"; diag.attachNote(target->getLoc()) << "target op"; - return diag; } + + // Check tracking listener error state. + DiagnosedSilenceableFailure trackingFailure = + trackingListener.checkAndResetError(); + if (!trackingFailure.succeeded()) { + if (diag.succeeded()) { + // Tracking failure is the only failure. + return trackingFailure; + } else { + diag.attachNote() << "tracking listener also failed: " + << trackingFailure.getMessage(); + (void)trackingFailure.silence(); + } + } + + if (!diag.succeeded()) + return diag; } return DiagnosedSilenceableFailure::success(); @@ -632,7 +663,11 @@ LogicalResult transform::ApplyConversionPatternsOp::verify() { void transform::ApplyConversionPatternsOp::getEffects( SmallVectorImpl &effects) { - transform::consumesHandle(getTarget(), effects); + if (!getPreserveHandles()) { + transform::consumesHandle(getTarget(), effects); + } else { + transform::onlyReadsHandle(getTarget(), effects); + } transform::modifiesPayload(effects); } diff --git a/mlir/test/Dialect/Transform/test-pattern-application.mlir b/mlir/test/Dialect/Transform/test-pattern-application.mlir index 0c41e81b17b5..fa8a555af921 100644 --- a/mlir/test/Dialect/Transform/test-pattern-application.mlir +++ b/mlir/test/Dialect/Transform/test-pattern-application.mlir @@ -417,3 +417,33 @@ module attributes { transform.with_named_sequence } { transform.yield } } + +// ----- + +// "test.foo" is tracked and replaced with "test.new_op" during a dialect +// conversion. Make sure that the handle is updated accordingly. + +// CHECK-LABEL: func @dialect_conversion_tracking +// CHECK-NEXT: %[[m:.*]] = "test.new_op"() {annotated} : () -> memref<5xf32> +// CHECK-NEXT: %[[cast:.*]] = builtin.unrealized_conversion_cast %0 : memref<5xf32> to tensor<5xf32> +// CHECK-NEXT: return %[[cast]] +func.func @dialect_conversion_tracking() -> tensor<5xf32> { + %0 = "test.foo"() {replace_with_new_op = "test.bar"} : () -> (tensor<5xf32>) + return %0 : tensor<5xf32> +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg1: !transform.any_op) { + %0 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op + %1 = transform.structured.match ops{["test.foo"]} in %0 : (!transform.any_op) -> !transform.any_op + transform.apply_conversion_patterns to %0 { + transform.apply_conversion_patterns.transform.test_conversion_patterns + } with type_converter { + transform.apply_conversion_patterns.transform.test_type_converter + } {legal_ops = ["func.func", "func.return", "test.new_op"], preserve_handles} + : !transform.any_op + // Add an attribute to %1, which is now mapped to a new op. + transform.annotate %1 "annotated" : !transform.any_op + transform.yield + } +} -- GitLab From 9b6bd7093ccb07ba8d6987220b2703549af02933 Mon Sep 17 00:00:00 2001 From: Matthias Springer Date: Sun, 10 Mar 2024 12:12:50 +0900 Subject: [PATCH 037/953] [mlir][IR] Add listener notifications for pattern begin/end (#84131) This commit adds two new notifications to `RewriterBase::Listener`: * `notifyPatternBegin`: Called when a pattern application begins during a greedy pattern rewrite or dialect conversion. * `notifyPatternEnd`: Called when a pattern application finishes during a greedy pattern rewrite or dialect conversion. The listener infrastructure already provides a `notifyMatchFailure` callback that notifies about the reason for a pattern match failure. The two new notifications provide additional information about pattern applications. This change is in preparation of improving the handle update mechanism in the `apply_conversion_patterns` transform op. --- mlir/include/mlir/IR/PatternMatch.h | 30 ++++++++++++++--- .../Transforms/Utils/DialectConversion.cpp | 29 +++++++++++----- .../Utils/GreedyPatternRewriteDriver.cpp | 33 +++++++++++++------ 3 files changed, 69 insertions(+), 23 deletions(-) diff --git a/mlir/include/mlir/IR/PatternMatch.h b/mlir/include/mlir/IR/PatternMatch.h index e3500b3f9446..49544c42790d 100644 --- a/mlir/include/mlir/IR/PatternMatch.h +++ b/mlir/include/mlir/IR/PatternMatch.h @@ -432,11 +432,22 @@ public: /// Note: This notification is not triggered when unlinking an operation. virtual void notifyOperationErased(Operation *op) {} - /// Notify the listener that the pattern failed to match the given - /// operation, and provide a callback to populate a diagnostic with the - /// reason why the failure occurred. This method allows for derived - /// listeners to optionally hook into the reason why a rewrite failed, and - /// display it to users. + /// Notify the listener that the specified pattern is about to be applied + /// at the specified root operation. + virtual void notifyPatternBegin(const Pattern &pattern, Operation *op) {} + + /// Notify the listener that a pattern application finished with the + /// specified status. "success" indicates that the pattern was applied + /// successfully. "failure" indicates that the pattern could not be + /// applied. The pattern may have communicated the reason for the failure + /// with `notifyMatchFailure`. + virtual void notifyPatternEnd(const Pattern &pattern, + LogicalResult status) {} + + /// Notify the listener that the pattern failed to match, and provide a + /// callback to populate a diagnostic with the reason why the failure + /// occurred. This method allows for derived listeners to optionally hook + /// into the reason why a rewrite failed, and display it to users. virtual void notifyMatchFailure(Location loc, function_ref reasonCallback) {} @@ -478,6 +489,15 @@ public: if (auto *rewriteListener = dyn_cast(listener)) rewriteListener->notifyOperationErased(op); } + void notifyPatternBegin(const Pattern &pattern, Operation *op) override { + if (auto *rewriteListener = dyn_cast(listener)) + rewriteListener->notifyPatternBegin(pattern, op); + } + void notifyPatternEnd(const Pattern &pattern, + LogicalResult status) override { + if (auto *rewriteListener = dyn_cast(listener)) + rewriteListener->notifyPatternEnd(pattern, status); + } void notifyMatchFailure( Location loc, function_ref reasonCallback) override { diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp b/mlir/lib/Transforms/Utils/DialectConversion.cpp index c1a261eab848..cd49bd121a62 100644 --- a/mlir/lib/Transforms/Utils/DialectConversion.cpp +++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp @@ -1856,7 +1856,8 @@ public: using LegalizationAction = ConversionTarget::LegalizationAction; OperationLegalizer(const ConversionTarget &targetInfo, - const FrozenRewritePatternSet &patterns); + const FrozenRewritePatternSet &patterns, + const ConversionConfig &config); /// Returns true if the given operation is known to be illegal on the target. bool isIllegal(Operation *op) const; @@ -1948,12 +1949,16 @@ private: /// The pattern applicator to use for conversions. PatternApplicator applicator; + + /// Dialect conversion configuration. + const ConversionConfig &config; }; } // namespace OperationLegalizer::OperationLegalizer(const ConversionTarget &targetInfo, - const FrozenRewritePatternSet &patterns) - : target(targetInfo), applicator(patterns) { + const FrozenRewritePatternSet &patterns, + const ConversionConfig &config) + : target(targetInfo), applicator(patterns), config(config) { // The set of patterns that can be applied to illegal operations to transform // them into legal ones. DenseMap legalizerPatterns; @@ -2098,7 +2103,10 @@ OperationLegalizer::legalizeWithPattern(Operation *op, // Functor that returns if the given pattern may be applied. auto canApply = [&](const Pattern &pattern) { - return canApplyPattern(op, pattern, rewriter); + bool canApply = canApplyPattern(op, pattern, rewriter); + if (canApply && config.listener) + config.listener->notifyPatternBegin(pattern, op); + return canApply; }; // Functor that cleans up the rewriter state after a pattern failed to match. @@ -2115,6 +2123,8 @@ OperationLegalizer::legalizeWithPattern(Operation *op, rewriterImpl.config.notifyCallback(diag); } }); + if (config.listener) + config.listener->notifyPatternEnd(pattern, failure()); rewriterImpl.resetState(curState); appliedPatterns.erase(&pattern); }; @@ -2127,6 +2137,8 @@ OperationLegalizer::legalizeWithPattern(Operation *op, appliedPatterns.erase(&pattern); if (failed(result)) rewriterImpl.resetState(curState); + if (config.listener) + config.listener->notifyPatternEnd(pattern, result); return result; }; @@ -2502,7 +2514,8 @@ struct OperationConverter { const FrozenRewritePatternSet &patterns, const ConversionConfig &config, OpConversionMode mode) - : opLegalizer(target, patterns), config(config), mode(mode) {} + : config(config), opLegalizer(target, patterns, this->config), + mode(mode) {} /// Converts the given operations to the conversion target. LogicalResult convertOperations(ArrayRef ops); @@ -2539,12 +2552,12 @@ private: ConversionPatternRewriterImpl &rewriterImpl, const DenseMap> &inverseMapping); - /// The legalizer to use when converting operations. - OperationLegalizer opLegalizer; - /// Dialect conversion configuration. ConversionConfig config; + /// The legalizer to use when converting operations. + OperationLegalizer opLegalizer; + /// The conversion mode to use when legalizing operations. OpConversionMode mode; }; diff --git a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp index 51d2f5e01b72..6cb5635e68c9 100644 --- a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp +++ b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp @@ -562,8 +562,7 @@ bool GreedyPatternRewriteDriver::processWorklist() { // Try to match one of the patterns. The rewriter is automatically // notified of any necessary changes, so there is nothing else to do // here. -#ifndef NDEBUG - auto canApply = [&](const Pattern &pattern) { + auto canApplyCallback = [&](const Pattern &pattern) { LLVM_DEBUG({ logger.getOStream() << "\n"; logger.startLine() << "* Pattern " << pattern.getDebugName() << " : '" @@ -572,20 +571,34 @@ bool GreedyPatternRewriteDriver::processWorklist() { logger.getOStream() << ")' {\n"; logger.indent(); }); + if (config.listener) + config.listener->notifyPatternBegin(pattern, op); return true; }; - auto onFailure = [&](const Pattern &pattern) { + function_ref canApply = canApplyCallback; + auto onFailureCallback = [&](const Pattern &pattern) { LLVM_DEBUG(logResult("failure", "pattern failed to match")); + if (config.listener) + config.listener->notifyPatternEnd(pattern, failure()); }; - auto onSuccess = [&](const Pattern &pattern) { + function_ref onFailure = onFailureCallback; + auto onSuccessCallback = [&](const Pattern &pattern) { LLVM_DEBUG(logResult("success", "pattern applied successfully")); + if (config.listener) + config.listener->notifyPatternEnd(pattern, success()); return success(); }; -#else - function_ref canApply = {}; - function_ref onFailure = {}; - function_ref onSuccess = {}; -#endif + function_ref onSuccess = onSuccessCallback; + +#ifdef NDEBUG + // Optimization: PatternApplicator callbacks are not needed when running in + // optimized mode and without a listener. + if (!config.listener) { + canApply = nullptr; + onFailure = nullptr; + onSuccess = nullptr; + } +#endif // NDEBUG #if MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS if (config.scope) { @@ -731,7 +744,7 @@ void GreedyPatternRewriteDriver::notifyMatchFailure( LLVM_DEBUG({ Diagnostic diag(loc, DiagnosticSeverity::Remark); reasonCallback(diag); - logger.startLine() << "** Failure : " << diag.str() << "\n"; + logger.startLine() << "** Match Failure : " << diag.str() << "\n"; }); if (config.listener) config.listener->notifyMatchFailure(loc, reasonCallback); -- GitLab From e95040f0f05b74406e9d7ee02b110470588cc5f0 Mon Sep 17 00:00:00 2001 From: OverMighty Date: Sun, 10 Mar 2024 05:54:03 +0000 Subject: [PATCH 038/953] [clang][Interp] Implement __builtin_popcountg (#84500) The previous code would truncate IntegerAPs wider than 64 bits. --- clang/lib/AST/Interp/InterpBuiltin.cpp | 7 ++--- clang/test/AST/Interp/builtin-functions.cpp | 29 +++++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index 5250d02be85a..c500b9d502d7 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -53,11 +53,7 @@ static APSInt peekToAPSInt(InterpStack &Stk, PrimType T, size_t Offset = 0) { Offset = align(primSize(T)); APSInt R; - INT_TYPE_SWITCH(T, { - T Val = Stk.peek(Offset); - R = APSInt(APInt(Val.bitWidth(), static_cast(Val), T::isSigned()), - !T::isSigned()); - }); + INT_TYPE_SWITCH(T, R = Stk.peek(Offset).toAPSInt()); return R; } @@ -1052,6 +1048,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, case Builtin::BI__builtin_popcount: case Builtin::BI__builtin_popcountl: case Builtin::BI__builtin_popcountll: + case Builtin::BI__builtin_popcountg: case Builtin::BI__popcnt16: // Microsoft variants of popcount case Builtin::BI__popcnt: case Builtin::BI__popcnt64: diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index ab8abac4b36e..08fca8428cf5 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -268,6 +268,24 @@ namespace popcount { static_assert(__builtin_popcountl(0) == 0, ""); static_assert(__builtin_popcountll(~0ull) == __CHAR_BIT__ * sizeof(unsigned long long), ""); static_assert(__builtin_popcountll(0) == 0, ""); + static_assert(__builtin_popcountg((unsigned char)~0) == __CHAR_BIT__ * sizeof(unsigned char), ""); + static_assert(__builtin_popcountg((unsigned char)0) == 0, ""); + static_assert(__builtin_popcountg((unsigned short)~0) == __CHAR_BIT__ * sizeof(unsigned short), ""); + static_assert(__builtin_popcountg((unsigned short)0) == 0, ""); + static_assert(__builtin_popcountg(~0u) == __CHAR_BIT__ * sizeof(unsigned int), ""); + static_assert(__builtin_popcountg(0u) == 0, ""); + static_assert(__builtin_popcountg(~0ul) == __CHAR_BIT__ * sizeof(unsigned long), ""); + static_assert(__builtin_popcountg(0ul) == 0, ""); + static_assert(__builtin_popcountg(~0ull) == __CHAR_BIT__ * sizeof(unsigned long long), ""); + static_assert(__builtin_popcountg(0ull) == 0, ""); +#ifdef __SIZEOF_INT128__ + static_assert(__builtin_popcountg(~(unsigned __int128)0) == __CHAR_BIT__ * sizeof(unsigned __int128), ""); + static_assert(__builtin_popcountg((unsigned __int128)0) == 0, ""); +#endif +#ifndef __AVR__ + static_assert(__builtin_popcountg(~(unsigned _BitInt(128))0) == __CHAR_BIT__ * sizeof(unsigned _BitInt(128)), ""); + static_assert(__builtin_popcountg((unsigned _BitInt(128))0) == 0, ""); +#endif /// From test/Sema/constant-builtins-2.c char popcount1[__builtin_popcount(0) == 0 ? 1 : -1]; @@ -280,6 +298,17 @@ namespace popcount { char popcount8[__builtin_popcountll(0LL) == 0 ? 1 : -1]; char popcount9[__builtin_popcountll(0xF0F0LL) == 8 ? 1 : -1]; char popcount10[__builtin_popcountll(~0LL) == BITSIZE(long long) ? 1 : -1]; + char popcount11[__builtin_popcountg(0U) == 0 ? 1 : -1]; + char popcount12[__builtin_popcountg(0xF0F0U) == 8 ? 1 : -1]; + char popcount13[__builtin_popcountg(~0U) == BITSIZE(int) ? 1 : -1]; + char popcount14[__builtin_popcountg(~0UL) == BITSIZE(long) ? 1 : -1]; + char popcount15[__builtin_popcountg(~0ULL) == BITSIZE(long long) ? 1 : -1]; +#ifdef __SIZEOF_INT128__ + char popcount16[__builtin_popcountg(~(unsigned __int128)0) == BITSIZE(__int128) ? 1 : -1]; +#endif +#ifndef __AVR__ + char popcount17[__builtin_popcountg(~(unsigned _BitInt(128))0) == BITSIZE(_BitInt(128)) ? 1 : -1]; +#endif } namespace parity { -- GitLab From d2353ae00c3b0b0e9a9b93578e9bb067f699f193 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Sat, 9 Mar 2024 22:34:18 -0800 Subject: [PATCH 039/953] [utils/TableGen/X86CompressEVEXTablesEmitter.cpp] Make sure the tablegen output for the `checkPredicate` function is deterministic (#84533) The output for the `checkPredicate` function was depending on a `std::map` iteration that was non-deterministic from run to run, because the keys were pointer values. Make a change so that the keys are `StringRef`s so the ordering is stable. --- llvm/utils/TableGen/X86CompressEVEXTablesEmitter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/utils/TableGen/X86CompressEVEXTablesEmitter.cpp b/llvm/utils/TableGen/X86CompressEVEXTablesEmitter.cpp index b96d16b9797c..0a9abbfe186e 100644 --- a/llvm/utils/TableGen/X86CompressEVEXTablesEmitter.cpp +++ b/llvm/utils/TableGen/X86CompressEVEXTablesEmitter.cpp @@ -46,7 +46,7 @@ class X86CompressEVEXTablesEmitter { typedef std::pair Entry; - typedef std::map> + typedef std::map> PredicateInstMap; std::vector Table; @@ -90,7 +90,7 @@ void X86CompressEVEXTablesEmitter::printCheckPredicate( for (const auto &[Key, Val] : PredicateInsts) { for (const auto &Inst : Val) OS << " case X86::" << Inst->TheDef->getName() << ":\n"; - OS << " return " << Key->getValueAsString("CondString") << ";\n"; + OS << " return " << Key << ";\n"; } OS << " }\n"; @@ -226,7 +226,7 @@ void X86CompressEVEXTablesEmitter::run(raw_ostream &OS) { Name == "HasAVXIFMA"; }); if (It != Predicates.end()) - PredicateInsts[*It].push_back(NewInst); + PredicateInsts[(*It)->getValueAsString("CondString")].push_back(NewInst); } printTable(Table, OS); -- GitLab From 35b784379e707423f3b4f5a2cfedabcfa6f5b47d Mon Sep 17 00:00:00 2001 From: Michael Flanders Date: Sat, 9 Mar 2024 22:46:39 -0800 Subject: [PATCH 040/953] [libc][stdbit][c23] fixes typos in bit_width, bit_floor C type-generic macros (#84659) Fixes #84658. Assuming these were typos in the first place. I am unsure of the best way to ensure that both sides of the preprocessor condition in `libc/include/llvm-libc-macros/stdbit-macros.h` are tested. Could someone point me in the right direction for adding test coverage to the non `__cplusplus` branch? Or maybe it is being tested and I've missed it. --- libc/include/llvm-libc-macros/stdbit-macros.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libc/include/llvm-libc-macros/stdbit-macros.h b/libc/include/llvm-libc-macros/stdbit-macros.h index 5b51068f866b..e3eb6630afdd 100644 --- a/libc/include/llvm-libc-macros/stdbit-macros.h +++ b/libc/include/llvm-libc-macros/stdbit-macros.h @@ -274,14 +274,14 @@ inline unsigned long long stdc_bit_floor(unsigned long long x) { unsigned long long: stdc_has_single_bit_ull)(x) #define stdc_bit_width(x) \ _Generic((x), \ - unsigned char: stdc_bit_width_ui, \ + unsigned char: stdc_bit_width_uc, \ unsigned short: stdc_bit_width_us, \ unsigned: stdc_bit_width_ui, \ unsigned long: stdc_bit_width_ul, \ unsigned long long: stdc_bit_width_ull)(x) #define stdc_bit_floor(x) \ _Generic((x), \ - unsigned char: stdc_bit_floor_ui, \ + unsigned char: stdc_bit_floor_uc, \ unsigned short: stdc_bit_floor_us, \ unsigned: stdc_bit_floor_ui, \ unsigned long: stdc_bit_floor_ul, \ -- GitLab From fa4cc39255767bbaf63a6a3b445dc94b43ebd447 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sun, 10 Mar 2024 09:56:55 +0000 Subject: [PATCH 041/953] [openmp] adding affinity support to DragonFlyBSD. (#84672) --- openmp/runtime/src/kmp.h | 2 +- openmp/runtime/src/kmp_affinity.cpp | 8 +++++--- openmp/runtime/src/kmp_affinity.h | 11 ++++++----- openmp/runtime/src/kmp_os.h | 3 ++- openmp/runtime/src/kmp_runtime.cpp | 6 ++++-- openmp/runtime/src/z_Linux_util.cpp | 8 ++++---- 6 files changed, 22 insertions(+), 16 deletions(-) diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index 26dda9e1d018..6510dd9b3561 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -3912,7 +3912,7 @@ extern void __kmp_balanced_affinity(kmp_info_t *th, int team_size); #if KMP_WEIGHTED_ITERATIONS_SUPPORTED extern int __kmp_get_first_osid_with_ecore(void); #endif -#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD +#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY extern int kmp_set_thread_affinity_mask_initial(void); #endif static inline void __kmp_assign_root_init_mask() { diff --git a/openmp/runtime/src/kmp_affinity.cpp b/openmp/runtime/src/kmp_affinity.cpp index f40215429417..ae0b6459d79e 100644 --- a/openmp/runtime/src/kmp_affinity.cpp +++ b/openmp/runtime/src/kmp_affinity.cpp @@ -2829,7 +2829,8 @@ static void __kmp_dispatch_set_hierarchy_values() { nPackages * nCoresPerPkg * __kmp_nThreadsPerCore; __kmp_hier_max_units[kmp_hier_layer_e::LAYER_L1 + 1] = __kmp_ncores; #if KMP_ARCH_X86_64 && \ - (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_WINDOWS) && \ + (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY || \ + KMP_OS_WINDOWS) && \ KMP_MIC_SUPPORTED if (__kmp_mic_type >= mic3) __kmp_hier_max_units[kmp_hier_layer_e::LAYER_L2 + 1] = __kmp_ncores / 2; @@ -2845,7 +2846,8 @@ static void __kmp_dispatch_set_hierarchy_values() { __kmp_hier_threads_per[kmp_hier_layer_e::LAYER_L1 + 1] = __kmp_nThreadsPerCore; #if KMP_ARCH_X86_64 && \ - (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_WINDOWS) && \ + (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY || \ + KMP_OS_WINDOWS) && \ KMP_MIC_SUPPORTED if (__kmp_mic_type >= mic3) __kmp_hier_threads_per[kmp_hier_layer_e::LAYER_L2 + 1] = @@ -5559,7 +5561,7 @@ void __kmp_balanced_affinity(kmp_info_t *th, int nthreads) { } } -#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD +#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY // We don't need this entry for Windows because // there is GetProcessAffinityMask() api // diff --git a/openmp/runtime/src/kmp_affinity.h b/openmp/runtime/src/kmp_affinity.h index a58a6f0e7c03..1c7db2f59943 100644 --- a/openmp/runtime/src/kmp_affinity.h +++ b/openmp/runtime/src/kmp_affinity.h @@ -191,7 +191,7 @@ public: }; #endif /* KMP_USE_HWLOC */ -#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD +#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY #if KMP_OS_LINUX /* On some of the older OS's that we build on, these constants aren't present in #included from . They must be the same on @@ -311,7 +311,7 @@ public: #else #error Unknown or unsupported architecture #endif /* KMP_ARCH_* */ -#elif KMP_OS_FREEBSD +#elif KMP_OS_FREEBSD || KMP_OS_DRAGONFLY #include #include #elif KMP_OS_NETBSD @@ -410,7 +410,7 @@ class KMPNativeAffinity : public KMPAffinity { #if KMP_OS_LINUX long retval = syscall(__NR_sched_getaffinity, 0, __kmp_affin_mask_size, mask); -#elif KMP_OS_FREEBSD || KMP_OS_NETBSD +#elif KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY int r = pthread_getaffinity_np(pthread_self(), __kmp_affin_mask_size, reinterpret_cast(mask)); int retval = (r == 0 ? 0 : -1); @@ -431,7 +431,7 @@ class KMPNativeAffinity : public KMPAffinity { #if KMP_OS_LINUX long retval = syscall(__NR_sched_setaffinity, 0, __kmp_affin_mask_size, mask); -#elif KMP_OS_FREEBSD || KMP_OS_NETBSD +#elif KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY int r = pthread_setaffinity_np(pthread_self(), __kmp_affin_mask_size, reinterpret_cast(mask)); int retval = (r == 0 ? 0 : -1); @@ -474,7 +474,8 @@ class KMPNativeAffinity : public KMPAffinity { } api_type get_api_type() const override { return NATIVE_OS; } }; -#endif /* KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD */ +#endif /* KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY \ + */ #if KMP_OS_WINDOWS class KMPNativeAffinity : public KMPAffinity { diff --git a/openmp/runtime/src/kmp_os.h b/openmp/runtime/src/kmp_os.h index 627d44fb7595..63da9e5fa15d 100644 --- a/openmp/runtime/src/kmp_os.h +++ b/openmp/runtime/src/kmp_os.h @@ -75,7 +75,8 @@ #error Unknown compiler #endif -#if (KMP_OS_LINUX || KMP_OS_WINDOWS || KMP_OS_FREEBSD || KMP_OS_NETBSD) && \ +#if (KMP_OS_LINUX || KMP_OS_WINDOWS || KMP_OS_FREEBSD || KMP_OS_NETBSD || \ + KMP_OS_DRAGONFLY) && \ !KMP_OS_WASI #define KMP_AFFINITY_SUPPORTED 1 #if KMP_OS_WINDOWS && KMP_ARCH_X86_64 diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp index 4016e6daf3f6..ce775ff49f4d 100644 --- a/openmp/runtime/src/kmp_runtime.cpp +++ b/openmp/runtime/src/kmp_runtime.cpp @@ -5376,7 +5376,8 @@ __kmp_allocate_team(kmp_root_t *root, int new_nproc, int max_nproc, __kmp_reinitialize_team(team, new_icvs, NULL); } -#if (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD) && KMP_AFFINITY_SUPPORTED +#if (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY) && \ + KMP_AFFINITY_SUPPORTED /* Temporarily set full mask for primary thread before creation of workers. The reason is that workers inherit the affinity from the primary thread, so if a lot of workers are created on the single @@ -5412,7 +5413,8 @@ __kmp_allocate_team(kmp_root_t *root, int new_nproc, int max_nproc, } } -#if (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD) && KMP_AFFINITY_SUPPORTED +#if (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY) && \ + KMP_AFFINITY_SUPPORTED /* Restore initial primary thread's affinity mask */ new_temp_affinity.restore(); #endif diff --git a/openmp/runtime/src/z_Linux_util.cpp b/openmp/runtime/src/z_Linux_util.cpp index ee08ea90213f..3f831d6e2a8f 100644 --- a/openmp/runtime/src/z_Linux_util.cpp +++ b/openmp/runtime/src/z_Linux_util.cpp @@ -125,7 +125,7 @@ static void __kmp_print_cond(char *buffer, kmp_cond_align_t *cond) { } #endif -#if ((KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD) && \ +#if ((KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY) && \ KMP_AFFINITY_SUPPORTED) /* Affinity support */ @@ -151,7 +151,7 @@ void __kmp_affinity_determine_capable(const char *env_var) { #if KMP_OS_LINUX #define KMP_CPU_SET_SIZE_LIMIT (1024 * 1024) #define KMP_CPU_SET_TRY_SIZE CACHE_LINE -#elif KMP_OS_FREEBSD +#elif KMP_OS_FREEBSD || KMP_OS_DRAGONFLY #define KMP_CPU_SET_SIZE_LIMIT (sizeof(cpuset_t)) #elif KMP_OS_NETBSD #define KMP_CPU_SET_SIZE_LIMIT (256) @@ -242,7 +242,7 @@ void __kmp_affinity_determine_capable(const char *env_var) { KMP_INTERNAL_FREE(buf); return; } -#elif KMP_OS_FREEBSD || KMP_OS_NETBSD +#elif KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY long gCode; unsigned char *buf; buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT); @@ -1268,7 +1268,7 @@ static void __kmp_atfork_child(void) { ++__kmp_fork_count; #if KMP_AFFINITY_SUPPORTED -#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD +#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY // reset the affinity in the child to the initial thread // affinity in the parent kmp_set_thread_affinity_mask_initial(); -- GitLab From 54bb4be0185b402565cc76a0c835c56f6441e188 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Sun, 10 Mar 2024 12:54:37 +0100 Subject: [PATCH 042/953] [InstSimplify] Handle vec values when simplifying comparisons using range metadata (#84673) Found that this failed with an assertion when vec was used in this optimization while working on https://github.com/llvm/llvm-project/pull/84627. --- llvm/lib/Analysis/InstructionSimplify.cpp | 4 +-- .../test/Transforms/InstCombine/icmp-range.ll | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 201472a3f10c..8c48174b9f52 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3788,10 +3788,10 @@ static Value *simplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, *LHS_Instr->getMetadata(LLVMContext::MD_range)); if (LHS_CR.icmp(Pred, RHS_CR)) - return ConstantInt::getTrue(RHS->getContext()); + return ConstantInt::getTrue(ITy); if (LHS_CR.icmp(CmpInst::getInversePredicate(Pred), RHS_CR)) - return ConstantInt::getFalse(RHS->getContext()); + return ConstantInt::getFalse(ITy); } } diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll b/llvm/test/Transforms/InstCombine/icmp-range.ll index 7af06e03fd4b..77bb5fdb6bfd 100644 --- a/llvm/test/Transforms/InstCombine/icmp-range.ll +++ b/llvm/test/Transforms/InstCombine/icmp-range.ll @@ -171,6 +171,42 @@ define i1 @test_two_ranges3(ptr nocapture readonly %arg1, ptr nocapture readonly ret i1 %rval } +; Values' ranges overlap each other, so it can not be simplified. +define <2 x i1> @test_two_ranges_vec(ptr nocapture readonly %arg1, ptr nocapture readonly %arg2) { +; CHECK-LABEL: @test_two_ranges_vec( +; CHECK-NEXT: [[VAL1:%.*]] = load <2 x i32>, ptr [[ARG1:%.*]], align 8, !range [[RNG4]] +; CHECK-NEXT: [[VAL2:%.*]] = load <2 x i32>, ptr [[ARG2:%.*]], align 8, !range [[RNG5]] +; CHECK-NEXT: [[RVAL:%.*]] = icmp ult <2 x i32> [[VAL2]], [[VAL1]] +; CHECK-NEXT: ret <2 x i1> [[RVAL]] +; + %val1 = load <2 x i32>, ptr %arg1, !range !5 + %val2 = load <2 x i32>, ptr %arg2, !range !6 + %rval = icmp ult <2 x i32> %val2, %val1 + ret <2 x i1> %rval +} + +; Values' ranges do not overlap each other, so it can simplified to false. +define <2 x i1> @test_two_ranges_vec_true(ptr nocapture readonly %arg1, ptr nocapture readonly %arg2) { +; CHECK-LABEL: @test_two_ranges_vec_true( +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %val1 = load <2 x i32>, ptr %arg1, !range !0 + %val2 = load <2 x i32>, ptr %arg2, !range !6 + %rval = icmp ult <2 x i32> %val2, %val1 + ret <2 x i1> %rval +} + +; Values' ranges do not overlap each other, so it can simplified to false. +define <2 x i1> @test_two_ranges_vec_false(ptr nocapture readonly %arg1, ptr nocapture readonly %arg2) { +; CHECK-LABEL: @test_two_ranges_vec_false( +; CHECK-NEXT: ret <2 x i1> +; + %val1 = load <2 x i32>, ptr %arg1, !range !0 + %val2 = load <2 x i32>, ptr %arg2, !range !6 + %rval = icmp ugt <2 x i32> %val2, %val1 + ret <2 x i1> %rval +} + define i1 @ugt_zext(i1 %b, i8 %x) { ; CHECK-LABEL: @ugt_zext( ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 -- GitLab From 3ec1f25f3cf9346590892397ec9ddd859397d363 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Sun, 10 Mar 2024 13:09:38 +0000 Subject: [PATCH 043/953] [MLIR/OpenACC] Remove unneeded LLVMIR include (#84543) MLIROpenACCTransforms does not use the LLVMIR dialect yet includes LLVMIR headers. This causes building MLIROpenACCTransforms only from a clean build to fail with: In file included from mlir/lib/Dialect/OpenACC/Transforms/LegalizeData.cpp:9: In file included from mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.h:12: mlir/include/mlir/Dialect/LLVMIR/Transforms/AddComdats.h:21:10: fatal error: 'mlir/Dialect/LLVMIR/Transforms/Passes.h.inc' file not found This patch removes the problematic includes. --- mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.h b/mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.h index 5a11056cda60..bb93c78bf6ea 100644 --- a/mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.h +++ b/mlir/include/mlir/Dialect/OpenACC/Transforms/Passes.h @@ -9,11 +9,6 @@ #ifndef MLIR_DIALECT_OPENACC_TRANSFORMS_PASSES_H #define MLIR_DIALECT_OPENACC_TRANSFORMS_PASSES_H -#include "mlir/Dialect/LLVMIR/Transforms/AddComdats.h" -#include "mlir/Dialect/LLVMIR/Transforms/LegalizeForExport.h" -#include "mlir/Dialect/LLVMIR/Transforms/OptimizeForNVVM.h" -#include "mlir/Dialect/LLVMIR/Transforms/RequestCWrappers.h" -#include "mlir/Dialect/LLVMIR/Transforms/TypeConsistency.h" #include "mlir/Pass/Pass.h" #define GEN_PASS_DECL -- GitLab From 033dbbe4f183cc0c401af72a2d57ab659e9693d4 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Sun, 10 Mar 2024 09:31:27 -0500 Subject: [PATCH 044/953] [libc][NFC] Clean up stray ';' and default enum warning Summary: Cleans up two warnings I get locally while building. --- libc/test/src/__support/FPUtil/fpbits_test.cpp | 2 -- libc/utils/gpu/loader/Loader.h | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/libc/test/src/__support/FPUtil/fpbits_test.cpp b/libc/test/src/__support/FPUtil/fpbits_test.cpp index 760031569c81..f5c27d4fc030 100644 --- a/libc/test/src/__support/FPUtil/fpbits_test.cpp +++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp @@ -237,8 +237,6 @@ template constexpr auto make(Sign sign, FP fp) { return T::signaling_nan(sign); case FP::QUIET_NAN: return T::quiet_nan(sign); - default: - __builtin_unreachable(); } } diff --git a/libc/utils/gpu/loader/Loader.h b/libc/utils/gpu/loader/Loader.h index e2aabb08c11d..cffbaa673afd 100644 --- a/libc/utils/gpu/loader/Loader.h +++ b/libc/utils/gpu/loader/Loader.h @@ -85,7 +85,7 @@ void *copy_argument_vector(int argc, char **argv, Allocator alloc) { // Ensure the vector is null terminated. reinterpret_cast(dev_argv)[argv_size] = nullptr; return dev_argv; -}; +} /// Copy the system's environment to GPU memory allocated using \p alloc. template @@ -95,7 +95,7 @@ void *copy_environment(char **envp, Allocator alloc) { ++envc; return copy_argument_vector(envc, envp, alloc); -}; +} inline void handle_error(const char *msg) { fprintf(stderr, "%s\n", msg); -- GitLab From 862c7e0218f27b55a5b75ae59a4f73cd4610448d Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sun, 10 Mar 2024 16:23:51 +0000 Subject: [PATCH 045/953] [X86] combineAndShuffleNot - ensure the type is legal before create X86ISD::ANDNP target nodes Fixes #84660 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 11 +++++++++-- llvm/test/CodeGen/X86/combine-and.ll | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index e1e6c22eb8cc..eb249b25374a 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -48179,6 +48179,7 @@ static SDValue combineAndShuffleNot(SDNode *N, SelectionDAG &DAG, SDValue X, Y; SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); if (SDValue Not = GetNot(N0)) { X = Not; @@ -48192,9 +48193,11 @@ static SDValue combineAndShuffleNot(SDNode *N, SelectionDAG &DAG, X = DAG.getBitcast(VT, X); Y = DAG.getBitcast(VT, Y); SDLoc DL(N); + // We do not split for SSE at all, but we need to split vectors for AVX1 and // AVX2. - if (!Subtarget.useAVX512Regs() && VT.is512BitVector()) { + if (!Subtarget.useAVX512Regs() && VT.is512BitVector() && + TLI.isTypeLegal(VT.getHalfNumVectorElementsVT(*DAG.getContext()))) { SDValue LoX, HiX; std::tie(LoX, HiX) = splitVector(X, DAG, DL); SDValue LoY, HiY; @@ -48204,7 +48207,11 @@ static SDValue combineAndShuffleNot(SDNode *N, SelectionDAG &DAG, SDValue HiV = DAG.getNode(X86ISD::ANDNP, DL, SplitVT, {HiX, HiY}); return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, {LoV, HiV}); } - return DAG.getNode(X86ISD::ANDNP, DL, VT, {X, Y}); + + if (TLI.isTypeLegal(VT)) + return DAG.getNode(X86ISD::ANDNP, DL, VT, {X, Y}); + + return SDValue(); } // Try to widen AND, OR and XOR nodes to VT in order to remove casts around diff --git a/llvm/test/CodeGen/X86/combine-and.ll b/llvm/test/CodeGen/X86/combine-and.ll index 71335a7b5882..cbdc867ddeb0 100644 --- a/llvm/test/CodeGen/X86/combine-and.ll +++ b/llvm/test/CodeGen/X86/combine-and.ll @@ -1171,6 +1171,25 @@ define <4 x i32> @neg_scalar_broadcast_two_uses(i32 %a0, <4 x i32> %a1, ptr %a2) ret <4 x i32> %4 } +; PR84660 - check for illegal types +define <2 x i128> @neg_scalar_broadcast_illegaltype(i128 %arg) { +; CHECK-LABEL: neg_scalar_broadcast_illegaltype: +; CHECK: # %bb.0: +; CHECK-NEXT: movq %rdi, %rax +; CHECK-NEXT: notl %esi +; CHECK-NEXT: andl $1, %esi +; CHECK-NEXT: movq %rsi, 16(%rdi) +; CHECK-NEXT: movq %rsi, (%rdi) +; CHECK-NEXT: movq $0, 24(%rdi) +; CHECK-NEXT: movq $0, 8(%rdi) +; CHECK-NEXT: retq + %i = xor i128 %arg, 1 + %i1 = insertelement <2 x i128> zeroinitializer, i128 %i, i64 0 + %i2 = shufflevector <2 x i128> %i1, <2 x i128> zeroinitializer, <2 x i32> zeroinitializer + %i3 = and <2 x i128> , %i2 + ret <2 x i128> %i3 +} + define <2 x i64> @andnp_xx(<2 x i64> %v0) nounwind { ; SSE-LABEL: andnp_xx: ; SSE: # %bb.0: -- GitLab From 75b0d384fbac42be7ce2da91cf62ed1027b8424b Mon Sep 17 00:00:00 2001 From: Michael Flanders Date: Sun, 10 Mar 2024 09:53:28 -0700 Subject: [PATCH 046/953] [libc][stdbit][c23] adds implementation of `stdc_bit_ceil` functions (#84657) Closes #84652. Based on #84233. --- libc/config/linux/x86_64/entrypoints.txt | 5 +++ libc/docs/stdbit.rst | 12 +++---- libc/include/llvm-libc-macros/stdbit-macros.h | 20 +++++++++++ libc/spec/stdc.td | 10 ++++-- libc/src/__support/CPP/bit.h | 2 +- libc/src/stdbit/CMakeLists.txt | 1 + libc/src/stdbit/stdc_bit_ceil_uc.cpp | 20 +++++++++++ libc/src/stdbit/stdc_bit_ceil_uc.h | 18 ++++++++++ libc/src/stdbit/stdc_bit_ceil_ui.cpp | 20 +++++++++++ libc/src/stdbit/stdc_bit_ceil_ui.h | 18 ++++++++++ libc/src/stdbit/stdc_bit_ceil_ul.cpp | 20 +++++++++++ libc/src/stdbit/stdc_bit_ceil_ul.h | 18 ++++++++++ libc/src/stdbit/stdc_bit_ceil_ull.cpp | 21 ++++++++++++ libc/src/stdbit/stdc_bit_ceil_ull.h | 18 ++++++++++ libc/src/stdbit/stdc_bit_ceil_us.cpp | 20 +++++++++++ libc/src/stdbit/stdc_bit_ceil_us.h | 18 ++++++++++ libc/test/include/stdbit_test.cpp | 17 ++++++++++ libc/test/src/stdbit/CMakeLists.txt | 1 + .../test/src/stdbit/stdc_bit_ceil_uc_test.cpp | 34 +++++++++++++++++++ .../test/src/stdbit/stdc_bit_ceil_ui_test.cpp | 30 ++++++++++++++++ .../test/src/stdbit/stdc_bit_ceil_ul_test.cpp | 30 ++++++++++++++++ .../src/stdbit/stdc_bit_ceil_ull_test.cpp | 31 +++++++++++++++++ .../test/src/stdbit/stdc_bit_ceil_us_test.cpp | 34 +++++++++++++++++++ 23 files changed, 409 insertions(+), 9 deletions(-) create mode 100644 libc/src/stdbit/stdc_bit_ceil_uc.cpp create mode 100644 libc/src/stdbit/stdc_bit_ceil_uc.h create mode 100644 libc/src/stdbit/stdc_bit_ceil_ui.cpp create mode 100644 libc/src/stdbit/stdc_bit_ceil_ui.h create mode 100644 libc/src/stdbit/stdc_bit_ceil_ul.cpp create mode 100644 libc/src/stdbit/stdc_bit_ceil_ul.h create mode 100644 libc/src/stdbit/stdc_bit_ceil_ull.cpp create mode 100644 libc/src/stdbit/stdc_bit_ceil_ull.h create mode 100644 libc/src/stdbit/stdc_bit_ceil_us.cpp create mode 100644 libc/src/stdbit/stdc_bit_ceil_us.h create mode 100644 libc/test/src/stdbit/stdc_bit_ceil_uc_test.cpp create mode 100644 libc/test/src/stdbit/stdc_bit_ceil_ui_test.cpp create mode 100644 libc/test/src/stdbit/stdc_bit_ceil_ul_test.cpp create mode 100644 libc/test/src/stdbit/stdc_bit_ceil_ull_test.cpp create mode 100644 libc/test/src/stdbit/stdc_bit_ceil_us_test.cpp diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index a7894af4b9ca..b51227e5f25d 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -158,6 +158,11 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdbit.stdc_bit_floor_ui libc.src.stdbit.stdc_bit_floor_ul libc.src.stdbit.stdc_bit_floor_ull + libc.src.stdbit.stdc_bit_ceil_uc + libc.src.stdbit.stdc_bit_ceil_us + libc.src.stdbit.stdc_bit_ceil_ui + libc.src.stdbit.stdc_bit_ceil_ul + libc.src.stdbit.stdc_bit_ceil_ull # stdlib.h entrypoints libc.src.stdlib.abs diff --git a/libc/docs/stdbit.rst b/libc/docs/stdbit.rst index 3ec46cf8d8ff..9b4974cf1479 100644 --- a/libc/docs/stdbit.rst +++ b/libc/docs/stdbit.rst @@ -96,11 +96,11 @@ stdc_bit_floor_us |check| stdc_bit_floor_ui |check| stdc_bit_floor_ul |check| stdc_bit_floor_ull |check| -stdc_bit_ceil_uc -stdc_bit_ceil_us -stdc_bit_ceil_ui -stdc_bit_ceil_ul -stdc_bit_ceil_ull +stdc_bit_ceil_uc |check| +stdc_bit_ceil_us |check| +stdc_bit_ceil_ui |check| +stdc_bit_ceil_ul |check| +stdc_bit_ceil_ull |check| ============================ ========= @@ -127,7 +127,7 @@ stdc_count_ones |check| stdc_has_single_bit |check| stdc_bit_width |check| stdc_bit_floor |check| -stdc_bit_ceil +stdc_bit_ceil |check| ========================= ========= Standards diff --git a/libc/include/llvm-libc-macros/stdbit-macros.h b/libc/include/llvm-libc-macros/stdbit-macros.h index e3eb6630afdd..10c0fac3c8dd 100644 --- a/libc/include/llvm-libc-macros/stdbit-macros.h +++ b/libc/include/llvm-libc-macros/stdbit-macros.h @@ -194,6 +194,19 @@ inline unsigned long stdc_bit_floor(unsigned long x) { inline unsigned long long stdc_bit_floor(unsigned long long x) { return stdc_bit_floor_ull(x); } +inline unsigned char stdc_bit_ceil(unsigned char x) { + return stdc_bit_ceil_uc(x); +} +inline unsigned short stdc_bit_ceil(unsigned short x) { + return stdc_bit_ceil_us(x); +} +inline unsigned stdc_bit_ceil(unsigned x) { return stdc_bit_ceil_ui(x); } +inline unsigned long stdc_bit_ceil(unsigned long x) { + return stdc_bit_ceil_ul(x); +} +inline unsigned long long stdc_bit_ceil(unsigned long long x) { + return stdc_bit_ceil_ull(x); +} #else #define stdc_leading_zeros(x) \ _Generic((x), \ @@ -286,6 +299,13 @@ inline unsigned long long stdc_bit_floor(unsigned long long x) { unsigned: stdc_bit_floor_ui, \ unsigned long: stdc_bit_floor_ul, \ unsigned long long: stdc_bit_floor_ull)(x) +#define stdc_bit_ceil(x) \ + _Generic((x), \ + unsigned char: stdc_bit_ceil_uc, \ + unsigned short: stdc_bit_ceil_us, \ + unsigned: stdc_bit_ceil_ui, \ + unsigned long: stdc_bit_ceil_ul, \ + unsigned long long: stdc_bit_ceil_ull)(x) #endif // __cplusplus #endif // __LLVM_LIBC_MACROS_STDBIT_MACROS_H diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index 766668c51e3e..d91f5c1f7233 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -816,7 +816,8 @@ def StdC : StandardSpec<"stdc"> { Macro<"stdc_count_ones">, Macro<"stdc_has_single_bit">, Macro<"std_bit_width">, - Macro<"std_bit_floor"> + Macro<"std_bit_floor">, + Macro<"std_bit_ceil"> ], // Macros [], // Types [], // Enumerations @@ -880,7 +881,12 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"stdc_bit_floor_us", RetValSpec, [ArgSpec]>, FunctionSpec<"stdc_bit_floor_ui", RetValSpec, [ArgSpec]>, FunctionSpec<"stdc_bit_floor_ul", RetValSpec, [ArgSpec]>, - FunctionSpec<"stdc_bit_floor_ull", RetValSpec, [ArgSpec]> + FunctionSpec<"stdc_bit_floor_ull", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_ceil_uc", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_ceil_us", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_ceil_ui", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_ceil_ul", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_ceil_ull", RetValSpec, [ArgSpec]> ] // Functions >; diff --git a/libc/src/__support/CPP/bit.h b/libc/src/__support/CPP/bit.h index 9c74a346949f..4464703e4b06 100644 --- a/libc/src/__support/CPP/bit.h +++ b/libc/src/__support/CPP/bit.h @@ -193,7 +193,7 @@ template bit_ceil(T value) { if (value < 2) return 1; - return T(1) << cpp::bit_width(value - 1u); + return static_cast(T(1) << cpp::bit_width(value - 1u)); } // Rotate algorithms make use of "Safe, Efficient, and Portable Rotate in C/C++" diff --git a/libc/src/stdbit/CMakeLists.txt b/libc/src/stdbit/CMakeLists.txt index 7ab4fee4454a..2aef2029f2df 100644 --- a/libc/src/stdbit/CMakeLists.txt +++ b/libc/src/stdbit/CMakeLists.txt @@ -12,6 +12,7 @@ set(prefixes has_single_bit bit_width bit_floor + bit_ceil ) set(suffixes c s i l ll) foreach(prefix IN LISTS prefixes) diff --git a/libc/src/stdbit/stdc_bit_ceil_uc.cpp b/libc/src/stdbit/stdc_bit_ceil_uc.cpp new file mode 100644 index 000000000000..675ae4a0edb0 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_uc.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of stdc_bit_ceil_uc --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_ceil_uc.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned char, stdc_bit_ceil_uc, (unsigned char value)) { + return cpp::bit_ceil(value); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_ceil_uc.h b/libc/src/stdbit/stdc_bit_ceil_uc.h new file mode 100644 index 000000000000..204261e41081 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_uc.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_ceil_uc --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UC_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UC_H + +namespace LIBC_NAMESPACE { + +unsigned char stdc_bit_ceil_uc(unsigned char value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UC_H diff --git a/libc/src/stdbit/stdc_bit_ceil_ui.cpp b/libc/src/stdbit/stdc_bit_ceil_ui.cpp new file mode 100644 index 000000000000..a8ac9726179b --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_ui.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of stdc_bit_ceil_ui --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_ceil_ui.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned, stdc_bit_ceil_ui, (unsigned value)) { + return cpp::bit_ceil(value); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_ceil_ui.h b/libc/src/stdbit/stdc_bit_ceil_ui.h new file mode 100644 index 000000000000..db66c336e366 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_ui.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_ceil_ui --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UI_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UI_H + +namespace LIBC_NAMESPACE { + +unsigned stdc_bit_ceil_ui(unsigned value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UI_H diff --git a/libc/src/stdbit/stdc_bit_ceil_ul.cpp b/libc/src/stdbit/stdc_bit_ceil_ul.cpp new file mode 100644 index 000000000000..18a9c38b5b4c --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_ul.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of stdc_bit_ceil_ul --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_ceil_ul.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned long, stdc_bit_ceil_ul, (unsigned long value)) { + return cpp::bit_ceil(value); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_ceil_ul.h b/libc/src/stdbit/stdc_bit_ceil_ul.h new file mode 100644 index 000000000000..f8393a42fcbf --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_ul.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_ceil_ul --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UL_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UL_H + +namespace LIBC_NAMESPACE { + +unsigned long stdc_bit_ceil_ul(unsigned long value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UL_H diff --git a/libc/src/stdbit/stdc_bit_ceil_ull.cpp b/libc/src/stdbit/stdc_bit_ceil_ull.cpp new file mode 100644 index 000000000000..0989f36ab768 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_ull.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of stdc_bit_ceil_ull -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_ceil_ull.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned long long, stdc_bit_ceil_ull, + (unsigned long long value)) { + return cpp::bit_ceil(value); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_ceil_ull.h b/libc/src/stdbit/stdc_bit_ceil_ull.h new file mode 100644 index 000000000000..e65f537efb17 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_ull.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_ceil_ull -------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_ULL_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_ULL_H + +namespace LIBC_NAMESPACE { + +unsigned long long stdc_bit_ceil_ull(unsigned long long value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_ULL_H diff --git a/libc/src/stdbit/stdc_bit_ceil_us.cpp b/libc/src/stdbit/stdc_bit_ceil_us.cpp new file mode 100644 index 000000000000..f86a216bb840 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_us.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of stdc_bit_ceil_us --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_ceil_us.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned short, stdc_bit_ceil_us, (unsigned short value)) { + return cpp::bit_ceil(value); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_ceil_us.h b/libc/src/stdbit/stdc_bit_ceil_us.h new file mode 100644 index 000000000000..16a14e51b743 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_us.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_ceil_us --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_US_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_US_H + +namespace LIBC_NAMESPACE { + +unsigned short stdc_bit_ceil_us(unsigned short value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_US_H diff --git a/libc/test/include/stdbit_test.cpp b/libc/test/include/stdbit_test.cpp index 20820d52fbde..6c12665c4454 100644 --- a/libc/test/include/stdbit_test.cpp +++ b/libc/test/include/stdbit_test.cpp @@ -98,6 +98,13 @@ unsigned long stdc_bit_floor_ul(unsigned long) noexcept { return 0x5DU; } unsigned long long stdc_bit_floor_ull(unsigned long long) noexcept { return 0x5EU; } +unsigned char stdc_bit_ceil_uc(unsigned char) noexcept { return 0x6AU; } +unsigned short stdc_bit_ceil_us(unsigned short) noexcept { return 0x6BU; } +unsigned stdc_bit_ceil_ui(unsigned) noexcept { return 0x6CU; } +unsigned long stdc_bit_ceil_ul(unsigned long) noexcept { return 0x6DU; } +unsigned long long stdc_bit_ceil_ull(unsigned long long) noexcept { + return 0x6EU; +} } #include "include/llvm-libc-macros/stdbit-macros.h" @@ -207,3 +214,13 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroBitFloor) { EXPECT_EQ(stdc_bit_floor(0UL), 0x5DUL); EXPECT_EQ(stdc_bit_floor(0ULL), 0x5EULL); } + +TEST(LlvmLibcStdbitTest, TypeGenericMacroBitCeil) { + EXPECT_EQ(stdc_bit_ceil(static_cast(0U)), + static_cast(0x6AU)); + EXPECT_EQ(stdc_bit_ceil(static_cast(0U)), + static_cast(0x6BU)); + EXPECT_EQ(stdc_bit_ceil(0U), 0x6CU); + EXPECT_EQ(stdc_bit_ceil(0UL), 0x6DUL); + EXPECT_EQ(stdc_bit_ceil(0ULL), 0x6EULL); +} diff --git a/libc/test/src/stdbit/CMakeLists.txt b/libc/test/src/stdbit/CMakeLists.txt index 3aed56c0e923..c3f8059d2d9b 100644 --- a/libc/test/src/stdbit/CMakeLists.txt +++ b/libc/test/src/stdbit/CMakeLists.txt @@ -14,6 +14,7 @@ set(prefixes has_single_bit bit_width bit_floor + bit_ceil ) set(suffixes c s i l ll) foreach(prefix IN LISTS prefixes) diff --git a/libc/test/src/stdbit/stdc_bit_ceil_uc_test.cpp b/libc/test/src/stdbit/stdc_bit_ceil_uc_test.cpp new file mode 100644 index 000000000000..1ef87b0d44de --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_ceil_uc_test.cpp @@ -0,0 +1,34 @@ +//===-- Unittests for stdc_bit_ceil_uc ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_ceil_uc.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitceilUcTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_uc(0U), + static_cast(1)); +} + +TEST(LlvmLibcStdcBitceilUcTest, Ones) { + for (unsigned i = 0U; i != UCHAR_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_uc(1U << i), + static_cast(1U << i)); +} + +TEST(LlvmLibcStdcBitceilUcTest, OneLessThanPowsTwo) { + for (unsigned i = 2U; i != UCHAR_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_uc((1U << i) - 1), + static_cast(1U << i)); +} + +TEST(LlvmLibcStdcBitceilUcTest, OneMoreThanPowsTwo) { + for (unsigned i = 1U; i != UCHAR_WIDTH - 1; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_uc((1U << i) + 1), + static_cast(1U << (i + 1))); +} diff --git a/libc/test/src/stdbit/stdc_bit_ceil_ui_test.cpp b/libc/test/src/stdbit/stdc_bit_ceil_ui_test.cpp new file mode 100644 index 000000000000..3b6f2a564ff1 --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_ceil_ui_test.cpp @@ -0,0 +1,30 @@ +//===-- Unittests for stdc_bit_ceil_ui ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_ceil_ui.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitceilUiTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ui(0U), 1U); +} + +TEST(LlvmLibcStdcBitceilUiTest, Ones) { + for (unsigned i = 0U; i != UINT_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ui(1U << i), 1U << i); +} + +TEST(LlvmLibcStdcBitceilUiTest, OneLessThanPowsTwo) { + for (unsigned i = 2U; i != UINT_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ui((1U << i) - 1), 1U << i); +} + +TEST(LlvmLibcStdcBitceilUiTest, OneMoreThanPowsTwo) { + for (unsigned i = 1U; i != UINT_WIDTH - 1; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ui((1U << i) + 1), 1U << (i + 1)); +} diff --git a/libc/test/src/stdbit/stdc_bit_ceil_ul_test.cpp b/libc/test/src/stdbit/stdc_bit_ceil_ul_test.cpp new file mode 100644 index 000000000000..d4dbb38ea02a --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_ceil_ul_test.cpp @@ -0,0 +1,30 @@ +//===-- Unittests for stdc_bit_ceil_ul ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_ceil_ul.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitceilUlTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ul(0UL), 1UL); +} + +TEST(LlvmLibcStdcBitceilUlTest, Ones) { + for (unsigned i = 0U; i != ULONG_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ul(1UL << i), 1UL << i); +} + +TEST(LlvmLibcStdcBitceilUlTest, OneLessThanPowsTwo) { + for (unsigned i = 2U; i != ULONG_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ul((1UL << i) - 1), 1UL << i); +} + +TEST(LlvmLibcStdcBitceilUlTest, OneMoreThanPowsTwo) { + for (unsigned i = 1U; i != ULONG_WIDTH - 1; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ul((1UL << i) + 1), 1UL << (i + 1)); +} diff --git a/libc/test/src/stdbit/stdc_bit_ceil_ull_test.cpp b/libc/test/src/stdbit/stdc_bit_ceil_ull_test.cpp new file mode 100644 index 000000000000..762f4f0627e6 --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_ceil_ull_test.cpp @@ -0,0 +1,31 @@ +//===-- Unittests for stdc_bit_ceil_ull -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_ceil_ull.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitceilUllTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ull(0ULL), 1ULL); +} + +TEST(LlvmLibcStdcBitceilUllTest, Ones) { + for (unsigned i = 0U; i != ULLONG_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ull(1ULL << i), 1ULL << i); +} + +TEST(LlvmLibcStdcBitceilUllTest, OneLessThanPowsTwo) { + for (unsigned i = 2U; i != ULLONG_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ull((1ULL << i) - 1), 1ULL << i); +} + +TEST(LlvmLibcStdcBitceilUllTest, OneMoreThanPowsTwo) { + for (unsigned i = 1U; i != ULLONG_WIDTH - 1; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ull((1ULL << i) + 1), + 1ULL << (i + 1)); +} diff --git a/libc/test/src/stdbit/stdc_bit_ceil_us_test.cpp b/libc/test/src/stdbit/stdc_bit_ceil_us_test.cpp new file mode 100644 index 000000000000..56873c51828f --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_ceil_us_test.cpp @@ -0,0 +1,34 @@ +//===-- Unittests for stdc_bit_ceil_us ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_ceil_us.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitceilUsTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_us(0U), + static_cast(1)); +} + +TEST(LlvmLibcStdcBitceilUsTest, Ones) { + for (unsigned i = 0U; i != USHRT_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_us(1U << i), + static_cast(1U << i)); +} + +TEST(LlvmLibcStdcBitceilUsTest, OneLessThanPowsTwo) { + for (unsigned i = 2U; i != USHRT_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_us((1U << i) - 1), + static_cast(1U << i)); +} + +TEST(LlvmLibcStdcBitceilUsTest, OneMoreThanPowsTwo) { + for (unsigned i = 1U; i != USHRT_WIDTH - 1; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_us((1U << i) + 1), + static_cast(1U << (i + 1))); +} -- GitLab From a066f71e70b9cbfdc2f2eb41e7c4d8372d216a6e Mon Sep 17 00:00:00 2001 From: Michael Flanders Date: Sun, 10 Mar 2024 11:44:06 -0700 Subject: [PATCH 047/953] [libc][stdbit] Fix truncation err in CPP bit_ceil (#84683) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After #84657 was merged, [buildbot](https://lab.llvm.org/buildbot/#/builders/250/builds/19808) is reporting two errors for libc-x86_64-debian-gcc-fullbuild-dbg. This PR addresses the truncation error for `CPP::bit_ceil` and `CPP::bit_ceil`. The errors are: ``` FAILED: projects/libc/src/stdbit/CMakeFiles/libc.src.stdbit.stdc_bit_ceil_uc.dir/stdc_bit_ceil_uc.cpp.o /usr/bin/g++ -DLIBC_NAMESPACE=__llvm_libc_19_0_0_git -D_DEBUG -I/home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/build/projects/libc/src/stdbit -I/home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/llvm-project/libc/src/stdbit -I/home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/llvm-project/libc -isystem /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/build/projects/libc/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -fno-lifetime-dse -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-maybe-uninitialized -Wno-nonnull -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wdelete-non-vir! tual-dtor -Wsuggest-override -Wno-comment -Wno-misleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -g -fpie -ffreestanding -fno-builtin -fno-exceptions -fno-lax-vector-conversions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti -ftrivial-auto-var-init=pattern -Wall -Wextra -Werror -Wconversion -Wno-sign-conversion -Wimplicit-fallthrough -Wwrite-strings -Wextra-semi -DLIBC_COPT_PUBLIC_PACKAGING -std=c++17 -MD -MT projects/libc/src/stdbit/CMakeFiles/libc.src.stdbit.stdc_bit_ceil_uc.dir/stdc_bit_ceil_uc.cpp.o -MF projects/libc/src/stdbit/CMakeFiles/libc.src.stdbit.stdc_bit_ceil_uc.dir/stdc_bit_ceil_uc.cpp.o.d -o projects/libc/src/stdbit/CMakeFiles/libc.src.stdbit.stdc_bit_ceil_uc.dir/stdc_bit_ceil_uc.cpp.o -c /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/llvm-project/libc/src/stdbit/stdc_bit_ceil_uc.cpp In file included from /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/llvm-project/libc/src/stdbit/stdc_bit_ceil_uc.cpp:11: /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/llvm-project/libc/src/__support/CPP/bit.h: In instantiation of ‘constexpr __llvm_libc_19_0_0_git::cpp::enable_if_t, T> __llvm_libc_19_0_0_git::cpp::bit_ceil(T) [with T = unsigned char; enable_if_t, T> = unsigned char]’: /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/llvm-project/libc/src/stdbit/stdc_bit_ceil_uc.cpp:17:23: required from here /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/llvm-project/libc/src/__support/CPP/bit.h:196:57: error: conversion from ‘unsigned int’ to ‘unsigned char’ may change value [-Werror=conversion] 196 | return static_cast(T(1) << cpp::bit_width(value - 1u)); | ~~~~~~^~~~ cc1plus: all warnings being treated as errors [138/466] Building CXX object projects/libc/src/stdbit/CMakeFiles/libc.src.stdbit.stdc_bit_ceil_us.dir/stdc_bit_ceil_us.cpp.o FAILED: projects/libc/src/stdbit/CMakeFiles/libc.src.stdbit.stdc_bit_ceil_us.dir/stdc_bit_ceil_us.cpp.o /usr/bin/g++ -DLIBC_NAMESPACE=__llvm_libc_19_0_0_git -D_DEBUG -I/home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/build/projects/libc/src/stdbit -I/home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/llvm-project/libc/src/stdbit -I/home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/llvm-project/libc -isystem /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/build/projects/libc/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -fno-lifetime-dse -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-maybe-uninitialized -Wno-nonnull -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wdelete-non-vir! tual-dtor -Wsuggest-override -Wno-comment -Wno-misleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -g -fpie -ffreestanding -fno-builtin -fno-exceptions -fno-lax-vector-conversions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti -ftrivial-auto-var-init=pattern -Wall -Wextra -Werror -Wconversion -Wno-sign-conversion -Wimplicit-fallthrough -Wwrite-strings -Wextra-semi -DLIBC_COPT_PUBLIC_PACKAGING -std=c++17 -MD -MT projects/libc/src/stdbit/CMakeFiles/libc.src.stdbit.stdc_bit_ceil_us.dir/stdc_bit_ceil_us.cpp.o -MF projects/libc/src/stdbit/CMakeFiles/libc.src.stdbit.stdc_bit_ceil_us.dir/stdc_bit_ceil_us.cpp.o.d -o projects/libc/src/stdbit/CMakeFiles/libc.src.stdbit.stdc_bit_ceil_us.dir/stdc_bit_ceil_us.cpp.o -c /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/llvm-project/libc/src/stdbit/stdc_bit_ceil_us.cpp In file included from /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/llvm-project/libc/src/stdbit/stdc_bit_ceil_us.cpp:11: /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/llvm-project/libc/src/__support/CPP/bit.h: In instantiation of ‘constexpr __llvm_libc_19_0_0_git::cpp::enable_if_t, T> __llvm_libc_19_0_0_git::cpp::bit_ceil(T) [with T = short unsigned int; enable_if_t, T> = short unsigned int]’: /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/llvm-project/libc/src/stdbit/stdc_bit_ceil_us.cpp:17:23: required from here /home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-gcc-fullbuild-dbg/llvm-project/libc/src/__support/CPP/bit.h:196:57: error: conversion from ‘unsigned int’ to ‘short unsigned int’ may change value [-Werror=conversion] 196 | return static_cast(T(1) << cpp::bit_width(value - 1u)); | ~~~~~~^~~~ cc1plus: all warnings being treated as errors ``` --- libc/src/__support/CPP/bit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/src/__support/CPP/bit.h b/libc/src/__support/CPP/bit.h index 4464703e4b06..1a05728b8506 100644 --- a/libc/src/__support/CPP/bit.h +++ b/libc/src/__support/CPP/bit.h @@ -193,7 +193,7 @@ template bit_ceil(T value) { if (value < 2) return 1; - return static_cast(T(1) << cpp::bit_width(value - 1u)); + return static_cast(T(1) << cpp::bit_width(value - 1U)); } // Rotate algorithms make use of "Safe, Efficient, and Portable Rotate in C/C++" -- GitLab From 8a790033073e005b41140b5c38a4eaada321c2f1 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Sun, 10 Mar 2024 14:06:56 -0500 Subject: [PATCH 048/953] [libc] Move RPC opcodes include out of the header Summary: This header isn't strictly necessary, and is currently broken because we install these to separate locations. --- libc/utils/gpu/loader/Loader.h | 1 + libc/utils/gpu/server/CMakeLists.txt | 4 ++++ libc/utils/gpu/server/llvmlibc_rpc_server.h | 4 +--- libc/utils/gpu/server/rpc_server.cpp | 10 +++++----- openmp/libomptarget/plugins-nextgen/common/src/RPC.cpp | 1 + 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/libc/utils/gpu/loader/Loader.h b/libc/utils/gpu/loader/Loader.h index cffbaa673afd..933803837019 100644 --- a/libc/utils/gpu/loader/Loader.h +++ b/libc/utils/gpu/loader/Loader.h @@ -11,6 +11,7 @@ #include "utils/gpu/server/llvmlibc_rpc_server.h" +#include "llvm-libc-types/rpc_opcodes_t.h" #include "include/llvm-libc-types/test_rpc_opcodes_t.h" #include diff --git a/libc/utils/gpu/server/CMakeLists.txt b/libc/utils/gpu/server/CMakeLists.txt index 8712f24de84f..10cfdb45a2c9 100644 --- a/libc/utils/gpu/server/CMakeLists.txt +++ b/libc/utils/gpu/server/CMakeLists.txt @@ -24,6 +24,10 @@ endif() install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/llvmlibc_rpc_server.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT libc-headers) +install(FILES ${LIBC_SOURCE_DIR}/include/llvm-libc-types/rpc_opcodes_t.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + RENAME llvmlibc_rpc_opcodes.h + COMPONENT libc-headers) install(TARGETS llvmlibc_rpc_server ARCHIVE DESTINATION "lib${LLVM_LIBDIR_SUFFIX}" COMPONENT libc) diff --git a/libc/utils/gpu/server/llvmlibc_rpc_server.h b/libc/utils/gpu/server/llvmlibc_rpc_server.h index f1a8fe06281c..b7f2a463b1f5 100644 --- a/libc/utils/gpu/server/llvmlibc_rpc_server.h +++ b/libc/utils/gpu/server/llvmlibc_rpc_server.h @@ -11,8 +11,6 @@ #include -#include "llvm-libc-types/rpc_opcodes_t.h" - #ifdef __cplusplus extern "C" { #endif @@ -84,7 +82,7 @@ rpc_status_t rpc_handle_server(uint32_t device_id); /// Register a callback to handle an opcode from the RPC client. The associated /// data must remain accessible as long as the user intends to handle the server /// with this callback. -rpc_status_t rpc_register_callback(uint32_t device_id, rpc_opcode_t opcode, +rpc_status_t rpc_register_callback(uint32_t device_id, uint16_t opcode, rpc_opcode_callback_ty callback, void *data); /// Obtain a pointer to a local client buffer that can be copied directly to the diff --git a/libc/utils/gpu/server/rpc_server.cpp b/libc/utils/gpu/server/rpc_server.cpp index 2c8186c13ffa..90af1569c4c5 100644 --- a/libc/utils/gpu/server/rpc_server.cpp +++ b/libc/utils/gpu/server/rpc_server.cpp @@ -30,8 +30,8 @@ static_assert(RPC_MAXIMUM_PORT_COUNT == rpc::MAX_PORT_COUNT, template rpc_status_t handle_server_impl( rpc::Server &server, - const std::unordered_map &callbacks, - const std::unordered_map &callback_data, + const std::unordered_map &callbacks, + const std::unordered_map &callback_data, uint32_t &index) { auto port = server.try_open(lane_size, index); if (!port) @@ -239,8 +239,8 @@ struct Device { void *buffer; rpc::Server server; rpc::Client client; - std::unordered_map callbacks; - std::unordered_map callback_data; + std::unordered_map callbacks; + std::unordered_map callback_data; }; // A struct containing all the runtime state required to run the RPC server. @@ -335,7 +335,7 @@ rpc_status_t rpc_handle_server(uint32_t device_id) { } } -rpc_status_t rpc_register_callback(uint32_t device_id, rpc_opcode_t opcode, +rpc_status_t rpc_register_callback(uint32_t device_id, uint16_t opcode, rpc_opcode_callback_ty callback, void *data) { if (!state) diff --git a/openmp/libomptarget/plugins-nextgen/common/src/RPC.cpp b/openmp/libomptarget/plugins-nextgen/common/src/RPC.cpp index 05ae5acb01dd..f46b27701b5b 100644 --- a/openmp/libomptarget/plugins-nextgen/common/src/RPC.cpp +++ b/openmp/libomptarget/plugins-nextgen/common/src/RPC.cpp @@ -13,6 +13,7 @@ #include "PluginInterface.h" #if defined(LIBOMPTARGET_RPC_SUPPORT) +#include "llvm-libc-types/rpc_opcodes_t.h" #include "llvmlibc_rpc_server.h" #endif -- GitLab From e3444ad0bd758ea1c8f67425063f8b53afe3d7de Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Wed, 13 Sep 2023 13:45:49 -0500 Subject: [PATCH 049/953] [InstCombine] Add tests for expanding `foldICmpWithLowBitMaskedVal`; NFC Differential Revision: https://reviews.llvm.org/D159057 --- .../InstCombine/icmp-and-lowbit-mask.ll | 662 ++++++++++++++++++ 1 file changed, 662 insertions(+) create mode 100644 llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll diff --git a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll new file mode 100644 index 000000000000..89f59eac60f8 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll @@ -0,0 +1,662 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +declare void @use.i8(i8) +declare void @use.i16(i16) +define i1 @src_is_mask_zext(i16 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_mask_zext( +; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[M_IN:%.*]] = lshr i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = zext i8 [[M_IN]] to i16 +; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[MASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i16 %x_in, 123 + %m_in = lshr i8 -1, %y + %mask = zext i8 %m_in to i16 + + %and = and i16 %x, %mask + %r = icmp eq i16 %and, %x + ret i1 %r +} + +define i1 @src_is_mask_zext_fail_not_mask(i16 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_mask_zext_fail_not_mask( +; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[M_IN:%.*]] = lshr i8 -2, [[Y:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = zext i8 [[M_IN]] to i16 +; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[MASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i16 %x_in, 123 + %m_in = lshr i8 -2, %y + %mask = zext i8 %m_in to i16 + + %and = and i16 %x, %mask + %r = icmp eq i16 %and, %x + ret i1 %r +} + +define i1 @src_is_mask_sext(i16 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_mask_sext( +; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[TMP1:%.*]] = ashr i8 -32, [[Y:%.*]] +; CHECK-NEXT: [[NOTMASK:%.*]] = sext i8 [[TMP1]] to i16 +; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[NOTMASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i16 %x_in, 123 + %m_in = lshr i8 31, %y + %mask = sext i8 %m_in to i16 + %notmask = xor i16 %mask, -1 + + %and = and i16 %notmask, %x + %r = icmp eq i16 %and, 0 + ret i1 %r +} + +define i1 @src_is_mask_sext_fail_multiuse(i16 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_mask_sext_fail_multiuse( +; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 122 +; CHECK-NEXT: [[M_IN:%.*]] = lshr i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[M_IN]], -1 +; CHECK-NEXT: [[NOTMASK:%.*]] = sext i8 [[TMP1]] to i16 +; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[NOTMASK]] +; CHECK-NEXT: call void @use.i16(i16 [[AND]]) +; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i16 %x_in, 123 + %m_in = lshr i8 -1, %y + %mask = sext i8 %m_in to i16 + %notmask = xor i16 %mask, -1 + + %and = and i16 %notmask, %x + call void @use.i16(i16 %and) + %r = icmp eq i16 %and, 0 + ret i1 %r +} + +define i1 @src_is_mask_and(i8 %x_in, i8 %y, i8 %z) { +; CHECK-LABEL: @src_is_mask_and( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[MY:%.*]] = lshr i8 7, [[Y:%.*]] +; CHECK-NEXT: [[MZ:%.*]] = lshr i8 -1, [[Z:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = and i8 [[MY]], [[MZ]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], [[AND]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %my = ashr i8 7, %y + %mz = lshr i8 -1, %z + %mask = and i8 %my, %mz + + %and = and i8 %x, %mask + %r = icmp eq i8 %x, %and + ret i1 %r +} + +define i1 @src_is_mask_and_fail_mixed(i8 %x_in, i8 %y, i8 %z) { +; CHECK-LABEL: @src_is_mask_and_fail_mixed( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[MY:%.*]] = ashr i8 -8, [[Y:%.*]] +; CHECK-NEXT: [[MZ:%.*]] = lshr i8 -1, [[Z:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = and i8 [[MY]], [[MZ]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], [[AND]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %my = ashr i8 -8, %y + %mz = lshr i8 -1, %z + %mask = and i8 %my, %mz + + %and = and i8 %x, %mask + %r = icmp eq i8 %x, %and + ret i1 %r +} + +define i1 @src_is_mask_or(i8 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_mask_or( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[MY:%.*]] = lshr i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = and i8 [[MY]], 7 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], [[AND]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %my = lshr i8 -1, %y + %mask = and i8 %my, 7 + + %and = and i8 %mask, %x + %r = icmp eq i8 %x, %and + ret i1 %r +} + +define i1 @src_is_mask_xor(i8 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_mask_xor( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 +; CHECK-NEXT: [[MASK:%.*]] = xor i8 [[Y_M1]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %y_m1 = add i8 %y, -1 + %mask = xor i8 %y, %y_m1 + %and = and i8 %x, %mask + %r = icmp ne i8 %and, %x + ret i1 %r +} + +define i1 @src_is_mask_xor_fail_notmask(i8 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_mask_xor_fail_notmask( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[Y:%.*]] +; CHECK-NEXT: [[NOTMASK:%.*]] = xor i8 [[TMP1]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %y_m1 = add i8 %y, -1 + %mask = xor i8 %y, %y_m1 + %notmask = xor i8 %mask, -1 + %and = and i8 %x, %notmask + %r = icmp ne i8 %and, %x + ret i1 %r +} + +define i1 @src_is_mask_select(i8 %x_in, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_is_mask_select( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 +; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] +; CHECK-NEXT: [[MASK:%.*]] = select i1 [[COND:%.*]], i8 [[YMASK]], i8 15 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %y_m1 = add i8 %y, -1 + %ymask = xor i8 %y, %y_m1 + %mask = select i1 %cond, i8 %ymask, i8 15 + + %and = and i8 %mask, %x + %r = icmp ne i8 %and, %x + ret i1 %r +} + +define i1 @src_is_mask_select_fail_wrong_pattern(i8 %x_in, i8 %y, i1 %cond, i8 %z) { +; CHECK-LABEL: @src_is_mask_select_fail_wrong_pattern( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 +; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] +; CHECK-NEXT: [[MASK:%.*]] = select i1 [[COND:%.*]], i8 [[YMASK]], i8 15 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[Z:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %y_m1 = add i8 %y, -1 + %ymask = xor i8 %y, %y_m1 + %mask = select i1 %cond, i8 %ymask, i8 15 + + %and = and i8 %mask, %x + %r = icmp ne i8 %and, %z + ret i1 %r +} + +define i1 @src_is_mask_shl_lshr(i8 %x_in, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_is_mask_shl_lshr( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 122 +; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[NOTMASK:%.*]] = xor i8 [[TMP1]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %m_shl = shl i8 -1, %y + %mask = lshr i8 %m_shl, %y + %notmask = xor i8 %mask, -1 + + %and = and i8 %x, %notmask + %r = icmp ne i8 0, %and + ret i1 %r +} + +define i1 @src_is_mask_shl_lshr_fail_not_allones(i8 %x_in, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_is_mask_shl_lshr_fail_not_allones( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = and i8 [[TMP1]], -2 +; CHECK-NEXT: [[NOTMASK:%.*]] = xor i8 [[MASK]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %m_shl = shl i8 -2, %y + %mask = lshr i8 %m_shl, %y + %notmask = xor i8 %mask, -1 + + %and = and i8 %x, %notmask + %r = icmp ne i8 0, %and + ret i1 %r +} + +define i1 @src_is_mask_lshr(i8 %x_in, i8 %y, i8 %z, i1 %cond) { +; CHECK-LABEL: @src_is_mask_lshr( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 +; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] +; CHECK-NEXT: [[SMASK:%.*]] = select i1 [[COND:%.*]], i8 [[YMASK]], i8 15 +; CHECK-NEXT: [[MASK:%.*]] = lshr i8 [[SMASK]], [[Z:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X]], [[AND]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %y_m1 = add i8 %y, -1 + %ymask = xor i8 %y, %y_m1 + %smask = select i1 %cond, i8 %ymask, i8 15 + %mask = lshr i8 %smask, %z + %and = and i8 %mask, %x + %r = icmp ne i8 %x, %and + ret i1 %r +} + +define i1 @src_is_mask_ashr(i8 %x_in, i8 %y, i8 %z, i1 %cond) { +; CHECK-LABEL: @src_is_mask_ashr( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 +; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] +; CHECK-NEXT: [[SMASK:%.*]] = select i1 [[COND:%.*]], i8 [[YMASK]], i8 15 +; CHECK-NEXT: [[MASK:%.*]] = ashr i8 [[SMASK]], [[Z:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %y_m1 = add i8 %y, -1 + %ymask = xor i8 %y, %y_m1 + %smask = select i1 %cond, i8 %ymask, i8 15 + %mask = ashr i8 %smask, %z + %and = and i8 %x, %mask + %r = icmp ult i8 %and, %x + ret i1 %r +} + +define i1 @src_is_mask_p2_m1(i8 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_mask_p2_m1( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[P2ORZ:%.*]] = shl i8 2, [[Y:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = add i8 [[P2ORZ]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %p2orz = shl i8 2, %y + %mask = add i8 %p2orz, -1 + %and = and i8 %mask, %x + %r = icmp ult i8 %and, %x + ret i1 %r +} + +define i1 @src_is_mask_umax(i8 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_mask_umax( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 +; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] +; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.umax.i8(i8 [[YMASK]], i8 3) +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %y_m1 = add i8 %y, -1 + %ymask = xor i8 %y, %y_m1 + %mask = call i8 @llvm.umax.i8(i8 %ymask, i8 3) + + %and = and i8 %x, %mask + %r = icmp ugt i8 %x, %and + ret i1 %r +} + +define i1 @src_is_mask_umin(i8 %x_in, i8 %y, i8 %z) { +; CHECK-LABEL: @src_is_mask_umin( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 +; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] +; CHECK-NEXT: [[ZMASK:%.*]] = lshr i8 15, [[Z:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.umin.i8(i8 [[YMASK]], i8 [[ZMASK]]) +; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %y_m1 = add i8 %y, -1 + %ymask = xor i8 %y, %y_m1 + %zmask = lshr i8 15, %z + %mask = call i8 @llvm.umin.i8(i8 %ymask, i8 %zmask) + + %and = and i8 %mask, %x + %r = icmp ugt i8 %x, %and + ret i1 %r +} + +define i1 @src_is_mask_umin_fail_mismatch(i8 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_mask_umin_fail_mismatch( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 +; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] +; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.umin.i8(i8 [[YMASK]], i8 -32) +; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %y_m1 = add i8 %y, -1 + %ymask = xor i8 %y, %y_m1 + %mask = call i8 @llvm.umin.i8(i8 %ymask, i8 -32) + + %and = and i8 %mask, %x + %r = icmp ugt i8 %x, %and + ret i1 %r +} + +define i1 @src_is_mask_smax(i8 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_mask_smax( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 +; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] +; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.smax.i8(i8 [[YMASK]], i8 -1) +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %y_m1 = add i8 %y, -1 + %ymask = xor i8 %y, %y_m1 + %mask = call i8 @llvm.smax.i8(i8 %ymask, i8 -1) + + %and = and i8 %x, %mask + %r = icmp uge i8 %and, %x + ret i1 %r +} + +define i1 @src_is_mask_smin(i8 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_mask_smin( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 +; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] +; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.smin.i8(i8 [[YMASK]], i8 0) +; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %y_m1 = add i8 %y, -1 + %ymask = xor i8 %y, %y_m1 + %mask = call i8 @llvm.smin.i8(i8 %ymask, i8 0) + + %and = and i8 %mask, %x + %r = icmp uge i8 %and, %x + ret i1 %r +} + +define i1 @src_is_mask_bitreverse_not_mask(i8 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_mask_bitreverse_not_mask( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[NMASK:%.*]] = shl nsw i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.bitreverse.i8(i8 [[NMASK]]) +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %nmask = shl i8 -1, %y + %mask = call i8 @llvm.bitreverse.i8(i8 %nmask) + + %and = and i8 %x, %mask + %r = icmp ule i8 %x, %and + ret i1 %r +} + +define i1 @src_is_notmask_sext(i16 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_notmask_sext( +; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[M_IN:%.*]] = shl i8 -8, [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[M_IN]], -1 +; CHECK-NEXT: [[MASK:%.*]] = sext i8 [[TMP1]] to i16 +; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[MASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i16 %x_in, 123 + %m_in = shl i8 -8, %y + %nmask = sext i8 %m_in to i16 + %mask = xor i16 %nmask, -1 + %and = and i16 %mask, %x + %r = icmp ule i16 %x, %and + ret i1 %r +} + +define i1 @src_is_notmask_shl(i8 %x_in, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_is_notmask_shl( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 122 +; CHECK-NEXT: [[NMASK:%.*]] = shl nsw i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[NMASK]], -1 +; CHECK-NEXT: [[NOTMASK0:%.*]] = call i8 @llvm.bitreverse.i8(i8 [[TMP1]]) +; CHECK-NEXT: [[NOTMASK:%.*]] = select i1 [[COND:%.*]], i8 [[NOTMASK0]], i8 -8 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %nmask = shl i8 -1, %y + %mask = call i8 @llvm.bitreverse.i8(i8 %nmask) + %notmask0 = xor i8 %mask, -1 + %notmask = select i1 %cond, i8 %notmask0, i8 -8 + %and = and i8 %x, %notmask + %r = icmp eq i8 %and, 0 + ret i1 %r +} + +define i1 @src_is_notmask_shl_fail_multiuse_invert(i8 %x_in, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_is_notmask_shl_fail_multiuse_invert( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 122 +; CHECK-NEXT: [[NMASK:%.*]] = shl nsw i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[NMASK]], -1 +; CHECK-NEXT: [[NOTMASK0:%.*]] = call i8 @llvm.bitreverse.i8(i8 [[TMP1]]) +; CHECK-NEXT: [[NOTMASK:%.*]] = select i1 [[COND:%.*]], i8 [[NOTMASK0]], i8 -8 +; CHECK-NEXT: call void @use.i8(i8 [[NOTMASK]]) +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %nmask = shl i8 -1, %y + %mask = call i8 @llvm.bitreverse.i8(i8 %nmask) + %notmask0 = xor i8 %mask, -1 + %notmask = select i1 %cond, i8 %notmask0, i8 -8 + call void @use.i8(i8 %notmask) + %and = and i8 %x, %notmask + %r = icmp eq i8 %and, 0 + ret i1 %r +} + +define i1 @src_is_notmask_lshr_shl(i8 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_notmask_lshr_shl( +; CHECK-NEXT: [[TMP1:%.*]] = shl nsw i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[X_IN:%.*]], -124 +; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[TMP2]], [[TMP1]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %mask_shr = lshr i8 -1, %y + %nmask = shl i8 %mask_shr, %y + %mask = xor i8 %nmask, -1 + %and = and i8 %mask, %x + %r = icmp eq i8 %and, %x + ret i1 %r +} + +define i1 @src_is_notmask_lshr_shl_fail_mismatch_shifts(i8 %x_in, i8 %y, i8 %z) { +; CHECK-LABEL: @src_is_notmask_lshr_shl_fail_mismatch_shifts( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[MASK_SHR:%.*]] = lshr i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[NMASK:%.*]] = shl i8 [[MASK_SHR]], [[Z:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = xor i8 [[NMASK]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %mask_shr = lshr i8 -1, %y + %nmask = shl i8 %mask_shr, %z + %mask = xor i8 %nmask, -1 + %and = and i8 %mask, %x + %r = icmp eq i8 %and, %x + ret i1 %r +} + +define i1 @src_is_notmask_ashr(i16 %x_in, i8 %y, i16 %z) { +; CHECK-LABEL: @src_is_notmask_ashr( +; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[M_IN:%.*]] = shl i8 -32, [[Y:%.*]] +; CHECK-NEXT: [[NMASK:%.*]] = sext i8 [[M_IN]] to i16 +; CHECK-NEXT: [[NMASK_SHR:%.*]] = ashr i16 [[NMASK]], [[Z:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = xor i16 [[NMASK_SHR]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[MASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[X]], [[AND]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i16 %x_in, 123 + %m_in = shl i8 -32, %y + %nmask = sext i8 %m_in to i16 + %nmask_shr = ashr i16 %nmask, %z + %mask = xor i16 %nmask_shr, -1 + %and = and i16 %x, %mask + %r = icmp eq i16 %x, %and + ret i1 %r +} + +define i1 @src_is_notmask_neg_p2(i8 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_notmask_neg_p2( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[Y]], -1 +; CHECK-NEXT: [[TMP3:%.*]] = and i8 [[TMP1]], [[TMP2]] +; CHECK-NEXT: [[NOTMASK:%.*]] = call i8 @llvm.bitreverse.i8(i8 [[TMP3]]) +; CHECK-NEXT: [[AND:%.*]] = and i8 [[NOTMASK]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %ny = sub i8 0, %y + %p2 = and i8 %ny, %y + %nmask = sub i8 0, %p2 + %mask = call i8 @llvm.bitreverse.i8(i8 %nmask) + %notmask = xor i8 %mask, -1 + %and = and i8 %notmask, %x + %r = icmp eq i8 0, %and + ret i1 %r +} + +define i1 @src_is_notmask_neg_p2_fail_not_invertable(i8 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_notmask_neg_p2_fail_not_invertable( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[NY:%.*]] = sub i8 0, [[Y:%.*]] +; CHECK-NEXT: [[P2:%.*]] = and i8 [[NY]], [[Y]] +; CHECK-NEXT: [[NOTMASK:%.*]] = sub i8 0, [[P2]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %ny = sub i8 0, %y + %p2 = and i8 %ny, %y + %notmask = sub i8 0, %p2 + %and = and i8 %notmask, %x + %r = icmp eq i8 0, %and + ret i1 %r +} + +define i1 @src_is_notmask_xor_fail(i8 %x_in, i8 %y) { +; CHECK-LABEL: @src_is_notmask_xor_fail( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[Y:%.*]] +; CHECK-NEXT: [[NOTMASK_REV:%.*]] = xor i8 [[TMP1]], [[Y]] +; CHECK-NEXT: [[NOTMASK:%.*]] = call i8 @llvm.bitreverse.i8(i8 [[NOTMASK_REV]]) +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] +; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %y_m1 = add i8 %y, -1 + %mask = xor i8 %y, %y_m1 + %notmask_rev = xor i8 %mask, -1 + %notmask = call i8 @llvm.bitreverse.i8(i8 %notmask_rev) + %and = and i8 %x, %notmask + %r = icmp slt i8 %and, %x + ret i1 %r +} + +define i1 @src_is_mask_const_slt(i8 %x_in) { +; CHECK-LABEL: @src_is_mask_const_slt( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], 7 +; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[X]], [[AND]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %and = and i8 %x, 7 + %r = icmp slt i8 %x, %and + ret i1 %r +} + +define i1 @src_is_mask_const_sgt(i8 %x_in) { +; CHECK-LABEL: @src_is_mask_const_sgt( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[X]], 7 +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %and = and i8 %x, 7 + %r = icmp sgt i8 %x, %and + ret i1 %r +} + +define i1 @src_is_mask_const_sle(i8 %x_in) { +; CHECK-LABEL: @src_is_mask_const_sle( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], 31 +; CHECK-NEXT: [[R:%.*]] = icmp sle i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %and = and i8 %x, 31 + %r = icmp sle i8 %and, %x + ret i1 %r +} + +define i1 @src_is_mask_const_sge(i8 %x_in) { +; CHECK-LABEL: @src_is_mask_const_sge( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[X]], 32 +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %and = and i8 %x, 31 + %r = icmp sge i8 %and, %x + ret i1 %r +} -- GitLab From f89e4e339f31ad331aeab9a35183bc75bc42f2b6 Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Sat, 9 Mar 2024 18:13:16 -0600 Subject: [PATCH 050/953] [InstCombine] Move `foldICmpWithLowBitMaskedVal` to `foldICmpCommutative`; NFC --- .../InstCombine/InstCombineCompares.cpp | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index fc2688f425bb..8786ef1c6b08 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4082,23 +4082,22 @@ Instruction *InstCombinerImpl::foldSelectICmp(ICmpInst::Predicate Pred, /// The Mask can be a constant, too. /// For some predicates, the operands are commutative. /// For others, x can only be on a specific side. -static Value *foldICmpWithLowBitMaskedVal(ICmpInst &I, +static Value *foldICmpWithLowBitMaskedVal(ICmpInst::Predicate Pred, Value *Op0, + Value *Op1, InstCombiner::BuilderTy &Builder) { - ICmpInst::Predicate SrcPred; - Value *X, *M, *Y; + Value *M, *Y; auto m_VariableMask = m_CombineOr( m_CombineOr(m_Not(m_Shl(m_AllOnes(), m_Value())), m_Add(m_Shl(m_One(), m_Value()), m_AllOnes())), m_CombineOr(m_LShr(m_AllOnes(), m_Value()), m_LShr(m_Shl(m_AllOnes(), m_Value(Y)), m_Deferred(Y)))); auto m_Mask = m_CombineOr(m_VariableMask, m_LowBitMask()); - if (!match(&I, m_c_ICmp(SrcPred, - m_c_And(m_CombineAnd(m_Mask, m_Value(M)), m_Value(X)), - m_Deferred(X)))) + + if (!match(Op0, m_c_And(m_CombineAnd(m_Mask, m_Value(M)), m_Specific(Op1)))) return nullptr; ICmpInst::Predicate DstPred; - switch (SrcPred) { + switch (Pred) { case ICmpInst::Predicate::ICMP_EQ: // x & (-1 >> y) == x -> x u<= (-1 >> y) DstPred = ICmpInst::Predicate::ICMP_ULE; @@ -4164,7 +4163,7 @@ static Value *foldICmpWithLowBitMaskedVal(ICmpInst &I, M = Constant::replaceUndefsWith(VecC, SafeReplacementConstant); } - return Builder.CreateICmp(DstPred, X, M); + return Builder.CreateICmp(DstPred, Op1, M); } /// Some comparisons can be simplified. @@ -5081,9 +5080,6 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I, if (Value *V = foldMultiplicationOverflowCheck(I)) return replaceInstUsesWith(I, V); - if (Value *V = foldICmpWithLowBitMaskedVal(I, Builder)) - return replaceInstUsesWith(I, V); - if (Instruction *R = foldICmpAndXX(I, Q, *this)) return R; @@ -6984,6 +6980,9 @@ Instruction *InstCombinerImpl::foldICmpCommutative(ICmpInst::Predicate Pred, } } + if (Value *V = foldICmpWithLowBitMaskedVal(Pred, Op0, Op1, Builder)) + return replaceInstUsesWith(CxtI, V); + return nullptr; } -- GitLab From d77eb9ea598f6e56a583eac40f95ca59b3130523 Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Wed, 13 Sep 2023 13:45:52 -0500 Subject: [PATCH 051/953] [InstCombine] Improve mask detection in `foldICmpWithLowBitMaskedVal` Make recursive matcher that is able to detect a lot more patterns. Proofs for all supported patterns: https://alive2.llvm.org/ce/z/fSQ3nZ Differential Revision: https://reviews.llvm.org/D159058 --- llvm/include/llvm/IR/PatternMatch.h | 25 ++++ .../InstCombine/InstCombineCompares.cpp | 122 ++++++++++++++++-- ...nt-low-bit-mask-and-icmp-eq-to-icmp-ule.ll | 3 +- ...nt-low-bit-mask-and-icmp-ne-to-icmp-ugt.ll | 3 +- ...t-low-bit-mask-and-icmp-sge-to-icmp-sle.ll | 3 +- ...t-low-bit-mask-and-icmp-sgt-to-icmp-sgt.ll | 3 +- ...t-low-bit-mask-and-icmp-sle-to-icmp-sle.ll | 3 +- ...t-low-bit-mask-and-icmp-slt-to-icmp-sgt.ll | 3 +- ...t-low-bit-mask-and-icmp-uge-to-icmp-ule.ll | 3 +- ...t-low-bit-mask-and-icmp-ugt-to-icmp-ugt.ll | 3 +- ...t-low-bit-mask-and-icmp-ule-to-icmp-ule.ll | 3 +- ...t-low-bit-mask-and-icmp-ult-to-icmp-ugt.ll | 3 +- .../InstCombine/icmp-and-lowbit-mask.ll | 53 +++----- llvm/unittests/IR/PatternMatch.cpp | 22 ++++ 14 files changed, 184 insertions(+), 68 deletions(-) diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index fed552414298..487ae170210d 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -564,6 +564,19 @@ inline api_pred_ty m_NegatedPower2(const APInt *&V) { return V; } +struct is_negated_power2_or_zero { + bool isValue(const APInt &C) { return !C || C.isNegatedPowerOf2(); } +}; +/// Match a integer or vector negated power-of-2. +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty m_NegatedPower2OrZero() { + return cst_pred_ty(); +} +inline api_pred_ty +m_NegatedPower2OrZero(const APInt *&V) { + return V; +} + struct is_power2_or_zero { bool isValue(const APInt &C) { return !C || C.isPowerOf2(); } }; @@ -595,6 +608,18 @@ inline cst_pred_ty m_LowBitMask() { } inline api_pred_ty m_LowBitMask(const APInt *&V) { return V; } +struct is_lowbit_mask_or_zero { + bool isValue(const APInt &C) { return !C || C.isMask(); } +}; +/// Match an integer or vector with only the low bit(s) set. +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty m_LowBitMaskOrZero() { + return cst_pred_ty(); +} +inline api_pred_ty m_LowBitMaskOrZero(const APInt *&V) { + return V; +} + struct icmp_pred_with_threshold { ICmpInst::Predicate Pred; const APInt *Thr; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 8786ef1c6b08..06ff93c90076 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4069,6 +4069,95 @@ Instruction *InstCombinerImpl::foldSelectICmp(ICmpInst::Predicate Pred, return nullptr; } +// Returns whether V is a Mask ((X + 1) & X == 0) or ~Mask (-Pow2OrZero) +static bool isMaskOrZero(const Value *V, bool Not, const SimplifyQuery &Q, + unsigned Depth = 0) { + if (Not ? match(V, m_NegatedPower2OrZero()) : match(V, m_LowBitMaskOrZero())) + return true; + if (V->getType()->getScalarSizeInBits() == 1) + return true; + if (Depth++ >= MaxAnalysisRecursionDepth) + return false; + Value *X; + const Instruction *I = dyn_cast(V); + if (!I) + return false; + switch (I->getOpcode()) { + case Instruction::ZExt: + // ZExt(Mask) is a Mask. + return !Not && isMaskOrZero(I->getOperand(0), Not, Q, Depth); + case Instruction::SExt: + // SExt(Mask) is a Mask. + // SExt(~Mask) is a ~Mask. + return isMaskOrZero(I->getOperand(0), Not, Q, Depth); + case Instruction::And: + case Instruction::Or: + // Mask0 | Mask1 is a Mask. + // Mask0 & Mask1 is a Mask. + // ~Mask0 | ~Mask1 is a ~Mask. + // ~Mask0 & ~Mask1 is a ~Mask. + return isMaskOrZero(I->getOperand(1), Not, Q, Depth) && + isMaskOrZero(I->getOperand(0), Not, Q, Depth); + case Instruction::Xor: + if (match(V, m_Not(m_Value(X)))) + return isMaskOrZero(X, !Not, Q, Depth); + + // (X ^ (X - 1)) is a Mask + return !Not && + match(V, m_c_Xor(m_Value(X), m_Add(m_Deferred(X), m_AllOnes()))); + case Instruction::Select: + // c ? Mask0 : Mask1 is a Mask. + return isMaskOrZero(I->getOperand(1), Not, Q, Depth) && + isMaskOrZero(I->getOperand(2), Not, Q, Depth); + case Instruction::Shl: + // (~Mask) << X is a ~Mask. + return Not && isMaskOrZero(I->getOperand(0), Not, Q, Depth); + case Instruction::LShr: + // Mask >> X is a Mask. + return !Not && isMaskOrZero(I->getOperand(0), Not, Q, Depth); + case Instruction::AShr: + // Mask s>> X is a Mask. + // ~Mask s>> X is a ~Mask. + return isMaskOrZero(I->getOperand(0), Not, Q, Depth); + case Instruction::Add: + // Pow2 - 1 is a Mask. + if (!Not && match(I->getOperand(1), m_AllOnes())) + return isKnownToBeAPowerOfTwo(I->getOperand(0), Q.DL, /*OrZero*/ true, + Depth, Q.AC, Q.CxtI, Q.DT); + break; + case Instruction::Sub: + // -Pow2 is a ~Mask. + if (Not && match(I->getOperand(0), m_Zero())) + return isKnownToBeAPowerOfTwo(I->getOperand(1), Q.DL, /*OrZero*/ true, + Depth, Q.AC, Q.CxtI, Q.DT); + break; + case Instruction::Call: { + if (auto *II = dyn_cast(I)) { + switch (II->getIntrinsicID()) { + // min/max(Mask0, Mask1) is a Mask. + // min/max(~Mask0, ~Mask1) is a ~Mask. + case Intrinsic::umax: + case Intrinsic::smax: + case Intrinsic::umin: + case Intrinsic::smin: + return isMaskOrZero(II->getArgOperand(1), Not, Q, Depth) && + isMaskOrZero(II->getArgOperand(0), Not, Q, Depth); + + // In the context of masks, bitreverse(Mask) == ~Mask + case Intrinsic::bitreverse: + return isMaskOrZero(II->getArgOperand(0), !Not, Q, Depth); + default: + break; + } + } + break; + } + default: + break; + } + return false; +} + /// Some comparisons can be simplified. /// In this case, we are looking for comparisons that look like /// a check for a lossy truncation. @@ -4083,17 +4172,21 @@ Instruction *InstCombinerImpl::foldSelectICmp(ICmpInst::Predicate Pred, /// For some predicates, the operands are commutative. /// For others, x can only be on a specific side. static Value *foldICmpWithLowBitMaskedVal(ICmpInst::Predicate Pred, Value *Op0, - Value *Op1, - InstCombiner::BuilderTy &Builder) { - Value *M, *Y; - auto m_VariableMask = m_CombineOr( - m_CombineOr(m_Not(m_Shl(m_AllOnes(), m_Value())), - m_Add(m_Shl(m_One(), m_Value()), m_AllOnes())), - m_CombineOr(m_LShr(m_AllOnes(), m_Value()), - m_LShr(m_Shl(m_AllOnes(), m_Value(Y)), m_Deferred(Y)))); - auto m_Mask = m_CombineOr(m_VariableMask, m_LowBitMask()); - - if (!match(Op0, m_c_And(m_CombineAnd(m_Mask, m_Value(M)), m_Specific(Op1)))) + Value *Op1, const SimplifyQuery &Q, + InstCombiner &IC) { + Value *M; + bool NeedsNot = false; + + auto CheckMask = [&](Value *V, bool Not) { + if (ICmpInst::isSigned(Pred) && !match(V, m_ImmConstant())) + return false; + return isMaskOrZero(V, Not, Q); + }; + + if (!match(Op0, m_c_And(m_Specific(Op1), m_Value(M)))) + return nullptr; + + if (!CheckMask(M, /*Not*/ false)) return nullptr; ICmpInst::Predicate DstPred; @@ -4163,7 +4256,9 @@ static Value *foldICmpWithLowBitMaskedVal(ICmpInst::Predicate Pred, Value *Op0, M = Constant::replaceUndefsWith(VecC, SafeReplacementConstant); } - return Builder.CreateICmp(DstPred, Op1, M); + if (NeedsNot) + M = IC.Builder.CreateNot(M); + return IC.Builder.CreateICmp(DstPred, Op1, M); } /// Some comparisons can be simplified. @@ -6980,7 +7075,8 @@ Instruction *InstCombinerImpl::foldICmpCommutative(ICmpInst::Predicate Pred, } } - if (Value *V = foldICmpWithLowBitMaskedVal(Pred, Op0, Op1, Builder)) + const SimplifyQuery Q = SQ.getWithInstruction(&CxtI); + if (Value *V = foldICmpWithLowBitMaskedVal(Pred, Op0, Op1, Q, *this)) return replaceInstUsesWith(CxtI, V); return nullptr; diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll index a957fb2d088e..5b7a99d53c30 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-eq-to-icmp-ule.ll @@ -62,8 +62,7 @@ define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) { define <2 x i1> @p2_vec_nonsplat_edgecase0(<2 x i8> %x) { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase0( -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[RET:%.*]] = icmp ult <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ne-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ne-to-icmp-ugt.ll index 57361cdf3897..160d968b9ac4 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ne-to-icmp-ugt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ne-to-icmp-ugt.ll @@ -62,8 +62,7 @@ define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) { define <2 x i1> @p2_vec_nonsplat_edgecase0(<2 x i8> %x) { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase0( -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[RET:%.*]] = icmp ugt <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll index 0dfc9f51baf9..60921042d524 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll @@ -50,8 +50,7 @@ define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) { define <2 x i1> @p2_vec_nonsplat_edgecase(<2 x i8> %x) { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase( -; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp sge <2 x i8> [[TMP0]], [[X]] +; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sgt-to-icmp-sgt.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sgt-to-icmp-sgt.ll index e0893ce4cf2e..6345e70d7220 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sgt-to-icmp-sgt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sgt-to-icmp-sgt.ll @@ -63,8 +63,7 @@ define <2 x i1> @p2_vec_nonsplat() { define <2 x i1> @p2_vec_nonsplat_edgecase() { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase( ; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @gen2x8() -; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X]], -; CHECK-NEXT: [[RET:%.*]] = icmp sgt <2 x i8> [[X]], [[TMP0]] +; CHECK-NEXT: [[RET:%.*]] = icmp sgt <2 x i8> [[X]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %x = call <2 x i8> @gen2x8() diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll index 81887a390915..b7aec53fed67 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll @@ -63,8 +63,7 @@ define <2 x i1> @p2_vec_nonsplat() { define <2 x i1> @p2_vec_nonsplat_edgecase() { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase( ; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @gen2x8() -; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X]], -; CHECK-NEXT: [[RET:%.*]] = icmp sle <2 x i8> [[X]], [[TMP0]] +; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[X]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %x = call <2 x i8> @gen2x8() diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-slt-to-icmp-sgt.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-slt-to-icmp-sgt.ll index 8ce8687f1984..56661d335c4f 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-slt-to-icmp-sgt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-slt-to-icmp-sgt.ll @@ -50,8 +50,7 @@ define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) { define <2 x i1> @p2_vec_nonsplat_edgecase(<2 x i8> %x) { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase( -; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[TMP0]], [[X]] +; CHECK-NEXT: [[RET:%.*]] = icmp sgt <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-uge-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-uge-to-icmp-ule.ll index ff09e255185b..a93e8f779435 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-uge-to-icmp-ule.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-uge-to-icmp-ule.ll @@ -62,8 +62,7 @@ define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) { define <2 x i1> @p2_vec_nonsplat_edgecase0(<2 x i8> %x) { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase0( -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[RET:%.*]] = icmp ult <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ugt-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ugt-to-icmp-ugt.ll index 4ad04710fd7b..73ea4d456d24 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ugt-to-icmp-ugt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ugt-to-icmp-ugt.ll @@ -75,8 +75,7 @@ define <2 x i1> @p2_vec_nonsplat() { define <2 x i1> @p2_vec_nonsplat_edgecase0() { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase0( ; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @gen2x8() -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X]], -; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[RET:%.*]] = icmp ugt <2 x i8> [[X]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %x = call <2 x i8> @gen2x8() diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ule-to-icmp-ule.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ule-to-icmp-ule.ll index 8e513dcbf4ef..53886b5f2dc9 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ule-to-icmp-ule.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ule-to-icmp-ule.ll @@ -75,8 +75,7 @@ define <2 x i1> @p2_vec_nonsplat() { define <2 x i1> @p2_vec_nonsplat_edgecase0() { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase0( ; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @gen2x8() -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X]], -; CHECK-NEXT: [[RET:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[RET:%.*]] = icmp ult <2 x i8> [[X]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %x = call <2 x i8> @gen2x8() diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ult-to-icmp-ugt.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ult-to-icmp-ugt.ll index d02ecf6965e8..d66be571008c 100644 --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ult-to-icmp-ugt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-ult-to-icmp-ugt.ll @@ -62,8 +62,7 @@ define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) { define <2 x i1> @p2_vec_nonsplat_edgecase0(<2 x i8> %x) { ; CHECK-LABEL: @p2_vec_nonsplat_edgecase0( -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RET:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[RET:%.*]] = icmp ugt <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[RET]] ; %tmp0 = and <2 x i8> %x, diff --git a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll index 89f59eac60f8..4a8339fd5e1b 100644 --- a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll +++ b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll @@ -8,8 +8,7 @@ define i1 @src_is_mask_zext(i16 %x_in, i8 %y) { ; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[M_IN:%.*]] = lshr i8 -1, [[Y:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = zext i8 [[M_IN]] to i16 -; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i16 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i16 %x_in, 123 @@ -86,8 +85,7 @@ define i1 @src_is_mask_and(i8 %x_in, i8 %y, i8 %z) { ; CHECK-NEXT: [[MY:%.*]] = lshr i8 7, [[Y:%.*]] ; CHECK-NEXT: [[MZ:%.*]] = lshr i8 -1, [[Z:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = and i8 [[MY]], [[MZ]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], [[AND]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -125,8 +123,7 @@ define i1 @src_is_mask_or(i8 %x_in, i8 %y) { ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[MY:%.*]] = lshr i8 -1, [[Y:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = and i8 [[MY]], 7 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], [[AND]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -143,8 +140,7 @@ define i1 @src_is_mask_xor(i8 %x_in, i8 %y) { ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[MASK:%.*]] = xor i8 [[Y_M1]], [[Y]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -179,8 +175,7 @@ define i1 @src_is_mask_select(i8 %x_in, i8 %y, i1 %cond) { ; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[MASK:%.*]] = select i1 [[COND:%.*]], i8 [[YMASK]], i8 15 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -259,8 +254,7 @@ define i1 @src_is_mask_lshr(i8 %x_in, i8 %y, i8 %z, i1 %cond) { ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[SMASK:%.*]] = select i1 [[COND:%.*]], i8 [[YMASK]], i8 15 ; CHECK-NEXT: [[MASK:%.*]] = lshr i8 [[SMASK]], [[Z:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X]], [[AND]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -280,8 +274,7 @@ define i1 @src_is_mask_ashr(i8 %x_in, i8 %y, i8 %z, i1 %cond) { ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[SMASK:%.*]] = select i1 [[COND:%.*]], i8 [[YMASK]], i8 15 ; CHECK-NEXT: [[MASK:%.*]] = ashr i8 [[SMASK]], [[Z:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -299,8 +292,7 @@ define i1 @src_is_mask_p2_m1(i8 %x_in, i8 %y) { ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[P2ORZ:%.*]] = shl i8 2, [[Y:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = add i8 [[P2ORZ]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -317,8 +309,7 @@ define i1 @src_is_mask_umax(i8 %x_in, i8 %y) { ; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.umax.i8(i8 [[YMASK]], i8 3) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -338,8 +329,7 @@ define i1 @src_is_mask_umin(i8 %x_in, i8 %y, i8 %z) { ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[ZMASK:%.*]] = lshr i8 15, [[Z:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.umin.i8(i8 [[YMASK]], i8 [[ZMASK]]) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -379,8 +369,7 @@ define i1 @src_is_mask_smax(i8 %x_in, i8 %y) { ; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.smax.i8(i8 [[YMASK]], i8 -1) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -399,8 +388,7 @@ define i1 @src_is_mask_smin(i8 %x_in, i8 %y) { ; CHECK-NEXT: [[Y_M1:%.*]] = add i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[YMASK:%.*]] = xor i8 [[Y_M1]], [[Y]] ; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.smin.i8(i8 [[YMASK]], i8 0) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -418,8 +406,7 @@ define i1 @src_is_mask_bitreverse_not_mask(i8 %x_in, i8 %y) { ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[NMASK:%.*]] = shl nsw i8 -1, [[Y:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = call i8 @llvm.bitreverse.i8(i8 [[NMASK]]) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[MASK]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -433,12 +420,10 @@ define i1 @src_is_mask_bitreverse_not_mask(i8 %x_in, i8 %y) { define i1 @src_is_notmask_sext(i16 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_notmask_sext( -; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[M_IN:%.*]] = shl i8 -8, [[Y:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[M_IN]], -1 -; CHECK-NEXT: [[MASK:%.*]] = sext i8 [[TMP1]] to i16 -; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i16 [[X_IN:%.*]], -124 +; CHECK-NEXT: [[TMP2:%.*]] = sext i8 [[M_IN]] to i16 +; CHECK-NEXT: [[R:%.*]] = icmp uge i16 [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i16 %x_in, 123 @@ -531,13 +516,11 @@ define i1 @src_is_notmask_lshr_shl_fail_mismatch_shifts(i8 %x_in, i8 %y, i8 %z) define i1 @src_is_notmask_ashr(i16 %x_in, i8 %y, i16 %z) { ; CHECK-LABEL: @src_is_notmask_ashr( -; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[M_IN:%.*]] = shl i8 -32, [[Y:%.*]] ; CHECK-NEXT: [[NMASK:%.*]] = sext i8 [[M_IN]] to i16 ; CHECK-NEXT: [[NMASK_SHR:%.*]] = ashr i16 [[NMASK]], [[Z:%.*]] -; CHECK-NEXT: [[MASK:%.*]] = xor i16 [[NMASK_SHR]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[MASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[X]], [[AND]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i16 [[X_IN:%.*]], -124 +; CHECK-NEXT: [[R:%.*]] = icmp uge i16 [[TMP1]], [[NMASK_SHR]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i16 %x_in, 123 diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp index 883149c686b4..533a30bfba45 100644 --- a/llvm/unittests/IR/PatternMatch.cpp +++ b/llvm/unittests/IR/PatternMatch.cpp @@ -579,17 +579,39 @@ TEST_F(PatternMatchTest, Power2) { EXPECT_TRUE(m_Power2().match(C128)); EXPECT_FALSE(m_Power2().match(CNeg128)); + EXPECT_TRUE(m_Power2OrZero().match(C128)); + EXPECT_FALSE(m_Power2OrZero().match(CNeg128)); + EXPECT_FALSE(m_NegatedPower2().match(C128)); EXPECT_TRUE(m_NegatedPower2().match(CNeg128)); + EXPECT_FALSE(m_NegatedPower2OrZero().match(C128)); + EXPECT_TRUE(m_NegatedPower2OrZero().match(CNeg128)); + Value *CIntMin = IRB.getInt64(APSInt::getSignedMinValue(64).getSExtValue()); Value *CNegIntMin = ConstantExpr::getNeg(cast(CIntMin)); EXPECT_TRUE(m_Power2().match(CIntMin)); EXPECT_TRUE(m_Power2().match(CNegIntMin)); + EXPECT_TRUE(m_Power2OrZero().match(CIntMin)); + EXPECT_TRUE(m_Power2OrZero().match(CNegIntMin)); + EXPECT_TRUE(m_NegatedPower2().match(CIntMin)); EXPECT_TRUE(m_NegatedPower2().match(CNegIntMin)); + + EXPECT_TRUE(m_NegatedPower2OrZero().match(CIntMin)); + EXPECT_TRUE(m_NegatedPower2OrZero().match(CNegIntMin)); + + Value *CZero = IRB.getInt64(0); + + EXPECT_FALSE(m_Power2().match(CZero)); + + EXPECT_TRUE(m_Power2OrZero().match(CZero)); + + EXPECT_FALSE(m_NegatedPower2().match(CZero)); + + EXPECT_TRUE(m_NegatedPower2OrZero().match(CZero)); } TEST_F(PatternMatchTest, Not) { -- GitLab From 193b3d6733b7bf606c70749b1b65b6a0daae97d5 Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Wed, 13 Sep 2023 13:45:55 -0500 Subject: [PATCH 052/953] [InstCombine] Recognize `(icmp eq/ne (and X, ~Mask), 0)` pattern in `foldICmpWithLowBitMaskedVal` `(icmp eq/ne (and X, ~Mask), 0)` is equivilent to `(icmp eq/ne (and X, Mask), X` and we sometimes generate the former pattern intentionally to reduce number of uses of `X`. Proof: https://alive2.llvm.org/ce/z/3u-usC Differential Revision: https://reviews.llvm.org/D159329 Closes #81562 --- .../InstCombine/InstCombineCompares.cpp | 22 ++++++++++++++----- .../InstCombine/icmp-and-lowbit-mask.ll | 20 +++++++---------- .../InstCombine/lshr-and-negC-icmpeq-zero.ll | 9 +++----- .../lshr-and-signbit-icmpeq-zero.ll | 9 +++----- .../InstCombine/shl-and-negC-icmpeq-zero.ll | 9 +++----- .../shl-and-signbit-icmpeq-zero.ll | 9 +++----- 6 files changed, 36 insertions(+), 42 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 06ff93c90076..5b412a52e164 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4163,6 +4163,7 @@ static bool isMaskOrZero(const Value *V, bool Not, const SimplifyQuery &Q, /// a check for a lossy truncation. /// Folds: /// icmp SrcPred (x & Mask), x to icmp DstPred x, Mask +/// icmp eq/ne (x & ~Mask), 0 to icmp DstPred x, Mask /// Where Mask is some pattern that produces all-ones in low bits: /// (-1 >> y) /// ((-1 << y) >> y) <- non-canonical, has extra uses @@ -4174,7 +4175,7 @@ static bool isMaskOrZero(const Value *V, bool Not, const SimplifyQuery &Q, static Value *foldICmpWithLowBitMaskedVal(ICmpInst::Predicate Pred, Value *Op0, Value *Op1, const SimplifyQuery &Q, InstCombiner &IC) { - Value *M; + Value *X, *M; bool NeedsNot = false; auto CheckMask = [&](Value *V, bool Not) { @@ -4183,11 +4184,20 @@ static Value *foldICmpWithLowBitMaskedVal(ICmpInst::Predicate Pred, Value *Op0, return isMaskOrZero(V, Not, Q); }; - if (!match(Op0, m_c_And(m_Specific(Op1), m_Value(M)))) - return nullptr; - - if (!CheckMask(M, /*Not*/ false)) + if (match(Op0, m_c_And(m_Specific(Op1), m_Value(M))) && + CheckMask(M, /*Not*/ false)) { + X = Op1; + } else if (match(Op1, m_Zero()) && ICmpInst::isEquality(Pred) && + match(Op0, m_OneUse(m_And(m_Value(X), m_Value(M))))) { + NeedsNot = true; + if (IC.isFreeToInvert(X, X->hasOneUse()) && CheckMask(X, /*Not*/ true)) + std::swap(X, M); + else if (!IC.isFreeToInvert(M, M->hasOneUse()) || + !CheckMask(M, /*Not*/ true)) + return nullptr; + } else { return nullptr; + } ICmpInst::Predicate DstPred; switch (Pred) { @@ -4258,7 +4268,7 @@ static Value *foldICmpWithLowBitMaskedVal(ICmpInst::Predicate Pred, Value *Op0, if (NeedsNot) M = IC.Builder.CreateNot(M); - return IC.Builder.CreateICmp(DstPred, Op1, M); + return IC.Builder.CreateICmp(DstPred, X, M); } /// Some comparisons can be simplified. diff --git a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll index 4a8339fd5e1b..640a95b05616 100644 --- a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll +++ b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll @@ -41,10 +41,9 @@ define i1 @src_is_mask_zext_fail_not_mask(i16 %x_in, i8 %y) { define i1 @src_is_mask_sext(i16 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_mask_sext( ; CHECK-NEXT: [[X:%.*]] = xor i16 [[X_IN:%.*]], 123 -; CHECK-NEXT: [[TMP1:%.*]] = ashr i8 -32, [[Y:%.*]] -; CHECK-NEXT: [[NOTMASK:%.*]] = sext i8 [[TMP1]] to i16 -; CHECK-NEXT: [[AND:%.*]] = and i16 [[X]], [[NOTMASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 31, [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = zext nneg i8 [[TMP1]] to i16 +; CHECK-NEXT: [[R:%.*]] = icmp ule i16 [[X]], [[TMP2]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i16 %x_in, 123 @@ -212,9 +211,7 @@ define i1 @src_is_mask_shl_lshr(i8 %x_in, i8 %y, i1 %cond) { ; CHECK-LABEL: @src_is_mask_shl_lshr( ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 122 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[Y:%.*]] -; CHECK-NEXT: [[NOTMASK:%.*]] = xor i8 [[TMP1]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X]], [[TMP1]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -558,11 +555,10 @@ define i1 @src_is_notmask_neg_p2(i8 %x_in, i8 %y) { define i1 @src_is_notmask_neg_p2_fail_not_invertable(i8 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_notmask_neg_p2_fail_not_invertable( ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 -; CHECK-NEXT: [[NY:%.*]] = sub i8 0, [[Y:%.*]] -; CHECK-NEXT: [[P2:%.*]] = and i8 [[NY]], [[Y]] -; CHECK-NEXT: [[NOTMASK:%.*]] = sub i8 0, [[P2]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[Y]], -1 +; CHECK-NEXT: [[TMP3:%.*]] = and i8 [[TMP1]], [[TMP2]] +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[TMP3]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 diff --git a/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll b/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll index 79aef3a5406c..847a7940bad8 100644 --- a/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll +++ b/llvm/test/Transforms/InstCombine/lshr-and-negC-icmpeq-zero.ll @@ -84,8 +84,7 @@ define <4 x i1> @vec_4xi32_lshr_and_negC_eq(<4 x i32> %x, <4 x i32> %y) { define <4 x i1> @vec_lshr_and_negC_eq_undef1(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_lshr_and_negC_eq_undef1( ; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer +; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %lshr = lshr <4 x i32> %x, %y @@ -97,8 +96,7 @@ define <4 x i1> @vec_lshr_and_negC_eq_undef1(<4 x i32> %x, <4 x i32> %y) { define <4 x i1> @vec_lshr_and_negC_eq_undef2(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_lshr_and_negC_eq_undef2( ; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %lshr = lshr <4 x i32> %x, %y @@ -110,8 +108,7 @@ define <4 x i1> @vec_lshr_and_negC_eq_undef2(<4 x i32> %x, <4 x i32> %y) { define <4 x i1> @vec_lshr_and_negC_eq_undef3(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_lshr_and_negC_eq_undef3( ; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[LSHR]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %lshr = lshr <4 x i32> %x, %y diff --git a/llvm/test/Transforms/InstCombine/lshr-and-signbit-icmpeq-zero.ll b/llvm/test/Transforms/InstCombine/lshr-and-signbit-icmpeq-zero.ll index 5335a4736896..39f4e58b25dc 100644 --- a/llvm/test/Transforms/InstCombine/lshr-and-signbit-icmpeq-zero.ll +++ b/llvm/test/Transforms/InstCombine/lshr-and-signbit-icmpeq-zero.ll @@ -84,8 +84,7 @@ define <4 x i1> @vec_4xi32_lshr_and_signbit_eq(<4 x i32> %x, <4 x i32> %y) { define <4 x i1> @vec_4xi32_lshr_and_signbit_eq_undef1(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_4xi32_lshr_and_signbit_eq_undef1( ; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer +; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[LSHR]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %lshr = lshr <4 x i32> %x, %y @@ -97,8 +96,7 @@ define <4 x i1> @vec_4xi32_lshr_and_signbit_eq_undef1(<4 x i32> %x, <4 x i32> %y define <4 x i1> @vec_4xi32_lshr_and_signbit_eq_undef2(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_4xi32_lshr_and_signbit_eq_undef2( ; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[LSHR]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %lshr = lshr <4 x i32> %x, %y @@ -110,8 +108,7 @@ define <4 x i1> @vec_4xi32_lshr_and_signbit_eq_undef2(<4 x i32> %x, <4 x i32> %y define <4 x i1> @vec_4xi32_lshr_and_signbit_eq_undef3(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_4xi32_lshr_and_signbit_eq_undef3( ; CHECK-NEXT: [[LSHR:%.*]] = lshr <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[LSHR]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %lshr = lshr <4 x i32> %x, %y diff --git a/llvm/test/Transforms/InstCombine/shl-and-negC-icmpeq-zero.ll b/llvm/test/Transforms/InstCombine/shl-and-negC-icmpeq-zero.ll index d8e7fe2e2a2c..406dc72f2646 100644 --- a/llvm/test/Transforms/InstCombine/shl-and-negC-icmpeq-zero.ll +++ b/llvm/test/Transforms/InstCombine/shl-and-negC-icmpeq-zero.ll @@ -84,8 +84,7 @@ define <4 x i1> @vec_4xi32_shl_and_negC_eq(<4 x i32> %x, <4 x i32> %y) { define <4 x i1> @vec_shl_and_negC_eq_undef1(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_shl_and_negC_eq_undef1( ; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer +; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[SHL]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %shl = shl <4 x i32> %x, %y @@ -97,8 +96,7 @@ define <4 x i1> @vec_shl_and_negC_eq_undef1(<4 x i32> %x, <4 x i32> %y) { define <4 x i1> @vec_shl_and_negC_eq_undef2(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_shl_and_negC_eq_undef2( ; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[SHL]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %shl = shl <4 x i32> %x, %y @@ -110,8 +108,7 @@ define <4 x i1> @vec_shl_and_negC_eq_undef2(<4 x i32> %x, <4 x i32> %y) { define <4 x i1> @vec_shl_and_negC_eq_undef3(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_shl_and_negC_eq_undef3( ; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp ult <4 x i32> [[SHL]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %shl = shl <4 x i32> %x, %y diff --git a/llvm/test/Transforms/InstCombine/shl-and-signbit-icmpeq-zero.ll b/llvm/test/Transforms/InstCombine/shl-and-signbit-icmpeq-zero.ll index 42b755f51a97..4c2c876e3925 100644 --- a/llvm/test/Transforms/InstCombine/shl-and-signbit-icmpeq-zero.ll +++ b/llvm/test/Transforms/InstCombine/shl-and-signbit-icmpeq-zero.ll @@ -84,8 +84,7 @@ define <4 x i1> @vec_4xi32_shl_and_signbit_eq(<4 x i32> %x, <4 x i32> %y) { define <4 x i1> @vec_4xi32_shl_and_signbit_eq_undef1(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_4xi32_shl_and_signbit_eq_undef1( ; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], zeroinitializer +; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[SHL]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %shl = shl <4 x i32> %x, %y @@ -97,8 +96,7 @@ define <4 x i1> @vec_4xi32_shl_and_signbit_eq_undef1(<4 x i32> %x, <4 x i32> %y) define <4 x i1> @vec_4xi32_shl_and_signbit_eq_undef2(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_4xi32_shl_and_signbit_eq_undef2( ; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[SHL]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %shl = shl <4 x i32> %x, %y @@ -110,8 +108,7 @@ define <4 x i1> @vec_4xi32_shl_and_signbit_eq_undef2(<4 x i32> %x, <4 x i32> %y) define <4 x i1> @vec_4xi32_shl_and_signbit_eq_undef3(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @vec_4xi32_shl_and_signbit_eq_undef3( ; CHECK-NEXT: [[SHL:%.*]] = shl <4 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[SHL]], -; CHECK-NEXT: [[R:%.*]] = icmp eq <4 x i32> [[AND]], +; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[SHL]], ; CHECK-NEXT: ret <4 x i1> [[R]] ; %shl = shl <4 x i32> %x, %y -- GitLab From a53401e9dff6168b872eeb61f62b0f60b185328a Mon Sep 17 00:00:00 2001 From: alx32 <103613512+alx32@users.noreply.github.com> Date: Sun, 10 Mar 2024 13:22:31 -0700 Subject: [PATCH 053/953] [lld-macho][NFC] Refactor ObjCSelRefsSection out of ObjCStubsSection (#83878) Currently ObjCStubsSection is handling both the logic for the "__objc_stubs" section, as well as the logic for the "__objc_selrefs" section. While this is OK for now, it will be an issue for other features that want to interact with the "__objc_selrefs" section, such as upcoming relative method lists feature - which will also want to create / reference entries in the "__objc_selrefs" section. In this PR we split the logic relating to handling the "__objc_selrefs" section into a new SyntheticSection (ObjCSelRefsSection). Non-functional change - neither the behavior nor implementation changes, the interface is just made more friendly to not have "__objc_selrefs" so bound to "__objc_stubs". --------- Co-authored-by: Alex B --- lld/MachO/SyntheticSections.cpp | 105 ++++++++++++++++++-------------- lld/MachO/SyntheticSections.h | 24 +++++++- lld/MachO/Writer.cpp | 3 +- 3 files changed, 83 insertions(+), 49 deletions(-) diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp index a5d66bb4ea08..7ee3261ce307 100644 --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -806,26 +806,10 @@ void StubHelperSection::setUp() { dyldPrivate->used = true; } -ObjCStubsSection::ObjCStubsSection() - : SyntheticSection(segment_names::text, section_names::objcStubs) { - flags = S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS; - align = config->objcStubsMode == ObjCStubsMode::fast - ? target->objcStubsFastAlignment - : target->objcStubsSmallAlignment; -} - -bool ObjCStubsSection::isObjCStubSymbol(Symbol *sym) { - return sym->getName().starts_with(symbolPrefix); -} +ObjCSelRefsSection::ObjCSelRefsSection() + : SyntheticSection(segment_names::data, section_names::objcSelrefs) {} -StringRef ObjCStubsSection::getMethname(Symbol *sym) { - assert(isObjCStubSymbol(sym) && "not an objc stub"); - auto name = sym->getName(); - StringRef methname = name.drop_front(symbolPrefix.size()); - return methname; -} - -void ObjCStubsSection::initialize() { +void ObjCSelRefsSection::initialize() { // Do not fold selrefs without ICF. if (config->icfLevel == ICFLevel::none) return; @@ -852,33 +836,62 @@ void ObjCStubsSection::initialize() { } } +ConcatInputSection *ObjCSelRefsSection::makeSelRef(StringRef methname) { + auto methnameOffset = + in.objcMethnameSection->getStringOffset(methname).outSecOff; + + size_t wordSize = target->wordSize; + uint8_t *selrefData = bAlloc().Allocate(wordSize); + write64le(selrefData, methnameOffset); + ConcatInputSection *objcSelref = + makeSyntheticInputSection(segment_names::data, section_names::objcSelrefs, + S_LITERAL_POINTERS | S_ATTR_NO_DEAD_STRIP, + ArrayRef{selrefData, wordSize}, + /*align=*/wordSize); + objcSelref->live = true; + objcSelref->relocs.push_back({/*type=*/target->unsignedRelocType, + /*pcrel=*/false, /*length=*/3, + /*offset=*/0, + /*addend=*/static_cast(methnameOffset), + /*referent=*/in.objcMethnameSection->isec}); + objcSelref->parent = ConcatOutputSection::getOrCreateForInput(objcSelref); + inputSections.push_back(objcSelref); + objcSelref->isFinal = true; + methnameToSelref[CachedHashStringRef(methname)] = objcSelref; + return objcSelref; +} + +ConcatInputSection *ObjCSelRefsSection::getSelRef(StringRef methname) { + auto it = methnameToSelref.find(CachedHashStringRef(methname)); + if (it == methnameToSelref.end()) + return nullptr; + return it->second; +} + +ObjCStubsSection::ObjCStubsSection() + : SyntheticSection(segment_names::text, section_names::objcStubs) { + flags = S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS; + align = config->objcStubsMode == ObjCStubsMode::fast + ? target->objcStubsFastAlignment + : target->objcStubsSmallAlignment; +} + +bool ObjCStubsSection::isObjCStubSymbol(Symbol *sym) { + return sym->getName().starts_with(symbolPrefix); +} + +StringRef ObjCStubsSection::getMethname(Symbol *sym) { + assert(isObjCStubSymbol(sym) && "not an objc stub"); + auto name = sym->getName(); + StringRef methname = name.drop_front(symbolPrefix.size()); + return methname; +} + void ObjCStubsSection::addEntry(Symbol *sym) { StringRef methname = getMethname(sym); // We create a selref entry for each unique methname. - if (!methnameToSelref.count(CachedHashStringRef(methname))) { - auto methnameOffset = - in.objcMethnameSection->getStringOffset(methname).outSecOff; - - size_t wordSize = target->wordSize; - uint8_t *selrefData = bAlloc().Allocate(wordSize); - write64le(selrefData, methnameOffset); - auto *objcSelref = makeSyntheticInputSection( - segment_names::data, section_names::objcSelrefs, - S_LITERAL_POINTERS | S_ATTR_NO_DEAD_STRIP, - ArrayRef{selrefData, wordSize}, - /*align=*/wordSize); - objcSelref->live = true; - objcSelref->relocs.push_back( - {/*type=*/target->unsignedRelocType, - /*pcrel=*/false, /*length=*/3, - /*offset=*/0, - /*addend=*/static_cast(methnameOffset), - /*referent=*/in.objcMethnameSection->isec}); - objcSelref->parent = ConcatOutputSection::getOrCreateForInput(objcSelref); - inputSections.push_back(objcSelref); - objcSelref->isFinal = true; - methnameToSelref[CachedHashStringRef(methname)] = objcSelref; - } + if (!in.objcSelRefs->getSelRef(methname)) + in.objcSelRefs->makeSelRef(methname); auto stubSize = config->objcStubsMode == ObjCStubsMode::fast ? target->objcStubsFastSize @@ -927,9 +940,9 @@ void ObjCStubsSection::writeTo(uint8_t *buf) const { Defined *sym = symbols[i]; auto methname = getMethname(sym); - auto j = methnameToSelref.find(CachedHashStringRef(methname)); - assert(j != methnameToSelref.end()); - auto selrefAddr = j->second->getVA(0); + InputSection *selRef = in.objcSelRefs->getSelRef(methname); + assert(selRef != nullptr && "no selref for methname"); + auto selrefAddr = selRef->getVA(0); target->writeObjCMsgSendStub(buf + stubOffset, sym, in.objcStubs->addr, stubOffset, selrefAddr, objcMsgSend); } diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h index 8d54cacc8d75..6d85f0aea8e0 100644 --- a/lld/MachO/SyntheticSections.h +++ b/lld/MachO/SyntheticSections.h @@ -315,6 +315,27 @@ public: Defined *dyldPrivate = nullptr; }; +class ObjCSelRefsSection final : public SyntheticSection { +public: + ObjCSelRefsSection(); + void initialize(); + + // This SyntheticSection does not do directly write data to the output, it is + // just a placeholder for easily creating SyntheticInputSection's which will + // be inserted into inputSections and handeled by the default writing + // mechanism. + uint64_t getSize() const override { return 0; } + bool isNeeded() const override { return false; } + void writeTo(uint8_t *buf) const override {} + + ConcatInputSection *getSelRef(StringRef methname); + ConcatInputSection *makeSelRef(StringRef methname); + +private: + llvm::DenseMap + methnameToSelref; +}; + // Objective-C stubs are hoisted objc_msgSend calls per selector called in the // program. Apple Clang produces undefined symbols to each stub, such as // '_objc_msgSend$foo', which are then synthesized by the linker. The stubs @@ -324,7 +345,6 @@ public: class ObjCStubsSection final : public SyntheticSection { public: ObjCStubsSection(); - void initialize(); void addEntry(Symbol *sym); uint64_t getSize() const override; bool isNeeded() const override { return !symbols.empty(); } @@ -338,7 +358,6 @@ public: private: std::vector symbols; - llvm::DenseMap methnameToSelref; Symbol *objcMsgSend = nullptr; }; @@ -794,6 +813,7 @@ struct InStruct { LazyPointerSection *lazyPointers = nullptr; StubsSection *stubs = nullptr; StubHelperSection *stubHelper = nullptr; + ObjCSelRefsSection *objcSelRefs = nullptr; ObjCStubsSection *objcStubs = nullptr; UnwindInfoSection *unwindInfo = nullptr; ObjCImageInfoSection *objCImageInfo = nullptr; diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp index 9b0a32c136e8..8f335188e12c 100644 --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -720,7 +720,7 @@ static void addNonWeakDefinition(const Defined *defined) { void Writer::scanSymbols() { TimeTraceScope timeScope("Scan symbols"); - in.objcStubs->initialize(); + in.objcSelRefs->initialize(); for (Symbol *sym : symtab->getSymbols()) { if (auto *defined = dyn_cast(sym)) { if (!defined->isLive()) @@ -1359,6 +1359,7 @@ void macho::createSyntheticSections() { in.got = make(); in.tlvPointers = make(); in.stubs = make(); + in.objcSelRefs = make(); in.objcStubs = make(); in.unwindInfo = makeUnwindInfoSection(); in.objCImageInfo = make(); -- GitLab From ea697dcc2ad9e6a1cc313d792b485d9218a943a1 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Sun, 10 Mar 2024 15:49:44 -0500 Subject: [PATCH 054/953] [libc][NFC] Move GPU allocator implementation to common header (#84690) Summary: This is a NFC move preceding more radical functional changes to the allocator implementation. We just move it to a common utility so it will be easier to write these in tandem. --- libc/src/__support/GPU/CMakeLists.txt | 12 +++++++ libc/src/__support/GPU/allocator.cpp | 45 +++++++++++++++++++++++++++ libc/src/__support/GPU/allocator.h | 23 ++++++++++++++ libc/src/stdlib/gpu/CMakeLists.txt | 4 +-- libc/src/stdlib/gpu/free.cpp | 11 ++----- libc/src/stdlib/gpu/malloc.cpp | 12 ++----- 6 files changed, 88 insertions(+), 19 deletions(-) create mode 100644 libc/src/__support/GPU/allocator.cpp create mode 100644 libc/src/__support/GPU/allocator.h diff --git a/libc/src/__support/GPU/CMakeLists.txt b/libc/src/__support/GPU/CMakeLists.txt index c181b2ed43c8..28fd9a1ebcc9 100644 --- a/libc/src/__support/GPU/CMakeLists.txt +++ b/libc/src/__support/GPU/CMakeLists.txt @@ -12,3 +12,15 @@ add_header_library( DEPENDS ${target_gpu_utils} ) + +add_object_library( + allocator + SRCS + allocator.cpp + HDRS + allocator.h + DEPENDS + libc.src.__support.common + libc.src.__support.GPU.utils + libc.src.__support.RPC.rpc_client +) diff --git a/libc/src/__support/GPU/allocator.cpp b/libc/src/__support/GPU/allocator.cpp new file mode 100644 index 000000000000..a049959964cf --- /dev/null +++ b/libc/src/__support/GPU/allocator.cpp @@ -0,0 +1,45 @@ +//===-- GPU memory allocator implementation ---------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "allocator.h" + +#include "src/__support/GPU/utils.h" +#include "src/__support/RPC/rpc_client.h" + +namespace LIBC_NAMESPACE { +namespace { + +void *rpc_allocate(uint64_t size) { + void *ptr = nullptr; + rpc::Client::Port port = rpc::client.open(); + port.send_and_recv([=](rpc::Buffer *buffer) { buffer->data[0] = size; }, + [&](rpc::Buffer *buffer) { + ptr = reinterpret_cast(buffer->data[0]); + }); + port.close(); + return ptr; +} + +void rpc_free(void *ptr) { + rpc::Client::Port port = rpc::client.open(); + port.send([=](rpc::Buffer *buffer) { + buffer->data[0] = reinterpret_cast(ptr); + }); + port.close(); +} + +} // namespace + +namespace gpu { + +void *allocate(uint64_t size) { return rpc_allocate(size); } + +void deallocate(void *ptr) { rpc_free(ptr); } + +} // namespace gpu +} // namespace LIBC_NAMESPACE diff --git a/libc/src/__support/GPU/allocator.h b/libc/src/__support/GPU/allocator.h new file mode 100644 index 000000000000..99eeb6826cc2 --- /dev/null +++ b/libc/src/__support/GPU/allocator.h @@ -0,0 +1,23 @@ +//===-- GPU memory allocator implementation ---------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC___SUPPORT_GPU_ALLOCATOR_H +#define LLVM_LIBC_SRC___SUPPORT_GPU_ALLOCATOR_H + +#include + +namespace LIBC_NAMESPACE { +namespace gpu { + +void *allocate(uint64_t size); +void deallocate(void *ptr); + +} // namespace gpu +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC___SUPPORT_GPU_ALLOCATOR_H diff --git a/libc/src/stdlib/gpu/CMakeLists.txt b/libc/src/stdlib/gpu/CMakeLists.txt index 71ae10648d00..f8a11ec3ffb0 100644 --- a/libc/src/stdlib/gpu/CMakeLists.txt +++ b/libc/src/stdlib/gpu/CMakeLists.txt @@ -6,7 +6,7 @@ add_entrypoint_object( ../malloc.h DEPENDS libc.include.stdlib - libc.src.__support.RPC.rpc_client + libc.src.__support.GPU.allocator ) add_entrypoint_object( @@ -28,5 +28,5 @@ add_entrypoint_object( ../abort.h DEPENDS libc.include.stdlib - libc.src.__support.RPC.rpc_client + libc.src.__support.GPU.allocator ) diff --git a/libc/src/stdlib/gpu/free.cpp b/libc/src/stdlib/gpu/free.cpp index 3a41e5febad0..fb5703b78ae6 100644 --- a/libc/src/stdlib/gpu/free.cpp +++ b/libc/src/stdlib/gpu/free.cpp @@ -7,17 +7,12 @@ //===----------------------------------------------------------------------===// #include "src/stdlib/free.h" -#include "src/__support/RPC/rpc_client.h" + +#include "src/__support/GPU/allocator.h" #include "src/__support/common.h" namespace LIBC_NAMESPACE { -LLVM_LIBC_FUNCTION(void, free, (void *ptr)) { - rpc::Client::Port port = rpc::client.open(); - port.send([=](rpc::Buffer *buffer) { - buffer->data[0] = reinterpret_cast(ptr); - }); - port.close(); -} +LLVM_LIBC_FUNCTION(void, free, (void *ptr)) { gpu::deallocate(ptr); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdlib/gpu/malloc.cpp b/libc/src/stdlib/gpu/malloc.cpp index a21969078305..93558231d081 100644 --- a/libc/src/stdlib/gpu/malloc.cpp +++ b/libc/src/stdlib/gpu/malloc.cpp @@ -7,20 +7,14 @@ //===----------------------------------------------------------------------===// #include "src/stdlib/malloc.h" -#include "src/__support/RPC/rpc_client.h" + +#include "src/__support/GPU/allocator.h" #include "src/__support/common.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(void *, malloc, (size_t size)) { - void *ptr = nullptr; - rpc::Client::Port port = rpc::client.open(); - port.send_and_recv([=](rpc::Buffer *buffer) { buffer->data[0] = size; }, - [&](rpc::Buffer *buffer) { - ptr = reinterpret_cast(buffer->data[0]); - }); - port.close(); - return ptr; + return gpu::allocate(size); } } // namespace LIBC_NAMESPACE -- GitLab From fe1645e25c5ab5e3ba8aa16d4f637633ded328ab Mon Sep 17 00:00:00 2001 From: Schrodinger ZHU Yifan Date: Sun, 10 Mar 2024 19:01:54 -0400 Subject: [PATCH 055/953] [libc][mman] Implement msync (#84700) Implement `msync` as specified in: 1. https://www.man7.org/linux/man-pages/man2/msync.2.html 2. https://pubs.opengroup.org/onlinepubs/9699919799/ --- libc/config/linux/aarch64/entrypoints.txt | 1 + libc/config/linux/riscv/entrypoints.txt | 1 + libc/config/linux/x86_64/entrypoints.txt | 1 + libc/spec/posix.td | 5 ++ libc/src/sys/mman/CMakeLists.txt | 7 +++ libc/src/sys/mman/linux/CMakeLists.txt | 13 ++++ libc/src/sys/mman/linux/msync.cpp | 25 ++++++++ libc/src/sys/mman/msync.h | 21 +++++++ libc/test/src/sys/mman/linux/CMakeLists.txt | 20 ++++++ libc/test/src/sys/mman/linux/msync_test.cpp | 69 +++++++++++++++++++++ 10 files changed, 163 insertions(+) create mode 100644 libc/src/sys/mman/linux/msync.cpp create mode 100644 libc/src/sys/mman/msync.h create mode 100644 libc/test/src/sys/mman/linux/msync_test.cpp diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index c24703840183..b447b5dfe098 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -185,6 +185,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.mman.munlock libc.src.sys.mman.mlockall libc.src.sys.mman.munlockall + libc.src.sys.mman.msync # sys/random.h entrypoints libc.src.sys.random.getrandom diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index f7a65615115f..5175b14adf2e 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -190,6 +190,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.mman.munlock libc.src.sys.mman.mlockall libc.src.sys.mman.munlockall + libc.src.sys.mman.msync # sys/random.h entrypoints libc.src.sys.random.getrandom diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index b51227e5f25d..b8bec14a3d2a 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -228,6 +228,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.mman.munlock libc.src.sys.mman.mlockall libc.src.sys.mman.munlockall + libc.src.sys.mman.msync # sys/random.h entrypoints libc.src.sys.random.getrandom diff --git a/libc/spec/posix.td b/libc/spec/posix.td index 70be692e208a..d0f5a4584dd4 100644 --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -309,6 +309,11 @@ def POSIX : StandardSpec<"POSIX"> { RetValSpec, [ArgSpec] >, + FunctionSpec< + "msync", + RetValSpec, + [ArgSpec, ArgSpec, ArgSpec] + >, ] >; diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt index f11f5ac9df9f..b49f73873c20 100644 --- a/libc/src/sys/mman/CMakeLists.txt +++ b/libc/src/sys/mman/CMakeLists.txt @@ -78,3 +78,10 @@ add_entrypoint_object( DEPENDS .${LIBC_TARGET_OS}.munlockall ) + +add_entrypoint_object( + msync + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.msync +) diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt index a6feff1f0bec..04086ee5d332 100644 --- a/libc/src/sys/mman/linux/CMakeLists.txt +++ b/libc/src/sys/mman/linux/CMakeLists.txt @@ -139,3 +139,16 @@ add_entrypoint_object( libc.src.__support.OSUtil.osutil libc.src.errno.errno ) + +add_entrypoint_object( + msync + SRCS + msync.cpp + HDRS + ../msync.h + DEPENDS + libc.include.sys_mman + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) diff --git a/libc/src/sys/mman/linux/msync.cpp b/libc/src/sys/mman/linux/msync.cpp new file mode 100644 index 000000000000..1d2544f023c2 --- /dev/null +++ b/libc/src/sys/mman/linux/msync.cpp @@ -0,0 +1,25 @@ +//===---------- Linux implementation of the msync function ----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/sys/mman/msync.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. + +#include "src/errno/libc_errno.h" +#include // For syscall numbers. + +namespace LIBC_NAMESPACE { +LLVM_LIBC_FUNCTION(int, msync, (void *addr, size_t len, int flags)) { + long ret = syscall_impl(SYS_msync, cpp::bit_cast(addr), len, flags); + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + return 0; +} +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/mman/msync.h b/libc/src/sys/mman/msync.h new file mode 100644 index 000000000000..08afdd8c0628 --- /dev/null +++ b/libc/src/sys/mman/msync.h @@ -0,0 +1,21 @@ +//===-- Implementation header for msync function ----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_SYS_MMAN_MSYNC_H +#define LLVM_LIBC_SRC_SYS_MMAN_MSYNC_H + +#include +#include + +namespace LIBC_NAMESPACE { + +int msync(void *addr, size_t len, int flags); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_MMAN_MSYNC_H diff --git a/libc/test/src/sys/mman/linux/CMakeLists.txt b/libc/test/src/sys/mman/linux/CMakeLists.txt index 09ab5b09be64..6f7fc34d8d3c 100644 --- a/libc/test/src/sys/mman/linux/CMakeLists.txt +++ b/libc/test/src/sys/mman/linux/CMakeLists.txt @@ -107,3 +107,23 @@ add_libc_unittest( libc.src.unistd.sysconf libc.test.UnitTest.ErrnoSetterMatcher ) + +add_libc_unittest( + msync_test + SUITE + libc_sys_mman_unittests + SRCS + msync_test.cpp + DEPENDS + libc.include.sys_mman + libc.include.unistd + libc.src.errno.errno + libc.src.sys.mman.mmap + libc.src.sys.mman.munmap + libc.src.sys.mman.msync + libc.src.sys.mman.mincore + libc.src.sys.mman.mlock + libc.src.sys.mman.munlock + libc.src.unistd.sysconf + libc.test.UnitTest.ErrnoSetterMatcher +) diff --git a/libc/test/src/sys/mman/linux/msync_test.cpp b/libc/test/src/sys/mman/linux/msync_test.cpp new file mode 100644 index 000000000000..0d60415b1243 --- /dev/null +++ b/libc/test/src/sys/mman/linux/msync_test.cpp @@ -0,0 +1,69 @@ +//===-- Unittests for msync -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/errno/libc_errno.h" +#include "src/sys/mman/mlock.h" +#include "src/sys/mman/mmap.h" +#include "src/sys/mman/msync.h" +#include "src/sys/mman/munlock.h" +#include "src/sys/mman/munmap.h" +#include "src/unistd/sysconf.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/LibcTest.h" +#include "test/UnitTest/Test.h" + +using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; + +struct PageHolder { + size_t size; + void *addr; + + PageHolder() + : size(LIBC_NAMESPACE::sysconf(_SC_PAGESIZE)), + addr(LIBC_NAMESPACE::mmap(nullptr, size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)) {} + ~PageHolder() { + if (addr != MAP_FAILED) + LIBC_NAMESPACE::munmap(addr, size); + } + + char &operator[](size_t i) { return reinterpret_cast(addr)[i]; } + + bool is_valid() { return addr != MAP_FAILED; } +}; + +TEST(LlvmLibcMsyncTest, UnMappedMemory) { + EXPECT_THAT(LIBC_NAMESPACE::msync(nullptr, 1024, MS_SYNC), Fails(ENOMEM)); + EXPECT_THAT(LIBC_NAMESPACE::msync(nullptr, 1024, MS_ASYNC), Fails(ENOMEM)); +} + +TEST(LlvmLibcMsyncTest, LockedPage) { + PageHolder page; + ASSERT_TRUE(page.is_valid()); + ASSERT_THAT(LIBC_NAMESPACE::mlock(page.addr, page.size), Succeeds()); + EXPECT_THAT( + LIBC_NAMESPACE::msync(page.addr, page.size, MS_SYNC | MS_INVALIDATE), + Fails(EBUSY)); + ASSERT_THAT(LIBC_NAMESPACE::munlock(page.addr, page.size), Succeeds()); + EXPECT_THAT(LIBC_NAMESPACE::msync(page.addr, page.size, MS_SYNC), Succeeds()); +} + +TEST(LlvmLibcMsyncTest, UnalignedAddress) { + PageHolder page; + ASSERT_TRUE(page.is_valid()); + EXPECT_THAT(LIBC_NAMESPACE::msync(&page[1], page.size - 1, MS_SYNC), + Fails(EINVAL)); +} + +TEST(LlvmLibcMsyncTest, InvalidFlag) { + PageHolder page; + ASSERT_TRUE(page.is_valid()); + EXPECT_THAT(LIBC_NAMESPACE::msync(page.addr, page.size, MS_SYNC | MS_ASYNC), + Fails(EINVAL)); + EXPECT_THAT(LIBC_NAMESPACE::msync(page.addr, page.size, -1), Fails(EINVAL)); +} -- GitLab From 7b275aa2438c22604505d618dd37ee60052f2800 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 11 Mar 2024 00:13:04 +0100 Subject: [PATCH 056/953] [LLD][COFF] Add support for IMPORT_NAME_EXPORTAS import library names. (#83211) This allows handling importlibs produced by llvm-dlltool in #78772. ARM64EC import libraries use it by default, but it's supported by MSVC link.exe on other platforms too. This also avoids assuming null-terminated input, like in #78769. --- lld/COFF/InputFiles.cpp | 17 +++++++++++------ lld/test/COFF/exportas.test | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 lld/test/COFF/exportas.test diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp index 1ed90d74229a..037fae45242c 100644 --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -944,18 +944,20 @@ ImportFile::ImportFile(COFFLinkerContext &ctx, MemoryBufferRef m) : InputFile(ctx, ImportKind, m), live(!ctx.config.doGC), thunkLive(live) {} void ImportFile::parse() { - const char *buf = mb.getBufferStart(); - const auto *hdr = reinterpret_cast(buf); + const auto *hdr = + reinterpret_cast(mb.getBufferStart()); // Check if the total size is valid. - if (mb.getBufferSize() != sizeof(*hdr) + hdr->SizeOfData) + if (mb.getBufferSize() < sizeof(*hdr) || + mb.getBufferSize() != sizeof(*hdr) + hdr->SizeOfData) fatal("broken import library"); // Read names and create an __imp_ symbol. - StringRef name = saver().save(StringRef(buf + sizeof(*hdr))); + StringRef buf = mb.getBuffer().substr(sizeof(*hdr)); + StringRef name = saver().save(buf.split('\0').first); StringRef impName = saver().save("__imp_" + name); - const char *nameStart = buf + sizeof(coff_import_header) + name.size() + 1; - dllName = std::string(StringRef(nameStart)); + buf = buf.substr(name.size() + 1); + dllName = buf.split('\0').first; StringRef extName; switch (hdr->getNameType()) { case IMPORT_ORDINAL: @@ -971,6 +973,9 @@ void ImportFile::parse() { extName = ltrim1(name, "?@_"); extName = extName.substr(0, extName.find('@')); break; + case IMPORT_NAME_EXPORTAS: + extName = buf.substr(dllName.size() + 1).split('\0').first; + break; } this->hdr = hdr; diff --git a/lld/test/COFF/exportas.test b/lld/test/COFF/exportas.test new file mode 100644 index 000000000000..c0295c3d7fb7 --- /dev/null +++ b/lld/test/COFF/exportas.test @@ -0,0 +1,19 @@ +REQUIRES: x86 +RUN: split-file %s %t.dir && cd %t.dir + +Link to an import library containing EXPORTAS and verify that we use proper name for the import. + +RUN: llvm-mc -filetype=obj -triple=x86_64-windows test.s -o test.obj +RUN: llvm-lib -machine:amd64 -out:test.lib -def:test.def +RUN: lld-link -out:out1.dll -dll -noentry test.obj test.lib +RUN: llvm-readobj --coff-imports out1.dll | FileCheck --check-prefix=IMPORT %s +IMPORT: Symbol: expfunc + +#--- test.s + .section ".test", "rd" + .rva __imp_func + +#--- test.def +LIBRARY test.dll +EXPORTS + func EXPORTAS expfunc -- GitLab From cef862e03c5dd0bfda43a57ca609d5239da3567a Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Sun, 10 Mar 2024 15:18:49 -0500 Subject: [PATCH 057/953] [InstCombine] Tests for `(icmp eq/ne (and (shl -1, X), Y), 0)` -> `(icmp eq/ne (lshr Y, X), 0)`; NFC --- .../Transforms/InstCombine/icmp-and-shift.ll | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/icmp-and-shift.ll b/llvm/test/Transforms/InstCombine/icmp-and-shift.ll index b0d4dabb7384..8986ede41607 100644 --- a/llvm/test/Transforms/InstCombine/icmp-and-shift.ll +++ b/llvm/test/Transforms/InstCombine/icmp-and-shift.ll @@ -520,3 +520,91 @@ define i1 @slt_and_shl_one(i8 %x, i8 %y) { %cmp = icmp slt i8 %and, %pow2 ret i1 %cmp } + +define i1 @fold_eq_lhs(i8 %x, i8 %y) { +; CHECK-LABEL: @fold_eq_lhs( +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 -1, [[X:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[SHL]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %shl = shl i8 -1, %x + %and = and i8 %shl, %y + %r = icmp eq i8 %and, 0 + ret i1 %r +} + +define i1 @fold_eq_lhs_fail_eq_nonzero(i8 %x, i8 %y) { +; CHECK-LABEL: @fold_eq_lhs_fail_eq_nonzero( +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 -1, [[X:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[SHL]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 1 +; CHECK-NEXT: ret i1 [[R]] +; + %shl = shl i8 -1, %x + %and = and i8 %shl, %y + %r = icmp eq i8 %and, 1 + ret i1 %r +} + +define i1 @fold_eq_lhs_fail_multiuse_shl(i8 %x, i8 %y) { +; CHECK-LABEL: @fold_eq_lhs_fail_multiuse_shl( +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 -1, [[X:%.*]] +; CHECK-NEXT: call void @use(i8 [[SHL]]) +; CHECK-NEXT: [[AND:%.*]] = and i8 [[SHL]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %shl = shl i8 -1, %x + call void @use(i8 %shl) + %and = and i8 %shl, %y + %r = icmp eq i8 %and, 0 + ret i1 %r +} + +define i1 @fold_ne_rhs(i8 %x, i8 %yy) { +; CHECK-LABEL: @fold_ne_rhs( +; CHECK-NEXT: [[Y:%.*]] = xor i8 [[YY:%.*]], 123 +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 -1, [[X:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y]], [[SHL]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %y = xor i8 %yy, 123 + %shl = shl i8 -1, %x + %and = and i8 %y, %shl + %r = icmp ne i8 %and, 0 + ret i1 %r +} + +define i1 @fold_ne_rhs_fail_multiuse_and(i8 %x, i8 %yy) { +; CHECK-LABEL: @fold_ne_rhs_fail_multiuse_and( +; CHECK-NEXT: [[Y:%.*]] = xor i8 [[YY:%.*]], 123 +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 -1, [[X:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y]], [[SHL]] +; CHECK-NEXT: call void @use(i8 [[AND]]) +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %y = xor i8 %yy, 123 + %shl = shl i8 -1, %x + %and = and i8 %y, %shl + call void @use(i8 %and) + %r = icmp ne i8 %and, 0 + ret i1 %r +} + +define i1 @fold_ne_rhs_fail_shift_not_1s(i8 %x, i8 %yy) { +; CHECK-LABEL: @fold_ne_rhs_fail_shift_not_1s( +; CHECK-NEXT: [[Y:%.*]] = xor i8 [[YY:%.*]], 122 +; CHECK-NEXT: [[SHL:%.*]] = shl i8 -2, [[X:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y]], [[SHL]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %y = xor i8 %yy, 123 + %shl = shl i8 -2, %x + %and = and i8 %y, %shl + %r = icmp ne i8 %and, 0 + ret i1 %r +} -- GitLab From 60dda1fc6ef82c5d7fe54000e6c0a21e7bafdeb5 Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Sun, 10 Mar 2024 13:10:07 -0500 Subject: [PATCH 058/953] [InstCombine] fold `(icmp eq/ne (and (shl -1, X), Y), 0)` -> `(icmp eq/ne (lshr Y, X), 0)` Proofs: https://alive2.llvm.org/ce/z/oSRGBt Closes #84691 --- .../Transforms/InstCombine/InstCombineCompares.cpp | 11 +++++++++++ llvm/test/Transforms/InstCombine/icmp-and-shift.ll | 6 ++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 5b412a52e164..e71f3e113b96 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1962,6 +1962,17 @@ Instruction *InstCombinerImpl::foldICmpAndConstant(ICmpInst &Cmp, return BinaryOperator::CreateAnd(TruncY, X); } + // (icmp eq/ne (and (shl -1, X), Y), 0) + // -> (icmp eq/ne (lshr Y, X), 0) + // We could technically handle any C == 0 or (C < 0 && isOdd(C)) but it seems + // highly unlikely the non-zero case will ever show up in code. + if (C.isZero() && + match(And, m_OneUse(m_c_And(m_OneUse(m_Shl(m_AllOnes(), m_Value(X))), + m_Value(Y))))) { + Value *LShr = Builder.CreateLShr(Y, X); + return new ICmpInst(Pred, LShr, Constant::getNullValue(LShr->getType())); + } + return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/icmp-and-shift.ll b/llvm/test/Transforms/InstCombine/icmp-and-shift.ll index 8986ede41607..08d23e84c396 100644 --- a/llvm/test/Transforms/InstCombine/icmp-and-shift.ll +++ b/llvm/test/Transforms/InstCombine/icmp-and-shift.ll @@ -523,8 +523,7 @@ define i1 @slt_and_shl_one(i8 %x, i8 %y) { define i1 @fold_eq_lhs(i8 %x, i8 %y) { ; CHECK-LABEL: @fold_eq_lhs( -; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 -1, [[X:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[SHL]], [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = lshr i8 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 ; CHECK-NEXT: ret i1 [[R]] ; @@ -565,8 +564,7 @@ define i1 @fold_eq_lhs_fail_multiuse_shl(i8 %x, i8 %y) { define i1 @fold_ne_rhs(i8 %x, i8 %yy) { ; CHECK-LABEL: @fold_ne_rhs( ; CHECK-NEXT: [[Y:%.*]] = xor i8 [[YY:%.*]], 123 -; CHECK-NEXT: [[SHL:%.*]] = shl nsw i8 -1, [[X:%.*]] -; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y]], [[SHL]] +; CHECK-NEXT: [[AND:%.*]] = lshr i8 [[Y]], [[X:%.*]] ; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], 0 ; CHECK-NEXT: ret i1 [[R]] ; -- GitLab From edd4c6c6dca4c556de22b2ab73d5bfc02d28e59b Mon Sep 17 00:00:00 2001 From: wanglei Date: Mon, 11 Mar 2024 08:59:17 +0800 Subject: [PATCH 059/953] [LoongArch] Make sure that the LoongArchISD::BSTRINS node uses the correct `MSB` value (#84454) The `MSB` must not be greater than `GRLen`. Without this patch, newly added test cases will crash with LoongArch32, resulting in a 'cannot select' error. --- llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp | 4 +++- llvm/test/CodeGen/LoongArch/bstrins_w.ll | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index c8e955a23336..2d71423d6dd5 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -2366,7 +2366,9 @@ Retry: return DAG.getNode( LoongArchISD::BSTRINS, DL, ValTy, N0.getOperand(0), DAG.getConstant(CN1->getSExtValue() >> MaskIdx0, DL, ValTy), - DAG.getConstant((MaskIdx0 + MaskLen0 - 1), DL, GRLenVT), + DAG.getConstant(ValBits == 32 ? (MaskIdx0 + (MaskLen0 & 31) - 1) + : (MaskIdx0 + MaskLen0 - 1), + DL, GRLenVT), DAG.getConstant(MaskIdx0, DL, GRLenVT)); } diff --git a/llvm/test/CodeGen/LoongArch/bstrins_w.ll b/llvm/test/CodeGen/LoongArch/bstrins_w.ll index dfbe000841cd..e008caacad2a 100644 --- a/llvm/test/CodeGen/LoongArch/bstrins_w.ll +++ b/llvm/test/CodeGen/LoongArch/bstrins_w.ll @@ -145,6 +145,19 @@ define i32 @pat5(i32 %a) nounwind { ret i32 %or } +;; The high bits of `const` are zero. +define i32 @pat5_high_zeros(i32 %a) nounwind { +; CHECK-LABEL: pat5_high_zeros: +; CHECK: # %bb.0: +; CHECK-NEXT: lu12i.w $a1, 1 +; CHECK-NEXT: ori $a1, $a1, 564 +; CHECK-NEXT: bstrins.w $a0, $a1, 31, 16 +; CHECK-NEXT: ret + %and = and i32 %a, 65535 ; 0x0000ffff + %or = or i32 %and, 305397760 ; 0x12340000 + ret i32 %or +} + ;; Pattern 6: a = b | ((c & mask) << shamt) ;; In this testcase b is 0x10000002, but in fact we do not require b being a ;; constant. As long as all positions in b to be overwritten by the incoming -- GitLab From f78688134026686288a8d310b493d9327753a022 Mon Sep 17 00:00:00 2001 From: fpasserby <125797601+fpasserby@users.noreply.github.com> Date: Mon, 11 Mar 2024 03:00:00 +0100 Subject: [PATCH 060/953] [coroutine] Implement llvm.coro.await.suspend intrinsic (#79712) Implement `llvm.coro.await.suspend` intrinsics, to deal with performance regression after prohibiting `.await_suspend` inlining, as suggested in #64945. Actually, there are three new intrinsics, which directly correspond to each of three forms of `await_suspend`: ``` void llvm.coro.await.suspend.void(ptr %awaiter, ptr %frame, ptr @wrapperFunction) i1 llvm.coro.await.suspend.bool(ptr %awaiter, ptr %frame, ptr @wrapperFunction) ptr llvm.coro.await.suspend.handle(ptr %awaiter, ptr %frame, ptr @wrapperFunction) ``` There are three different versions instead of one, because in `bool` case it's result is used for resuming via a branch, and in `coroutine_handle` case exceptions from `await_suspend` are handled in the coroutine, and exceptions from the subsequent `.resume()` are propagated to the caller. Await-suspend block is simplified down to intrinsic calls only, for example for symmetric transfer: ``` %id = call token @llvm.coro.save(ptr null) %handle = call ptr @llvm.coro.await.suspend.handle(ptr %awaiter, ptr %frame, ptr @wrapperFunction) call void @llvm.coro.resume(%handle) %result = call i8 @llvm.coro.suspend(token %id, i1 false) switch i8 %result, ... ``` All await-suspend logic is moved out into a wrapper function, generated for each suspension point. The signature of the function is ` wrapperFunction(ptr %awaiter, ptr %frame)` where `` is one of `void` `i1` or `ptr`, depending on the return type of `await_suspend`. Intrinsic calls are lowered during `CoroSplit` pass, right after the split. Because I'm new to LLVM, I'm not sure if the helper function generation, calls to them and lowering are implemented in the right way, especially with regard to various metadata and attributes, i. e. for TBAA. All things that seemed questionable are marked with `FIXME` comments. There is another detail: in case of symmetric transfer raw pointer to the frame of coroutine, that should be resumed, is returned from the helper function and a direct call to `@llvm.coro.resume` is generated. C++ standard demands, that `.resume()` method is evaluated. Not sure how important is this, because code has been generated in the same way before, sans helper function. --- clang/include/clang/AST/ExprCXX.h | 21 ++ clang/lib/CodeGen/CGCoroutine.cpp | 161 ++++++++++- clang/lib/CodeGen/CodeGenFunction.h | 19 ++ clang/lib/Sema/SemaCoroutine.cpp | 94 +------ clang/test/AST/coroutine-locals-cleanup.cpp | 10 +- .../CodeGenCoroutines/coro-always-inline.cpp | 2 +- clang/test/CodeGenCoroutines/coro-await.cpp | 79 ++++-- .../coro-awaiter-noinline-suspend.cpp | 168 ----------- clang/test/CodeGenCoroutines/coro-dwarf.cpp | 12 + .../coro-function-try-block.cpp | 2 +- .../coro-symmetric-transfer-01.cpp | 7 +- .../coro-symmetric-transfer-02.cpp | 12 +- clang/test/CodeGenCoroutines/pr56329.cpp | 4 + clang/test/CodeGenCoroutines/pr59181.cpp | 7 +- clang/test/CodeGenCoroutines/pr65054.cpp | 9 +- llvm/docs/Coroutines.rst | 264 +++++++++++++++++- llvm/include/llvm/IR/Intrinsics.td | 12 + llvm/lib/IR/Verifier.cpp | 3 + llvm/lib/Transforms/Coroutines/CoroInstr.h | 33 +++ llvm/lib/Transforms/Coroutines/CoroInternal.h | 1 + llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 51 ++++ llvm/lib/Transforms/Coroutines/Coroutines.cpp | 9 +- .../coro-await-suspend-lower-invoke.ll | 123 ++++++++ .../Coroutines/coro-await-suspend-lower.ll | 96 +++++++ 24 files changed, 874 insertions(+), 325 deletions(-) delete mode 100644 clang/test/CodeGenCoroutines/coro-awaiter-noinline-suspend.cpp create mode 100644 llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll create mode 100644 llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index a0e467b35778..6003b866c9f5 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -5038,6 +5038,9 @@ class CoroutineSuspendExpr : public Expr { OpaqueValueExpr *OpaqueValue = nullptr; public: + // These types correspond to the three C++ 'await_suspend' return variants + enum class SuspendReturnType { SuspendVoid, SuspendBool, SuspendHandle }; + CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Operand, Expr *Common, Expr *Ready, Expr *Suspend, Expr *Resume, OpaqueValueExpr *OpaqueValue) @@ -5097,6 +5100,24 @@ public: return static_cast(SubExprs[SubExpr::Operand]); } + SuspendReturnType getSuspendReturnType() const { + auto *SuspendExpr = getSuspendExpr(); + assert(SuspendExpr); + + auto SuspendType = SuspendExpr->getType(); + + if (SuspendType->isVoidType()) + return SuspendReturnType::SuspendVoid; + if (SuspendType->isBooleanType()) + return SuspendReturnType::SuspendBool; + + // Void pointer is the type of handle.address(), which is returned + // from the await suspend wrapper so that the temporary coroutine handle + // value won't go to the frame by mistake + assert(SuspendType->isVoidPointerType()); + return SuspendReturnType::SuspendHandle; + } + SourceLocation getKeywordLoc() const { return KeywordLoc; } SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; } diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index 888d30bfb3e1..b7142ec08af9 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -141,7 +141,7 @@ static bool FunctionCanThrow(const FunctionDecl *D) { Proto->canThrow() != CT_Cannot; } -static bool ResumeStmtCanThrow(const Stmt *S) { +static bool StmtCanThrow(const Stmt *S) { if (const auto *CE = dyn_cast(S)) { const auto *Callee = CE->getDirectCallee(); if (!Callee) @@ -167,7 +167,7 @@ static bool ResumeStmtCanThrow(const Stmt *S) { } for (const auto *child : S->children()) - if (ResumeStmtCanThrow(child)) + if (StmtCanThrow(child)) return true; return false; @@ -178,18 +178,31 @@ static bool ResumeStmtCanThrow(const Stmt *S) { // auto && x = CommonExpr(); // if (!x.await_ready()) { // llvm_coro_save(); -// x.await_suspend(...); (*) -// llvm_coro_suspend(); (**) +// llvm_coro_await_suspend(&x, frame, wrapper) (*) (**) +// llvm_coro_suspend(); (***) // } // x.await_resume(); // // where the result of the entire expression is the result of x.await_resume() // -// (*) If x.await_suspend return type is bool, it allows to veto a suspend: +// (*) llvm_coro_await_suspend_{void, bool, handle} is lowered to +// wrapper(&x, frame) when it's certain not to interfere with +// coroutine transform. await_suspend expression is +// asynchronous to the coroutine body and not all analyses +// and transformations can handle it correctly at the moment. +// +// Wrapper function encapsulates x.await_suspend(...) call and looks like: +// +// auto __await_suspend_wrapper(auto& awaiter, void* frame) { +// std::coroutine_handle<> handle(frame); +// return awaiter.await_suspend(handle); +// } +// +// (**) If x.await_suspend return type is bool, it allows to veto a suspend: // if (x.await_suspend(...)) // llvm_coro_suspend(); // -// (**) llvm_coro_suspend() encodes three possible continuations as +// (***) llvm_coro_suspend() encodes three possible continuations as // a switch instruction: // // %where-to = call i8 @llvm.coro.suspend(...) @@ -212,9 +225,10 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co bool ignoreResult, bool forLValue) { auto *E = S.getCommonExpr(); - auto Binder = + auto CommonBinder = CodeGenFunction::OpaqueValueMappingData::bind(CGF, S.getOpaqueValue(), E); - auto UnbindOnExit = llvm::make_scope_exit([&] { Binder.unbind(CGF); }); + auto UnbindCommonOnExit = + llvm::make_scope_exit([&] { CommonBinder.unbind(CGF); }); auto Prefix = buildSuspendPrefixStr(Coro, Kind); BasicBlock *ReadyBlock = CGF.createBasicBlock(Prefix + Twine(".ready")); @@ -232,16 +246,73 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co auto *NullPtr = llvm::ConstantPointerNull::get(CGF.CGM.Int8PtrTy); auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr}); + auto SuspendWrapper = CodeGenFunction(CGF.CGM).generateAwaitSuspendWrapper( + CGF.CurFn->getName(), Prefix, S); + CGF.CurCoro.InSuspendBlock = true; - auto *SuspendRet = CGF.EmitScalarExpr(S.getSuspendExpr()); + + assert(CGF.CurCoro.Data && CGF.CurCoro.Data->CoroBegin && + "expected to be called in coroutine context"); + + SmallVector SuspendIntrinsicCallArgs; + SuspendIntrinsicCallArgs.push_back( + CGF.getOrCreateOpaqueLValueMapping(S.getOpaqueValue()).getPointer(CGF)); + + SuspendIntrinsicCallArgs.push_back(CGF.CurCoro.Data->CoroBegin); + SuspendIntrinsicCallArgs.push_back(SuspendWrapper); + + const auto SuspendReturnType = S.getSuspendReturnType(); + llvm::Intrinsic::ID AwaitSuspendIID; + + switch (SuspendReturnType) { + case CoroutineSuspendExpr::SuspendReturnType::SuspendVoid: + AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_void; + break; + case CoroutineSuspendExpr::SuspendReturnType::SuspendBool: + AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_bool; + break; + case CoroutineSuspendExpr::SuspendReturnType::SuspendHandle: + AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_handle; + break; + } + + llvm::Function *AwaitSuspendIntrinsic = CGF.CGM.getIntrinsic(AwaitSuspendIID); + + const auto AwaitSuspendCanThrow = StmtCanThrow(S.getSuspendExpr()); + + llvm::CallBase *SuspendRet = nullptr; + // FIXME: add call attributes? + if (AwaitSuspendCanThrow) + SuspendRet = + CGF.EmitCallOrInvoke(AwaitSuspendIntrinsic, SuspendIntrinsicCallArgs); + else + SuspendRet = CGF.EmitNounwindRuntimeCall(AwaitSuspendIntrinsic, + SuspendIntrinsicCallArgs); + + assert(SuspendRet); CGF.CurCoro.InSuspendBlock = false; - if (SuspendRet != nullptr && SuspendRet->getType()->isIntegerTy(1)) { + switch (SuspendReturnType) { + case CoroutineSuspendExpr::SuspendReturnType::SuspendVoid: + assert(SuspendRet->getType()->isVoidTy()); + break; + case CoroutineSuspendExpr::SuspendReturnType::SuspendBool: { + assert(SuspendRet->getType()->isIntegerTy()); + // Veto suspension if requested by bool returning await_suspend. BasicBlock *RealSuspendBlock = CGF.createBasicBlock(Prefix + Twine(".suspend.bool")); CGF.Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock); CGF.EmitBlock(RealSuspendBlock); + break; + } + case CoroutineSuspendExpr::SuspendReturnType::SuspendHandle: { + assert(SuspendRet->getType()->isPointerTy()); + + auto ResumeIntrinsic = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_resume); + Builder.CreateCall(ResumeIntrinsic, SuspendRet); + break; + } } // Emit the suspend point. @@ -267,7 +338,7 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co // is marked as 'noexcept', we avoid generating this additional IR. CXXTryStmt *TryStmt = nullptr; if (Coro.ExceptionHandler && Kind == AwaitKind::Init && - ResumeStmtCanThrow(S.getResumeExpr())) { + StmtCanThrow(S.getResumeExpr())) { Coro.ResumeEHVar = CGF.CreateTempAlloca(Builder.getInt1Ty(), Prefix + Twine("resume.eh")); Builder.CreateFlagStore(true, Coro.ResumeEHVar); @@ -338,6 +409,69 @@ static QualType getCoroutineSuspendExprReturnType(const ASTContext &Ctx, } #endif +llvm::Function * +CodeGenFunction::generateAwaitSuspendWrapper(Twine const &CoroName, + Twine const &SuspendPointName, + CoroutineSuspendExpr const &S) { + std::string FuncName = "__await_suspend_wrapper_"; + FuncName += CoroName.str(); + FuncName += '_'; + FuncName += SuspendPointName.str(); + + ASTContext &C = getContext(); + + FunctionArgList args; + + ImplicitParamDecl AwaiterDecl(C, C.VoidPtrTy, ImplicitParamKind::Other); + ImplicitParamDecl FrameDecl(C, C.VoidPtrTy, ImplicitParamKind::Other); + QualType ReturnTy = S.getSuspendExpr()->getType(); + + args.push_back(&AwaiterDecl); + args.push_back(&FrameDecl); + + const CGFunctionInfo &FI = + CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args); + + llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI); + + llvm::Function *Fn = llvm::Function::Create( + LTy, llvm::GlobalValue::PrivateLinkage, FuncName, &CGM.getModule()); + + Fn->addParamAttr(0, llvm::Attribute::AttrKind::NonNull); + Fn->addParamAttr(0, llvm::Attribute::AttrKind::NoUndef); + + Fn->addParamAttr(1, llvm::Attribute::AttrKind::NoUndef); + + Fn->setMustProgress(); + Fn->addFnAttr(llvm::Attribute::AttrKind::AlwaysInline); + + StartFunction(GlobalDecl(), ReturnTy, Fn, FI, args); + + // FIXME: add TBAA metadata to the loads + llvm::Value *AwaiterPtr = Builder.CreateLoad(GetAddrOfLocalVar(&AwaiterDecl)); + auto AwaiterLValue = + MakeNaturalAlignAddrLValue(AwaiterPtr, AwaiterDecl.getType()); + + CurAwaitSuspendWrapper.FramePtr = + Builder.CreateLoad(GetAddrOfLocalVar(&FrameDecl)); + + auto AwaiterBinder = CodeGenFunction::OpaqueValueMappingData::bind( + *this, S.getOpaqueValue(), AwaiterLValue); + + auto *SuspendRet = EmitScalarExpr(S.getSuspendExpr()); + + auto UnbindCommonOnExit = + llvm::make_scope_exit([&] { AwaiterBinder.unbind(*this); }); + if (SuspendRet != nullptr) { + Fn->addRetAttr(llvm::Attribute::AttrKind::NoUndef); + Builder.CreateStore(SuspendRet, ReturnValue); + } + + CurAwaitSuspendWrapper.FramePtr = nullptr; + FinishFunction(); + return Fn; +} + LValue CodeGenFunction::EmitCoawaitLValue(const CoawaitExpr *E) { assert(getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() && @@ -834,6 +968,11 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E, if (CurCoro.Data && CurCoro.Data->CoroBegin) { return RValue::get(CurCoro.Data->CoroBegin); } + + if (CurAwaitSuspendWrapper.FramePtr) { + return RValue::get(CurAwaitSuspendWrapper.FramePtr); + } + CGM.Error(E->getBeginLoc(), "this builtin expect that __builtin_coro_begin " "has been used earlier in this function"); auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getPtrTy()); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 06327a184717..6c825a302913 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -352,6 +352,25 @@ public: return isCoroutine() && CurCoro.InSuspendBlock; } + // Holds FramePtr for await_suspend wrapper generation, + // so that __builtin_coro_frame call can be lowered + // directly to value of its second argument + struct AwaitSuspendWrapperInfo { + llvm::Value *FramePtr = nullptr; + }; + AwaitSuspendWrapperInfo CurAwaitSuspendWrapper; + + // Generates wrapper function for `llvm.coro.await.suspend.*` intrinisics. + // It encapsulates SuspendExpr in a function, to separate it's body + // from the main coroutine to avoid miscompilations. Intrinisic + // is lowered to this function call in CoroSplit pass + // Function signature is: + // __await_suspend_wrapper_(ptr %awaiter, ptr %hdl) + // where type is one of (void, i1, ptr) + llvm::Function *generateAwaitSuspendWrapper(Twine const &CoroName, + Twine const &SuspendPointName, + CoroutineSuspendExpr const &S); + /// CurGD - The GlobalDecl for the current function being compiled. GlobalDecl CurGD; diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 301a5ff72a3b..5206fc7621c7 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -348,99 +348,15 @@ static Expr *maybeTailCall(Sema &S, QualType RetType, Expr *E, Expr *JustAddress = AddressExpr.get(); - // FIXME: Without optimizations, the temporary result from `await_suspend()` - // may be put on the coroutine frame since the coroutine frame constructor - // will think the temporary variable will escape from the - // `coroutine_handle<>::address()` call. This is problematic since the - // coroutine should be considered to be suspended after it enters - // `await_suspend` so it shouldn't access/update the coroutine frame after - // that. - // - // See https://github.com/llvm/llvm-project/issues/65054 for the report. - // - // The long term solution may wrap the whole logic about `await-suspend` - // into a standalone function. This is similar to the proposed solution - // in tryMarkAwaitSuspendNoInline. See the comments there for details. - // - // The short term solution here is to mark `coroutine_handle<>::address()` - // function as always-inline so that the coroutine frame constructor won't - // think the temporary result is escaped incorrectly. - if (auto *FD = cast(JustAddress)->getDirectCallee()) - if (!FD->hasAttr() && !FD->hasAttr()) - FD->addAttr(AlwaysInlineAttr::CreateImplicit(S.getASTContext(), - FD->getLocation())); - // Check that the type of AddressExpr is void* if (!JustAddress->getType().getTypePtr()->isVoidPointerType()) S.Diag(cast(JustAddress)->getCalleeDecl()->getLocation(), diag::warn_coroutine_handle_address_invalid_return_type) << JustAddress->getType(); - // Clean up temporary objects so that they don't live across suspension points - // unnecessarily. We choose to clean up before the call to - // __builtin_coro_resume so that the cleanup code are not inserted in-between - // the resume call and return instruction, which would interfere with the - // musttail call contract. - JustAddress = S.MaybeCreateExprWithCleanups(JustAddress); - return S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_resume, - JustAddress); -} - -/// The await_suspend call performed by co_await is essentially asynchronous -/// to the execution of the coroutine. Inlining it normally into an unsplit -/// coroutine can cause miscompilation because the coroutine CFG misrepresents -/// the true control flow of the program: things that happen in the -/// await_suspend are not guaranteed to happen prior to the resumption of the -/// coroutine, and things that happen after the resumption of the coroutine -/// (including its exit and the potential deallocation of the coroutine frame) -/// are not guaranteed to happen only after the end of await_suspend. -/// -/// See https://github.com/llvm/llvm-project/issues/56301 and -/// https://reviews.llvm.org/D157070 for the example and the full discussion. -/// -/// The short-term solution to this problem is to mark the call as uninlinable. -/// But we don't want to do this if the call is known to be trivial, which is -/// very common. -/// -/// The long-term solution may introduce patterns like: -/// -/// call @llvm.coro.await_suspend(ptr %awaiter, ptr %handle, -/// ptr @awaitSuspendFn) -/// -/// Then it is much easier to perform the safety analysis in the middle end. -/// If it is safe to inline the call to awaitSuspend, we can replace it in the -/// CoroEarly pass. Otherwise we could replace it in the CoroSplit pass. -static void tryMarkAwaitSuspendNoInline(Sema &S, OpaqueValueExpr *Awaiter, - CallExpr *AwaitSuspend) { - // The method here to extract the awaiter decl is not precise. - // This is intentional. Since it is hard to perform the analysis in the - // frontend due to the complexity of C++'s type systems. - // And we prefer to perform such analysis in the middle end since it is - // easier to implement and more powerful. - CXXRecordDecl *AwaiterDecl = - Awaiter->getType().getNonReferenceType()->getAsCXXRecordDecl(); - - if (AwaiterDecl && AwaiterDecl->field_empty()) - return; - - FunctionDecl *FD = AwaitSuspend->getDirectCallee(); - - assert(FD); - - // If the `await_suspend()` function is marked as `always_inline` explicitly, - // we should give the user the right to control the codegen. - if (FD->hasAttr() || FD->hasAttr()) - return; - - // This is problematic if the user calls the await_suspend standalone. But on - // the on hand, it is not incorrect semantically since inlining is not part - // of the standard. On the other hand, it is relatively rare to call - // the await_suspend function standalone. - // - // And given we've already had the long-term plan, the current workaround - // looks relatively tolerant. - FD->addAttr( - NoInlineAttr::CreateImplicit(S.getASTContext(), FD->getLocation())); + // Clean up temporary objects, because the resulting expression + // will become the body of await_suspend wrapper. + return S.MaybeCreateExprWithCleanups(JustAddress); } /// Build calls to await_ready, await_suspend, and await_resume for a co_await @@ -514,10 +430,6 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, // type Z. QualType RetType = AwaitSuspend->getCallReturnType(S.Context); - // We need to mark await_suspend as noinline temporarily. See the comment - // of tryMarkAwaitSuspendNoInline for details. - tryMarkAwaitSuspendNoInline(S, Operand, AwaitSuspend); - // Support for coroutine_handle returning await_suspend. if (Expr *TailCallSuspend = maybeTailCall(S, RetType, AwaitSuspend, Loc)) diff --git a/clang/test/AST/coroutine-locals-cleanup.cpp b/clang/test/AST/coroutine-locals-cleanup.cpp index ce106b8e230a..6264df01fa2a 100644 --- a/clang/test/AST/coroutine-locals-cleanup.cpp +++ b/clang/test/AST/coroutine-locals-cleanup.cpp @@ -90,10 +90,7 @@ Task bar() { // CHECK: ExprWithCleanups {{.*}} 'bool' // CHECK-NEXT: CXXMemberCallExpr {{.*}} 'bool' // CHECK-NEXT: MemberExpr {{.*}} .await_ready -// CHECK: CallExpr {{.*}} 'void' -// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(void *)' -// CHECK-NEXT: DeclRefExpr {{.*}} '__builtin_coro_resume' 'void (void *)' -// CHECK-NEXT: ExprWithCleanups {{.*}} 'void *' +// CHECK: ExprWithCleanups {{.*}} 'void *' // CHECK: CaseStmt // CHECK: ExprWithCleanups {{.*}} 'void' @@ -103,7 +100,4 @@ Task bar() { // CHECK: ExprWithCleanups {{.*}} 'bool' // CHECK-NEXT: CXXMemberCallExpr {{.*}} 'bool' // CHECK-NEXT: MemberExpr {{.*}} .await_ready -// CHECK: CallExpr {{.*}} 'void' -// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(void *)' -// CHECK-NEXT: DeclRefExpr {{.*}} '__builtin_coro_resume' 'void (void *)' -// CHECK-NEXT: ExprWithCleanups {{.*}} 'void *' +// CHECK: ExprWithCleanups {{.*}} 'void *' diff --git a/clang/test/CodeGenCoroutines/coro-always-inline.cpp b/clang/test/CodeGenCoroutines/coro-always-inline.cpp index 6e13a62fbd98..d4f67a73f517 100644 --- a/clang/test/CodeGenCoroutines/coro-always-inline.cpp +++ b/clang/test/CodeGenCoroutines/coro-always-inline.cpp @@ -34,7 +34,7 @@ struct coroutine_traits { // CHECK-LABEL: @_Z3foov // CHECK-LABEL: entry: // CHECK: %ref.tmp.reload.addr = getelementptr -// CHECK: %ref.tmp4.reload.addr = getelementptr +// CHECK: %ref.tmp3.reload.addr = getelementptr void foo() { co_return; } // Check that bar is not inlined even it's marked as always_inline. diff --git a/clang/test/CodeGenCoroutines/coro-await.cpp b/clang/test/CodeGenCoroutines/coro-await.cpp index dc5a765ccb83..75851d8805bb 100644 --- a/clang/test/CodeGenCoroutines/coro-await.cpp +++ b/clang/test/CodeGenCoroutines/coro-await.cpp @@ -71,16 +71,13 @@ extern "C" void f0() { // CHECK: [[SUSPEND_BB]]: // CHECK: %[[SUSPEND_ID:.+]] = call token @llvm.coro.save( // --------------------------- - // Build the coroutine handle and pass it to await_suspend + // Call coro.await.suspend // --------------------------- - // CHECK: call ptr @_ZNSt16coroutine_handleINSt16coroutine_traitsIJvEE12promise_typeEE12from_addressEPv(ptr %[[FRAME]]) - // ... many lines of code to coerce coroutine_handle into an ptr scalar - // CHECK: %[[CH:.+]] = load ptr, ptr %{{.+}} - // CHECK: call void @_ZN14suspend_always13await_suspendESt16coroutine_handleIvE(ptr {{[^,]*}} %[[AWAITABLE]], ptr %[[CH]]) + // CHECK-NEXT: call void @llvm.coro.await.suspend.void(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @__await_suspend_wrapper_f0_await) // ------------------------- // Generate a suspend point: // ------------------------- - // CHECK: %[[OUTCOME:.+]] = call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false) + // CHECK-NEXT: %[[OUTCOME:.+]] = call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false) // CHECK: switch i8 %[[OUTCOME]], label %[[RET_BB:.+]] [ // CHECK: i8 0, label %[[READY_BB]] // CHECK: i8 1, label %[[CLEANUP_BB:.+]] @@ -101,6 +98,17 @@ extern "C" void f0() { // CHECK-NEXT: call zeroext i1 @_ZN10final_susp11await_readyEv(ptr // CHECK: %[[FINALSP_ID:.+]] = call token @llvm.coro.save( // CHECK: call i8 @llvm.coro.suspend(token %[[FINALSP_ID]], i1 true) + + // Await suspend wrapper + // CHECK: define{{.*}} @__await_suspend_wrapper_f0_await(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]]) + // CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]], + // CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]], + // CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]] + // CHECK: %[[FRAME:.+]] = load ptr, ptr %[[FRAME_TMP]] + // CHECK: call ptr @_ZNSt16coroutine_handleINSt16coroutine_traitsIJvEE12promise_typeEE12from_addressEPv(ptr %[[FRAME]]) + // ... many lines of code to coerce coroutine_handle into an ptr scalar + // CHECK: %[[CH:.+]] = load ptr, ptr %{{.+}} + // CHECK: call void @_ZN14suspend_always13await_suspendESt16coroutine_handleIvE(ptr {{[^,]*}} %[[AWAITABLE]], ptr %[[CH]]) } struct suspend_maybe { @@ -131,7 +139,7 @@ extern "C" void f1(int) { // See if we need to suspend: // -------------------------- - // CHECK: %[[READY:.+]] = call zeroext i1 @_ZN13suspend_maybe11await_readyEv(ptr {{[^,]*}} %[[AWAITABLE]]) + // CHECK: %[[READY:.+]] = call zeroext i1 @_ZN13suspend_maybe11await_readyEv(ptr {{[^,]*}} %[[AWAITABLE:.+]]) // CHECK: br i1 %[[READY]], label %[[READY_BB:.+]], label %[[SUSPEND_BB:.+]] // If we are suspending: @@ -139,12 +147,9 @@ extern "C" void f1(int) { // CHECK: [[SUSPEND_BB]]: // CHECK: %[[SUSPEND_ID:.+]] = call token @llvm.coro.save( // --------------------------- - // Build the coroutine handle and pass it to await_suspend + // Call coro.await.suspend // --------------------------- - // CHECK: call ptr @_ZNSt16coroutine_handleINSt16coroutine_traitsIJviEE12promise_typeEE12from_addressEPv(ptr %[[FRAME]]) - // ... many lines of code to coerce coroutine_handle into an ptr scalar - // CHECK: %[[CH:.+]] = load ptr, ptr %{{.+}} - // CHECK: %[[YES:.+]] = call zeroext i1 @_ZN13suspend_maybe13await_suspendESt16coroutine_handleIvE(ptr {{[^,]*}} %[[AWAITABLE]], ptr %[[CH]]) + // CHECK-NEXT: %[[YES:.+]] = call i1 @llvm.coro.await.suspend.bool(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @__await_suspend_wrapper_f1_yield) // ------------------------------------------- // See if await_suspend decided not to suspend // ------------------------------------------- @@ -155,6 +160,18 @@ extern "C" void f1(int) { // CHECK: [[READY_BB]]: // CHECK: call void @_ZN13suspend_maybe12await_resumeEv(ptr {{[^,]*}} %[[AWAITABLE]]) + + // Await suspend wrapper + // CHECK: define {{.*}} i1 @__await_suspend_wrapper_f1_yield(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]]) + // CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]], + // CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]], + // CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]] + // CHECK: %[[FRAME:.+]] = load ptr, ptr %[[FRAME_TMP]] + // CHECK: call ptr @_ZNSt16coroutine_handleINSt16coroutine_traitsIJviEE12promise_typeEE12from_addressEPv(ptr %[[FRAME]]) + // ... many lines of code to coerce coroutine_handle into an ptr scalar + // CHECK: %[[CH:.+]] = load ptr, ptr %{{.+}} + // CHECK: %[[YES:.+]] = call zeroext i1 @_ZN13suspend_maybe13await_suspendESt16coroutine_handleIvE(ptr {{[^,]*}} %[[AWAITABLE]], ptr %[[CH]]) + // CHECK-NEXT: ret i1 %[[YES]] } struct ComplexAwaiter { @@ -340,11 +357,39 @@ struct TailCallAwait { // CHECK-LABEL: @TestTailcall( extern "C" void TestTailcall() { + // CHECK: %[[PROMISE:.+]] = alloca %"struct.std::coroutine_traits::promise_type" + // CHECK: %[[FRAME:.+]] = call ptr @llvm.coro.begin( co_await TailCallAwait{}; + // CHECK: %[[READY:.+]] = call zeroext i1 @_ZN13TailCallAwait11await_readyEv(ptr {{[^,]*}} %[[AWAITABLE:.+]]) + // CHECK: br i1 %[[READY]], label %[[READY_BB:.+]], label %[[SUSPEND_BB:.+]] - // CHECK: %[[RESULT:.+]] = call ptr @_ZN13TailCallAwait13await_suspendESt16coroutine_handleIvE(ptr - // CHECK: %[[COERCE:.+]] = getelementptr inbounds %"struct.std::coroutine_handle", ptr %[[TMP:.+]], i32 0, i32 0 - // CHECK: store ptr %[[RESULT]], ptr %[[COERCE]] - // CHECK: %[[ADDR:.+]] = call ptr @_ZNSt16coroutine_handleIvE7addressEv(ptr {{[^,]*}} %[[TMP]]) - // CHECK: call void @llvm.coro.resume(ptr %[[ADDR]]) + // If we are suspending: + // --------------------- + // CHECK: [[SUSPEND_BB]]: + // CHECK: %[[SUSPEND_ID:.+]] = call token @llvm.coro.save( + // --------------------------- + // Call coro.await.suspend + // --------------------------- + // CHECK-NEXT: %[[RESUMED:.+]] = call ptr @llvm.coro.await.suspend.handle(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @__await_suspend_wrapper_TestTailcall_await) + // CHECK-NEXT: call void @llvm.coro.resume(ptr %[[RESUMED]]) + // CHECK-NEXT: %[[OUTCOME:.+]] = call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false) + // CHECK-NEXT: switch i8 %[[OUTCOME]], label %[[RET_BB:.+]] [ + // CHECK-NEXT: i8 0, label %[[READY_BB]] + // CHECK-NEXT: i8 1, label %{{.+}} + // CHECK-NEXT: ] + + // Await suspend wrapper + // CHECK: define {{.*}} ptr @__await_suspend_wrapper_TestTailcall_await(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]]) + // CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]], + // CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]], + // CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]] + // CHECK: %[[FRAME:.+]] = load ptr, ptr %[[FRAME_TMP]] + // CHECK: call ptr @_ZNSt16coroutine_handleINSt16coroutine_traitsIJvEE12promise_typeEE12from_addressEPv(ptr %[[FRAME]]) + // ... many lines of code to coerce coroutine_handle into an ptr scalar + // CHECK: %[[CH:.+]] = load ptr, ptr %{{.+}} + // CHECK-NEXT: %[[RESULT:.+]] = call ptr @_ZN13TailCallAwait13await_suspendESt16coroutine_handleIvE(ptr {{[^,]*}} %[[AWAITABLE]], ptr %[[CH]]) + // CHECK-NEXT: %[[COERCE:.+]] = getelementptr inbounds %"struct.std::coroutine_handle", ptr %[[TMP:.+]], i32 0, i32 0 + // CHECK-NEXT: store ptr %[[RESULT]], ptr %[[COERCE]] + // CHECK-NEXT: %[[ADDR:.+]] = call ptr @_ZNSt16coroutine_handleIvE7addressEv(ptr {{[^,]*}} %[[TMP]]) + // CHECK-NEXT: ret ptr %[[ADDR]] } diff --git a/clang/test/CodeGenCoroutines/coro-awaiter-noinline-suspend.cpp b/clang/test/CodeGenCoroutines/coro-awaiter-noinline-suspend.cpp deleted file mode 100644 index f95286faf46e..000000000000 --- a/clang/test/CodeGenCoroutines/coro-awaiter-noinline-suspend.cpp +++ /dev/null @@ -1,168 +0,0 @@ -// Tests that we can mark await-suspend as noinline correctly. -// -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s \ -// RUN: -O1 -disable-llvm-passes | FileCheck %s - -#include "Inputs/coroutine.h" - -struct Task { - struct promise_type { - struct FinalAwaiter { - bool await_ready() const noexcept { return false; } - template - std::coroutine_handle<> await_suspend(std::coroutine_handle h) noexcept { - return h.promise().continuation; - } - void await_resume() noexcept {} - }; - - Task get_return_object() noexcept { - return std::coroutine_handle::from_promise(*this); - } - - std::suspend_always initial_suspend() noexcept { return {}; } - FinalAwaiter final_suspend() noexcept { return {}; } - void unhandled_exception() noexcept {} - void return_void() noexcept {} - - std::coroutine_handle<> continuation; - }; - - Task(std::coroutine_handle handle); - ~Task(); - -private: - std::coroutine_handle handle; -}; - -struct StatefulAwaiter { - int value; - bool await_ready() const noexcept { return false; } - template - void await_suspend(std::coroutine_handle h) noexcept {} - void await_resume() noexcept {} -}; - -typedef std::suspend_always NoStateAwaiter; -using AnotherStatefulAwaiter = StatefulAwaiter; - -template -struct TemplatedAwaiter { - T value; - bool await_ready() const noexcept { return false; } - template - void await_suspend(std::coroutine_handle h) noexcept {} - void await_resume() noexcept {} -}; - - -class Awaitable {}; -StatefulAwaiter operator co_await(Awaitable) { - return StatefulAwaiter{}; -} - -StatefulAwaiter GlobalAwaiter; -class Awaitable2 {}; -StatefulAwaiter& operator co_await(Awaitable2) { - return GlobalAwaiter; -} - -struct AlwaysInlineStatefulAwaiter { - void* value; - bool await_ready() const noexcept { return false; } - - template - __attribute__((always_inline)) - void await_suspend(std::coroutine_handle h) noexcept {} - - void await_resume() noexcept {} -}; - -Task testing() { - co_await std::suspend_always{}; - co_await StatefulAwaiter{}; - co_await AnotherStatefulAwaiter{}; - - // Test lvalue case. - StatefulAwaiter awaiter; - co_await awaiter; - - // The explicit call to await_suspend is not considered suspended. - awaiter.await_suspend(std::coroutine_handle::from_address(nullptr)); - - co_await TemplatedAwaiter{}; - TemplatedAwaiter TemplatedAwaiterInstace; - co_await TemplatedAwaiterInstace; - - co_await Awaitable{}; - co_await Awaitable2{}; - - co_await AlwaysInlineStatefulAwaiter{}; -} - -struct AwaitTransformTask { - struct promise_type { - struct FinalAwaiter { - bool await_ready() const noexcept { return false; } - template - std::coroutine_handle<> await_suspend(std::coroutine_handle h) noexcept { - return h.promise().continuation; - } - void await_resume() noexcept {} - }; - - AwaitTransformTask get_return_object() noexcept { - return std::coroutine_handle::from_promise(*this); - } - - std::suspend_always initial_suspend() noexcept { return {}; } - FinalAwaiter final_suspend() noexcept { return {}; } - void unhandled_exception() noexcept {} - void return_void() noexcept {} - - template - auto await_transform(Awaitable &&awaitable) { - return awaitable; - } - - std::coroutine_handle<> continuation; - }; - - AwaitTransformTask(std::coroutine_handle handle); - ~AwaitTransformTask(); - -private: - std::coroutine_handle handle; -}; - -struct awaitableWithGetAwaiter { - bool await_ready() const noexcept { return false; } - template - void await_suspend(std::coroutine_handle h) noexcept {} - void await_resume() noexcept {} -}; - -AwaitTransformTask testingWithAwaitTransform() { - co_await awaitableWithGetAwaiter{}; -} - -// CHECK: define{{.*}}@_ZNSt14suspend_always13await_suspendESt16coroutine_handleIvE{{.*}}#[[NORMAL_ATTR:[0-9]+]] - -// CHECK: define{{.*}}@_ZN15StatefulAwaiter13await_suspendIN4Task12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[NOINLINE_ATTR:[0-9]+]] - -// CHECK: define{{.*}}@_ZN15StatefulAwaiter13await_suspendIvEEvSt16coroutine_handleIT_E{{.*}}#[[NORMAL_ATTR]] - -// CHECK: define{{.*}}@_ZN16TemplatedAwaiterIiE13await_suspendIN4Task12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[NOINLINE_ATTR]] - -// CHECK: define{{.*}}@_ZN27AlwaysInlineStatefulAwaiter13await_suspendIN4Task12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[ALWAYS_INLINE_ATTR:[0-9]+]] - -// CHECK: define{{.*}}@_ZN4Task12promise_type12FinalAwaiter13await_suspendIS0_EESt16coroutine_handleIvES3_IT_E{{.*}}#[[NORMAL_ATTR]] - -// CHECK: define{{.*}}@_ZN23awaitableWithGetAwaiter13await_suspendIN18AwaitTransformTask12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[NORMAL_ATTR]] - -// CHECK: define{{.*}}@_ZN18AwaitTransformTask12promise_type12FinalAwaiter13await_suspendIS0_EESt16coroutine_handleIvES3_IT_E{{.*}}#[[NORMAL_ATTR]] - -// CHECK-NOT: attributes #[[NORMAL_ATTR]] = noinline -// CHECK: attributes #[[NOINLINE_ATTR]] = {{.*}}noinline -// CHECK-NOT: attributes #[[ALWAYS_INLINE_ATTR]] = {{.*}}noinline -// CHECK: attributes #[[ALWAYS_INLINE_ATTR]] = {{.*}}alwaysinline diff --git a/clang/test/CodeGenCoroutines/coro-dwarf.cpp b/clang/test/CodeGenCoroutines/coro-dwarf.cpp index 7914babe5483..2c9c827e6753 100644 --- a/clang/test/CodeGenCoroutines/coro-dwarf.cpp +++ b/clang/test/CodeGenCoroutines/coro-dwarf.cpp @@ -70,3 +70,15 @@ void f_coro(int val, MoveOnly moParam, MoveAndCopy mcParam) { // CHECK: !{{[0-9]+}} = !DILocalVariable(name: "moParam", arg: 2, scope: ![[SP]], file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}) // CHECK: !{{[0-9]+}} = !DILocalVariable(name: "mcParam", arg: 3, scope: ![[SP]], file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}}) // CHECK: !{{[0-9]+}} = !DILocalVariable(name: "__promise", + +// CHECK: !{{[0-9]+}} = distinct !DISubprogram(linkageName: "__await_suspend_wrapper__Z6f_coroi8MoveOnly11MoveAndCopy_init" +// CHECK-NEXT: !{{[0-9]+}} = !DIFile +// CHECK-NEXT: !{{[0-9]+}} = !DISubroutineType +// CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 1, +// CHECK-NEXT: !{{[0-9]+}} = !DILocation +// CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 2, + +// CHECK: !{{[0-9]+}} = distinct !DISubprogram(linkageName: "__await_suspend_wrapper__Z6f_coroi8MoveOnly11MoveAndCopy_final" +// CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 1, +// CHECK-NEXT: !{{[0-9]+}} = !DILocation +// CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 2, diff --git a/clang/test/CodeGenCoroutines/coro-function-try-block.cpp b/clang/test/CodeGenCoroutines/coro-function-try-block.cpp index f609eb55b8e7..b7a796cc241a 100644 --- a/clang/test/CodeGenCoroutines/coro-function-try-block.cpp +++ b/clang/test/CodeGenCoroutines/coro-function-try-block.cpp @@ -19,5 +19,5 @@ task f() try { } // CHECK-LABEL: define{{.*}} void @_Z1fv( -// CHECK: call void @_ZNSt13suspend_never13await_suspendESt16coroutine_handleIvE( +// CHECK: call void @llvm.coro.await.suspend.void( // CHECK: call void @_ZN4task12promise_type11return_voidEv( diff --git a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp index c0b9e9ee2c55..da30e12c63cf 100644 --- a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp +++ b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp @@ -50,10 +50,5 @@ detached_task foo() { // check that the lifetime of the coroutine handle used to obtain the address is contained within single basic block, and hence does not live across suspension points. // CHECK-LABEL: final.suspend: // CHECK: %{{.+}} = call token @llvm.coro.save(ptr null) -// CHECK: call void @llvm.lifetime.start.p0(i64 8, ptr %[[HDL:.+]]) -// CHECK: %[[CALL:.+]] = call ptr @_ZN13detached_task12promise_type13final_awaiter13await_suspendESt16coroutine_handleIS0_E( -// CHECK: %[[HDL_CAST2:.+]] = getelementptr inbounds %"struct.std::coroutine_handle.0", ptr %[[HDL]], i32 0, i32 0 -// CHECK: store ptr %[[CALL]], ptr %[[HDL_CAST2]], align 8 -// CHECK: %[[HDL_TRANSFER:.+]] = call noundef ptr @_ZNKSt16coroutine_handleIvE7addressEv(ptr noundef {{.*}}%[[HDL]]) -// CHECK: call void @llvm.lifetime.end.p0(i64 8, ptr %[[HDL]]) +// CHECK: %[[HDL_TRANSFER:.+]] = call ptr @llvm.coro.await.suspend.handle // CHECK: call void @llvm.coro.resume(ptr %[[HDL_TRANSFER]]) diff --git a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp index 890d55e41de9..ca6cf74115a3 100644 --- a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp +++ b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp @@ -89,10 +89,8 @@ Task bar() { // CHECK: br i1 %{{.+}}, label %[[CASE1_AWAIT_READY:.+]], label %[[CASE1_AWAIT_SUSPEND:.+]] // CHECK: [[CASE1_AWAIT_SUSPEND]]: // CHECK-NEXT: %{{.+}} = call token @llvm.coro.save(ptr null) -// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr %[[TMP1:.+]]) - -// CHECK: call void @llvm.lifetime.end.p0(i64 8, ptr %[[TMP1]]) -// CHECK-NEXT: call void @llvm.coro.resume +// CHECK-NEXT: %[[HANDLE1_PTR:.+]] = call ptr @llvm.coro.await.suspend.handle +// CHECK-NEXT: call void @llvm.coro.resume(ptr %[[HANDLE1_PTR]]) // CHECK-NEXT: %{{.+}} = call i8 @llvm.coro.suspend // CHECK-NEXT: switch i8 %{{.+}}, label %coro.ret [ // CHECK-NEXT: i8 0, label %[[CASE1_AWAIT_READY]] @@ -106,10 +104,8 @@ Task bar() { // CHECK: br i1 %{{.+}}, label %[[CASE2_AWAIT_READY:.+]], label %[[CASE2_AWAIT_SUSPEND:.+]] // CHECK: [[CASE2_AWAIT_SUSPEND]]: // CHECK-NEXT: %{{.+}} = call token @llvm.coro.save(ptr null) -// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr %[[TMP2:.+]]) - -// CHECK: call void @llvm.lifetime.end.p0(i64 8, ptr %[[TMP2]]) -// CHECK-NEXT: call void @llvm.coro.resume +// CHECK-NEXT: %[[HANDLE2_PTR:.+]] = call ptr @llvm.coro.await.suspend.handle +// CHECK-NEXT: call void @llvm.coro.resume(ptr %[[HANDLE2_PTR]]) // CHECK-NEXT: %{{.+}} = call i8 @llvm.coro.suspend // CHECK-NEXT: switch i8 %{{.+}}, label %coro.ret [ // CHECK-NEXT: i8 0, label %[[CASE2_AWAIT_READY]] diff --git a/clang/test/CodeGenCoroutines/pr56329.cpp b/clang/test/CodeGenCoroutines/pr56329.cpp index 31d4849af4e7..ad8b1b990179 100644 --- a/clang/test/CodeGenCoroutines/pr56329.cpp +++ b/clang/test/CodeGenCoroutines/pr56329.cpp @@ -115,5 +115,9 @@ Task Outer() { // CHECK-NOT: _exit // CHECK: musttail call // CHECK: musttail call +// CHECK: musttail call // CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: unreachable: +// CHECK-NEXT: unreachable // CHECK-NEXT: } diff --git a/clang/test/CodeGenCoroutines/pr59181.cpp b/clang/test/CodeGenCoroutines/pr59181.cpp index 80f4634db252..21e784e0031d 100644 --- a/clang/test/CodeGenCoroutines/pr59181.cpp +++ b/clang/test/CodeGenCoroutines/pr59181.cpp @@ -52,9 +52,8 @@ void foo() { // CHECK-NEXT: load i8 // CHECK-NEXT: trunc // CHECK-NEXT: store i1 false -// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[REF:%ref.tmp[0-9]+]]) // CHECK: await.suspend:{{.*}} -// CHECK-NOT: call void @llvm.lifetime.start.p0(i64 8, ptr [[REF]]) -// CHECK: call void @_ZZN4Task12promise_type15await_transformES_EN10Suspension13await_suspendESt16coroutine_handleIvE -// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[REF]]) +// CHECK-NOT: call void @llvm.lifetime +// CHECK: call void @llvm.coro.await.suspend.void( +// CHECK-NEXT: %{{[0-9]+}} = call i8 @llvm.coro.suspend( diff --git a/clang/test/CodeGenCoroutines/pr65054.cpp b/clang/test/CodeGenCoroutines/pr65054.cpp index 834b71050f59..7af9c04fca18 100644 --- a/clang/test/CodeGenCoroutines/pr65054.cpp +++ b/clang/test/CodeGenCoroutines/pr65054.cpp @@ -1,7 +1,3 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 \ -// RUN: -O0 -disable-llvm-passes -emit-llvm %s -o - \ -// RUN: | FileCheck %s --check-prefix=FRONTEND - // The output of O0 is highly redundant and hard to test. Also it is not good // limit the output of O0. So we test the optimized output from O0. The idea // is the optimizations shouldn't change the semantics of the program. @@ -51,10 +47,7 @@ MyTask FooBar() { } } -// FRONTEND: define{{.*}}@_ZNKSt16coroutine_handleIvE7addressEv{{.*}}#[[address_attr:[0-9]+]] -// FRONTEND: attributes #[[address_attr]] = {{.*}}alwaysinline - // CHECK-O0: define{{.*}}@_Z6FooBarv.resume -// CHECK-O0: call{{.*}}@_ZN7Awaiter13await_suspendESt16coroutine_handleIvE +// CHECK-O0: call{{.*}}@__await_suspend_wrapper__Z6FooBarv_await( // CHECK-O0-NOT: store // CHECK-O0: ret void diff --git a/llvm/docs/Coroutines.rst b/llvm/docs/Coroutines.rst index d6219d264e4a..83369d93c309 100644 --- a/llvm/docs/Coroutines.rst +++ b/llvm/docs/Coroutines.rst @@ -1744,6 +1744,266 @@ a call to ``llvm.coro.suspend.retcon`` after resuming abnormally. In a yield-once coroutine, it is undefined behavior if the coroutine executes a call to ``llvm.coro.suspend.retcon`` after resuming in any way. +.. _coro.await.suspend.void: + +'llvm.coro.await.suspend.void' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:: + + declare void @llvm.coro.await.suspend.void( + ptr , + ptr , + ptr ) + +Overview: +""""""""" + +The '``llvm.coro.await.suspend.void``' intrinsic encapsulates C++ +`await-suspend` block until it can't interfere with coroutine transform. + +The `await_suspend` block of `co_await` is essentially asynchronous +to the execution of the coroutine. Inlining it normally into an unsplit +coroutine can cause miscompilation because the coroutine CFG misrepresents +the true control flow of the program: things that happen in the +await_suspend are not guaranteed to happen prior to the resumption of the +coroutine, and things that happen after the resumption of the coroutine +(including its exit and the potential deallocation of the coroutine frame) +are not guaranteed to happen only after the end of `await_suspend`. + +This version of intrinsic corresponds to +'``void awaiter.await_suspend(...)``' variant. + +Arguments: +"""""""""" + +The first argument is a pointer to `awaiter` object. + +The second argument is a pointer to the current coroutine's frame. + +The third argument is a pointer to the wrapper function encapsulating +`await-suspend` logic. Its signature must be + +.. code-block:: llvm + + declare void @await_suspend_function(ptr %awaiter, ptr %hdl) + +Semantics: +"""""""""" + +The intrinsic must be used between corresponding `coro.save`_ and +`coro.suspend`_ calls. It is lowered to a direct +`await_suspend_function` call during `CoroSplit`_ pass. + +Example: +"""""""" + +.. code-block:: llvm + + ; before lowering + await.suspend: + %save = call token @llvm.coro.save(ptr %hdl) + call void @llvm.coro.await.suspend.void( + ptr %awaiter, + ptr %hdl, + ptr @await_suspend_function) + %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) + ... + + ; after lowering + await.suspend: + %save = call token @llvm.coro.save(ptr %hdl) + ; the call to await_suspend_function can be inlined + call void @await_suspend_function( + ptr %awaiter, + ptr %hdl) + %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) + ... + + ; wrapper function example + define void @await_suspend_function(ptr %awaiter, ptr %hdl) + entry: + %hdl.arg = ... ; construct std::coroutine_handle from %hdl + call void @"Awaiter::await_suspend"(ptr %awaiter, ptr %hdl.arg) + ret void + +.. _coro.await.suspend.bool: + +'llvm.coro.await.suspend.bool' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:: + + declare i1 @llvm.coro.await.suspend.bool( + ptr , + ptr , + ptr ) + +Overview: +""""""""" + +The '``llvm.coro.await.suspend.bool``' intrinsic encapsulates C++ +`await-suspend` block until it can't interfere with coroutine transform. + +The `await_suspend` block of `co_await` is essentially asynchronous +to the execution of the coroutine. Inlining it normally into an unsplit +coroutine can cause miscompilation because the coroutine CFG misrepresents +the true control flow of the program: things that happen in the +await_suspend are not guaranteed to happen prior to the resumption of the +coroutine, and things that happen after the resumption of the coroutine +(including its exit and the potential deallocation of the coroutine frame) +are not guaranteed to happen only after the end of `await_suspend`. + +This version of intrinsic corresponds to +'``bool awaiter.await_suspend(...)``' variant. + +Arguments: +"""""""""" + +The first argument is a pointer to `awaiter` object. + +The second argument is a pointer to the current coroutine's frame. + +The third argument is a pointer to the wrapper function encapsulating +`await-suspend` logic. Its signature must be + +.. code-block:: llvm + + declare i1 @await_suspend_function(ptr %awaiter, ptr %hdl) + +Semantics: +"""""""""" + +The intrinsic must be used between corresponding `coro.save`_ and +`coro.suspend`_ calls. It is lowered to a direct +`await_suspend_function` call during `CoroSplit`_ pass. + +If `await_suspend_function` call returns `true`, the current coroutine is +immediately resumed. + +Example: +"""""""" + +.. code-block:: llvm + + ; before lowering + await.suspend: + %save = call token @llvm.coro.save(ptr %hdl) + %resume = call i1 @llvm.coro.await.suspend.bool( + ptr %awaiter, + ptr %hdl, + ptr @await_suspend_function) + br i1 %resume, %await.suspend.bool, %await.ready + await.suspend.bool: + %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) + ... + await.ready: + call void @"Awaiter::await_resume"(ptr %awaiter) + ... + + ; after lowering + await.suspend: + %save = call token @llvm.coro.save(ptr %hdl) + ; the call to await_suspend_function can inlined + %resume = call i1 @await_suspend_function( + ptr %awaiter, + ptr %hdl) + br i1 %resume, %await.suspend.bool, %await.ready + ... + + ; wrapper function example + define i1 @await_suspend_function(ptr %awaiter, ptr %hdl) + entry: + %hdl.arg = ... ; construct std::coroutine_handle from %hdl + %resume = call i1 @"Awaiter::await_suspend"(ptr %awaiter, ptr %hdl.arg) + ret i1 %resume + +.. _coro.await.suspend.handle: + +'llvm.coro.await.suspend.handle' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:: + + declare ptr @llvm.coro.await.suspend.handle( + ptr , + ptr , + ptr ) + +Overview: +""""""""" + +The '``llvm.coro.await.suspend.handle``' intrinsic encapsulates C++ +`await-suspend` block until it can't interfere with coroutine transform. + +The `await_suspend` block of `co_await` is essentially asynchronous +to the execution of the coroutine. Inlining it normally into an unsplit +coroutine can cause miscompilation because the coroutine CFG misrepresents +the true control flow of the program: things that happen in the +await_suspend are not guaranteed to happen prior to the resumption of the +coroutine, and things that happen after the resumption of the coroutine +(including its exit and the potential deallocation of the coroutine frame) +are not guaranteed to happen only after the end of `await_suspend`. + +This version of intrinsic corresponds to +'``std::corouine_handle<> awaiter.await_suspend(...)``' variant. + +Arguments: +"""""""""" + +The first argument is a pointer to `awaiter` object. + +The second argument is a pointer to the current coroutine's frame. + +The third argument is a pointer to the wrapper function encapsulating +`await-suspend` logic. Its signature must be + +.. code-block:: llvm + + declare ptr @await_suspend_function(ptr %awaiter, ptr %hdl) + +Semantics: +"""""""""" + +The intrinsic must be used between corresponding `coro.save`_ and +`coro.suspend`_ calls. It is lowered to a direct +`await_suspend_function` call during `CoroSplit`_ pass. + +`await_suspend_function` must return a pointer to a valid +coroutine frame, which is immediately resumed + +Example: +"""""""" + +.. code-block:: llvm + + ; before lowering + await.suspend: + %save = call token @llvm.coro.save(ptr %hdl) + %next = call ptr @llvm.coro.await.suspend.handle( + ptr %awaiter, + ptr %hdl, + ptr @await_suspend_function) + call void @llvm.coro.resume(%next) + %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) + ... + + ; after lowering + await.suspend: + %save = call token @llvm.coro.save(ptr %hdl) + ; the call to await_suspend_function can be inlined + %next = call ptr @await_suspend_function( + ptr %awaiter, + ptr %hdl) + call void @llvm.coro.resume(%next) + %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) + ... + + ; wrapper function example + define ptr @await_suspend_function(ptr %awaiter, ptr %hdl) + entry: + %hdl.arg = ... ; construct std::coroutine_handle from %hdl + %hdl.raw = call ptr @"Awaiter::await_suspend"(ptr %awaiter, ptr %hdl.arg) + %hdl.result = ... ; get address of returned coroutine handle + ret ptr %hdl.result + Coroutine Transformation Passes =============================== CoroEarly @@ -1758,7 +2018,9 @@ and `coro.promise`_ intrinsics. CoroSplit --------- The pass CoroSplit builds coroutine frame and outlines resume and destroy parts -into separate functions. +into separate functions. This pass also lowers `coro.await.suspend.void`_, +`coro.await.suspend.bool`_ and `coro.await.suspend.handle`_ intrinsics. + CoroElide --------- diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index c2c0f74c315b..144298fd7c01 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1692,6 +1692,18 @@ def int_coro_promise : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_i1_ty], [IntrNoMem, NoCapture>]>; +def int_coro_await_suspend_void : Intrinsic<[], + [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], + [Throws]>; + +def int_coro_await_suspend_bool : Intrinsic<[llvm_i1_ty], + [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], + [Throws]>; + +def int_coro_await_suspend_handle : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], + [Throws]>; + // Coroutine Lowering Intrinsics. Used internally by coroutine passes. def int_coro_subfn_addr : DefaultAttrsIntrinsic< diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 3cf5e81efb3b..ce090c3b8a74 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -4999,6 +4999,9 @@ void Verifier::visitInstruction(Instruction &I) { F->getIntrinsicID() == Intrinsic::seh_scope_end || F->getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID() == Intrinsic::coro_destroy || + F->getIntrinsicID() == Intrinsic::coro_await_suspend_void || + F->getIntrinsicID() == Intrinsic::coro_await_suspend_bool || + F->getIntrinsicID() == Intrinsic::coro_await_suspend_handle || F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64 || diff --git a/llvm/lib/Transforms/Coroutines/CoroInstr.h b/llvm/lib/Transforms/Coroutines/CoroInstr.h index f01aa58eb899..79e745bb162c 100644 --- a/llvm/lib/Transforms/Coroutines/CoroInstr.h +++ b/llvm/lib/Transforms/Coroutines/CoroInstr.h @@ -78,6 +78,39 @@ public: } }; +/// This represents the llvm.coro.await.suspend instruction. +// FIXME: add callback metadata +// FIXME: make a proper IntrinisicInst. Currently this is not possible, +// because llvm.coro.await.suspend can be invoked. +class LLVM_LIBRARY_VISIBILITY CoroAwaitSuspendInst : public CallBase { + enum { AwaiterArg, FrameArg, WrapperArg }; + +public: + Value *getAwaiter() const { return getArgOperand(AwaiterArg); } + + Value *getFrame() const { return getArgOperand(FrameArg); } + + Function *getWrapperFunction() const { + return cast(getArgOperand(WrapperArg)); + } + + // Methods to support type inquiry through isa, cast, and dyn_cast: + static bool classof(const CallBase *CB) { + if (const Function *CF = CB->getCalledFunction()) { + auto IID = CF->getIntrinsicID(); + return IID == Intrinsic::coro_await_suspend_void || + IID == Intrinsic::coro_await_suspend_bool || + IID == Intrinsic::coro_await_suspend_handle; + } + + return false; + } + + static bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + /// This represents a common base class for llvm.coro.id instructions. class LLVM_LIBRARY_VISIBILITY AnyCoroIdInst : public IntrinsicInst { public: diff --git a/llvm/lib/Transforms/Coroutines/CoroInternal.h b/llvm/lib/Transforms/Coroutines/CoroInternal.h index 388cf8d2aee7..09d1430b4c55 100644 --- a/llvm/lib/Transforms/Coroutines/CoroInternal.h +++ b/llvm/lib/Transforms/Coroutines/CoroInternal.h @@ -84,6 +84,7 @@ struct LLVM_LIBRARY_VISIBILITY Shape { SmallVector CoroAligns; SmallVector CoroSuspends; SmallVector SwiftErrorOps; + SmallVector CoroAwaitSuspends; // Field indexes for special fields in the switch lowering. struct SwitchFieldIndex { diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 99675aa495f5..58b95e43b899 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -167,6 +167,55 @@ private: } // end anonymous namespace +// FIXME: +// Lower the intrinisc in CoroEarly phase if coroutine frame doesn't escape +// and it is known that other transformations, for example, sanitizers +// won't lead to incorrect code. +static void lowerAwaitSuspend(IRBuilder<> &Builder, CoroAwaitSuspendInst *CB) { + auto Wrapper = CB->getWrapperFunction(); + auto Awaiter = CB->getAwaiter(); + auto FramePtr = CB->getFrame(); + + Builder.SetInsertPoint(CB); + + CallBase *NewCall = nullptr; + // await_suspend has only 2 parameters, awaiter and handle. + // Copy parameter attributes from the intrinsic call, but remove the last, + // because the last parameter now becomes the function that is being called. + AttributeList NewAttributes = + CB->getAttributes().removeParamAttributes(CB->getContext(), 2); + + if (auto Invoke = dyn_cast(CB)) { + auto WrapperInvoke = + Builder.CreateInvoke(Wrapper, Invoke->getNormalDest(), + Invoke->getUnwindDest(), {Awaiter, FramePtr}); + + WrapperInvoke->setCallingConv(Invoke->getCallingConv()); + std::copy(Invoke->bundle_op_info_begin(), Invoke->bundle_op_info_end(), + WrapperInvoke->bundle_op_info_begin()); + WrapperInvoke->setAttributes(NewAttributes); + WrapperInvoke->setDebugLoc(Invoke->getDebugLoc()); + NewCall = WrapperInvoke; + } else if (auto Call = dyn_cast(CB)) { + auto WrapperCall = Builder.CreateCall(Wrapper, {Awaiter, FramePtr}); + + WrapperCall->setAttributes(NewAttributes); + WrapperCall->setDebugLoc(Call->getDebugLoc()); + NewCall = WrapperCall; + } else { + llvm_unreachable("Unexpected coro_await_suspend invocation method"); + } + + CB->replaceAllUsesWith(NewCall); + CB->eraseFromParent(); +} + +static void lowerAwaitSuspends(Function &F, coro::Shape &Shape) { + IRBuilder<> Builder(F.getContext()); + for (auto *AWS : Shape.CoroAwaitSuspends) + lowerAwaitSuspend(Builder, AWS); +} + static void maybeFreeRetconStorage(IRBuilder<> &Builder, const coro::Shape &Shape, Value *FramePtr, CallGraph *CG) { @@ -2025,6 +2074,8 @@ splitCoroutine(Function &F, SmallVectorImpl &Clones, if (!Shape.CoroBegin) return Shape; + lowerAwaitSuspends(F, Shape); + simplifySuspendPoints(Shape); buildCoroutineFrame(F, Shape, TTI, MaterializableCallback); replaceFrameSizeAndAlignment(Shape); diff --git a/llvm/lib/Transforms/Coroutines/Coroutines.cpp b/llvm/lib/Transforms/Coroutines/Coroutines.cpp index 7bd151ed4dc1..a1c78d6a44ef 100644 --- a/llvm/lib/Transforms/Coroutines/Coroutines.cpp +++ b/llvm/lib/Transforms/Coroutines/Coroutines.cpp @@ -67,6 +67,9 @@ static const char *const CoroIntrinsics[] = { "llvm.coro.async.resume", "llvm.coro.async.size.replace", "llvm.coro.async.store_resume", + "llvm.coro.await.suspend.bool", + "llvm.coro.await.suspend.handle", + "llvm.coro.await.suspend.void", "llvm.coro.begin", "llvm.coro.destroy", "llvm.coro.done", @@ -174,7 +177,11 @@ void coro::Shape::buildFrom(Function &F) { SmallVector UnusedCoroSaves; for (Instruction &I : instructions(F)) { - if (auto II = dyn_cast(&I)) { + // FIXME: coro_await_suspend_* are not proper `IntrinisicInst`s + // because they might be invoked + if (auto AWS = dyn_cast(&I)) { + CoroAwaitSuspends.push_back(AWS); + } else if (auto II = dyn_cast(&I)) { switch (II->getIntrinsicID()) { default: continue; diff --git a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll new file mode 100644 index 000000000000..fbc4a2c006f8 --- /dev/null +++ b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll @@ -0,0 +1,123 @@ +; Tests that invoke @llvm.coro.await.suspend lowers to invoke @helper +; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split),simplifycfg' -S | FileCheck %s + +%Awaiter = type {} + +; CHECK: define {{[^@]*}} @f.resume(ptr {{[^%]*}} %[[HDL:.+]]) +; CHECK: %[[AWAITER:.+]] = getelementptr inbounds %f.Frame, ptr %[[HDL]], i32 0, i32 0 +define void @f() presplitcoroutine personality i32 0 { +entry: + %awaiter = alloca %Awaiter + %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) + %size = call i32 @llvm.coro.size.i32() + %alloc = call ptr @malloc(i32 %size) + %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc) + ; Initial suspend so that all 3 await_suspend invocations are inside f.resume + %suspend.init = call i8 @llvm.coro.suspend(token none, i1 false) + switch i8 %suspend.init, label %ret [ + i8 0, label %step + i8 1, label %cleanup + ] + +; CHECK: invoke void @await_suspend_wrapper_void(ptr %[[AWAITER]], ptr %[[HDL]]) +; CHECK-NEXT: to label %[[STEP_CONT:[^ ]+]] unwind label %[[PAD:[^ ]+]] +step: + %save = call token @llvm.coro.save(ptr null) + invoke void @llvm.coro.await.suspend.void(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_void) + to label %step.continue unwind label %pad + +; CHECK [[STEP_CONT]]: +step.continue: + %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) + switch i8 %suspend, label %ret [ + i8 0, label %step1 + i8 1, label %cleanup + ] + +; CHECK: %[[RESUME:.+]] = invoke i1 @await_suspend_wrapper_bool(ptr %[[AWAITER]], ptr %[[HDL]]) +; CHECK-NEXT: to label %[[STEP1_CONT:[^ ]+]] unwind label %[[PAD]] +step1: + %save1 = call token @llvm.coro.save(ptr null) + %resume.bool = invoke i1 @llvm.coro.await.suspend.bool(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_bool) + to label %step1.continue unwind label %pad + +; CHECK: [[STEP1_CONT]]: +; CHECK-NEXT: br i1 %[[RESUME]], label %{{[^,]+}}, label %[[STEP2:.+]] +step1.continue: + br i1 %resume.bool, label %suspend.cond, label %step2 + +suspend.cond: + %suspend1 = call i8 @llvm.coro.suspend(token %save1, i1 false) + switch i8 %suspend1, label %ret [ + i8 0, label %step2 + i8 1, label %cleanup + ] + +; CHECK: [[STEP2]]: +; CHECK: %[[NEXT_HDL:.+]] = invoke ptr @await_suspend_wrapper_handle(ptr %[[AWAITER]], ptr %[[HDL]]) +; CHECK-NEXT: to label %[[STEP2_CONT:[^ ]+]] unwind label %[[PAD]] +step2: + %save2 = call token @llvm.coro.save(ptr null) + %resume.handle = invoke ptr @llvm.coro.await.suspend.handle(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_handle) + to label %step2.continue unwind label %pad + +; CHECK: [[STEP2_CONT]]: +; CHECK-NEXT: %[[NEXT_RESUME:.+]] = call ptr @llvm.coro.subfn.addr(ptr %[[NEXT_HDL]], i8 0) +; CHECK-NEXT: musttail call {{.*}} void %[[NEXT_RESUME]](ptr %[[NEXT_HDL]]) +step2.continue: + call void @llvm.coro.resume(ptr %resume.handle) + %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) + switch i8 %suspend2, label %ret [ + i8 0, label %step3 + i8 1, label %cleanup + ] + +step3: + br label %cleanup + +pad: + %lp = landingpad { ptr, i32 } + catch ptr null + %exn = extractvalue { ptr, i32 } %lp, 0 + call ptr @__cxa_begin_catch(ptr %exn) + call void @__cxa_end_catch() + br label %cleanup + +cleanup: + %mem = call ptr @llvm.coro.free(token %id, ptr %hdl) + call void @free(ptr %mem) + br label %ret + +ret: + call i1 @llvm.coro.end(ptr %hdl, i1 0, token none) + ret void +} + +; check that we were haven't accidentally went out of @f.resume body +; CHECK-LABEL: @f.destroy( +; CHECK-LABEL: @f.cleanup( + +declare void @await_suspend_wrapper_void(ptr, ptr) +declare i1 @await_suspend_wrapper_bool(ptr, ptr) +declare ptr @await_suspend_wrapper_handle(ptr, ptr) + +declare ptr @llvm.coro.free(token, ptr) +declare i32 @llvm.coro.size.i32() +declare i8 @llvm.coro.suspend(token, i1) +declare void @llvm.coro.resume(ptr) +declare void @llvm.coro.destroy(ptr) + +declare token @llvm.coro.id(i32, ptr, ptr, ptr) +declare i1 @llvm.coro.alloc(token) +declare ptr @llvm.coro.begin(token, ptr) +declare void @llvm.coro.await.suspend.void(ptr, ptr, ptr) +declare i1 @llvm.coro.await.suspend.bool(ptr, ptr, ptr) +declare ptr @llvm.coro.await.suspend.handle(ptr, ptr, ptr) +declare i1 @llvm.coro.end(ptr, i1, token) + +declare ptr @__cxa_begin_catch(ptr) +declare void @use_val(i32) +declare void @__cxa_end_catch() + +declare noalias ptr @malloc(i32) +declare void @free(ptr) diff --git a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll new file mode 100644 index 000000000000..0f574c4acc26 --- /dev/null +++ b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll @@ -0,0 +1,96 @@ +; Tests lowerings of different versions of coro.await.suspend +; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split),simplifycfg' -S | FileCheck %s + +%Awaiter = type {} + +; CHECK: define {{[^@]*}} @f.resume(ptr {{[^%]*}} %[[HDL:.+]]) +; CHECK: %[[AWAITER:.+]] = getelementptr inbounds %f.Frame, ptr %[[HDL]], i32 0, i32 0 +define void @f() presplitcoroutine { +entry: + %awaiter = alloca %Awaiter + %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) + %size = call i32 @llvm.coro.size.i32() + %alloc = call ptr @malloc(i32 %size) + %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc) + %suspend.init = call i8 @llvm.coro.suspend(token none, i1 false) + switch i8 %suspend.init, label %ret [ + i8 0, label %step + i8 1, label %cleanup + ] + +; CHECK: call void @await_suspend_wrapper_void(ptr %[[AWAITER]], ptr %[[HDL]]) +; CHECK-NEXT: br label %{{.*}} +step: + %save = call token @llvm.coro.save(ptr null) + call void @llvm.coro.await.suspend.void(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_void) + %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) + switch i8 %suspend, label %ret [ + i8 0, label %step1 + i8 1, label %cleanup + ] + +; CHECK: %[[RESUME:.+]] = call i1 @await_suspend_wrapper_bool(ptr %[[AWAITER]], ptr %[[HDL]]) +; CHECK-NEXT: br i1 %[[RESUME]], label %{{[^,]+}}, label %[[STEP2:.+]] +step1: + %save1 = call token @llvm.coro.save(ptr null) + %resume.bool = call i1 @llvm.coro.await.suspend.bool(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_bool) + br i1 %resume.bool, label %suspend.cond, label %step2 + +suspend.cond: + %suspend1 = call i8 @llvm.coro.suspend(token %save1, i1 false) + switch i8 %suspend1, label %ret [ + i8 0, label %step2 + i8 1, label %cleanup + ] + +; CHECK: [[STEP2]]: +; CHECK: %[[NEXT_HDL:.+]] = call ptr @await_suspend_wrapper_handle(ptr %[[AWAITER]], ptr %[[HDL]]) +; CHECK-NEXT: %[[CONT:.+]] = call ptr @llvm.coro.subfn.addr(ptr %[[NEXT_HDL]], i8 0) +; CHECK-NEXT: musttail call {{.*}} void %[[CONT]](ptr %[[NEXT_HDL]]) +step2: + %save2 = call token @llvm.coro.save(ptr null) + %resume.handle = call ptr @llvm.coro.await.suspend.handle(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_handle) + call void @llvm.coro.resume(ptr %resume.handle) + %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) + switch i8 %suspend2, label %ret [ + i8 0, label %step3 + i8 1, label %cleanup + ] + +step3: + br label %cleanup + +cleanup: + %mem = call ptr @llvm.coro.free(token %id, ptr %hdl) + call void @free(ptr %mem) + br label %ret + +ret: + call i1 @llvm.coro.end(ptr %hdl, i1 0, token none) + ret void +} + +; check that we were haven't accidentally went out of @f.resume body +; CHECK-LABEL: @f.destroy( +; CHECK-LABEL: @f.cleanup( + +declare void @await_suspend_wrapper_void(ptr, ptr) +declare i1 @await_suspend_wrapper_bool(ptr, ptr) +declare ptr @await_suspend_wrapper_handle(ptr, ptr) + +declare ptr @llvm.coro.free(token, ptr) +declare i32 @llvm.coro.size.i32() +declare i8 @llvm.coro.suspend(token, i1) +declare void @llvm.coro.resume(ptr) +declare void @llvm.coro.destroy(ptr) + +declare token @llvm.coro.id(i32, ptr, ptr, ptr) +declare i1 @llvm.coro.alloc(token) +declare ptr @llvm.coro.begin(token, ptr) +declare void @llvm.coro.await.suspend.void(ptr, ptr, ptr) +declare i1 @llvm.coro.await.suspend.bool(ptr, ptr, ptr) +declare ptr @llvm.coro.await.suspend.handle(ptr, ptr, ptr) +declare i1 @llvm.coro.end(ptr, i1, token) + +declare noalias ptr @malloc(i32) +declare void @free(ptr) -- GitLab From 6bec4fc76de50a090d1d0b36498da66c4a324851 Mon Sep 17 00:00:00 2001 From: lntue <35648136+lntue@users.noreply.github.com> Date: Sun, 10 Mar 2024 22:16:56 -0400 Subject: [PATCH 061/953] [libc] Fix flag parsing bugs. (#84706) --- libc/cmake/modules/LLVMLibCCompileOptionRules.cmake | 6 +++--- libc/cmake/modules/LLVMLibCFlagRules.cmake | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake index 72b04822d8b8..893a807b5b61 100644 --- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake +++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake @@ -2,10 +2,10 @@ function(_get_compile_options_from_flags output_var) set(compile_options "") if(LIBC_TARGET_ARCHITECTURE_IS_RISCV64 OR(LIBC_CPU_FEATURES MATCHES "FMA")) - check_flag(ADD_FMA_FLAG ${FMA_OPT_FLAG} ${flags}) + check_flag(ADD_FMA_FLAG ${FMA_OPT_FLAG} ${ARGN}) endif() - check_flag(ADD_SSE4_2_FLAG ${ROUND_OPT_FLAG} ${flags}) - check_flag(ADD_EXPLICIT_SIMD_OPT_FLAG ${EXPLICIT_SIMD_OPT_FLAG} ${flags}) + check_flag(ADD_SSE4_2_FLAG ${ROUND_OPT_FLAG} ${ARGN}) + check_flag(ADD_EXPLICIT_SIMD_OPT_FLAG ${EXPLICIT_SIMD_OPT_FLAG} ${ARGN}) if(LLVM_COMPILER_IS_GCC_COMPATIBLE) if(ADD_FMA_FLAG) diff --git a/libc/cmake/modules/LLVMLibCFlagRules.cmake b/libc/cmake/modules/LLVMLibCFlagRules.cmake index 9bec716516f2..18e36dfde5cc 100644 --- a/libc/cmake/modules/LLVMLibCFlagRules.cmake +++ b/libc/cmake/modules/LLVMLibCFlagRules.cmake @@ -131,9 +131,9 @@ endfunction(get_fq_dep_list_without_flag) # Check if a `flag` is set function(check_flag result flag_name) - list(FIND ARGN ${flag_name}_FLAG has_flag) + list(FIND ARGN ${flag_name} has_flag) if(${has_flag} LESS 0) - list(FIND ARGN "${flag_name}_FLAG__ONLY" has_flag) + list(FIND ARGN "${flag_name}__ONLY" has_flag) endif() if(${has_flag} GREATER -1) set(${result} TRUE PARENT_SCOPE) -- GitLab From fab2bb8bfda865bd438dee981d7be7df8017b76d Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Sun, 10 Mar 2024 20:00:13 -0700 Subject: [PATCH 062/953] Add llvm::min/max_element and use it in llvm/ and mlir/ directories. (#84678) For some reason this was missing from STLExtras. --- llvm/include/llvm/ADT/STLExtras.h | 16 +++++++++++++ llvm/include/llvm/CodeGen/RegAllocPBQP.h | 6 ++--- llvm/lib/Analysis/ScalarEvolution.cpp | 7 +++--- llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp | 3 +-- llvm/lib/IR/DataLayout.cpp | 2 +- llvm/lib/ObjCopy/MachO/MachOWriter.cpp | 2 +- llvm/lib/ProfileData/GCOV.cpp | 2 +- llvm/lib/Target/AArch64/SVEIntrinsicOpts.cpp | 4 ++-- llvm/lib/Target/AMDGPU/GCNILPSched.cpp | 10 ++++---- llvm/lib/Target/AMDGPU/SIFixSGPRCopies.cpp | 5 ++-- llvm/lib/Target/AMDGPU/SIMachineScheduler.cpp | 6 ++--- llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp | 2 +- .../Target/Hexagon/HexagonConstExtenders.cpp | 9 ++++---- llvm/lib/Target/Hexagon/HexagonGenInsert.cpp | 2 +- .../Target/Hexagon/HexagonVectorCombine.cpp | 6 ++--- llvm/lib/Transforms/Scalar/GVNSink.cpp | 3 +-- llvm/lib/Transforms/Scalar/JumpThreading.cpp | 8 +++---- .../Transforms/Scalar/LoopLoadElimination.cpp | 23 ++++++++++--------- llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 2 +- .../Vectorize/LoadStoreVectorizer.cpp | 9 ++++---- .../Transforms/Vectorize/SLPVectorizer.cpp | 9 ++++---- .../lib/LatencyBenchmarkRunner.cpp | 4 ++-- .../llvm-mca/Views/BottleneckAnalysis.cpp | 7 +++--- .../llvm-mca/Views/SchedulerStatistics.cpp | 3 +-- llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp | 9 ++++---- llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp | 6 ++--- llvm/tools/llvm-rc/ResourceFileWriter.cpp | 9 ++++---- llvm/utils/FileCheck/FileCheck.cpp | 13 ++++------- llvm/utils/TableGen/CodeGenSchedule.cpp | 2 +- llvm/utils/TableGen/RegisterInfoEmitter.cpp | 4 ++-- .../toy/Ch5/mlir/LowerToAffineLoops.cpp | 3 +-- .../toy/Ch6/mlir/LowerToAffineLoops.cpp | 3 +-- .../toy/Ch7/mlir/LowerToAffineLoops.cpp | 3 +-- .../PDLToPDLInterp/PredicateTree.cpp | 3 +-- mlir/lib/Dialect/Affine/IR/AffineOps.cpp | 4 ++-- mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp | 2 +- .../GPU/TransformOps/GPUTransformOps.cpp | 5 ++-- .../Transforms/ConvertToDestinationStyle.cpp | 2 +- .../Transforms/UnifyAliasedResourcePass.cpp | 4 ++-- .../BufferizableOpInterfaceImpl.cpp | 2 +- mlir/lib/IR/AffineMap.cpp | 2 +- mlir/lib/Reducer/ReductionNode.cpp | 4 ++-- 42 files changed, 111 insertions(+), 119 deletions(-) diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index 15845dd9333c..5ac549c44756 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -1971,6 +1971,22 @@ auto upper_bound(R &&Range, T &&Value, Compare C) { std::forward(Value), C); } +template auto min_element(R &&Range) { + return std::min_element(adl_begin(Range), adl_end(Range)); +} + +template auto min_element(R &&Range, Compare C) { + return std::min_element(adl_begin(Range), adl_end(Range), C); +} + +template auto max_element(R &&Range) { + return std::max_element(adl_begin(Range), adl_end(Range)); +} + +template auto max_element(R &&Range, Compare C) { + return std::max_element(adl_begin(Range), adl_end(Range), C); +} + template void stable_sort(R &&Range) { std::stable_sort(adl_begin(Range), adl_end(Range)); diff --git a/llvm/include/llvm/CodeGen/RegAllocPBQP.h b/llvm/include/llvm/CodeGen/RegAllocPBQP.h index 1ea8840947bc..234f1c6ff115 100644 --- a/llvm/include/llvm/CodeGen/RegAllocPBQP.h +++ b/llvm/include/llvm/CodeGen/RegAllocPBQP.h @@ -462,10 +462,8 @@ private: NodeStack.push_back(NId); G.disconnectAllNeighborsFromNode(NId); } else if (!NotProvablyAllocatableNodes.empty()) { - NodeSet::iterator NItr = - std::min_element(NotProvablyAllocatableNodes.begin(), - NotProvablyAllocatableNodes.end(), - SpillCostComparator(G)); + NodeSet::iterator NItr = llvm::min_element(NotProvablyAllocatableNodes, + SpillCostComparator(G)); NodeId NId = *NItr; NotProvablyAllocatableNodes.erase(NItr); NodeStack.push_back(NId); diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index acc0aa23107b..515b9d0744f6 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -10839,10 +10839,9 @@ bool ScalarEvolution::isKnownViaInduction(ICmpInst::Predicate Pred, #endif const Loop *MDL = - *std::max_element(LoopsUsed.begin(), LoopsUsed.end(), - [&](const Loop *L1, const Loop *L2) { - return DT.properlyDominates(L1->getHeader(), L2->getHeader()); - }); + *llvm::max_element(LoopsUsed, [&](const Loop *L1, const Loop *L2) { + return DT.properlyDominates(L1->getHeader(), L2->getHeader()); + }); // Get init and post increment value for LHS. auto SplitLHS = SplitIntoInitAndPostInc(MDL, LHS); diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp index 471d183a5f53..0232cae6e389 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -86,8 +86,7 @@ uint32_t PDBFile::getNumStreams() const { } uint32_t PDBFile::getMaxStreamSize() const { - return *std::max_element(ContainerLayout.StreamSizes.begin(), - ContainerLayout.StreamSizes.end()); + return *llvm::max_element(ContainerLayout.StreamSizes); } uint32_t PDBFile::getStreamByteSize(uint32_t StreamIndex) const { diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp index a2f5714c7068..274116533248 100644 --- a/llvm/lib/IR/DataLayout.cpp +++ b/llvm/lib/IR/DataLayout.cpp @@ -898,7 +898,7 @@ Type *DataLayout::getSmallestLegalIntType(LLVMContext &C, unsigned Width) const } unsigned DataLayout::getLargestLegalIntTypeSizeInBits() const { - auto Max = std::max_element(LegalIntWidths.begin(), LegalIntWidths.end()); + auto Max = llvm::max_element(LegalIntWidths); return Max != LegalIntWidths.end() ? *Max : 0; } diff --git a/llvm/lib/ObjCopy/MachO/MachOWriter.cpp b/llvm/lib/ObjCopy/MachO/MachOWriter.cpp index f416796496e9..1ff741c830bd 100644 --- a/llvm/lib/ObjCopy/MachO/MachOWriter.cpp +++ b/llvm/lib/ObjCopy/MachO/MachOWriter.cpp @@ -126,7 +126,7 @@ size_t MachOWriter::totalSize() const { } if (!Ends.empty()) - return *std::max_element(Ends.begin(), Ends.end()); + return *llvm::max_element(Ends); // Otherwise, we have only Mach header and load commands. return headerSize() + loadCommandsSize(); diff --git a/llvm/lib/ProfileData/GCOV.cpp b/llvm/lib/ProfileData/GCOV.cpp index fcfeb5b0f584..ee61784abade 100644 --- a/llvm/lib/ProfileData/GCOV.cpp +++ b/llvm/lib/ProfileData/GCOV.cpp @@ -703,7 +703,7 @@ void Context::collectFunction(GCOVFunction &f, Summary &summary) { for (const GCOVBlock &b : f.blocksRange()) { if (b.lines.empty()) continue; - uint32_t maxLineNum = *std::max_element(b.lines.begin(), b.lines.end()); + uint32_t maxLineNum = *llvm::max_element(b.lines); if (maxLineNum >= si.lines.size()) si.lines.resize(maxLineNum + 1); for (uint32_t lineNum : b.lines) { diff --git a/llvm/lib/Target/AArch64/SVEIntrinsicOpts.cpp b/llvm/lib/Target/AArch64/SVEIntrinsicOpts.cpp index 880ff8498b87..fe68203ad539 100644 --- a/llvm/lib/Target/AArch64/SVEIntrinsicOpts.cpp +++ b/llvm/lib/Target/AArch64/SVEIntrinsicOpts.cpp @@ -138,8 +138,8 @@ bool SVEIntrinsicOpts::coalescePTrueIntrinsicCalls( return false; // Find the ptrue with the most lanes. - auto *MostEncompassingPTrue = *std::max_element( - PTrues.begin(), PTrues.end(), [](auto *PTrue1, auto *PTrue2) { + auto *MostEncompassingPTrue = + *llvm::max_element(PTrues, [](auto *PTrue1, auto *PTrue2) { auto *PTrue1VTy = cast(PTrue1->getType()); auto *PTrue2VTy = cast(PTrue2->getType()); return PTrue1VTy->getElementCount().getKnownMinValue() < diff --git a/llvm/lib/Target/AMDGPU/GCNILPSched.cpp b/llvm/lib/Target/AMDGPU/GCNILPSched.cpp index 8629db2e2563..559dd0ed0c41 100644 --- a/llvm/lib/Target/AMDGPU/GCNILPSched.cpp +++ b/llvm/lib/Target/AMDGPU/GCNILPSched.cpp @@ -313,11 +313,11 @@ GCNILPScheduler::schedule(ArrayRef BotRoots, Schedule.reserve(SUnits.size()); while (true) { if (AvailQueue.empty() && !PendingQueue.empty()) { - auto EarliestSU = std::min_element( - PendingQueue.begin(), PendingQueue.end(), - [=](const Candidate& C1, const Candidate& C2) { - return C1.SU->getHeight() < C2.SU->getHeight(); - })->SU; + auto EarliestSU = + llvm::min_element(PendingQueue, [=](const Candidate &C1, + const Candidate &C2) { + return C1.SU->getHeight() < C2.SU->getHeight(); + })->SU; advanceToCycle(std::max(CurCycle + 1, EarliestSU->getHeight())); } if (AvailQueue.empty()) diff --git a/llvm/lib/Target/AMDGPU/SIFixSGPRCopies.cpp b/llvm/lib/Target/AMDGPU/SIFixSGPRCopies.cpp index 86980ee851bb..8b21c22b4497 100644 --- a/llvm/lib/Target/AMDGPU/SIFixSGPRCopies.cpp +++ b/llvm/lib/Target/AMDGPU/SIFixSGPRCopies.cpp @@ -973,9 +973,8 @@ bool SIFixSGPRCopies::needToBeConvertedToVALU(V2SCopyInfo *Info) { Info->Score = 0; return true; } - Info->Siblings = SiblingPenalty[*std::max_element( - Info->SChain.begin(), Info->SChain.end(), - [&](MachineInstr *A, MachineInstr *B) -> bool { + Info->Siblings = SiblingPenalty[*llvm::max_element( + Info->SChain, [&](MachineInstr *A, MachineInstr *B) -> bool { return SiblingPenalty[A].size() < SiblingPenalty[B].size(); })]; Info->Siblings.remove_if([&](unsigned ID) { return ID == Info->ID; }); diff --git a/llvm/lib/Target/AMDGPU/SIMachineScheduler.cpp b/llvm/lib/Target/AMDGPU/SIMachineScheduler.cpp index 677f1590287e..4476adf95f8d 100644 --- a/llvm/lib/Target/AMDGPU/SIMachineScheduler.cpp +++ b/llvm/lib/Target/AMDGPU/SIMachineScheduler.cpp @@ -904,10 +904,8 @@ void SIScheduleBlockCreator::colorEndsAccordingToDependencies() { CurrentTopDownReservedDependencyColoring.size() == DAGSize); // If there is no reserved block at all, do nothing. We don't want // everything in one block. - if (*std::max_element(CurrentBottomUpReservedDependencyColoring.begin(), - CurrentBottomUpReservedDependencyColoring.end()) == 0 && - *std::max_element(CurrentTopDownReservedDependencyColoring.begin(), - CurrentTopDownReservedDependencyColoring.end()) == 0) + if (*llvm::max_element(CurrentBottomUpReservedDependencyColoring) == 0 && + *llvm::max_element(CurrentTopDownReservedDependencyColoring) == 0) return; for (unsigned SUNum : DAG->BottomUpIndex2SU) { diff --git a/llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp b/llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp index 5ad749074a8e..4ead8c68cb90 100644 --- a/llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp +++ b/llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp @@ -593,7 +593,7 @@ void HexagonCommonGEP::common() { using ProjMap = std::map; ProjMap PM; for (const NodeSet &S : EqRel) { - GepNode *Min = *std::min_element(S.begin(), S.end(), NodeOrder); + GepNode *Min = *llvm::min_element(S, NodeOrder); std::pair Ins = PM.insert(std::make_pair(&S, Min)); (void)Ins; assert(Ins.second && "Cannot add minimal element"); diff --git a/llvm/lib/Target/Hexagon/HexagonConstExtenders.cpp b/llvm/lib/Target/Hexagon/HexagonConstExtenders.cpp index 400bb6cfc731..f2a02fe9540b 100644 --- a/llvm/lib/Target/Hexagon/HexagonConstExtenders.cpp +++ b/llvm/lib/Target/Hexagon/HexagonConstExtenders.cpp @@ -1388,11 +1388,10 @@ void HCE::assignInits(const ExtRoot &ER, unsigned Begin, unsigned End, break; // Find the best candidate with respect to the number of extenders covered. - auto BestIt = std::max_element(Counts.begin(), Counts.end(), - [](const CMap::value_type &A, const CMap::value_type &B) { - return A.second < B.second || - (A.second == B.second && A < B); - }); + auto BestIt = llvm::max_element( + Counts, [](const CMap::value_type &A, const CMap::value_type &B) { + return A.second < B.second || (A.second == B.second && A < B); + }); int32_t Best = BestIt->first; ExtValue BestV(ER, Best); for (RangeTree::Node *N : Tree.nodesWith(Best)) { diff --git a/llvm/lib/Target/Hexagon/HexagonGenInsert.cpp b/llvm/lib/Target/Hexagon/HexagonGenInsert.cpp index 44f21dbacd3c..1e373f6061bb 100644 --- a/llvm/lib/Target/Hexagon/HexagonGenInsert.cpp +++ b/llvm/lib/Target/Hexagon/HexagonGenInsert.cpp @@ -1314,7 +1314,7 @@ void HexagonGenInsert::selectCandidates() { // element found is adequate, we will put it back on the list, other- // wise the list will remain empty, and the entry for this register // will be removed (i.e. this register will not be replaced by insert). - IFListType::iterator MinI = std::min_element(LL.begin(), LL.end(), IFO); + IFListType::iterator MinI = llvm::min_element(LL, IFO); assert(MinI != LL.end()); IFRecordWithRegSet M = *MinI; LL.clear(); diff --git a/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp b/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp index 7231388445d5..797b798520aa 100644 --- a/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp +++ b/llvm/lib/Target/Hexagon/HexagonVectorCombine.cpp @@ -1411,9 +1411,9 @@ auto AlignVectors::realignGroup(const MoveGroup &Move) const -> bool { // Return the element with the maximum alignment from Range, // where GetValue obtains the value to compare from an element. auto getMaxOf = [](auto Range, auto GetValue) { - return *std::max_element( - Range.begin(), Range.end(), - [&GetValue](auto &A, auto &B) { return GetValue(A) < GetValue(B); }); + return *llvm::max_element(Range, [&GetValue](auto &A, auto &B) { + return GetValue(A) < GetValue(B); + }); }; const AddrList &BaseInfos = AddrGroups.at(Move.Base); diff --git a/llvm/lib/Transforms/Scalar/GVNSink.cpp b/llvm/lib/Transforms/Scalar/GVNSink.cpp index 2b38831139a5..d4907326eb0a 100644 --- a/llvm/lib/Transforms/Scalar/GVNSink.cpp +++ b/llvm/lib/Transforms/Scalar/GVNSink.cpp @@ -655,8 +655,7 @@ GVNSink::analyzeInstructionForSinking(LockstepReverseIterator &LRI, return std::nullopt; VNums[N]++; } - unsigned VNumToSink = - std::max_element(VNums.begin(), VNums.end(), llvm::less_second())->first; + unsigned VNumToSink = llvm::max_element(VNums, llvm::less_second())->first; if (VNums[VNumToSink] == 1) // Can't sink anything! diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp index a04987ce6624..221b122caba2 100644 --- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -1488,7 +1488,7 @@ findMostPopularDest(BasicBlock *BB, // Populate DestPopularity with the successors in the order they appear in the // successor list. This way, we ensure determinism by iterating it in the - // same order in std::max_element below. We map nullptr to 0 so that we can + // same order in llvm::max_element below. We map nullptr to 0 so that we can // return nullptr when PredToDestList contains nullptr only. DestPopularity[nullptr] = 0; for (auto *SuccBB : successors(BB)) @@ -1499,8 +1499,7 @@ findMostPopularDest(BasicBlock *BB, DestPopularity[PredToDest.second]++; // Find the most popular dest. - auto MostPopular = std::max_element( - DestPopularity.begin(), DestPopularity.end(), llvm::less_second()); + auto MostPopular = llvm::max_element(DestPopularity, llvm::less_second()); // Okay, we have finally picked the most popular destination. return MostPopular->first; @@ -2553,8 +2552,7 @@ void JumpThreadingPass::updateBlockFreqAndEdgeWeight(BasicBlock *PredBB, BBSuccFreq.push_back(SuccFreq.getFrequency()); } - uint64_t MaxBBSuccFreq = - *std::max_element(BBSuccFreq.begin(), BBSuccFreq.end()); + uint64_t MaxBBSuccFreq = *llvm::max_element(BBSuccFreq); SmallVector BBSuccProbs; if (MaxBBSuccFreq == 0) diff --git a/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp b/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp index 914cf6e21028..edddfb1b9240 100644 --- a/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp +++ b/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp @@ -349,19 +349,20 @@ public: // ld0. LoadInst *LastLoad = - std::max_element(Candidates.begin(), Candidates.end(), - [&](const StoreToLoadForwardingCandidate &A, - const StoreToLoadForwardingCandidate &B) { - return getInstrIndex(A.Load) < getInstrIndex(B.Load); - }) + llvm::max_element(Candidates, + [&](const StoreToLoadForwardingCandidate &A, + const StoreToLoadForwardingCandidate &B) { + return getInstrIndex(A.Load) < + getInstrIndex(B.Load); + }) ->Load; StoreInst *FirstStore = - std::min_element(Candidates.begin(), Candidates.end(), - [&](const StoreToLoadForwardingCandidate &A, - const StoreToLoadForwardingCandidate &B) { - return getInstrIndex(A.Store) < - getInstrIndex(B.Store); - }) + llvm::min_element(Candidates, + [&](const StoreToLoadForwardingCandidate &A, + const StoreToLoadForwardingCandidate &B) { + return getInstrIndex(A.Store) < + getInstrIndex(B.Store); + }) ->Store; // We're looking for stores after the first forwarding store until the end diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index fe65e52110f9..5b9a38c0b74e 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1084,7 +1084,7 @@ static void GetBranchWeights(Instruction *TI, /// Keep halving the weights until all can fit in uint32_t. static void FitWeights(MutableArrayRef Weights) { - uint64_t Max = *std::max_element(Weights.begin(), Weights.end()); + uint64_t Max = *llvm::max_element(Weights); if (Max > UINT_MAX) { unsigned Offset = 32 - llvm::countl_zero(Max); for (uint64_t &I : Weights) diff --git a/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp b/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp index 1f11d4894f77..6ba278794b7f 100644 --- a/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp @@ -892,7 +892,7 @@ bool Vectorizer::vectorizeChain(Chain &C) { // Loads get hoisted to the location of the first load in the chain. We may // also need to hoist the (transitive) operands of the loads. Builder.SetInsertPoint( - std::min_element(C.begin(), C.end(), [](const auto &A, const auto &B) { + llvm::min_element(C, [](const auto &A, const auto &B) { return A.Inst->comesBefore(B.Inst); })->Inst); @@ -944,10 +944,9 @@ bool Vectorizer::vectorizeChain(Chain &C) { reorder(VecInst); } else { // Stores get sunk to the location of the last store in the chain. - Builder.SetInsertPoint( - std::max_element(C.begin(), C.end(), [](auto &A, auto &B) { - return A.Inst->comesBefore(B.Inst); - })->Inst); + Builder.SetInsertPoint(llvm::max_element(C, [](auto &A, auto &B) { + return A.Inst->comesBefore(B.Inst); + })->Inst); // Build the vector to store. Value *Vec = PoisonValue::get(VecTy); diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 36dc9094538a..7b99c3ac8c55 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -10172,11 +10172,10 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry( // No 2 source vectors with the same vector factor - just choose 2 with max // index. if (Entries.empty()) { - Entries.push_back( - *std::max_element(UsedTEs.front().begin(), UsedTEs.front().end(), - [](const TreeEntry *TE1, const TreeEntry *TE2) { - return TE1->Idx < TE2->Idx; - })); + Entries.push_back(*llvm::max_element( + UsedTEs.front(), [](const TreeEntry *TE1, const TreeEntry *TE2) { + return TE1->Idx < TE2->Idx; + })); Entries.push_back(SecondEntries.front()); VF = std::max(Entries.front()->getVectorFactor(), Entries.back()->getVectorFactor()); diff --git a/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp index de61fff64329..684868cf23e8 100644 --- a/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp @@ -52,13 +52,13 @@ static double computeVariance(const SmallVector &Values) { static int64_t findMin(const SmallVector &Values) { if (Values.empty()) return 0; - return *std::min_element(Values.begin(), Values.end()); + return *llvm::min_element(Values); } static int64_t findMax(const SmallVector &Values) { if (Values.empty()) return 0; - return *std::max_element(Values.begin(), Values.end()); + return *llvm::max_element(Values); } static int64_t findMean(const SmallVector &Values) { diff --git a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp index b702113b3961..409a7010b80c 100644 --- a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp +++ b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp @@ -270,9 +270,10 @@ void DependencyGraph::getCriticalSequence( // To obtain the sequence of critical edges, we simply follow the chain of // critical predecessors starting from node N (field // DGNode::CriticalPredecessor). - const auto It = std::max_element( - Nodes.begin(), Nodes.end(), - [](const DGNode &Lhs, const DGNode &Rhs) { return Lhs.Cost < Rhs.Cost; }); + const auto It = + llvm::max_element(Nodes, [](const DGNode &Lhs, const DGNode &Rhs) { + return Lhs.Cost < Rhs.Cost; + }); unsigned IID = std::distance(Nodes.begin(), It); Seq.resize(Nodes[IID].Depth); for (const DependencyEdge *&DE : llvm::reverse(Seq)) { diff --git a/llvm/tools/llvm-mca/Views/SchedulerStatistics.cpp b/llvm/tools/llvm-mca/Views/SchedulerStatistics.cpp index 06caeda344c8..43f8b62864af 100644 --- a/llvm/tools/llvm-mca/Views/SchedulerStatistics.cpp +++ b/llvm/tools/llvm-mca/Views/SchedulerStatistics.cpp @@ -105,8 +105,7 @@ void SchedulerStatistics::printSchedulerStats(raw_ostream &OS) const { OS << "[# issued], [# cycles]\n"; bool HasColors = OS.has_colors(); - const auto It = - std::max_element(IssueWidthPerCycle.begin(), IssueWidthPerCycle.end()); + const auto It = llvm::max_element(IssueWidthPerCycle); for (const std::pair &Entry : IssueWidthPerCycle) { unsigned NumIssued = Entry.first; if (NumIssued == It->first && HasColors) diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp index 5ce663e2efc9..63b173a727ce 100644 --- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp +++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp @@ -1070,8 +1070,7 @@ Error DumpOutputStyle::dumpStringTableFromPdb() { if (IS->name_ids().empty()) P.formatLine("Empty"); else { - auto MaxID = - std::max_element(IS->name_ids().begin(), IS->name_ids().end()); + auto MaxID = llvm::max_element(IS->name_ids(), IS->name_ids()); uint32_t Digits = NumDigits(*MaxID); P.formatLine("{0} | {1}", fmt_align("ID", AlignStyle::Right, Digits), @@ -1836,9 +1835,9 @@ Error DumpOutputStyle::dumpSectionContribs() { class Visitor : public ISectionContribVisitor { public: Visitor(LinePrinter &P, ArrayRef Names) : P(P), Names(Names) { - auto Max = std::max_element( - Names.begin(), Names.end(), - [](StringRef S1, StringRef S2) { return S1.size() < S2.size(); }); + auto Max = llvm::max_element(Names, [](StringRef S1, StringRef S2) { + return S1.size() < S2.size(); + }); MaxNameLen = (Max == Names.end() ? 0 : Max->size()); } void visit(const SectionContrib &SC) override { diff --git a/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp b/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp index a4077820eb03..db3a752d5816 100644 --- a/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp +++ b/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp @@ -308,7 +308,7 @@ Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, if (Indices.empty()) return Error::success(); - auto Max = std::max_element(Indices.begin(), Indices.end()); + auto Max = llvm::max_element(Indices); uint32_t W = NumDigits(Max->getIndex()) + 2; for (auto I : Indices) @@ -323,7 +323,7 @@ Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, if (Indices.empty()) return Error::success(); - auto Max = std::max_element(Indices.begin(), Indices.end()); + auto Max = llvm::max_element(Indices); uint32_t W = NumDigits(Max->getIndex()) + 2; for (auto I : Indices) @@ -493,7 +493,7 @@ Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, if (Indices.empty()) return Error::success(); - auto Max = std::max_element(Indices.begin(), Indices.end()); + auto Max = llvm::max_element(Indices); uint32_t W = NumDigits(Max->getIndex()) + 2; for (auto I : Indices) diff --git a/llvm/tools/llvm-rc/ResourceFileWriter.cpp b/llvm/tools/llvm-rc/ResourceFileWriter.cpp index 9738fd49343a..d507525970ec 100644 --- a/llvm/tools/llvm-rc/ResourceFileWriter.cpp +++ b/llvm/tools/llvm-rc/ResourceFileWriter.cpp @@ -1537,15 +1537,14 @@ Error ResourceFileWriter::writeVersionInfoBody(const RCResource *Base) { }; auto FileVer = GetField(VersionInfoFixed::FtFileVersion); - RETURN_IF_ERROR(checkNumberFits( - *std::max_element(FileVer.begin(), FileVer.end()), "FILEVERSION fields")); + RETURN_IF_ERROR(checkNumberFits(*llvm::max_element(FileVer), + "FILEVERSION fields")); FixedInfo.FileVersionMS = (FileVer[0] << 16) | FileVer[1]; FixedInfo.FileVersionLS = (FileVer[2] << 16) | FileVer[3]; auto ProdVer = GetField(VersionInfoFixed::FtProductVersion); - RETURN_IF_ERROR(checkNumberFits( - *std::max_element(ProdVer.begin(), ProdVer.end()), - "PRODUCTVERSION fields")); + RETURN_IF_ERROR(checkNumberFits(*llvm::max_element(ProdVer), + "PRODUCTVERSION fields")); FixedInfo.ProductVersionMS = (ProdVer[0] << 16) | ProdVer[1]; FixedInfo.ProductVersionLS = (ProdVer[2] << 16) | ProdVer[3]; diff --git a/llvm/utils/FileCheck/FileCheck.cpp b/llvm/utils/FileCheck/FileCheck.cpp index e74a79e1312b..a96251867c08 100644 --- a/llvm/utils/FileCheck/FileCheck.cpp +++ b/llvm/utils/FileCheck/FileCheck.cpp @@ -742,20 +742,15 @@ int main(int argc, char **argv) { // In the latter case, the general rule of thumb is to choose the value that // provides the most information. DumpInputValue DumpInput = - DumpInputs.empty() - ? DumpInputFail - : *std::max_element(DumpInputs.begin(), DumpInputs.end()); + DumpInputs.empty() ? DumpInputFail : *llvm::max_element(DumpInputs); DumpInputFilterValue DumpInputFilter; if (DumpInputFilters.empty()) DumpInputFilter = DumpInput == DumpInputAlways ? DumpInputFilterAll : DumpInputFilterError; else - DumpInputFilter = - *std::max_element(DumpInputFilters.begin(), DumpInputFilters.end()); - unsigned DumpInputContext = DumpInputContexts.empty() - ? 5 - : *std::max_element(DumpInputContexts.begin(), - DumpInputContexts.end()); + DumpInputFilter = *llvm::max_element(DumpInputFilters); + unsigned DumpInputContext = + DumpInputContexts.empty() ? 5 : *llvm::max_element(DumpInputContexts); if (DumpInput == DumpInputHelp) { DumpInputAnnotationHelp(outs()); diff --git a/llvm/utils/TableGen/CodeGenSchedule.cpp b/llvm/utils/TableGen/CodeGenSchedule.cpp index d819016f8b56..0e81623a6aa3 100644 --- a/llvm/utils/TableGen/CodeGenSchedule.cpp +++ b/llvm/utils/TableGen/CodeGenSchedule.cpp @@ -287,7 +287,7 @@ static APInt constructOperandMask(ArrayRef Indices) { if (Indices.empty()) return OperandMask; - int64_t MaxIndex = *std::max_element(Indices.begin(), Indices.end()); + int64_t MaxIndex = *llvm::max_element(Indices); assert(MaxIndex >= 0 && "Invalid negative indices in input!"); OperandMask = OperandMask.zext(MaxIndex + 1); for (const int64_t Index : Indices) { diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp index 8919e07a7547..d074e31c6245 100644 --- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -803,8 +803,8 @@ void RegisterInfoEmitter::emitComposeSubRegIndexLaneMask( OS << " // Sequence " << Idx << "\n"; Idx += Sequence.size() + 1; } - auto *IntType = getMinimalTypeForRange(*std::max_element( - SubReg2SequenceIndexMap.begin(), SubReg2SequenceIndexMap.end())); + auto *IntType = + getMinimalTypeForRange(*llvm::max_element(SubReg2SequenceIndexMap)); OS << " };\n" " static const " << IntType << " CompositeSequences[] = {\n"; diff --git a/mlir/examples/toy/Ch5/mlir/LowerToAffineLoops.cpp b/mlir/examples/toy/Ch5/mlir/LowerToAffineLoops.cpp index ae4bd980c34b..bded61542188 100644 --- a/mlir/examples/toy/Ch5/mlir/LowerToAffineLoops.cpp +++ b/mlir/examples/toy/Ch5/mlir/LowerToAffineLoops.cpp @@ -173,8 +173,7 @@ struct ConstantOpLowering : public OpRewritePattern { SmallVector constantIndices; if (!valueShape.empty()) { - for (auto i : llvm::seq( - 0, *std::max_element(valueShape.begin(), valueShape.end()))) + for (auto i : llvm::seq(0, *llvm::max_element(valueShape))) constantIndices.push_back( rewriter.create(loc, i)); } else { diff --git a/mlir/examples/toy/Ch6/mlir/LowerToAffineLoops.cpp b/mlir/examples/toy/Ch6/mlir/LowerToAffineLoops.cpp index ae4bd980c34b..bded61542188 100644 --- a/mlir/examples/toy/Ch6/mlir/LowerToAffineLoops.cpp +++ b/mlir/examples/toy/Ch6/mlir/LowerToAffineLoops.cpp @@ -173,8 +173,7 @@ struct ConstantOpLowering : public OpRewritePattern { SmallVector constantIndices; if (!valueShape.empty()) { - for (auto i : llvm::seq( - 0, *std::max_element(valueShape.begin(), valueShape.end()))) + for (auto i : llvm::seq(0, *llvm::max_element(valueShape))) constantIndices.push_back( rewriter.create(loc, i)); } else { diff --git a/mlir/examples/toy/Ch7/mlir/LowerToAffineLoops.cpp b/mlir/examples/toy/Ch7/mlir/LowerToAffineLoops.cpp index ae4bd980c34b..bded61542188 100644 --- a/mlir/examples/toy/Ch7/mlir/LowerToAffineLoops.cpp +++ b/mlir/examples/toy/Ch7/mlir/LowerToAffineLoops.cpp @@ -173,8 +173,7 @@ struct ConstantOpLowering : public OpRewritePattern { SmallVector constantIndices; if (!valueShape.empty()) { - for (auto i : llvm::seq( - 0, *std::max_element(valueShape.begin(), valueShape.end()))) + for (auto i : llvm::seq(0, *llvm::max_element(valueShape))) constantIndices.push_back( rewriter.create(loc, i)); } else { diff --git a/mlir/lib/Conversion/PDLToPDLInterp/PredicateTree.cpp b/mlir/lib/Conversion/PDLToPDLInterp/PredicateTree.cpp index 419ea8639197..fe27a2229491 100644 --- a/mlir/lib/Conversion/PDLToPDLInterp/PredicateTree.cpp +++ b/mlir/lib/Conversion/PDLToPDLInterp/PredicateTree.cpp @@ -272,8 +272,7 @@ static void getConstraintPredicates(pdl::ApplyNativeConstraintOp op, allPositions.push_back(inputs.lookup(arg)); // Push the constraint to the furthest position. - Position *pos = *std::max_element(allPositions.begin(), allPositions.end(), - comparePosDepth); + Position *pos = *llvm::max_element(allPositions, comparePosDepth); ResultRange results = op.getResults(); PredicateBuilder::Predicate pred = builder.getConstraint( op.getName(), allPositions, SmallVector(results.getTypes()), diff --git a/mlir/lib/Dialect/Affine/IR/AffineOps.cpp b/mlir/lib/Dialect/Affine/IR/AffineOps.cpp index a4df863ab083..8a070d256398 100644 --- a/mlir/lib/Dialect/Affine/IR/AffineOps.cpp +++ b/mlir/lib/Dialect/Affine/IR/AffineOps.cpp @@ -3269,8 +3269,8 @@ static OpFoldResult foldMinMaxOp(T op, ArrayRef operands) { // Otherwise, completely fold the op into a constant. auto resultIt = std::is_same::value - ? std::min_element(results.begin(), results.end()) - : std::max_element(results.begin(), results.end()); + ? llvm::min_element(results) + : llvm::max_element(results); if (resultIt == results.end()) return {}; return IntegerAttr::get(IndexType::get(op.getContext()), *resultIt); diff --git a/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp b/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp index 3794ef2dabe1..af59973d7a92 100644 --- a/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp +++ b/mlir/lib/Dialect/Affine/Utils/LoopUtils.cpp @@ -261,7 +261,7 @@ LogicalResult mlir::affine::affineForOpBodySkew(AffineForOp forOp, unsigned numChildOps = shifts.size(); // Do a linear time (counting) sort for the shifts. - uint64_t maxShift = *std::max_element(shifts.begin(), shifts.end()); + uint64_t maxShift = *llvm::max_element(shifts); if (maxShift >= numChildOps) { // Large shifts are not the typical use case. forOp.emitWarning("not shifting because shifts are unrealistically large"); diff --git a/mlir/lib/Dialect/GPU/TransformOps/GPUTransformOps.cpp b/mlir/lib/Dialect/GPU/TransformOps/GPUTransformOps.cpp index 07da222055d4..ada985b5979e 100644 --- a/mlir/lib/Dialect/GPU/TransformOps/GPUTransformOps.cpp +++ b/mlir/lib/Dialect/GPU/TransformOps/GPUTransformOps.cpp @@ -442,9 +442,8 @@ static DiagnosedSilenceableFailure rewriteOneForallCommonImpl( // Step 1.b. In the linear case, compute the max mapping to avoid needlessly // mapping all dimensions. In the 3-D mapping case we need to map all // dimensions. - DeviceMappingAttrInterface maxMapping = - cast(*std::max_element( - forallMappingAttrs.begin(), forallMappingAttrs.end(), comparator)); + DeviceMappingAttrInterface maxMapping = cast( + *llvm::max_element(forallMappingAttrs, comparator)); DeviceMappingAttrInterface maxLinearMapping; if (maxMapping.isLinearMapping()) maxLinearMapping = maxMapping; diff --git a/mlir/lib/Dialect/Linalg/Transforms/ConvertToDestinationStyle.cpp b/mlir/lib/Dialect/Linalg/Transforms/ConvertToDestinationStyle.cpp index ff13aaf9b4ab..b95677b7457e 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/ConvertToDestinationStyle.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/ConvertToDestinationStyle.cpp @@ -361,7 +361,7 @@ FailureOr mlir::linalg::rewriteInDestinationPassingStyle( } // Create constants for the range of possible indices [0, max{shape_i}). - auto maxDim = *std::max_element(shape.begin(), shape.end()); + auto maxDim = *llvm::max_element(shape); SmallVector constants; constants.reserve(maxDim); for (int i = 0; i < maxDim; ++i) diff --git a/mlir/lib/Dialect/SPIRV/Transforms/UnifyAliasedResourcePass.cpp b/mlir/lib/Dialect/SPIRV/Transforms/UnifyAliasedResourcePass.cpp index 49382856a64c..07cf26926a1d 100644 --- a/mlir/lib/Dialect/SPIRV/Transforms/UnifyAliasedResourcePass.cpp +++ b/mlir/lib/Dialect/SPIRV/Transforms/UnifyAliasedResourcePass.cpp @@ -119,7 +119,7 @@ deduceCanonicalResource(ArrayRef types) { // Choose the *vector* with the smallest bitwidth as the canonical resource, // so that we can still keep vectorized load/store and avoid partial updates // to large vectors. - auto *minVal = std::min_element(vectorNumBits.begin(), vectorNumBits.end()); + auto *minVal = llvm::min_element(vectorNumBits); // Make sure that the canonical resource's bitwidth is divisible by others. // With out this, we cannot properly adjust the index later. if (llvm::any_of(vectorNumBits, @@ -139,7 +139,7 @@ deduceCanonicalResource(ArrayRef types) { // All element types are scalars. Then choose the smallest bitwidth as the // cannonical resource to avoid subcomponent load/store. - auto *minVal = std::min_element(scalarNumBits.begin(), scalarNumBits.end()); + auto *minVal = llvm::min_element(scalarNumBits); if (llvm::any_of(scalarNumBits, [minVal](int64_t bit) { return bit % *minVal != 0; })) return std::nullopt; diff --git a/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp index 957f6314f358..58ea4cc4da3c 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp +++ b/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp @@ -508,7 +508,7 @@ struct FromElementsOpInterface } // Create constants for the range of possible indices [0, max{shape_i}). - auto maxDim = *std::max_element(shape.begin(), shape.end()); + auto maxDim = *llvm::max_element(shape); SmallVector constants; constants.reserve(maxDim); for (int i = 0; i < maxDim; ++i) diff --git a/mlir/lib/IR/AffineMap.cpp b/mlir/lib/IR/AffineMap.cpp index 4aa0d4f34a09..00a0f05b6333 100644 --- a/mlir/lib/IR/AffineMap.cpp +++ b/mlir/lib/IR/AffineMap.cpp @@ -249,7 +249,7 @@ AffineMap AffineMap::getPermutationMap(ArrayRef permutation, MLIRContext *context) { assert(!permutation.empty() && "Cannot create permutation map from empty permutation vector"); - const auto *m = std::max_element(permutation.begin(), permutation.end()); + const auto *m = llvm::max_element(permutation); auto permutationMap = getMultiDimMapWithTargets(*m + 1, permutation, context); assert(permutationMap.isPermutation() && "Invalid permutation vector"); return permutationMap; diff --git a/mlir/lib/Reducer/ReductionNode.cpp b/mlir/lib/Reducer/ReductionNode.cpp index b4596419ed17..d57ee932bfca 100644 --- a/mlir/lib/Reducer/ReductionNode.cpp +++ b/mlir/lib/Reducer/ReductionNode.cpp @@ -74,8 +74,8 @@ ArrayRef ReductionNode::generateNewVariants() { // the above example, we split the range {4, 9} into {4, 6}, {6, 9}, and // create two variants with range {{1, 3}, {4, 6}} and {{1, 3}, {6, 9}}. The // final ranges vector will be {{1, 3}, {4, 6}, {6, 9}}. - auto maxElement = std::max_element( - ranges.begin(), ranges.end(), [](const Range &lhs, const Range &rhs) { + auto maxElement = + llvm::max_element(ranges, [](const Range &lhs, const Range &rhs) { return (lhs.second - lhs.first) > (rhs.second - rhs.first); }); -- GitLab From 7dfa8398354e435cdee5a8ea6d6b17d1e4557733 Mon Sep 17 00:00:00 2001 From: Amirreza Ashouri Date: Mon, 11 Mar 2024 06:53:23 +0330 Subject: [PATCH 063/953] [clang] Fix behavior of `__is_trivially_relocatable(volatile int)` (#77092) Consistent with `__is_trivially_copyable(volatile int) == true` and `__is_trivially_relocatable(volatile Trivial) == true`, `__is_trivially_relocatable(volatile int)` should also be `true`. Fixes https://github.com/llvm/llvm-project/issues/77091 [clang] [test] New tests for __is_trivially_relocatable(cv-qualified type) --- clang/docs/ReleaseNotes.rst | 3 + clang/lib/AST/Type.cpp | 2 + clang/test/SemaCXX/type-traits.cpp | 181 +++++++++++++++++------------ 3 files changed, 111 insertions(+), 75 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 3b89d5a87207..bce27dc8c4a9 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -251,6 +251,9 @@ Bug Fixes in This Version for logical operators in C23. Fixes (#GH64356). +- ``__is_trivially_relocatable`` no longer returns ``false`` for volatile-qualified types. + Fixes (#GH77091). + - Clang no longer produces a false-positive `-Wunused-variable` warning for variables created through copy initialization having side-effects in C++17 and later. Fixes (#GH64356) (#GH79518). diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 78dcd3f4007a..22666184c56c 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2682,6 +2682,8 @@ bool QualType::isTriviallyRelocatableType(const ASTContext &Context) const { return false; } else if (const auto *RD = BaseElementType->getAsRecordDecl()) { return RD->canPassInRegisters(); + } else if (BaseElementType.isTriviallyCopyableType(Context)) { + return true; } else { switch (isNonTrivialToPrimitiveDestructiveMove()) { case PCK_Trivial: diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp index f50f51cc7098..14ec17989ec7 100644 --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -1722,91 +1722,91 @@ struct StructWithAnonUnion3 { void is_layout_compatible(int n) { - static_assert(__is_layout_compatible(void, void), ""); - static_assert(!__is_layout_compatible(void, int), ""); - static_assert(__is_layout_compatible(void, const void), ""); - static_assert(__is_layout_compatible(void, volatile void), ""); - static_assert(__is_layout_compatible(const int, volatile int), ""); - static_assert(__is_layout_compatible(int, int), ""); - static_assert(__is_layout_compatible(int, const int), ""); - static_assert(__is_layout_compatible(int, volatile int), ""); - static_assert(__is_layout_compatible(const int, volatile int), ""); - static_assert(__is_layout_compatible(int *, int * __restrict), ""); + static_assert(__is_layout_compatible(void, void)); + static_assert(!__is_layout_compatible(void, int)); + static_assert(__is_layout_compatible(void, const void)); + static_assert(__is_layout_compatible(void, volatile void)); + static_assert(__is_layout_compatible(const int, volatile int)); + static_assert(__is_layout_compatible(int, int)); + static_assert(__is_layout_compatible(int, const int)); + static_assert(__is_layout_compatible(int, volatile int)); + static_assert(__is_layout_compatible(const int, volatile int)); + static_assert(__is_layout_compatible(int *, int * __restrict)); // Note: atomic qualification matters for layout compatibility. - static_assert(!__is_layout_compatible(int, _Atomic int), ""); - static_assert(__is_layout_compatible(_Atomic(int), _Atomic int), ""); - static_assert(!__is_layout_compatible(int, unsigned int), ""); - static_assert(!__is_layout_compatible(char, unsigned char), ""); - static_assert(!__is_layout_compatible(char, signed char), ""); - static_assert(!__is_layout_compatible(unsigned char, signed char), ""); - static_assert(__is_layout_compatible(int[], int[]), ""); - static_assert(__is_layout_compatible(int[2], int[2]), ""); - static_assert(!__is_layout_compatible(int[n], int[2]), ""); // FIXME: VLAs should be rejected - static_assert(!__is_layout_compatible(int[n], int[n]), ""); // FIXME: VLAs should be rejected - static_assert(__is_layout_compatible(int&, int&), ""); - static_assert(!__is_layout_compatible(int&, char&), ""); - static_assert(__is_layout_compatible(void(int), void(int)), ""); - static_assert(!__is_layout_compatible(void(int), void(char)), ""); - static_assert(__is_layout_compatible(void(&)(int), void(&)(int)), ""); - static_assert(!__is_layout_compatible(void(&)(int), void(&)(char)), ""); - static_assert(__is_layout_compatible(void(*)(int), void(*)(int)), ""); - static_assert(!__is_layout_compatible(void(*)(int), void(*)(char)), ""); + static_assert(!__is_layout_compatible(int, _Atomic int)); + static_assert(__is_layout_compatible(_Atomic(int), _Atomic int)); + static_assert(!__is_layout_compatible(int, unsigned int)); + static_assert(!__is_layout_compatible(char, unsigned char)); + static_assert(!__is_layout_compatible(char, signed char)); + static_assert(!__is_layout_compatible(unsigned char, signed char)); + static_assert(__is_layout_compatible(int[], int[])); + static_assert(__is_layout_compatible(int[2], int[2])); + static_assert(!__is_layout_compatible(int[n], int[2])); // FIXME: VLAs should be rejected + static_assert(!__is_layout_compatible(int[n], int[n])); // FIXME: VLAs should be rejected + static_assert(__is_layout_compatible(int&, int&)); + static_assert(!__is_layout_compatible(int&, char&)); + static_assert(__is_layout_compatible(void(int), void(int))); + static_assert(!__is_layout_compatible(void(int), void(char))); + static_assert(__is_layout_compatible(void(&)(int), void(&)(int))); + static_assert(!__is_layout_compatible(void(&)(int), void(&)(char))); + static_assert(__is_layout_compatible(void(*)(int), void(*)(int))); + static_assert(!__is_layout_compatible(void(*)(int), void(*)(char))); using function_type = void(); using function_type2 = void(char); - static_assert(__is_layout_compatible(const function_type, const function_type), ""); + static_assert(__is_layout_compatible(const function_type, const function_type)); // expected-warning@-1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}} // expected-warning@-2 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}} - static_assert(__is_layout_compatible(function_type, const function_type), ""); + static_assert(__is_layout_compatible(function_type, const function_type)); // expected-warning@-1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}} - static_assert(!__is_layout_compatible(const function_type, const function_type2), ""); + static_assert(!__is_layout_compatible(const function_type, const function_type2)); // expected-warning@-1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}} // expected-warning@-2 {{'const' qualifier on function type 'function_type2' (aka 'void (char)') has no effect}} - static_assert(__is_layout_compatible(CStruct, CStruct2), ""); - static_assert(__is_layout_compatible(CStruct, const CStruct2), ""); - static_assert(__is_layout_compatible(CStruct, volatile CStruct2), ""); - static_assert(__is_layout_compatible(const CStruct, volatile CStruct2), ""); - static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2), ""); - static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2), ""); - static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2), ""); - static_assert(!__is_layout_compatible(CppStructNonStandardByBase, CppStructNonStandardByBase2), ""); - static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, CppStructNonStandardByVirt2), ""); - static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, CppStructNonStandardByMemb2), ""); - static_assert(!__is_layout_compatible(CppStructNonStandardByProt, CppStructNonStandardByProt2), ""); - static_assert(!__is_layout_compatible(CppStructNonStandardByVirtBase, CppStructNonStandardByVirtBase2), ""); - static_assert(!__is_layout_compatible(CppStructNonStandardBySameBase, CppStructNonStandardBySameBase2), ""); - static_assert(!__is_layout_compatible(CppStructNonStandardBy2ndVirtBase, CppStructNonStandardBy2ndVirtBase2), ""); - static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers), ""); - static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) != bool(__has_cpp_attribute(no_unique_address)), ""); - static_assert(__is_layout_compatible(CStructNoUniqueAddress, CStructNoUniqueAddress2) != bool(__has_cpp_attribute(no_unique_address)), ""); - static_assert(__is_layout_compatible(CStruct, CStructAlignment), ""); - static_assert(!__is_layout_compatible(CStruct, CStructAlignedMembers), ""); - static_assert(__is_layout_compatible(UnionNoOveralignedMembers, UnionWithOveralignedMembers), ""); - static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds), ""); - static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds2), ""); - static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds3), ""); - static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds4), ""); - static_assert(__is_layout_compatible(int CStruct2::*, int CStruct2::*), ""); - static_assert(!__is_layout_compatible(int CStruct2::*, char CStruct2::*), ""); - static_assert(__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(int)), ""); - static_assert(!__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(char)), ""); - static_assert(__is_layout_compatible(CStructNested, CStructNested2), ""); - static_assert(__is_layout_compatible(UnionLayout, UnionLayout), ""); - static_assert(!__is_layout_compatible(UnionLayout, UnionLayout2), ""); - static_assert(!__is_layout_compatible(UnionLayout, UnionLayout3), ""); - static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion2), ""); - static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3), ""); - static_assert(__is_layout_compatible(EnumLayout, EnumClassLayout), ""); - static_assert(__is_layout_compatible(EnumForward, EnumForward), ""); - static_assert(__is_layout_compatible(EnumForward, EnumClassForward), ""); + static_assert(__is_layout_compatible(CStruct, CStruct2)); + static_assert(__is_layout_compatible(CStruct, const CStruct2)); + static_assert(__is_layout_compatible(CStruct, volatile CStruct2)); + static_assert(__is_layout_compatible(const CStruct, volatile CStruct2)); + static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2)); + static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2)); + static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2)); + static_assert(!__is_layout_compatible(CppStructNonStandardByBase, CppStructNonStandardByBase2)); + static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, CppStructNonStandardByVirt2)); + static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, CppStructNonStandardByMemb2)); + static_assert(!__is_layout_compatible(CppStructNonStandardByProt, CppStructNonStandardByProt2)); + static_assert(!__is_layout_compatible(CppStructNonStandardByVirtBase, CppStructNonStandardByVirtBase2)); + static_assert(!__is_layout_compatible(CppStructNonStandardBySameBase, CppStructNonStandardBySameBase2)); + static_assert(!__is_layout_compatible(CppStructNonStandardBy2ndVirtBase, CppStructNonStandardBy2ndVirtBase2)); + static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers)); + static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) != bool(__has_cpp_attribute(no_unique_address))); + static_assert(__is_layout_compatible(CStructNoUniqueAddress, CStructNoUniqueAddress2) != bool(__has_cpp_attribute(no_unique_address))); + static_assert(__is_layout_compatible(CStruct, CStructAlignment)); + static_assert(!__is_layout_compatible(CStruct, CStructAlignedMembers)); + static_assert(__is_layout_compatible(UnionNoOveralignedMembers, UnionWithOveralignedMembers)); + static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds)); + static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds2)); + static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds3)); + static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds4)); + static_assert(__is_layout_compatible(int CStruct2::*, int CStruct2::*)); + static_assert(!__is_layout_compatible(int CStruct2::*, char CStruct2::*)); + static_assert(__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(int))); + static_assert(!__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(char))); + static_assert(__is_layout_compatible(CStructNested, CStructNested2)); + static_assert(__is_layout_compatible(UnionLayout, UnionLayout)); + static_assert(!__is_layout_compatible(UnionLayout, UnionLayout2)); + static_assert(!__is_layout_compatible(UnionLayout, UnionLayout3)); + static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion2)); + static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3)); + static_assert(__is_layout_compatible(EnumLayout, EnumClassLayout)); + static_assert(__is_layout_compatible(EnumForward, EnumForward)); + static_assert(__is_layout_compatible(EnumForward, EnumClassForward)); // Layout compatibility for enums might be relaxed in the future. See https://github.com/cplusplus/CWG/issues/39#issuecomment-1184791364 - static_assert(!__is_layout_compatible(EnumLayout, int), ""); - static_assert(!__is_layout_compatible(EnumClassLayout, int), ""); - static_assert(!__is_layout_compatible(EnumForward, int), ""); - static_assert(!__is_layout_compatible(EnumClassForward, int), ""); + static_assert(!__is_layout_compatible(EnumLayout, int)); + static_assert(!__is_layout_compatible(EnumClassLayout, int)); + static_assert(!__is_layout_compatible(EnumForward, int)); + static_assert(!__is_layout_compatible(EnumClassForward, int)); // FIXME: the following should be rejected (array of unknown bound and void are the only allowed incomplete types) - static_assert(__is_layout_compatible(CStructIncomplete, CStructIncomplete), ""); - static_assert(!__is_layout_compatible(CStruct, CStructIncomplete), ""); - static_assert(__is_layout_compatible(CStructIncomplete[2], CStructIncomplete[2]), ""); + static_assert(__is_layout_compatible(CStructIncomplete, CStructIncomplete)); + static_assert(!__is_layout_compatible(CStruct, CStructIncomplete)); + static_assert(__is_layout_compatible(CStructIncomplete[2], CStructIncomplete[2])); } void is_signed() @@ -3340,6 +3340,8 @@ namespace is_trivially_relocatable { static_assert(!__is_trivially_relocatable(void)); static_assert(__is_trivially_relocatable(int)); static_assert(__is_trivially_relocatable(int[])); +static_assert(__is_trivially_relocatable(const int)); +static_assert(__is_trivially_relocatable(volatile int)); enum Enum {}; static_assert(__is_trivially_relocatable(Enum)); @@ -3351,7 +3353,28 @@ static_assert(__is_trivially_relocatable(Union[])); struct Trivial {}; static_assert(__is_trivially_relocatable(Trivial)); +static_assert(__is_trivially_relocatable(const Trivial)); +static_assert(__is_trivially_relocatable(volatile Trivial)); + static_assert(__is_trivially_relocatable(Trivial[])); +static_assert(__is_trivially_relocatable(const Trivial[])); +static_assert(__is_trivially_relocatable(volatile Trivial[])); + +static_assert(__is_trivially_relocatable(int[10])); +static_assert(__is_trivially_relocatable(const int[10])); +static_assert(__is_trivially_relocatable(volatile int[10])); + +static_assert(__is_trivially_relocatable(int[10][10])); +static_assert(__is_trivially_relocatable(const int[10][10])); +static_assert(__is_trivially_relocatable(volatile int[10][10])); + +static_assert(__is_trivially_relocatable(int[])); +static_assert(__is_trivially_relocatable(const int[])); +static_assert(__is_trivially_relocatable(volatile int[])); + +static_assert(__is_trivially_relocatable(int[][10])); +static_assert(__is_trivially_relocatable(const int[][10])); +static_assert(__is_trivially_relocatable(volatile int[][10])); struct Incomplete; // expected-note {{forward declaration of 'is_trivially_relocatable::Incomplete'}} bool unused = __is_trivially_relocatable(Incomplete); // expected-error {{incomplete type}} @@ -3361,6 +3384,8 @@ struct NontrivialDtor { }; static_assert(!__is_trivially_relocatable(NontrivialDtor)); static_assert(!__is_trivially_relocatable(NontrivialDtor[])); +static_assert(!__is_trivially_relocatable(const NontrivialDtor)); +static_assert(!__is_trivially_relocatable(volatile NontrivialDtor)); struct NontrivialCopyCtor { NontrivialCopyCtor(const NontrivialCopyCtor&) {} @@ -3379,12 +3404,16 @@ struct [[clang::trivial_abi]] TrivialAbiNontrivialDtor { }; static_assert(__is_trivially_relocatable(TrivialAbiNontrivialDtor)); static_assert(__is_trivially_relocatable(TrivialAbiNontrivialDtor[])); +static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialDtor)); +static_assert(__is_trivially_relocatable(volatile TrivialAbiNontrivialDtor)); struct [[clang::trivial_abi]] TrivialAbiNontrivialCopyCtor { TrivialAbiNontrivialCopyCtor(const TrivialAbiNontrivialCopyCtor&) {} }; static_assert(__is_trivially_relocatable(TrivialAbiNontrivialCopyCtor)); static_assert(__is_trivially_relocatable(TrivialAbiNontrivialCopyCtor[])); +static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialCopyCtor)); +static_assert(__is_trivially_relocatable(volatile TrivialAbiNontrivialCopyCtor)); // A more complete set of tests for the behavior of trivial_abi can be found in // clang/test/SemaCXX/attr-trivial-abi.cpp @@ -3393,6 +3422,8 @@ struct [[clang::trivial_abi]] TrivialAbiNontrivialMoveCtor { }; static_assert(__is_trivially_relocatable(TrivialAbiNontrivialMoveCtor)); static_assert(__is_trivially_relocatable(TrivialAbiNontrivialMoveCtor[])); +static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialMoveCtor)); +static_assert(__is_trivially_relocatable(volatile TrivialAbiNontrivialMoveCtor)); } // namespace is_trivially_relocatable -- GitLab From 099be86433a69f264aeb70e512ba1bbd0c7aefd7 Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Sun, 10 Mar 2024 20:31:22 -0700 Subject: [PATCH 064/953] Fix broken build after https://github.com/llvm/llvm-project/pull/84678 (sorry). --- llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp index 63b173a727ce..1cecbfc463fe 100644 --- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp +++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp @@ -1070,7 +1070,7 @@ Error DumpOutputStyle::dumpStringTableFromPdb() { if (IS->name_ids().empty()) P.formatLine("Empty"); else { - auto MaxID = llvm::max_element(IS->name_ids(), IS->name_ids()); + auto MaxID = llvm::max_element(IS->name_ids()); uint32_t Digits = NumDigits(*MaxID); P.formatLine("{0} | {1}", fmt_align("ID", AlignStyle::Right, Digits), -- GitLab From 3f6bc1adf805681293c2ef0b93b708ff52244c00 Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Mon, 11 Mar 2024 11:14:40 +0800 Subject: [PATCH 065/953] [C++20] [Moduls] Avoid computing odr hash for functions from comparing constraint expression Previously we disabled to compute ODR hash for declarations from the global module fragment. However, we missed the case that the functions lives in the concept requiments (see the attached the test files for example). And the mismatch causes the potential crashment. Due to we will set the function body as lazy after we deserialize it and we will only take its body when needed. However, we don't allow to take the body during deserializing. So it is actually potentially problematic if we set the body as lazy first and computing the hash value of the function, which requires to deserialize its body. So we will meet a crash here. This patch tries to solve the issue by not taking the body of the function from GMF. Note that we can't skip comparing the constraint expression from the GMF directly since it is an key part of the function selecting and it may be the reason why we can't return 0 directly for `FunctionDecl::getODRHash()` from the GMF. --- clang/include/clang/AST/DeclBase.h | 10 +++ clang/include/clang/Serialization/ASTReader.h | 7 -- clang/lib/AST/Decl.cpp | 2 +- clang/lib/AST/DeclBase.cpp | 5 ++ clang/lib/Serialization/ASTReader.cpp | 2 +- clang/lib/Serialization/ASTReaderDecl.cpp | 8 +-- clang/lib/Serialization/ASTWriter.cpp | 2 +- clang/lib/Serialization/ASTWriterDecl.cpp | 8 +-- .../hashing-decls-in-exprs-from-gmf.cppm | 67 +++++++++++++++++++ 9 files changed, 93 insertions(+), 18 deletions(-) create mode 100644 clang/test/Modules/hashing-decls-in-exprs-from-gmf.cppm diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 76810a86a78a..47ed6d0d1db0 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -673,6 +673,16 @@ public: /// fragment. See [module.global.frag]p3,4 for details. bool isDiscardedInGlobalModuleFragment() const { return false; } + /// Check if we should skip checking ODRHash for declaration \param D. + /// + /// The existing ODRHash mechanism seems to be not stable enough and + /// the false positive ODR violation reports are annoying and we rarely see + /// true ODR violation reports. Also we learned that MSVC disabled ODR checks + /// for declarations in GMF. So we try to disable ODR checks in the GMF to + /// get better user experiences before we make the ODR violation checks stable + /// enough. + bool shouldSkipCheckingODR() const; + /// Return true if this declaration has an attribute which acts as /// definition of the entity, such as 'alias' or 'ifunc'. bool hasDefiningAttr() const; diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 2002bf23c959..370d8037a4da 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -2456,13 +2456,6 @@ private: uint32_t Value; uint32_t CurrentBitsIndex = ~0; }; - -inline bool shouldSkipCheckingODR(const Decl *D) { - return D->getOwningModule() && - D->getASTContext().getLangOpts().SkipODRCheckInGMF && - D->getOwningModule()->isExplicitGlobalModule(); -} - } // namespace clang #endif // LLVM_CLANG_SERIALIZATION_ASTREADER_H diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index d681791d3920..8626f04012f7 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4496,7 +4496,7 @@ unsigned FunctionDecl::getODRHash() { } class ODRHash Hash; - Hash.AddFunctionDecl(this); + Hash.AddFunctionDecl(this, /*SkipBody=*/shouldSkipCheckingODR()); setHasODRHash(true); ODRHash = Hash.CalculateHash(); return ODRHash; diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index fcedb3cfd176..04bbc49ab2f3 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -1102,6 +1102,11 @@ bool Decl::isInAnotherModuleUnit() const { return M != getASTContext().getCurrentNamedModule(); } +bool Decl::shouldSkipCheckingODR() const { + return getASTContext().getLangOpts().SkipODRCheckInGMF && getOwningModule() && + getOwningModule()->isExplicitGlobalModule(); +} + static Decl::Kind getKind(const Decl *D) { return D->getKind(); } static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 683a076e6bc3..ede9f6e93469 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -9762,7 +9762,7 @@ void ASTReader::finishPendingActions() { !NonConstDefn->isLateTemplateParsed() && // We only perform ODR checks for decls not in the explicit // global module fragment. - !shouldSkipCheckingODR(FD) && + !FD->shouldSkipCheckingODR() && FD->getODRHash() != NonConstDefn->getODRHash()) { if (!isa(FD)) { PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index d5309e3fc31f..a22f760408c6 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -832,7 +832,7 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { Reader.mergeDefinitionVisibility(OldDef, ED); // We don't want to check the ODR hash value for declarations from global // module fragment. - if (!shouldSkipCheckingODR(ED) && + if (!ED->shouldSkipCheckingODR() && OldDef->getODRHash() != ED->getODRHash()) Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED); } else { @@ -874,7 +874,7 @@ void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); // We should only reach here if we're in C/Objective-C. There is no // global module fragment. - assert(!shouldSkipCheckingODR(RD)); + assert(!RD->shouldSkipCheckingODR()); RD->setODRHash(Record.readInt()); // Maintain the invariant of a redeclaration chain containing only @@ -2152,7 +2152,7 @@ void ASTDeclReader::MergeDefinitionData( } // We don't want to check ODR for decls in the global module fragment. - if (shouldSkipCheckingODR(MergeDD.Definition)) + if (MergeDD.Definition->shouldSkipCheckingODR()) return; if (D->getODRHash() != MergeDD.ODRHash) { @@ -3526,7 +3526,7 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { // same template specialization into the same CXXRecordDecl. auto MergedDCIt = Reader.MergedDeclContexts.find(D->getLexicalDeclContext()); if (MergedDCIt != Reader.MergedDeclContexts.end() && - !shouldSkipCheckingODR(D) && MergedDCIt->second == D->getDeclContext()) + !D->shouldSkipCheckingODR() && MergedDCIt->second == D->getDeclContext()) Reader.PendingOdrMergeChecks.push_back(D); return FindExistingResult(Reader, D, /*Existing=*/nullptr, diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 6904c924c2fd..3653d94c6e07 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -6060,7 +6060,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { BitsPacker DefinitionBits; - bool ShouldSkipCheckingODR = shouldSkipCheckingODR(D); + bool ShouldSkipCheckingODR = D->shouldSkipCheckingODR(); DefinitionBits.addBit(ShouldSkipCheckingODR); #define FIELD(Name, Width, Merge) \ diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index e1862de4a35b..d04e1c781b4e 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -519,7 +519,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { BitsPacker EnumDeclBits; EnumDeclBits.addBits(D->getNumPositiveBits(), /*BitWidth=*/8); EnumDeclBits.addBits(D->getNumNegativeBits(), /*BitWidth=*/8); - bool ShouldSkipCheckingODR = shouldSkipCheckingODR(D); + bool ShouldSkipCheckingODR = D->shouldSkipCheckingODR(); EnumDeclBits.addBit(ShouldSkipCheckingODR); EnumDeclBits.addBit(D->isScoped()); EnumDeclBits.addBit(D->isScopedUsingClassTag()); @@ -545,7 +545,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { !D->isTopLevelDeclInObjCContainer() && !CXXRecordDecl::classofKind(D->getKind()) && !D->getIntegerTypeSourceInfo() && !D->getMemberSpecializationInfo() && - !needsAnonymousDeclarationNumber(D) && !shouldSkipCheckingODR(D) && + !needsAnonymousDeclarationNumber(D) && !D->shouldSkipCheckingODR() && D->getDeclName().getNameKind() == DeclarationName::Identifier) AbbrevToUse = Writer.getDeclEnumAbbrev(); @@ -711,7 +711,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { // FIXME: stable encoding FunctionDeclBits.addBits(llvm::to_underlying(D->getLinkageInternal()), 3); FunctionDeclBits.addBits((uint32_t)D->getStorageClass(), /*BitWidth=*/3); - bool ShouldSkipCheckingODR = shouldSkipCheckingODR(D); + bool ShouldSkipCheckingODR = D->shouldSkipCheckingODR(); FunctionDeclBits.addBit(ShouldSkipCheckingODR); FunctionDeclBits.addBit(D->isInlineSpecified()); FunctionDeclBits.addBit(D->isInlined()); @@ -1545,7 +1545,7 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && !D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() && D->getDeclName().getNameKind() == DeclarationName::Identifier && - !shouldSkipCheckingODR(D) && !D->hasExtInfo() && + !D->shouldSkipCheckingODR() && !D->hasExtInfo() && !D->isExplicitlyDefaulted()) { if (D->getTemplatedKind() == FunctionDecl::TK_NonTemplate || D->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate || diff --git a/clang/test/Modules/hashing-decls-in-exprs-from-gmf.cppm b/clang/test/Modules/hashing-decls-in-exprs-from-gmf.cppm new file mode 100644 index 000000000000..8db53c0ace87 --- /dev/null +++ b/clang/test/Modules/hashing-decls-in-exprs-from-gmf.cppm @@ -0,0 +1,67 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/A.cppm -emit-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/B.cppm -emit-module-interface -o %t/B.pcm +// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/test.cpp -fprebuilt-module-path=%t -fsyntax-only -verify + +//--- header.h +#pragma once +template +class Optional {}; + +template +concept C = requires(const _Tp& __t) { + [](const Optional<_Up>&) {}(__t); +}; + +//--- func.h +#include "header.h" +template +void func() {} + +//--- duplicated_func.h +#include "header.h" +template +void duplicated_func() {} + +//--- test_func.h +#include "func.h" + +void test_func() { + func>(); +} + +//--- test_duplicated_func.h +#include "duplicated_func.h" + +void test_duplicated_func() { + duplicated_func>(); +} + +//--- A.cppm +module; +#include "header.h" +#include "test_duplicated_func.h" +export module A; +export using ::test_duplicated_func; + +//--- B.cppm +module; +#include "header.h" +#include "test_func.h" +#include "test_duplicated_func.h" +export module B; +export using ::test_func; +export using ::test_duplicated_func; + +//--- test.cpp +// expected-no-diagnostics +import A; +import B; + +void test() { + test_func(); + test_duplicated_func(); +} -- GitLab From d8d2dea7fc6f452ac6a24948fe3ff99920f81c99 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 10 Mar 2024 21:22:37 -0700 Subject: [PATCH 066/953] [RISCV] Handle FP riscv_masked_strided_load with 0 stride. (#84576) Previously, we tried to create an integer extending load. We need to a non-extending FP load instead. Fixes #84541. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 11 ++++-- .../fixed-vectors-strided-load-store-asm.ll | 39 +++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 9b748cdcf745..fa37306a4999 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -9080,15 +9080,20 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op, SDValue Result, Chain; // TODO: We restrict this to unmasked loads currently in consideration of - // the complexity of hanlding all falses masks. - if (IsUnmasked && isNullConstant(Stride)) { - MVT ScalarVT = ContainerVT.getVectorElementType(); + // the complexity of handling all falses masks. + MVT ScalarVT = ContainerVT.getVectorElementType(); + if (IsUnmasked && isNullConstant(Stride) && ContainerVT.isInteger()) { SDValue ScalarLoad = DAG.getExtLoad(ISD::ZEXTLOAD, DL, XLenVT, Load->getChain(), Ptr, ScalarVT, Load->getMemOperand()); Chain = ScalarLoad.getValue(1); Result = lowerScalarSplat(SDValue(), ScalarLoad, VL, ContainerVT, DL, DAG, Subtarget); + } else if (IsUnmasked && isNullConstant(Stride) && isTypeLegal(ScalarVT)) { + SDValue ScalarLoad = DAG.getLoad(ScalarVT, DL, Load->getChain(), Ptr, + Load->getMemOperand()); + Chain = ScalarLoad.getValue(1); + Result = DAG.getSplat(ContainerVT, DL, ScalarLoad); } else { SDValue IntID = DAG.getTargetConstant( IsUnmasked ? Intrinsic::riscv_vlse : Intrinsic::riscv_vlse_mask, DL, diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-store-asm.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-store-asm.ll index 17d64c86dd53..c38406bafa8a 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-store-asm.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-store-asm.ll @@ -915,3 +915,42 @@ bb4: ; preds = %bb4, %bb2 bb16: ; preds = %bb4, %bb ret void } + +define void @gather_zero_stride_fp(ptr noalias nocapture %A, ptr noalias nocapture readonly %B) { +; CHECK-LABEL: gather_zero_stride_fp: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lui a2, 1 +; CHECK-NEXT: add a2, a0, a2 +; CHECK-NEXT: vsetivli zero, 8, e32, m1, ta, ma +; CHECK-NEXT: .LBB15_1: # %vector.body +; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: flw fa5, 0(a1) +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vfadd.vf v8, v8, fa5 +; CHECK-NEXT: vse32.v v8, (a0) +; CHECK-NEXT: addi a0, a0, 128 +; CHECK-NEXT: addi a1, a1, 640 +; CHECK-NEXT: bne a0, a2, .LBB15_1 +; CHECK-NEXT: # %bb.2: # %for.cond.cleanup +; CHECK-NEXT: ret +entry: + br label %vector.body + +vector.body: ; preds = %vector.body, %entry + %index = phi i64 [ 0, %entry ], [ %index.next, %vector.body ] + %vec.ind = phi <8 x i64> [ zeroinitializer, %entry ], [ %vec.ind.next, %vector.body ] + %i = mul nuw nsw <8 x i64> %vec.ind, + %i1 = getelementptr inbounds float, ptr %B, <8 x i64> %i + %wide.masked.gather = call <8 x float> @llvm.masked.gather.v8f32.v32p0(<8 x ptr> %i1, i32 4, <8 x i1> , <8 x float> undef) + %i2 = getelementptr inbounds float, ptr %A, i64 %index + %wide.load = load <8 x float>, ptr %i2, align 4 + %i4 = fadd <8 x float> %wide.load, %wide.masked.gather + store <8 x float> %i4, ptr %i2, align 4 + %index.next = add nuw i64 %index, 32 + %vec.ind.next = add <8 x i64> %vec.ind, + %i6 = icmp eq i64 %index.next, 1024 + br i1 %i6, label %for.cond.cleanup, label %vector.body + +for.cond.cleanup: ; preds = %vector.body + ret void +} -- GitLab From d9e6aa70484955c9f581577c3b93efc1d277fa46 Mon Sep 17 00:00:00 2001 From: Carl Ritson Date: Mon, 11 Mar 2024 14:54:11 +0900 Subject: [PATCH 067/953] [AMDGPU] Update LiveInterval def index for early-clobber (#79285) On converting an instruction to an early-clobber definition in convertToThreeAddress, we must also update live intervals for the register to start at the early-clobber index. --- llvm/lib/Target/AMDGPU/SIInstrInfo.cpp | 22 ++++++++++++++++++- llvm/test/CodeGen/AMDGPU/acc-ldst.ll | 1 + .../AMDGPU/mfma-no-register-aliasing.ll | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp index e8022c8b0afa..c19c3c6017a7 100644 --- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp +++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp @@ -3780,8 +3780,28 @@ MachineInstr *SIInstrInfo::convertToThreeAddress(MachineInstr &MI, for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) MIB.add(MI.getOperand(I)); updateLiveVariables(LV, MI, *MIB); - if (LIS) + if (LIS) { LIS->ReplaceMachineInstrInMaps(MI, *MIB); + // SlotIndex of defs needs to be updated when converting to early-clobber + MachineOperand &Def = MIB->getOperand(0); + if (Def.isEarlyClobber() && Def.isReg() && + LIS->hasInterval(Def.getReg())) { + SlotIndex OldIndex = LIS->getInstructionIndex(*MIB).getRegSlot(false); + SlotIndex NewIndex = LIS->getInstructionIndex(*MIB).getRegSlot(true); + auto &LI = LIS->getInterval(Def.getReg()); + auto UpdateDefIndex = [&](LiveRange &LR) { + auto S = LR.find(OldIndex); + if (S != LR.end() && S->start == OldIndex) { + assert(S->valno && S->valno->def == OldIndex); + S->start = NewIndex; + S->valno->def = NewIndex; + } + }; + UpdateDefIndex(LI); + for (auto &SR : LI.subranges()) + UpdateDefIndex(SR); + } + } return MIB; } diff --git a/llvm/test/CodeGen/AMDGPU/acc-ldst.ll b/llvm/test/CodeGen/AMDGPU/acc-ldst.ll index cf9c5a2e8f51..be4d6a2c2789 100644 --- a/llvm/test/CodeGen/AMDGPU/acc-ldst.ll +++ b/llvm/test/CodeGen/AMDGPU/acc-ldst.ll @@ -1,4 +1,5 @@ ; RUN: llc -mtriple=amdgcn -mcpu=gfx90a -verify-machineinstrs < %s | FileCheck -enable-var-scope --check-prefix=GCN %s +; RUN: llc -mtriple=amdgcn -mcpu=gfx90a -verify-machineinstrs -early-live-intervals < %s | FileCheck -enable-var-scope --check-prefix=GCN %s declare <32 x float> @llvm.amdgcn.mfma.f32.32x32x1f32(float, float, <32 x float>, i32, i32, i32) declare <4 x i32> @llvm.amdgcn.mfma.i32.4x4x4i8(i32, i32, <4 x i32>, i32, i32, i32) diff --git a/llvm/test/CodeGen/AMDGPU/mfma-no-register-aliasing.ll b/llvm/test/CodeGen/AMDGPU/mfma-no-register-aliasing.ll index 8ae6e1330344..8dbbab3c57f7 100644 --- a/llvm/test/CodeGen/AMDGPU/mfma-no-register-aliasing.ll +++ b/llvm/test/CodeGen/AMDGPU/mfma-no-register-aliasing.ll @@ -1,5 +1,6 @@ ; RUN: llc -mtriple=amdgcn -mcpu=gfx908 -verify-machineinstrs < %s | FileCheck -enable-var-scope --check-prefixes=GCN,GREEDY,GREEDY908 %s ; RUN: llc -mtriple=amdgcn -mcpu=gfx90a -verify-machineinstrs < %s | FileCheck -enable-var-scope --check-prefixes=GCN,GREEDY,GREEDY90A %s +; RUN: llc -mtriple=amdgcn -mcpu=gfx90a -early-live-intervals -verify-machineinstrs < %s | FileCheck -enable-var-scope --check-prefixes=GCN,GREEDY,GREEDY90A %s ; RUN: llc -mtriple=amdgcn -mcpu=gfx940 -verify-machineinstrs < %s | FileCheck -enable-var-scope --check-prefixes=GCN,GREEDY,GREEDY90A %s ; RUN: llc -global-isel -mtriple=amdgcn -mcpu=gfx90a -verify-machineinstrs < %s | FileCheck -enable-var-scope --check-prefixes=GCN,GREEDY,GREEDY90A-GISEL %s ; RUN: llc -mtriple=amdgcn -mcpu=gfx90a -sgpr-regalloc=fast -vgpr-regalloc=fast -verify-machineinstrs < %s | FileCheck -enable-var-scope --check-prefixes=GCN,FAST %s -- GitLab From b7f97d3661814c4ae11b8772f8a27c029d01648b Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Mon, 11 Mar 2024 13:57:06 +0800 Subject: [PATCH 068/953] [RISCV] Place mergeable small read only data into srodata section (#82214) Small mergeable read only data was place on the sdata before, but it also means it lose the mergeable property, which means lose some code size optimization opportunity during link time. --- .../Target/RISCV/RISCVTargetObjectFile.cpp | 25 +++++++++- llvm/lib/Target/RISCV/RISCVTargetObjectFile.h | 5 ++ llvm/test/CodeGen/RISCV/srodata.ll | 47 +++++++++++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/RISCV/srodata.ll diff --git a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp index 1535149b919b..e7c1a7e5d8bc 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp @@ -32,6 +32,16 @@ void RISCVELFTargetObjectFile::Initialize(MCContext &Ctx, ".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); + SmallRODataSection = + getContext().getELFSection(".srodata", ELF::SHT_PROGBITS, ELF::SHF_ALLOC); + SmallROData4Section = getContext().getELFSection( + ".srodata.cst4", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_MERGE, 4); + SmallROData8Section = getContext().getELFSection( + ".srodata.cst8", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_MERGE, 8); + SmallROData16Section = getContext().getELFSection( + ".srodata.cst16", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_MERGE, 16); + SmallROData32Section = getContext().getELFSection( + ".srodata.cst32", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_MERGE, 32); } const MCExpr *RISCVELFTargetObjectFile::getIndirectSymViaGOTPCRel( @@ -126,8 +136,19 @@ bool RISCVELFTargetObjectFile::isConstantInSmallSection( MCSection *RISCVELFTargetObjectFile::getSectionForConstant( const DataLayout &DL, SectionKind Kind, const Constant *C, Align &Alignment) const { - if (isConstantInSmallSection(DL, C)) - return SmallDataSection; + if (isConstantInSmallSection(DL, C)) { + if (Kind.isMergeableConst4()) + return SmallROData4Section; + if (Kind.isMergeableConst8()) + return SmallROData8Section; + if (Kind.isMergeableConst16()) + return SmallROData16Section; + if (Kind.isMergeableConst32()) + return SmallROData32Section; + // LLVM only generate up to .rodata.cst32, and use .rodata section if more + // than 32 bytes, so just use .srodata here. + return SmallRODataSection; + } // Otherwise, we work the same as ELF. return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C, diff --git a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h index 0910fbd3d950..05e61ac874ab 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h +++ b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h @@ -16,6 +16,11 @@ namespace llvm { /// This implementation is used for RISC-V ELF targets. class RISCVELFTargetObjectFile : public TargetLoweringObjectFileELF { MCSection *SmallDataSection; + MCSection *SmallRODataSection; + MCSection *SmallROData4Section; + MCSection *SmallROData8Section; + MCSection *SmallROData16Section; + MCSection *SmallROData32Section; MCSection *SmallBSSSection; unsigned SSThreshold = 8; diff --git a/llvm/test/CodeGen/RISCV/srodata.ll b/llvm/test/CodeGen/RISCV/srodata.ll new file mode 100644 index 000000000000..1d5bd904f233 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/srodata.ll @@ -0,0 +1,47 @@ +; RUN: sed 's/SMALL_DATA_LIMIT/0/g' %s | \ +; RUN: llc -mtriple=riscv32 -mattr=+d | \ +; RUN: FileCheck -check-prefix=CHECK-SDL-0 %s +; RUN: sed 's/SMALL_DATA_LIMIT/0/g' %s | \ +; RUN: llc -mtriple=riscv64 -mattr=+d | \ +; RUN: FileCheck -check-prefix=CHECK-SDL-0 %s +; RUN: sed 's/SMALL_DATA_LIMIT/4/g' %s | \ +; RUN: llc -mtriple=riscv32 -mattr=+d | \ +; RUN: FileCheck -check-prefix=CHECK-SDL-4 %s +; RUN: sed 's/SMALL_DATA_LIMIT/4/g' %s | \ +; RUN: llc -mtriple=riscv64 -mattr=+d | \ +; RUN: FileCheck -check-prefix=CHECK-SDL-4 %s +; RUN: sed 's/SMALL_DATA_LIMIT/8/g' %s | \ +; RUN: llc -mtriple=riscv32 -mattr=+d | \ +; RUN: FileCheck -check-prefix=CHECK-SDL-8 %s +; RUN: sed 's/SMALL_DATA_LIMIT/8/g' %s | \ +; RUN: llc -mtriple=riscv64 -mattr=+d | \ +; RUN: FileCheck -check-prefix=CHECK-SDL-8 %s +; RUN: sed 's/SMALL_DATA_LIMIT/16/g' %s | \ +; RUN: llc -mtriple=riscv32 -mattr=+d | \ +; RUN: FileCheck -check-prefix=CHECK-SDL-16 %s +; RUN: sed 's/SMALL_DATA_LIMIT/16/g' %s | \ +; RUN: llc -mtriple=riscv64 -mattr=+d | \ +; RUN: FileCheck -check-prefix=CHECK-SDL-16 %s + +define dso_local float @foof() { +entry: + ret float 0x400A08ACA0000000 +} + +define dso_local double @foo() { +entry: + ret double 0x400A08AC91C3E242 +} + +!llvm.module.flags = !{!0} + +!0 = !{i32 8, !"SmallDataLimit", i32 SMALL_DATA_LIMIT} + +; CHECK-SDL-0-NOT: .section .srodata.cst4 +; CHECK-SDL-0-NOT: .section .srodata.cst8 +; CHECK-SDL-4: .section .srodata.cst4 +; CHECK-SDL-4-NOT: .section .srodata.cst8 +; CHECK-SDL-8: .section .srodata.cst4 +; CHECK-SDL-8: .section .srodata.cst8 +; CHECK-SDL-16: .section .srodata.cst4 +; CHECK-SDL-16: .section .srodata.cst8 -- GitLab From f6455606bbbb02bbc155a713ae07eab1c7419041 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 10 Mar 2024 23:01:26 -0700 Subject: [PATCH 069/953] [ELF] Move getSymbol/getRelocTargetSym from ObjFile to InputFile. NFC This removes lots of unneeded `template getFile()`. --- lld/ELF/Arch/AArch64.cpp | 2 +- lld/ELF/Arch/PPC64.cpp | 2 +- lld/ELF/Driver.cpp | 4 ++-- lld/ELF/ICF.cpp | 16 ++++++++-------- lld/ELF/InputFiles.h | 23 ++++++++++++----------- lld/ELF/InputSection.cpp | 4 ++-- lld/ELF/MarkLive.cpp | 3 +-- lld/ELF/SyntheticSections.cpp | 5 ++--- 8 files changed, 29 insertions(+), 30 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 71a1b1111e42..30ccd68f7b75 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -994,7 +994,7 @@ addTaggedSymbolReferences(InputSectionBase &sec, error("non-RELA relocations are not allowed with memtag globals"); for (const typename ELFT::Rela &rel : rels.relas) { - Symbol &sym = sec.getFile()->getRelocTargetSym(rel); + Symbol &sym = sec.file->getRelocTargetSym(rel); // Linker-synthesized symbols such as __executable_start may be referenced // as tagged in input objfiles, and we don't want them to be tagged. A // cheap way to exclude them is the type check, but their type is diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index 019c073bd541..657332deebfd 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -347,7 +347,7 @@ getRelaTocSymAndAddend(InputSectionBase *tocSec, uint64_t offset) { uint64_t index = std::min(offset / 8, relas.size() - 1); for (;;) { if (relas[index].r_offset == offset) { - Symbol &sym = tocSec->getFile()->getRelocTargetSym(relas[index]); + Symbol &sym = tocSec->file->getRelocTargetSym(relas[index]); return {dyn_cast(&sym), getAddend(relas[index])}; } if (relas[index].r_offset < offset || index == 0) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 24faa1753f1e..de4b2e345ac9 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -2302,9 +2302,9 @@ static void readSymbolPartitionSection(InputSectionBase *s) { Symbol *sym; const RelsOrRelas rels = s->template relsOrRelas(); if (rels.areRelocsRel()) - sym = &s->getFile()->getRelocTargetSym(rels.rels[0]); + sym = &s->file->getRelocTargetSym(rels.rels[0]); else - sym = &s->getFile()->getRelocTargetSym(rels.relas[0]); + sym = &s->file->getRelocTargetSym(rels.relas[0]); if (!isa(sym) || !sym->includeInDynsym()) return; diff --git a/lld/ELF/ICF.cpp b/lld/ELF/ICF.cpp index 9d7251037fb6..2551c2e807b7 100644 --- a/lld/ELF/ICF.cpp +++ b/lld/ELF/ICF.cpp @@ -247,8 +247,8 @@ bool ICF::constantEq(const InputSection *secA, ArrayRef ra, uint64_t addA = getAddend(ra[i]); uint64_t addB = getAddend(rb[i]); - Symbol &sa = secA->template getFile()->getRelocTargetSym(ra[i]); - Symbol &sb = secB->template getFile()->getRelocTargetSym(rb[i]); + Symbol &sa = secA->file->getRelocTargetSym(ra[i]); + Symbol &sb = secB->file->getRelocTargetSym(rb[i]); if (&sa == &sb) { if (addA == addB) continue; @@ -338,8 +338,8 @@ bool ICF::variableEq(const InputSection *secA, ArrayRef ra, for (size_t i = 0; i < ra.size(); ++i) { // The two sections must be identical. - Symbol &sa = secA->template getFile()->getRelocTargetSym(ra[i]); - Symbol &sb = secB->template getFile()->getRelocTargetSym(rb[i]); + Symbol &sa = secA->file->getRelocTargetSym(ra[i]); + Symbol &sb = secB->file->getRelocTargetSym(rb[i]); if (&sa == &sb) continue; @@ -437,12 +437,12 @@ void ICF::forEachClass(llvm::function_ref fn) { // Combine the hashes of the sections referenced by the given section into its // hash. -template +template static void combineRelocHashes(unsigned cnt, InputSection *isec, ArrayRef rels) { uint32_t hash = isec->eqClass[cnt % 2]; for (RelTy rel : rels) { - Symbol &s = isec->template getFile()->getRelocTargetSym(rel); + Symbol &s = isec->file->getRelocTargetSym(rel); if (auto *d = dyn_cast(&s)) if (auto *relSec = dyn_cast_or_null(d->section)) hash += relSec->eqClass[cnt % 2]; @@ -504,9 +504,9 @@ template void ICF::run() { parallelForEach(sections, [&](InputSection *s) { const RelsOrRelas rels = s->template relsOrRelas(); if (rels.areRelocsRel()) - combineRelocHashes(cnt, s, rels.rels); + combineRelocHashes(cnt, s, rels.rels); else - combineRelocHashes(cnt, s, rels.relas); + combineRelocHashes(cnt, s, rels.relas); }); } diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 0cbe00aa396a..54de842a81cf 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -99,6 +99,18 @@ public: return {symbols.get(), numSymbols}; } + Symbol &getSymbol(uint32_t symbolIndex) const { + assert(fileKind == ObjKind); + if (symbolIndex >= numSymbols) + fatal(toString(this) + ": invalid symbol index"); + return *this->symbols[symbolIndex]; + } + + template Symbol &getRelocTargetSym(const RelT &rel) const { + uint32_t symIndex = rel.getSymbol(config->isMips64EL); + return getSymbol(symIndex); + } + // Get filename to use for linker script processing. StringRef getNameForScript() const; @@ -242,19 +254,8 @@ public: StringRef getShtGroupSignature(ArrayRef sections, const Elf_Shdr &sec); - Symbol &getSymbol(uint32_t symbolIndex) const { - if (symbolIndex >= numSymbols) - fatal(toString(this) + ": invalid symbol index"); - return *this->symbols[symbolIndex]; - } - uint32_t getSectionIndex(const Elf_Sym &sym) const; - template Symbol &getRelocTargetSym(const RelT &rel) const { - uint32_t symIndex = rel.getSymbol(config->isMips64EL); - return getSymbol(symIndex); - } - std::optional getDILineInfo(const InputSectionBase *, uint64_t); std::optional> diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index e033a715b592..7508a1336c91 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -924,7 +924,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { if (!RelTy::IsRela) addend += target.getImplicitAddend(bufLoc, type); - Symbol &sym = getFile()->getRelocTargetSym(rel); + Symbol &sym = this->file->getRelocTargetSym(rel); RelExpr expr = target.getRelExpr(type, sym, bufLoc); if (expr == R_NONE) continue; @@ -939,7 +939,7 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { val = *tombstone; } else { val = sym.getVA(addend) - - (getFile()->getRelocTargetSym(rels[i]).getVA(0) + + (this->file->getRelocTargetSym(rels[i]).getVA(0) + getAddend(rels[i])); } if (overwriteULEB128(bufLoc, val) >= 0x80) diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index 0073ed42112a..93c66e81d2fa 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -89,9 +89,8 @@ template template void MarkLive::resolveReloc(InputSectionBase &sec, RelTy &rel, bool fromFDE) { - Symbol &sym = sec.getFile()->getRelocTargetSym(rel); - // If a symbol is referenced in a live section, it is used. + Symbol &sym = sec.file->getRelocTargetSym(rel); sym.used = true; if (auto *d = dyn_cast(&sym)) { diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 66b3e835cabc..206fb0f53766 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -365,8 +365,7 @@ CieRecord *EhFrameSection::addCie(EhSectionPiece &cie, ArrayRef rels) { Symbol *personality = nullptr; unsigned firstRelI = cie.firstRelocation; if (firstRelI != (unsigned)-1) - personality = - &cie.sec->template getFile()->getRelocTargetSym(rels[firstRelI]); + personality = &cie.sec->file->getRelocTargetSym(rels[firstRelI]); // Search for an existing CIE by CIE contents/relocation target pair. CieRecord *&rec = cieMap[{cie.data(), personality}]; @@ -396,7 +395,7 @@ Defined *EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef rels) { return nullptr; const RelTy &rel = rels[firstRelI]; - Symbol &b = sec->template getFile()->getRelocTargetSym(rel); + Symbol &b = sec->file->getRelocTargetSym(rel); // FDEs for garbage-collected or merged-by-ICF sections, or sections in // another partition, are dead. -- GitLab From 4a21e3afa29521192ce686605eb945495455ca5e Mon Sep 17 00:00:00 2001 From: Carl Ritson Date: Mon, 11 Mar 2024 15:24:17 +0900 Subject: [PATCH 070/953] [LiveIntervals] repairIntervalsInRange: recompute width changes (#78564) Extend repairIntervalsInRange to completely recompute the interva for a register if subregister defs exist without precise subrange matches (LaneMask exactly matching subregister). This occurs when register sequences are lowered to copies such that the size of the copies do not match any uses of the subregisters formed (i.e. during twoaddressinstruction). The subranges without this change are probably legal, but do not match those generated by live interval computation. This creates problems with other code that assumes subranges precisely cover all subregisters defined, e.g. shrinkToUses(). --- llvm/lib/CodeGen/LiveIntervals.cpp | 26 ++++++++++++++----- .../test/CodeGen/AMDGPU/lds-misaligned-bug.ll | 1 + 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/llvm/lib/CodeGen/LiveIntervals.cpp b/llvm/lib/CodeGen/LiveIntervals.cpp index 68fff9bc221d..42c769399a14 100644 --- a/llvm/lib/CodeGen/LiveIntervals.cpp +++ b/llvm/lib/CodeGen/LiveIntervals.cpp @@ -1666,13 +1666,27 @@ LiveIntervals::repairIntervalsInRange(MachineBasicBlock *MBB, for (const MachineOperand &MO : MI.operands()) { if (MO.isReg() && MO.getReg().isVirtual()) { Register Reg = MO.getReg(); - // If the new instructions refer to subregs but the old instructions did - // not, throw away any old live interval so it will be recomputed with - // subranges. if (MO.getSubReg() && hasInterval(Reg) && - !getInterval(Reg).hasSubRanges() && - MRI->shouldTrackSubRegLiveness(Reg)) - removeInterval(Reg); + MRI->shouldTrackSubRegLiveness(Reg)) { + LiveInterval &LI = getInterval(Reg); + if (!LI.hasSubRanges()) { + // If the new instructions refer to subregs but the old instructions + // did not, throw away any old live interval so it will be + // recomputed with subranges. + removeInterval(Reg); + } else if (MO.isDef()) { + // Similarly if a subreg def has no precise subrange match then + // assume we need to recompute all subranges. + unsigned SubReg = MO.getSubReg(); + LaneBitmask Mask = TRI->getSubRegIndexLaneMask(SubReg); + if (llvm::none_of(LI.subranges(), + [Mask](LiveInterval::SubRange &SR) { + return SR.LaneMask == Mask; + })) { + removeInterval(Reg); + } + } + } if (!hasInterval(Reg)) { createAndComputeVirtRegInterval(Reg); // Don't bother to repair a freshly calculated live interval. diff --git a/llvm/test/CodeGen/AMDGPU/lds-misaligned-bug.ll b/llvm/test/CodeGen/AMDGPU/lds-misaligned-bug.ll index 3a8f06ba59a1..01af33465238 100644 --- a/llvm/test/CodeGen/AMDGPU/lds-misaligned-bug.ll +++ b/llvm/test/CodeGen/AMDGPU/lds-misaligned-bug.ll @@ -5,6 +5,7 @@ ; RUN: llc -mtriple=amdgcn -mcpu=gfx1010 -verify-machineinstrs -mattr=+cumode,+unaligned-access-mode < %s | FileCheck -check-prefixes=GCN,UNALIGNED,VECT %s ; RUN: llc -mtriple=amdgcn -mcpu=gfx1100 -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,ALIGNED,VECT %s ; RUN: llc -mtriple=amdgcn -mcpu=gfx1100 -verify-machineinstrs -mattr=+cumode < %s | FileCheck -check-prefixes=GCN,ALIGNED,VECT %s +; RUN: llc -mtriple=amdgcn -mcpu=gfx1100 -verify-machineinstrs -mattr=+cumode -early-live-intervals < %s | FileCheck -check-prefixes=GCN,ALIGNED,VECT %s ; RUN: llc -mtriple=amdgcn -mcpu=gfx1100 -verify-machineinstrs -mattr=+cumode,+unaligned-access-mode < %s | FileCheck -check-prefixes=GCN,UNALIGNED,VECT %s ; GCN-LABEL: test_local_misaligned_v2: -- GitLab From cf1319f9c6561afea381bbfc1a18f5c1fb7b46b0 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Mon, 11 Mar 2024 07:44:26 +0100 Subject: [PATCH 071/953] [compiler-rt] Mark more calls as blocking (#77789) If we're in a blocking call, we need to run the signal immediately, as the call may not return for a very long time (if ever). Not running the handler can cause deadlocks if the rest of the program waits (in one way or another) for the signal handler to execute. I've gone through the list of functions in sanitizer_common_interceptors and marked as blocking those that I know can block, but I don't claim the list to be exhaustive. In particular, I did not mark libc FILE* functions as blocking, because these can end up calling user functions. To do that correctly, /I think/ it would be necessary to clear the "is in blocking call" flag inside the fopencookie wrappers. The test for the bug (deadlock) uses the read call (which is the one that I ran into originally), but the same kind of test could be written for any other blocking syscall. --- .../sanitizer_common_interceptors.inc | 83 ++++++++++--------- .../test/tsan/pthread_atfork_deadlock3.c | 4 +- compiler-rt/test/tsan/signal_in_read.c | 59 +++++++++++++ 3 files changed, 107 insertions(+), 39 deletions(-) create mode 100644 compiler-rt/test/tsan/signal_in_read.c diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 3ecdb55cdbf7..a1be676730a7 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -974,7 +974,7 @@ INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - SSIZE_T res = REAL(read)(fd, ptr, count); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(read)(fd, ptr, count); if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); return res; @@ -1009,7 +1009,7 @@ INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - SSIZE_T res = REAL(pread)(fd, ptr, count, offset); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pread)(fd, ptr, count, offset); if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); return res; @@ -1027,7 +1027,7 @@ INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - SSIZE_T res = REAL(pread64)(fd, ptr, count, offset); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pread64)(fd, ptr, count, offset); if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); return res; @@ -1043,7 +1043,7 @@ INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov, void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); - SSIZE_T res = REAL(readv)(fd, iov, iovcnt); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(readv)(fd, iov, iovcnt); if (res > 0) write_iovec(ctx, iov, iovcnt, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); return res; @@ -1059,7 +1059,7 @@ INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt, void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); - SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(preadv)(fd, iov, iovcnt, offset); if (res > 0) write_iovec(ctx, iov, iovcnt, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); return res; @@ -1075,7 +1075,8 @@ INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt, void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); - SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset); + SSIZE_T res = + COMMON_INTERCEPTOR_BLOCK_REAL(preadv64)(fd, iov, iovcnt, offset); if (res > 0) write_iovec(ctx, iov, iovcnt, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); return res; @@ -1091,8 +1092,9 @@ INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) { COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); - SSIZE_T res = REAL(write)(fd, ptr, count); - // FIXME: this check should be _before_ the call to REAL(write), not after + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(write)(fd, ptr, count); + // FIXME: this check should be _before_ the call to + // COMMON_INTERCEPTOR_BLOCK_REAL(write), not after if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res); return res; } @@ -1121,7 +1123,7 @@ INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) { COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); - SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pwrite)(fd, ptr, count, offset); if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res); return res; } @@ -1137,7 +1139,7 @@ INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count, COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); - SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pwrite64)(fd, ptr, count, offset); if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res); return res; } @@ -1153,7 +1155,7 @@ INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov, COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); - SSIZE_T res = REAL(writev)(fd, iov, iovcnt); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(writev)(fd, iov, iovcnt); if (res > 0) read_iovec(ctx, iov, iovcnt, res); return res; } @@ -1169,7 +1171,7 @@ INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt, COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); - SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pwritev)(fd, iov, iovcnt, offset); if (res > 0) read_iovec(ctx, iov, iovcnt, res); return res; } @@ -1185,7 +1187,8 @@ INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt, COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); - SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset); + SSIZE_T res = + COMMON_INTERCEPTOR_BLOCK_REAL(pwritev64)(fd, iov, iovcnt, offset); if (res > 0) read_iovec(ctx, iov, iovcnt, res); return res; } @@ -2549,7 +2552,7 @@ INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - int res = REAL(wait)(status); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(wait)(status); if (res != -1 && status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); return res; @@ -2567,7 +2570,7 @@ INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop, // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - int res = REAL(waitid)(idtype, id, infop, options); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(waitid)(idtype, id, infop, options); if (res != -1 && infop) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz); return res; @@ -2578,7 +2581,7 @@ INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - int res = REAL(waitpid)(pid, status, options); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(waitpid)(pid, status, options); if (res != -1 && status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); return res; @@ -2589,7 +2592,7 @@ INTERCEPTOR(int, wait3, int *status, int options, void *rusage) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - int res = REAL(wait3)(status, options, rusage); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(wait3)(status, options, rusage); if (res != -1) { if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz); @@ -2603,7 +2606,8 @@ INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - int res = REAL(__wait4)(pid, status, options, rusage); + int res = + COMMON_INTERCEPTOR_BLOCK_REAL(__wait4)(pid, status, options, rusage); if (res != -1) { if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz); @@ -2618,7 +2622,7 @@ INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - int res = REAL(wait4)(pid, status, options, rusage); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(wait4)(pid, status, options, rusage); if (res != -1) { if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz); @@ -2996,7 +3000,7 @@ INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) { COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen)); addrlen0 = *addrlen; } - int fd2 = REAL(accept)(fd, addr, addrlen); + int fd2 = COMMON_INTERCEPTOR_BLOCK_REAL(accept)(fd, addr, addrlen); if (fd2 >= 0) { if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2); if (addr && addrlen) @@ -3021,7 +3025,7 @@ INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - int fd2 = REAL(accept4)(fd, addr, addrlen, f); + int fd2 = COMMON_INTERCEPTOR_BLOCK_REAL(accept4)(fd, addr, addrlen, f); if (fd2 >= 0) { if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2); if (addr && addrlen) @@ -3045,7 +3049,7 @@ INTERCEPTOR(int, paccept, int fd, void *addr, unsigned *addrlen, addrlen0 = *addrlen; } if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set)); - int fd2 = REAL(paccept)(fd, addr, addrlen, set, f); + int fd2 = COMMON_INTERCEPTOR_BLOCK_REAL(paccept)(fd, addr, addrlen, set, f); if (fd2 >= 0) { if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2); if (addr && addrlen) @@ -3126,7 +3130,7 @@ INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg, // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - SSIZE_T res = REAL(recvmsg)(fd, msg, flags); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(recvmsg)(fd, msg, flags); if (res >= 0) { if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); if (msg) { @@ -3147,7 +3151,8 @@ INTERCEPTOR(int, recvmmsg, int fd, struct __sanitizer_mmsghdr *msgvec, void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, recvmmsg, fd, msgvec, vlen, flags, timeout); if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz); - int res = REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout); + int res = + COMMON_INTERCEPTOR_BLOCK_REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout); if (res >= 0) { if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); for (int i = 0; i < res; ++i) { @@ -3225,7 +3230,7 @@ INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg, COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); } - SSIZE_T res = REAL(sendmsg)(fd, msg, flags); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(sendmsg)(fd, msg, flags); if (common_flags()->intercept_send && res >= 0 && msg) read_msghdr(ctx, msg, res); return res; @@ -3244,7 +3249,7 @@ INTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec, COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); } - int res = REAL(sendmmsg)(fd, msgvec, vlen, flags); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(sendmmsg)(fd, msgvec, vlen, flags); if (res >= 0 && msgvec) { for (int i = 0; i < res; ++i) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len, @@ -3267,7 +3272,7 @@ INTERCEPTOR(int, msgsnd, int msqid, const void *msgp, SIZE_T msgsz, COMMON_INTERCEPTOR_ENTER(ctx, msgsnd, msqid, msgp, msgsz, msgflg); if (msgp) COMMON_INTERCEPTOR_READ_RANGE(ctx, msgp, sizeof(long) + msgsz); - int res = REAL(msgsnd)(msqid, msgp, msgsz, msgflg); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(msgsnd)(msqid, msgp, msgsz, msgflg); return res; } @@ -3275,7 +3280,8 @@ INTERCEPTOR(SSIZE_T, msgrcv, int msqid, void *msgp, SIZE_T msgsz, long msgtyp, int msgflg) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, msgrcv, msqid, msgp, msgsz, msgtyp, msgflg); - SSIZE_T len = REAL(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg); + SSIZE_T len = + COMMON_INTERCEPTOR_BLOCK_REAL(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg); if (len != -1) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msgp, sizeof(long) + len); return len; @@ -6119,7 +6125,7 @@ INTERCEPTOR(int, flopen, const char *path, int flags, ...) { if (path) { COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1); } - return REAL(flopen)(path, flags, mode); + return COMMON_INTERCEPTOR_BLOCK_REAL(flopen)(path, flags, mode); } INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) { @@ -6132,7 +6138,7 @@ INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) { if (path) { COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1); } - return REAL(flopenat)(dirfd, path, flags, mode); + return COMMON_INTERCEPTOR_BLOCK_REAL(flopenat)(dirfd, path, flags, mode); } #define INIT_FLOPEN \ @@ -6717,7 +6723,7 @@ INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, recv, fd, buf, len, flags); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); - SSIZE_T res = REAL(recv)(fd, buf, len, flags); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(recv)(fd, buf, len, flags); if (res > 0) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len)); } @@ -6734,7 +6740,8 @@ INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags, SIZE_T srcaddr_sz; if (srcaddr) srcaddr_sz = *addrlen; (void)srcaddr_sz; // prevent "set but not used" warning - SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(recvfrom)(fd, buf, len, flags, + srcaddr, addrlen); if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len)); if (res >= 0 && srcaddr) @@ -6757,7 +6764,7 @@ INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) { COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); } - SSIZE_T res = REAL(send)(fd, buf, len, flags); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(send)(fd, buf, len, flags); if (common_flags()->intercept_send && res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len)); return res; @@ -6772,7 +6779,8 @@ INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags, COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); } // Can't check dstaddr as it may have uninitialized padding at the end. - SSIZE_T res = REAL(sendto)(fd, buf, len, flags, dstaddr, addrlen); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(sendto)(fd, buf, len, flags, + dstaddr, addrlen); if (common_flags()->intercept_send && res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len)); return res; @@ -6789,7 +6797,7 @@ INTERCEPTOR(int, eventfd_read, int fd, __sanitizer_eventfd_t *value) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, eventfd_read, fd, value); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); - int res = REAL(eventfd_read)(fd, value); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(eventfd_read)(fd, value); if (res == 0) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, sizeof(*value)); if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); @@ -6803,7 +6811,7 @@ INTERCEPTOR(int, eventfd_write, int fd, __sanitizer_eventfd_t value) { COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); } - int res = REAL(eventfd_write)(fd, value); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(eventfd_write)(fd, value); return res; } #define INIT_EVENTFD_READ_WRITE \ @@ -7426,7 +7434,8 @@ INTERCEPTOR(int, open_by_handle_at, int mount_fd, struct file_handle* handle, COMMON_INTERCEPTOR_READ_RANGE( ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes); - return REAL(open_by_handle_at)(mount_fd, handle, flags); + return COMMON_INTERCEPTOR_BLOCK_REAL(open_by_handle_at)(mount_fd, handle, + flags); } #define INIT_OPEN_BY_HANDLE_AT COMMON_INTERCEPT_FUNCTION(open_by_handle_at) diff --git a/compiler-rt/test/tsan/pthread_atfork_deadlock3.c b/compiler-rt/test/tsan/pthread_atfork_deadlock3.c index 793eaf6ac867..41b8f051b33c 100644 --- a/compiler-rt/test/tsan/pthread_atfork_deadlock3.c +++ b/compiler-rt/test/tsan/pthread_atfork_deadlock3.c @@ -28,17 +28,17 @@ void *worker(void *main) { } void atfork() { + write(2, "in atfork\n", strlen("in atfork\n")); barrier_wait(&barrier); barrier_wait(&barrier); - write(2, "in atfork\n", strlen("in atfork\n")); static volatile long a; __atomic_fetch_add(&a, 1, __ATOMIC_RELEASE); } void afterfork() { + write(2, "in afterfork\n", strlen("in afterfork\n")); barrier_wait(&barrier); barrier_wait(&barrier); - write(2, "in afterfork\n", strlen("in afterfork\n")); static volatile long a; __atomic_fetch_add(&a, 1, __ATOMIC_RELEASE); } diff --git a/compiler-rt/test/tsan/signal_in_read.c b/compiler-rt/test/tsan/signal_in_read.c new file mode 100644 index 000000000000..ec50d9d02174 --- /dev/null +++ b/compiler-rt/test/tsan/signal_in_read.c @@ -0,0 +1,59 @@ +// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s + +#include "test.h" + +#include +#include +#include +#include +#include +#include +#include + +static int SignalPipeFd[] = {-1, -1}; +static int BlockingPipeFd[] = {-1, -1}; + +static void Handler(int _) { assert(write(SignalPipeFd[1], ".", 1) == 1); } + +static void *ThreadFunc(void *_) { + char C; + assert(read(BlockingPipeFd[0], &C, sizeof(C)) == 1); + assert(C == '.'); + return 0; +} + +int main() { + alarm(60); // Kill the test if it hangs. + + assert(pipe(SignalPipeFd) == 0); + assert(pipe(BlockingPipeFd) == 0); + + struct sigaction act; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + act.sa_handler = Handler; + assert(sigaction(SIGUSR1, &act, 0) == 0); + + pthread_t Thr; + assert(pthread_create(&Thr, 0, ThreadFunc, 0) == 0); + + // Give the thread enough time to block in the read call. + usleep(1000000); + + // Signal the thread, this should run the signal handler and unblock the read + // below. + pthread_kill(Thr, SIGUSR1); + char C; + assert(read(SignalPipeFd[0], &C, 1) == 1); + + // Unblock the thread and join it. + assert(write(BlockingPipeFd[1], &C, 1) == 1); + void *_ = 0; + assert(pthread_join(Thr, &_) == 0); + + fprintf(stderr, "PASS\n"); + return 0; +} + +// CHECK-NOT: WARNING: ThreadSanitizer: +// CHECK: PASS -- GitLab From 4e0e9b17c6cacdc3b1ea3a43f85ae443cb146af8 Mon Sep 17 00:00:00 2001 From: AtariDreams <83477269+AtariDreams@users.noreply.github.com> Date: Mon, 11 Mar 2024 03:17:39 -0400 Subject: [PATCH 072/953] [SelectionDAG] Switch to LiveRegUnits (#84197) --- llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h | 4 ++-- llvm/lib/CodeGen/ScheduleDAGInstrs.cpp | 10 ++++++---- llvm/test/CodeGen/AMDGPU/add.ll | 6 ------ llvm/test/CodeGen/AMDGPU/ctpop16.ll | 4 ---- llvm/test/CodeGen/AMDGPU/ctpop64.ll | 3 --- llvm/test/CodeGen/AMDGPU/llvm.amdgcn.set.inactive.ll | 1 - llvm/test/CodeGen/AMDGPU/mul.ll | 6 ------ 7 files changed, 8 insertions(+), 26 deletions(-) diff --git a/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h b/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h index 85de18f5169e..32ff15fc7593 100644 --- a/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -20,7 +20,7 @@ #include "llvm/ADT/SparseMultiSet.h" #include "llvm/ADT/SparseSet.h" #include "llvm/ADT/identity.h" -#include "llvm/CodeGen/LivePhysRegs.h" +#include "llvm/CodeGen/LiveRegUnits.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/ScheduleDAG.h" #include "llvm/CodeGen/TargetRegisterInfo.h" @@ -263,7 +263,7 @@ namespace llvm { MachineInstr *FirstDbgValue = nullptr; /// Set of live physical registers for updating kill flags. - LivePhysRegs LiveRegs; + LiveRegUnits LiveRegs; public: explicit ScheduleDAGInstrs(MachineFunction &mf, diff --git a/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp b/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp index 0190fa345eb3..51ede7992af5 100644 --- a/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp +++ b/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -1103,7 +1103,7 @@ void ScheduleDAGInstrs::reduceHugeMemNodeMaps(Value2SUsMap &stores, dbgs() << "Loading SUnits:\n"; loads.dump()); } -static void toggleKills(const MachineRegisterInfo &MRI, LivePhysRegs &LiveRegs, +static void toggleKills(const MachineRegisterInfo &MRI, LiveRegUnits &LiveRegs, MachineInstr &MI, bool addToLiveRegs) { for (MachineOperand &MO : MI.operands()) { if (!MO.isReg() || !MO.readsReg()) @@ -1113,8 +1113,10 @@ static void toggleKills(const MachineRegisterInfo &MRI, LivePhysRegs &LiveRegs, continue; // Things that are available after the instruction are killed by it. - bool IsKill = LiveRegs.available(MRI, Reg); - MO.setIsKill(IsKill); + bool IsKill = LiveRegs.available(Reg); + + // Exception: Do not kill reserved registers + MO.setIsKill(IsKill && !MRI.isReserved(Reg)); if (addToLiveRegs) LiveRegs.addReg(Reg); } @@ -1144,7 +1146,7 @@ void ScheduleDAGInstrs::fixupKills(MachineBasicBlock &MBB) { continue; LiveRegs.removeReg(Reg); } else if (MO.isRegMask()) { - LiveRegs.removeRegsInMask(MO); + LiveRegs.removeRegsNotPreserved(MO.getRegMask()); } } diff --git a/llvm/test/CodeGen/AMDGPU/add.ll b/llvm/test/CodeGen/AMDGPU/add.ll index 39f9cf7cf8ff..422e2747094c 100644 --- a/llvm/test/CodeGen/AMDGPU/add.ll +++ b/llvm/test/CodeGen/AMDGPU/add.ll @@ -1263,7 +1263,6 @@ define amdgpu_kernel void @add64_in_branch(ptr addrspace(1) %out, ptr addrspace( ; GFX10-NEXT: ; %bb.1: ; %else ; GFX10-NEXT: s_add_u32 s4, s4, s6 ; GFX10-NEXT: s_addc_u32 s5, s5, s7 -; GFX10-NEXT: s_mov_b32 s6, 0 ; GFX10-NEXT: s_cbranch_execnz .LBB9_3 ; GFX10-NEXT: .LBB9_2: ; %if ; GFX10-NEXT: s_load_dwordx2 s[4:5], s[2:3], 0x0 @@ -1275,7 +1274,6 @@ define amdgpu_kernel void @add64_in_branch(ptr addrspace(1) %out, ptr addrspace( ; GFX10-NEXT: global_store_dwordx2 v2, v[0:1], s[0:1] ; GFX10-NEXT: s_endpgm ; GFX10-NEXT: .LBB9_4: -; GFX10-NEXT: s_mov_b32 s6, -1 ; GFX10-NEXT: ; implicit-def: $sgpr4_sgpr5 ; GFX10-NEXT: s_branch .LBB9_2 ; @@ -1288,7 +1286,6 @@ define amdgpu_kernel void @add64_in_branch(ptr addrspace(1) %out, ptr addrspace( ; GFX11-NEXT: ; %bb.1: ; %else ; GFX11-NEXT: s_add_u32 s4, s4, s6 ; GFX11-NEXT: s_addc_u32 s5, s5, s7 -; GFX11-NEXT: s_mov_b32 s6, 0 ; GFX11-NEXT: s_cbranch_execnz .LBB9_3 ; GFX11-NEXT: .LBB9_2: ; %if ; GFX11-NEXT: s_load_b64 s[4:5], s[2:3], 0x0 @@ -1301,7 +1298,6 @@ define amdgpu_kernel void @add64_in_branch(ptr addrspace(1) %out, ptr addrspace( ; GFX11-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) ; GFX11-NEXT: s_endpgm ; GFX11-NEXT: .LBB9_4: -; GFX11-NEXT: s_mov_b32 s6, -1 ; GFX11-NEXT: ; implicit-def: $sgpr4_sgpr5 ; GFX11-NEXT: s_branch .LBB9_2 ; @@ -1313,7 +1309,6 @@ define amdgpu_kernel void @add64_in_branch(ptr addrspace(1) %out, ptr addrspace( ; GFX12-NEXT: s_cbranch_scc0 .LBB9_4 ; GFX12-NEXT: ; %bb.1: ; %else ; GFX12-NEXT: s_add_nc_u64 s[4:5], s[4:5], s[6:7] -; GFX12-NEXT: s_mov_b32 s6, 0 ; GFX12-NEXT: s_cbranch_execnz .LBB9_3 ; GFX12-NEXT: .LBB9_2: ; %if ; GFX12-NEXT: s_load_b64 s[4:5], s[2:3], 0x0 @@ -1326,7 +1321,6 @@ define amdgpu_kernel void @add64_in_branch(ptr addrspace(1) %out, ptr addrspace( ; GFX12-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) ; GFX12-NEXT: s_endpgm ; GFX12-NEXT: .LBB9_4: -; GFX12-NEXT: s_mov_b32 s6, -1 ; GFX12-NEXT: ; implicit-def: $sgpr4_sgpr5 ; GFX12-NEXT: s_branch .LBB9_2 entry: diff --git a/llvm/test/CodeGen/AMDGPU/ctpop16.ll b/llvm/test/CodeGen/AMDGPU/ctpop16.ll index 502e6f390433..b6359f181697 100644 --- a/llvm/test/CodeGen/AMDGPU/ctpop16.ll +++ b/llvm/test/CodeGen/AMDGPU/ctpop16.ll @@ -1499,7 +1499,6 @@ define amdgpu_kernel void @ctpop_i16_in_br(ptr addrspace(1) %out, ptr addrspace( ; SI-NEXT: s_mov_b32 s8, s2 ; SI-NEXT: s_mov_b32 s9, s3 ; SI-NEXT: buffer_load_ushort v0, off, s[8:11], 0 offset:2 -; SI-NEXT: s_mov_b64 s[2:3], 0 ; SI-NEXT: s_cbranch_execnz .LBB14_3 ; SI-NEXT: .LBB14_2: ; %if ; SI-NEXT: s_and_b32 s2, s4, 0xffff @@ -1513,7 +1512,6 @@ define amdgpu_kernel void @ctpop_i16_in_br(ptr addrspace(1) %out, ptr addrspace( ; SI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; SI-NEXT: s_endpgm ; SI-NEXT: .LBB14_4: -; SI-NEXT: s_mov_b64 s[2:3], -1 ; SI-NEXT: v_mov_b32_e32 v0, 0 ; SI-NEXT: s_branch .LBB14_2 ; @@ -1531,7 +1529,6 @@ define amdgpu_kernel void @ctpop_i16_in_br(ptr addrspace(1) %out, ptr addrspace( ; VI-NEXT: s_mov_b32 s8, s2 ; VI-NEXT: s_mov_b32 s9, s3 ; VI-NEXT: buffer_load_ushort v0, off, s[8:11], 0 offset:2 -; VI-NEXT: s_mov_b64 s[2:3], 0 ; VI-NEXT: s_cbranch_execnz .LBB14_3 ; VI-NEXT: .LBB14_2: ; %if ; VI-NEXT: s_and_b32 s2, s4, 0xffff @@ -1545,7 +1542,6 @@ define amdgpu_kernel void @ctpop_i16_in_br(ptr addrspace(1) %out, ptr addrspace( ; VI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; VI-NEXT: s_endpgm ; VI-NEXT: .LBB14_4: -; VI-NEXT: s_mov_b64 s[2:3], -1 ; VI-NEXT: ; implicit-def: $vgpr0 ; VI-NEXT: s_branch .LBB14_2 ; diff --git a/llvm/test/CodeGen/AMDGPU/ctpop64.ll b/llvm/test/CodeGen/AMDGPU/ctpop64.ll index 3b9c3e3ba175..131ce14a7847 100644 --- a/llvm/test/CodeGen/AMDGPU/ctpop64.ll +++ b/llvm/test/CodeGen/AMDGPU/ctpop64.ll @@ -358,7 +358,6 @@ define amdgpu_kernel void @ctpop_i64_in_br(ptr addrspace(1) %out, ptr addrspace( ; SI-NEXT: buffer_store_dwordx2 v[0:1], off, s[4:7], 0 ; SI-NEXT: s_endpgm ; SI-NEXT: .LBB7_4: -; SI-NEXT: s_mov_b64 s[6:7], -1 ; SI-NEXT: ; implicit-def: $sgpr0_sgpr1 ; SI-NEXT: s_branch .LBB7_2 ; @@ -372,7 +371,6 @@ define amdgpu_kernel void @ctpop_i64_in_br(ptr addrspace(1) %out, ptr addrspace( ; VI-NEXT: s_cbranch_scc0 .LBB7_4 ; VI-NEXT: ; %bb.1: ; %else ; VI-NEXT: s_load_dwordx2 s[0:1], s[6:7], 0x8 -; VI-NEXT: s_mov_b64 s[6:7], 0 ; VI-NEXT: s_cbranch_execnz .LBB7_3 ; VI-NEXT: .LBB7_2: ; %if ; VI-NEXT: s_waitcnt lgkmcnt(0) @@ -387,7 +385,6 @@ define amdgpu_kernel void @ctpop_i64_in_br(ptr addrspace(1) %out, ptr addrspace( ; VI-NEXT: buffer_store_dwordx2 v[0:1], off, s[4:7], 0 ; VI-NEXT: s_endpgm ; VI-NEXT: .LBB7_4: -; VI-NEXT: s_mov_b64 s[6:7], -1 ; VI-NEXT: ; implicit-def: $sgpr0_sgpr1 ; VI-NEXT: s_branch .LBB7_2 entry: diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.set.inactive.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.set.inactive.ll index f30c890934c9..8302af7450ed 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.set.inactive.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.set.inactive.ll @@ -100,7 +100,6 @@ define amdgpu_kernel void @set_inactive_scc(ptr addrspace(1) %out, i32 %in, <4 x ; GCN-NEXT: s_mov_b32 s3, 0xf000 ; GCN-NEXT: s_mov_b32 s2, -1 ; GCN-NEXT: buffer_store_dword v1, off, s[0:3], 0 -; GCN-NEXT: s_mov_b64 s[2:3], 0 ; GCN-NEXT: s_cbranch_execnz .LBB4_2 ; GCN-NEXT: .LBB4_4: ; %.zero ; GCN-NEXT: s_mov_b32 s3, 0xf000 diff --git a/llvm/test/CodeGen/AMDGPU/mul.ll b/llvm/test/CodeGen/AMDGPU/mul.ll index 0d2558c4f012..b4272049f36a 100644 --- a/llvm/test/CodeGen/AMDGPU/mul.ll +++ b/llvm/test/CodeGen/AMDGPU/mul.ll @@ -2517,7 +2517,6 @@ define amdgpu_kernel void @mul64_in_branch(ptr addrspace(1) %out, ptr addrspace( ; GFX10-NEXT: s_add_i32 s7, s8, s7 ; GFX10-NEXT: s_mul_i32 s4, s4, s6 ; GFX10-NEXT: s_add_i32 s5, s7, s5 -; GFX10-NEXT: s_mov_b32 s6, 0 ; GFX10-NEXT: s_cbranch_execnz .LBB16_4 ; GFX10-NEXT: .LBB16_2: ; %if ; GFX10-NEXT: s_mov_b32 s7, 0x31016000 @@ -2527,7 +2526,6 @@ define amdgpu_kernel void @mul64_in_branch(ptr addrspace(1) %out, ptr addrspace( ; GFX10-NEXT: buffer_load_dwordx2 v[0:1], off, s[4:7], 0 ; GFX10-NEXT: s_branch .LBB16_5 ; GFX10-NEXT: .LBB16_3: -; GFX10-NEXT: s_mov_b32 s6, -1 ; GFX10-NEXT: ; implicit-def: $sgpr4_sgpr5 ; GFX10-NEXT: s_branch .LBB16_2 ; GFX10-NEXT: .LBB16_4: @@ -2553,7 +2551,6 @@ define amdgpu_kernel void @mul64_in_branch(ptr addrspace(1) %out, ptr addrspace( ; GFX11-NEXT: s_add_i32 s7, s8, s7 ; GFX11-NEXT: s_mul_i32 s4, s4, s6 ; GFX11-NEXT: s_add_i32 s5, s7, s5 -; GFX11-NEXT: s_mov_b32 s6, 0 ; GFX11-NEXT: s_cbranch_execnz .LBB16_4 ; GFX11-NEXT: .LBB16_2: ; %if ; GFX11-NEXT: s_mov_b32 s7, 0x31016000 @@ -2563,7 +2560,6 @@ define amdgpu_kernel void @mul64_in_branch(ptr addrspace(1) %out, ptr addrspace( ; GFX11-NEXT: buffer_load_b64 v[0:1], off, s[4:7], 0 ; GFX11-NEXT: s_branch .LBB16_5 ; GFX11-NEXT: .LBB16_3: -; GFX11-NEXT: s_mov_b32 s6, -1 ; GFX11-NEXT: ; implicit-def: $sgpr4_sgpr5 ; GFX11-NEXT: s_branch .LBB16_2 ; GFX11-NEXT: .LBB16_4: @@ -2585,7 +2581,6 @@ define amdgpu_kernel void @mul64_in_branch(ptr addrspace(1) %out, ptr addrspace( ; GFX12-NEXT: s_cbranch_scc0 .LBB16_3 ; GFX12-NEXT: ; %bb.1: ; %else ; GFX12-NEXT: s_mul_u64 s[4:5], s[4:5], s[6:7] -; GFX12-NEXT: s_mov_b32 s6, 0 ; GFX12-NEXT: s_cbranch_execnz .LBB16_4 ; GFX12-NEXT: .LBB16_2: ; %if ; GFX12-NEXT: s_mov_b32 s7, 0x31016000 @@ -2595,7 +2590,6 @@ define amdgpu_kernel void @mul64_in_branch(ptr addrspace(1) %out, ptr addrspace( ; GFX12-NEXT: buffer_load_b64 v[0:1], off, s[4:7], null ; GFX12-NEXT: s_branch .LBB16_5 ; GFX12-NEXT: .LBB16_3: -; GFX12-NEXT: s_mov_b32 s6, -1 ; GFX12-NEXT: ; implicit-def: $sgpr4_sgpr5 ; GFX12-NEXT: s_branch .LBB16_2 ; GFX12-NEXT: .LBB16_4: -- GitLab From 561ddb1687c21b82feb92890762a85c2ae1f6e0c Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 10 Mar 2024 22:51:53 -0700 Subject: [PATCH 073/953] Revert "[TypePromotion] Support positive addition amounts in isSafeWrap. (#81690)" This reverts commit 0813b90ff5d195d8a40c280f6b745f1cc43e087a. Fixes miscompile reported in #84718. --- llvm/lib/CodeGen/TypePromotion.cpp | 125 ++++++++---------- llvm/test/CodeGen/AArch64/and-mask-removal.ll | 18 +-- .../AArch64/signed-truncation-check.ll | 2 +- .../CodeGen/AArch64/typepromotion-overflow.ll | 5 +- .../CodeGen/RISCV/typepromotion-overflow.ll | 5 +- .../Transforms/TypePromotion/ARM/icmps.ll | 7 +- .../Transforms/TypePromotion/ARM/wrapping.ll | 10 +- 7 files changed, 81 insertions(+), 91 deletions(-) diff --git a/llvm/lib/CodeGen/TypePromotion.cpp b/llvm/lib/CodeGen/TypePromotion.cpp index 34aeb62a87a0..48ad8de77801 100644 --- a/llvm/lib/CodeGen/TypePromotion.cpp +++ b/llvm/lib/CodeGen/TypePromotion.cpp @@ -136,7 +136,6 @@ public: class TypePromotionImpl { unsigned TypeSize = 0; - const TargetLowering *TLI = nullptr; LLVMContext *Ctx = nullptr; unsigned RegisterBitWidth = 0; SmallPtrSet AllVisited; @@ -273,58 +272,64 @@ bool TypePromotionImpl::isSink(Value *V) { /// Return whether this instruction can safely wrap. bool TypePromotionImpl::isSafeWrap(Instruction *I) { - // We can support a potentially wrapping Add/Sub instruction (I) if: + // We can support a potentially wrapping instruction (I) if: // - It is only used by an unsigned icmp. // - The icmp uses a constant. + // - The wrapping value (I) is decreasing, i.e would underflow - wrapping + // around zero to become a larger number than before. // - The wrapping instruction (I) also uses a constant. // - // This a common pattern emitted to check if a value is within a range. + // We can then use the two constants to calculate whether the result would + // wrap in respect to itself in the original bitwidth. If it doesn't wrap, + // just underflows the range, the icmp would give the same result whether the + // result has been truncated or not. We calculate this by: + // - Zero extending both constants, if needed, to RegisterBitWidth. + // - Take the absolute value of I's constant, adding this to the icmp const. + // - Check that this value is not out of range for small type. If it is, it + // means that it has underflowed enough to wrap around the icmp constant. // // For example: // - // %sub = sub i8 %a, C1 - // %cmp = icmp ule i8 %sub, C2 - // - // or - // - // %add = add i8 %a, C1 - // %cmp = icmp ule i8 %add, C2. - // - // We will treat an add as though it were a subtract by -C1. To promote - // the Add/Sub we will zero extend the LHS and the subtracted amount. For Add, - // this means we need to negate the constant, zero extend to RegisterBitWidth, - // and negate in the larger type. + // %sub = sub i8 %a, 2 + // %cmp = icmp ule i8 %sub, 254 // - // This will produce a value in the range [-zext(C1), zext(X)-zext(C1)] where - // C1 is the subtracted amount. This is either a small unsigned number or a - // large unsigned number in the promoted type. + // If %a = 0, %sub = -2 == FE == 254 + // But if this is evalulated as a i32 + // %sub = -2 == FF FF FF FE == 4294967294 + // So the unsigned compares (i8 and i32) would not yield the same result. // - // Now we need to correct the compare constant C2. Values >= C1 in the - // original add result range have been remapped to large values in the - // promoted range. If the compare constant fell into this range we need to - // remap it as well. We can do this as -(zext(-C2)). + // Another way to look at it is: + // %a - 2 <= 254 + // %a + 2 <= 254 + 2 + // %a <= 256 + // And we can't represent 256 in the i8 format, so we don't support it. // - // For example: + // Whereas: // - // %sub = sub i8 %a, 2 + // %sub i8 %a, 1 // %cmp = icmp ule i8 %sub, 254 // - // becomes + // If %a = 0, %sub = -1 == FF == 255 + // As i32: + // %sub = -1 == FF FF FF FF == 4294967295 // - // %zext = zext %a to i32 - // %sub = sub i32 %zext, 2 - // %cmp = icmp ule i32 %sub, 4294967294 + // In this case, the unsigned compare results would be the same and this + // would also be true for ult, uge and ugt: + // - (255 < 254) == (0xFFFFFFFF < 254) == false + // - (255 <= 254) == (0xFFFFFFFF <= 254) == false + // - (255 > 254) == (0xFFFFFFFF > 254) == true + // - (255 >= 254) == (0xFFFFFFFF >= 254) == true // - // Another example: + // To demonstrate why we can't handle increasing values: // - // %sub = sub i8 %a, 1 - // %cmp = icmp ule i8 %sub, 254 + // %add = add i8 %a, 2 + // %cmp = icmp ult i8 %add, 127 // - // becomes + // If %a = 254, %add = 256 == (i8 1) + // As i32: + // %add = 256 // - // %zext = zext %a to i32 - // %sub = sub i32 %zext, 1 - // %cmp = icmp ule i32 %sub, 254 + // (1 < 127) != (256 < 127) unsigned Opc = I->getOpcode(); if (Opc != Instruction::Add && Opc != Instruction::Sub) @@ -351,23 +356,15 @@ bool TypePromotionImpl::isSafeWrap(Instruction *I) { APInt OverflowConst = cast(I->getOperand(1))->getValue(); if (Opc == Instruction::Sub) OverflowConst = -OverflowConst; - - // If the constant is positive, we will end up filling the promoted bits with - // all 1s. Make sure that results in a cheap add constant. - if (!OverflowConst.isNonPositive()) { - // We don't have the true promoted width, just use 64 so we can create an - // int64_t for the isLegalAddImmediate call. - if (OverflowConst.getBitWidth() >= 64) - return false; - - APInt NewConst = -((-OverflowConst).zext(64)); - if (!TLI->isLegalAddImmediate(NewConst.getSExtValue())) - return false; - } + if (!OverflowConst.isNonPositive()) + return false; SafeWrap.insert(I); - if (OverflowConst.ugt(ICmpConst)) { + // Using C1 = OverflowConst and C2 = ICmpConst, we can either prove that: + // zext(x) + sext(C1) s C2 + // zext(x) + sext(C1) (Op)) { - // For subtract, we only need to zext the constant. We only put it in + // For subtract, we don't need to sext the constant. We only put it in // SafeWrap because SafeWrap.size() is used elsewhere. - // For Add and ICmp we need to find how far the constant is from the - // top of its original unsigned range and place it the same distance - // from the top of its new unsigned range. We can do this by negating - // the constant, zero extending it, then negating in the new type. - APInt NewConst; - if (SafeWrap.contains(I)) { - if (I->getOpcode() == Instruction::ICmp) - NewConst = -((-Const->getValue()).zext(PromotedWidth)); - else if (I->getOpcode() == Instruction::Add && i == 1) - NewConst = -((-Const->getValue()).zext(PromotedWidth)); - else - NewConst = Const->getValue().zext(PromotedWidth); - } else - NewConst = Const->getValue().zext(PromotedWidth); - - I->setOperand(i, ConstantInt::get(Const->getContext(), NewConst)); + // For cmp, we need to sign extend a constant appearing in either + // operand. For add, we should only sign extend the RHS. + Constant *NewConst = + ConstantInt::get(Const->getContext(), + (SafeWrap.contains(I) && + (I->getOpcode() == Instruction::ICmp || i == 1) && + I->getOpcode() != Instruction::Sub) + ? Const->getValue().sext(PromotedWidth) + : Const->getValue().zext(PromotedWidth)); + I->setOperand(i, NewConst); } else if (isa(Op)) I->setOperand(i, ConstantInt::get(ExtTy, 0)); } @@ -926,7 +917,7 @@ bool TypePromotionImpl::run(Function &F, const TargetMachine *TM, bool MadeChange = false; const DataLayout &DL = F.getParent()->getDataLayout(); const TargetSubtargetInfo *SubtargetInfo = TM->getSubtargetImpl(F); - TLI = SubtargetInfo->getTargetLowering(); + const TargetLowering *TLI = SubtargetInfo->getTargetLowering(); RegisterBitWidth = TTI.getRegisterBitWidth(TargetTransformInfo::RGK_Scalar).getFixedValue(); Ctx = &F.getParent()->getContext(); diff --git a/llvm/test/CodeGen/AArch64/and-mask-removal.ll b/llvm/test/CodeGen/AArch64/and-mask-removal.ll index a8a59f159126..17ff01597016 100644 --- a/llvm/test/CodeGen/AArch64/and-mask-removal.ll +++ b/llvm/test/CodeGen/AArch64/and-mask-removal.ll @@ -65,8 +65,9 @@ if.end: ; preds = %if.then, %entry define zeroext i1 @test8_0(i8 zeroext %x) align 2 { ; CHECK-LABEL: test8_0: ; CHECK: ; %bb.0: ; %entry -; CHECK-NEXT: sub w8, w0, #182 -; CHECK-NEXT: cmn w8, #20 +; CHECK-NEXT: add w8, w0, #74 +; CHECK-NEXT: and w8, w8, #0xff +; CHECK-NEXT: cmp w8, #236 ; CHECK-NEXT: cset w0, lo ; CHECK-NEXT: ret entry: @@ -507,17 +508,16 @@ define i64 @pr58109(i8 signext %0) { define i64 @pr58109b(i8 signext %0, i64 %a, i64 %b) { ; CHECK-SD-LABEL: pr58109b: ; CHECK-SD: ; %bb.0: -; CHECK-SD-NEXT: and w8, w0, #0xff -; CHECK-SD-NEXT: sub w8, w8, #255 -; CHECK-SD-NEXT: cmn w8, #254 -; CHECK-SD-NEXT: csel x0, x1, x2, lo +; CHECK-SD-NEXT: add w8, w0, #1 +; CHECK-SD-NEXT: tst w8, #0xfe +; CHECK-SD-NEXT: csel x0, x1, x2, eq ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: pr58109b: ; CHECK-GI: ; %bb.0: -; CHECK-GI-NEXT: mov w8, #-255 ; =0xffffff01 -; CHECK-GI-NEXT: add w8, w8, w0, uxtb -; CHECK-GI-NEXT: cmn w8, #254 +; CHECK-GI-NEXT: add w8, w0, #1 +; CHECK-GI-NEXT: and w8, w8, #0xff +; CHECK-GI-NEXT: cmp w8, #2 ; CHECK-GI-NEXT: csel x0, x1, x2, lo ; CHECK-GI-NEXT: ret %2 = add i8 %0, 1 diff --git a/llvm/test/CodeGen/AArch64/signed-truncation-check.ll b/llvm/test/CodeGen/AArch64/signed-truncation-check.ll index bb4df6d8935b..ab42e6463fee 100644 --- a/llvm/test/CodeGen/AArch64/signed-truncation-check.ll +++ b/llvm/test/CodeGen/AArch64/signed-truncation-check.ll @@ -396,7 +396,7 @@ define i1 @add_ultcmp_bad_i24_i8(i24 %x) nounwind { define i1 @add_ulecmp_bad_i16_i8(i16 %x) nounwind { ; CHECK-LABEL: add_ulecmp_bad_i16_i8: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w0, #1 // =0x1 +; CHECK-NEXT: mov w0, #1 ; CHECK-NEXT: ret %tmp0 = add i16 %x, 128 ; 1U << (8-1) %tmp1 = icmp ule i16 %tmp0, -1 ; when we +1 it, it will wrap to 0 diff --git a/llvm/test/CodeGen/AArch64/typepromotion-overflow.ll b/llvm/test/CodeGen/AArch64/typepromotion-overflow.ll index 39edc03ced44..ccfbf456693d 100644 --- a/llvm/test/CodeGen/AArch64/typepromotion-overflow.ll +++ b/llvm/test/CodeGen/AArch64/typepromotion-overflow.ll @@ -246,8 +246,9 @@ define i32 @safe_sub_var_imm(ptr nocapture readonly %b) local_unnamed_addr #1 { ; CHECK-LABEL: safe_sub_var_imm: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: ldrb w8, [x0] -; CHECK-NEXT: sub w8, w8, #248 -; CHECK-NEXT: cmn w8, #4 +; CHECK-NEXT: add w8, w8, #8 +; CHECK-NEXT: and w8, w8, #0xff +; CHECK-NEXT: cmp w8, #252 ; CHECK-NEXT: cset w0, hi ; CHECK-NEXT: ret entry: diff --git a/llvm/test/CodeGen/RISCV/typepromotion-overflow.ll b/llvm/test/CodeGen/RISCV/typepromotion-overflow.ll index ec7e0ecce80c..3740dc675949 100644 --- a/llvm/test/CodeGen/RISCV/typepromotion-overflow.ll +++ b/llvm/test/CodeGen/RISCV/typepromotion-overflow.ll @@ -283,8 +283,9 @@ define i32 @safe_sub_var_imm(ptr nocapture readonly %b) local_unnamed_addr #1 { ; CHECK-LABEL: safe_sub_var_imm: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: lbu a0, 0(a0) -; CHECK-NEXT: addi a0, a0, -248 -; CHECK-NEXT: sltiu a0, a0, -3 +; CHECK-NEXT: addi a0, a0, 8 +; CHECK-NEXT: andi a0, a0, 255 +; CHECK-NEXT: sltiu a0, a0, 253 ; CHECK-NEXT: xori a0, a0, 1 ; CHECK-NEXT: ret entry: diff --git a/llvm/test/Transforms/TypePromotion/ARM/icmps.ll b/llvm/test/Transforms/TypePromotion/ARM/icmps.ll index fb537a1f6470..842aab121b96 100644 --- a/llvm/test/Transforms/TypePromotion/ARM/icmps.ll +++ b/llvm/test/Transforms/TypePromotion/ARM/icmps.ll @@ -4,9 +4,8 @@ define i32 @test_ult_254_inc_imm(i8 zeroext %x) { ; CHECK-LABEL: @test_ult_254_inc_imm( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[X:%.*]] to i32 -; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], -255 -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], -2 +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X:%.*]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[ADD]], -2 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47 ; CHECK-NEXT: ret i32 [[RES]] ; @@ -369,7 +368,7 @@ if.end: define i32 @degenerateicmp() { ; CHECK-LABEL: @degenerateicmp( ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 190, 0 -; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 -31, [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 225, [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 1, i32 0 ; CHECK-NEXT: ret i32 [[TMP3]] ; diff --git a/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll b/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll index 78c5e7323cea..377708cf7113 100644 --- a/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll +++ b/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll @@ -89,9 +89,8 @@ define i32 @overflow_add_const_limit(i8 zeroext %a, i8 zeroext %b) { define i32 @overflow_add_positive_const_limit(i8 zeroext %a) { ; CHECK-LABEL: @overflow_add_positive_const_limit( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP1]], -255 -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[ADD]], -128 +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[A:%.*]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[ADD]], -128 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16 ; CHECK-NEXT: ret i32 [[RES]] ; @@ -145,9 +144,8 @@ define i32 @safe_add_underflow_neg(i8 zeroext %a) { define i32 @overflow_sub_negative_const_limit(i8 zeroext %a) { ; CHECK-LABEL: @overflow_sub_negative_const_limit( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[TMP1]], 255 -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[SUB]], -128 +; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[A:%.*]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[SUB]], -128 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16 ; CHECK-NEXT: ret i32 [[RES]] ; -- GitLab From 3093d731dff93df02899dcc62f5e7ba02461ff2a Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Mon, 11 Mar 2024 04:16:45 -0400 Subject: [PATCH 074/953] [clangd] Avoid libFormat's objective-c guessing heuristic where possible (#84133) This avoids a known libFormat bug where the heuristic can OOM on certain large files (particularly single-header libraries such as miniaudio.h). The OOM will still happen on affected files if you actually try to format them (this is harder to avoid since the underlyting issue affects the actual formatting logic, not just the language-guessing heuristic), but at least it's avoided during non-modifying operations like hover, and modifying operations that do local formatting like code completion. Fixes https://github.com/clangd/clangd/issues/719 Fixes https://github.com/clangd/clangd/issues/1384 Fixes https://github.com/llvm/llvm-project/issues/70945 --- clang-tools-extra/clangd/ClangdServer.cpp | 10 ++--- clang-tools-extra/clangd/CodeComplete.cpp | 4 +- clang-tools-extra/clangd/IncludeCleaner.cpp | 2 +- clang-tools-extra/clangd/ParsedAST.cpp | 2 +- clang-tools-extra/clangd/SourceCode.cpp | 16 +++++++- clang-tools-extra/clangd/SourceCode.h | 6 ++- clang-tools-extra/clangd/tool/Check.cpp | 2 +- .../clangd/unittests/SourceCodeTests.cpp | 38 +++++++++++++++++++ 8 files changed, 68 insertions(+), 12 deletions(-) diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index 2907e3ba3c30..5790273d625e 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -523,7 +523,7 @@ void ClangdServer::formatFile(PathRef File, std::optional Rng, auto Action = [File = File.str(), Code = std::move(*Code), Ranges = std::vector{RequestedRange}, CB = std::move(CB), this]() mutable { - format::FormatStyle Style = getFormatStyleForFile(File, Code, TFS); + format::FormatStyle Style = getFormatStyleForFile(File, Code, TFS, true); tooling::Replacements IncludeReplaces = format::sortIncludes(Style, Code, Ranges, File); auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces); @@ -551,7 +551,7 @@ void ClangdServer::formatOnType(PathRef File, Position Pos, auto Action = [File = File.str(), Code = std::move(*Code), TriggerText = TriggerText.str(), CursorPos = *CursorPos, CB = std::move(CB), this]() mutable { - auto Style = getFormatStyleForFile(File, Code, TFS); + auto Style = getFormatStyleForFile(File, Code, TFS, false); std::vector Result; for (const tooling::Replacement &R : formatIncremental(Code, CursorPos, TriggerText, Style)) @@ -605,7 +605,7 @@ void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName, if (Opts.WantFormat) { auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents, - *InpAST->Inputs.TFS); + *InpAST->Inputs.TFS, false); llvm::Error Err = llvm::Error::success(); for (auto &E : R->GlobalChanges) Err = @@ -762,7 +762,7 @@ void ClangdServer::applyTweak(PathRef File, Range Sel, StringRef TweakID, for (auto &It : (*Effect)->ApplyEdits) { Edit &E = It.second; format::FormatStyle Style = - getFormatStyleForFile(File, E.InitialCode, TFS); + getFormatStyleForFile(File, E.InitialCode, TFS, false); if (llvm::Error Err = reformatEdit(E, Style)) elog("Failed to format {0}: {1}", It.first(), std::move(Err)); } @@ -825,7 +825,7 @@ void ClangdServer::findHover(PathRef File, Position Pos, if (!InpAST) return CB(InpAST.takeError()); format::FormatStyle Style = getFormatStyleForFile( - File, InpAST->Inputs.Contents, *InpAST->Inputs.TFS); + File, InpAST->Inputs.Contents, *InpAST->Inputs.TFS, false); CB(clangd::getHover(InpAST->AST, Pos, std::move(Style), Index)); }; diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 0e5f08cec440..036eb9808ea0 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -1628,7 +1628,7 @@ public: IsUsingDeclaration = Recorder->CCContext.isUsingDeclaration(); auto Style = getFormatStyleForFile(SemaCCInput.FileName, SemaCCInput.ParseInput.Contents, - *SemaCCInput.ParseInput.TFS); + *SemaCCInput.ParseInput.TFS, false); const auto NextToken = findTokenAfterCompletionPoint( Recorder->CCSema->getPreprocessor().getCodeCompletionLoc(), Recorder->CCSema->getSourceManager(), Recorder->CCSema->LangOpts); @@ -1719,7 +1719,7 @@ public: ProxSources[FileName].Cost = 0; FileProximity.emplace(ProxSources); - auto Style = getFormatStyleForFile(FileName, Content, TFS); + auto Style = getFormatStyleForFile(FileName, Content, TFS, false); // This will only insert verbatim headers. Inserter.emplace(FileName, Content, Style, /*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr); diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp b/clang-tools-extra/clangd/IncludeCleaner.cpp index 7375b7b08609..8e48f546d94e 100644 --- a/clang-tools-extra/clangd/IncludeCleaner.cpp +++ b/clang-tools-extra/clangd/IncludeCleaner.cpp @@ -116,7 +116,7 @@ std::vector generateMissingIncludeDiagnostics( const SourceManager &SM = AST.getSourceManager(); const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID()); - auto FileStyle = getFormatStyleForFile(AST.tuPath(), Code, TFS); + auto FileStyle = getFormatStyleForFile(AST.tuPath(), Code, TFS, false); tooling::HeaderIncludes HeaderIncludes(AST.tuPath(), Code, FileStyle.IncludeStyle); diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp index 862f06196a71..3ff759415f7c 100644 --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -626,7 +626,7 @@ ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs, // (e.g. incomplete type) and attach include insertion fixes to diagnostics. if (Inputs.Index && !BuildDir.getError()) { auto Style = - getFormatStyleForFile(Filename, Inputs.Contents, *Inputs.TFS); + getFormatStyleForFile(Filename, Inputs.Contents, *Inputs.TFS, false); auto Inserter = std::make_shared( Filename, Inputs.Contents, Style, BuildDir.get(), &Clang->getPreprocessor().getHeaderSearchInfo()); diff --git a/clang-tools-extra/clangd/SourceCode.cpp b/clang-tools-extra/clangd/SourceCode.cpp index 3e741f6e0b53..3af99b9db056 100644 --- a/clang-tools-extra/clangd/SourceCode.cpp +++ b/clang-tools-extra/clangd/SourceCode.cpp @@ -582,7 +582,21 @@ std::optional digestFile(const SourceManager &SM, FileID FID) { format::FormatStyle getFormatStyleForFile(llvm::StringRef File, llvm::StringRef Content, - const ThreadsafeFS &TFS) { + const ThreadsafeFS &TFS, + bool FormatFile) { + // Unless we're formatting a substantial amount of code (the entire file + // or an arbitrarily large range), skip libFormat's heuristic check for + // .h files that tries to determine whether the file contains objective-c + // code. (This is accomplished by passing empty code contents to getStyle(). + // The heuristic is the only thing that looks at the contents.) + // This is a workaround for PR60151, a known issue in libFormat where this + // heuristic can OOM on large files. If we *are* formatting the entire file, + // there's no point in doing this because the actual format::reformat() call + // will run into the same OOM; we'd just be risking inconsistencies between + // clangd and clang-format on smaller .h files where they disagree on what + // language is detected. + if (!FormatFile) + Content = {}; auto Style = format::getStyle(format::DefaultFormatStyle, File, format::DefaultFallbackStyle, Content, TFS.view(/*CWD=*/std::nullopt).get()); diff --git a/clang-tools-extra/clangd/SourceCode.h b/clang-tools-extra/clangd/SourceCode.h index a1bb44c17612..028549f659d6 100644 --- a/clang-tools-extra/clangd/SourceCode.h +++ b/clang-tools-extra/clangd/SourceCode.h @@ -171,9 +171,13 @@ std::optional getCanonicalPath(const FileEntryRef F, /// FIXME: should we be caching the .clang-format file search? /// This uses format::DefaultFormatStyle and format::DefaultFallbackStyle, /// though the latter may have been overridden in main()! +/// \p FormatFile indicates whether the returned FormatStyle is used +/// to format the entire main file (or a range selected by the user +/// which can be arbitrarily long). format::FormatStyle getFormatStyleForFile(llvm::StringRef File, llvm::StringRef Content, - const ThreadsafeFS &TFS); + const ThreadsafeFS &TFS, + bool FormatFile); /// Cleanup and format the given replacements. llvm::Expected diff --git a/clang-tools-extra/clangd/tool/Check.cpp b/clang-tools-extra/clangd/tool/Check.cpp index b5c4d145619d..45e2e1e278de 100644 --- a/clang-tools-extra/clangd/tool/Check.cpp +++ b/clang-tools-extra/clangd/tool/Check.cpp @@ -226,7 +226,7 @@ public: // FIXME: Check that resource-dir/built-in-headers exist? - Style = getFormatStyleForFile(File, Inputs.Contents, TFS); + Style = getFormatStyleForFile(File, Inputs.Contents, TFS, false); return true; } diff --git a/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp b/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp index 1be5b7f6a8db..801d535c1b9d 100644 --- a/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp +++ b/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp @@ -1090,6 +1090,44 @@ TEST(ApplyEditsTest, EndLineOutOfRange) { FailedWithMessage("Line value is out of range (100)")); } +TEST(FormatStyleForFile, LanguageGuessingHeuristic) { + StringRef ObjCContent = "@interface Foo\n@end\n"; + StringRef CppContent = "class Foo {};\n"; + using LK = format::FormatStyle::LanguageKind; + struct TestCase { + llvm::StringRef Filename; + llvm::StringRef Contents; + bool FormatFile; + LK ExpectedLanguage; + } TestCases[] = { + // If the file extension identifies the file as ObjC, the guessed + // language should be ObjC regardless of content or FormatFile flag. + {"foo.mm", ObjCContent, true, LK::LK_ObjC}, + {"foo.mm", ObjCContent, false, LK::LK_ObjC}, + {"foo.mm", CppContent, true, LK::LK_ObjC}, + {"foo.mm", CppContent, false, LK::LK_ObjC}, + + // If the file extension is ambiguous like .h, FormatFile=true should + // result in using libFormat's heuristic to guess the language based + // on the file contents. + {"foo.h", ObjCContent, true, LK::LK_ObjC}, + {"foo.h", CppContent, true, LK::LK_Cpp}, + + // With FomatFile=false, the language guessing heuristic should be + // bypassed + {"foo.h", ObjCContent, false, LK::LK_Cpp}, + {"foo.h", CppContent, false, LK::LK_Cpp}, + }; + + MockFS FS; + for (const auto &[Filename, Contents, FormatFile, ExpectedLanguage] : + TestCases) { + EXPECT_EQ( + getFormatStyleForFile(Filename, Contents, FS, FormatFile).Language, + ExpectedLanguage); + } +} + } // namespace } // namespace clangd } // namespace clang -- GitLab From d4569d42b5cb8ba076f0115d3d21d89f68e6ce9d Mon Sep 17 00:00:00 2001 From: Pierre van Houtryve Date: Mon, 11 Mar 2024 09:20:01 +0100 Subject: [PATCH 075/953] [AMDGPU] Let LowerModuleLDS run twice on the same module (#81729) If all variables in the module are absolute, this means we're running the pass again on an already lowered module, and that works. If none of them are absolute, lowering can proceed as usual. Only diagnose cases where we have a mix of absolute/non-absolute GVs, which means we added LDS GVs after lowering, which is broken. See #81491 Split from #75333 --- .../Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp | 18 ++++++++++++++---- ... => lds-reject-mixed-absolute-addresses.ll} | 4 ++-- .../AMDGPU/lds-run-twice-absolute-md.ll | 16 ++++++++++++++++ llvm/test/CodeGen/AMDGPU/lds-run-twice.ll | 14 ++++++++++++++ 4 files changed, 46 insertions(+), 6 deletions(-) rename llvm/test/CodeGen/AMDGPU/{lds-reject-absolute-addresses.ll => lds-reject-mixed-absolute-addresses.ll} (81%) create mode 100644 llvm/test/CodeGen/AMDGPU/lds-run-twice-absolute-md.ll create mode 100644 llvm/test/CodeGen/AMDGPU/lds-run-twice.ll diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp index 5762f1906a16..b85cb26fdc95 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp @@ -340,15 +340,25 @@ public: // Get uses from the current function, excluding uses by called functions // Two output variables to avoid walking the globals list twice + std::optional HasAbsoluteGVs; for (auto &GV : M.globals()) { if (!AMDGPU::isLDSVariableToLower(GV)) { continue; } - if (GV.isAbsoluteSymbolRef()) { - report_fatal_error( - "LDS variables with absolute addresses are unimplemented."); - } + // Check if the module is consistent: either all GVs are absolute (happens + // when we run the pass more than once), or none are. + const bool IsAbsolute = GV.isAbsoluteSymbolRef(); + if (HasAbsoluteGVs.has_value()) { + if (*HasAbsoluteGVs != IsAbsolute) { + report_fatal_error( + "Module cannot mix absolute and non-absolute LDS GVs"); + } + } else + HasAbsoluteGVs = IsAbsolute; + + if (IsAbsolute) + continue; for (User *V : GV.users()) { if (auto *I = dyn_cast(V)) { diff --git a/llvm/test/CodeGen/AMDGPU/lds-reject-absolute-addresses.ll b/llvm/test/CodeGen/AMDGPU/lds-reject-mixed-absolute-addresses.ll similarity index 81% rename from llvm/test/CodeGen/AMDGPU/lds-reject-absolute-addresses.ll rename to llvm/test/CodeGen/AMDGPU/lds-reject-mixed-absolute-addresses.ll index 659cdb55ded2..b512a43aa102 100644 --- a/llvm/test/CodeGen/AMDGPU/lds-reject-absolute-addresses.ll +++ b/llvm/test/CodeGen/AMDGPU/lds-reject-mixed-absolute-addresses.ll @@ -2,8 +2,9 @@ ; RUN: not --crash opt -S -mtriple=amdgcn-- -passes=amdgpu-lower-module-lds < %s 2>&1 | FileCheck %s @var1 = addrspace(3) global i32 undef, !absolute_symbol !0 +@var2 = addrspace(3) global i32 undef -; CHECK: LLVM ERROR: LDS variables with absolute addresses are unimplemented. +; CHECK: Module cannot mix absolute and non-absolute LDS GVs define amdgpu_kernel void @kern() { %val0 = load i32, ptr addrspace(3) @var1 %val1 = add i32 %val0, 4 @@ -12,4 +13,3 @@ define amdgpu_kernel void @kern() { } !0 = !{i32 0, i32 1} - diff --git a/llvm/test/CodeGen/AMDGPU/lds-run-twice-absolute-md.ll b/llvm/test/CodeGen/AMDGPU/lds-run-twice-absolute-md.ll new file mode 100644 index 000000000000..52b44eea35c8 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/lds-run-twice-absolute-md.ll @@ -0,0 +1,16 @@ +; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds %s -o %t.ll +; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds %t.ll -o %t.second.ll +; RUN: diff -ub %t.ll %t.second.ll -I ".*ModuleID.*" + +; Check AMDGPULowerModuleLDS can run more than once on the same module, and that +; the second run is a no-op. + +@lds = internal unnamed_addr addrspace(3) global i32 undef, align 4, !absolute_symbol !0 + +define amdgpu_kernel void @test() { +entry: + store i32 1, ptr addrspace(3) @lds + ret void +} + +!0 = !{i32 0, i32 1} diff --git a/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll b/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll new file mode 100644 index 000000000000..b830ccb944a2 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll @@ -0,0 +1,14 @@ +; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds %s -o %t.ll +; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds %t.ll -o %t.second.ll +; RUN: diff -ub %t.ll %t.second.ll -I ".*ModuleID.*" + +; Check AMDGPULowerModuleLDS can run more than once on the same module, and that +; the second run is a no-op. + +@lds = internal unnamed_addr addrspace(3) global i32 undef, align 4 + +define amdgpu_kernel void @test() { +entry: + store i32 1, ptr addrspace(3) @lds + ret void +} -- GitLab From f1aa7837884c745ede497e365cc75d5581ecc714 Mon Sep 17 00:00:00 2001 From: Matthias Springer Date: Mon, 11 Mar 2024 17:36:18 +0900 Subject: [PATCH 076/953] [mlir][IR] Fix overload resolution on MSVC build (#84589) #82629 added additional overloads to `replaceAllUsesWith` and `replaceUsesWithIf`. This caused a build breakage with MSVC when called with ops that can implicitly convert to `Value`. ``` external/llvm-project/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp(881): error C2666: 'mlir::RewriterBase::replaceAllUsesWith': 2 overloads have similar conversions external/llvm-project/mlir/include\mlir/IR/PatternMatch.h(631): note: could be 'void mlir::RewriterBase::replaceAllUsesWith(mlir::Operation *,mlir::ValueRange)' external/llvm-project/mlir/include\mlir/IR/PatternMatch.h(626): note: or 'void mlir::RewriterBase::replaceAllUsesWith(mlir::ValueRange,mlir::ValueRange)' external/llvm-project/mlir/include\mlir/IR/PatternMatch.h(616): note: or 'void mlir::RewriterBase::replaceAllUsesWith(mlir::Value,mlir::Value)' external/llvm-project/mlir/lib/Dialect/SCF/Transforms/TileUsingInterface.cpp(882): note: while trying to match the argument list '(mlir::tensor::ExtractSliceOp, T)' with [ T=mlir::Value ] ``` Note: The LLVM build bots (Linux and Windows) did not break, this seems to be an issue with `Tools\MSVC\14.29.30133\bin\HostX64\x64\cl.exe`. This change renames the newly added overloads to `replaceAllOpUsesWith` and `replaceOpUsesWithIf`. --- mlir/include/mlir/IR/PatternMatch.h | 20 ++++++++++++------- .../Linalg/Transforms/DecomposeLinalgOps.cpp | 4 ++-- mlir/lib/IR/PatternMatch.cpp | 4 ++-- mlir/lib/Transforms/Utils/RegionUtils.cpp | 2 +- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/mlir/include/mlir/IR/PatternMatch.h b/mlir/include/mlir/IR/PatternMatch.h index 49544c42790d..ef53a0b82866 100644 --- a/mlir/include/mlir/IR/PatternMatch.h +++ b/mlir/include/mlir/IR/PatternMatch.h @@ -648,7 +648,10 @@ public: for (auto it : llvm::zip(from, to)) replaceAllUsesWith(std::get<0>(it), std::get<1>(it)); } - void replaceAllUsesWith(Operation *from, ValueRange to) { + // Note: This function cannot be called `replaceAllUsesWith` because the + // overload resolution, when called with an op that can be implicitly + // converted to a Value, would be ambiguous. + void replaceAllOpUsesWith(Operation *from, ValueRange to) { replaceAllUsesWith(from->getResults(), to); } @@ -662,9 +665,12 @@ public: void replaceUsesWithIf(ValueRange from, ValueRange to, function_ref functor, bool *allUsesReplaced = nullptr); - void replaceUsesWithIf(Operation *from, ValueRange to, - function_ref functor, - bool *allUsesReplaced = nullptr) { + // Note: This function cannot be called `replaceOpUsesWithIf` because the + // overload resolution, when called with an op that can be implicitly + // converted to a Value, would be ambiguous. + void replaceOpUsesWithIf(Operation *from, ValueRange to, + function_ref functor, + bool *allUsesReplaced = nullptr) { replaceUsesWithIf(from->getResults(), to, functor, allUsesReplaced); } @@ -672,9 +678,9 @@ public: /// the listener about every in-place op modification (for every use that was /// replaced). The optional `allUsesReplaced` flag is set to "true" if all /// uses were replaced. - void replaceUsesWithinBlock(Operation *op, ValueRange newValues, Block *block, - bool *allUsesReplaced = nullptr) { - replaceUsesWithIf( + void replaceOpUsesWithinBlock(Operation *op, ValueRange newValues, + Block *block, bool *allUsesReplaced = nullptr) { + replaceOpUsesWithIf( op, newValues, [block](OpOperand &use) { return block->getParentOp()->isProperAncestor(use.getOwner()); diff --git a/mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp b/mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp index 1658ea67a460..999359c7fa87 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp @@ -370,8 +370,8 @@ DecomposeLinalgOp::matchAndRewrite(GenericOp genericOp, scalarReplacements.push_back( residualGenericOpBody->getArgument(num + origNumInputs)); bool allUsesReplaced = false; - rewriter.replaceUsesWithinBlock(peeledScalarOperation, scalarReplacements, - residualGenericOpBody, &allUsesReplaced); + rewriter.replaceOpUsesWithinBlock(peeledScalarOperation, scalarReplacements, + residualGenericOpBody, &allUsesReplaced); assert(!allUsesReplaced && "peeled scalar operation is erased when it wasnt expected to be"); } diff --git a/mlir/lib/IR/PatternMatch.cpp b/mlir/lib/IR/PatternMatch.cpp index 0a88e40f73ec..4079ccc75672 100644 --- a/mlir/lib/IR/PatternMatch.cpp +++ b/mlir/lib/IR/PatternMatch.cpp @@ -122,7 +122,7 @@ void RewriterBase::replaceOp(Operation *op, ValueRange newValues) { rewriteListener->notifyOperationReplaced(op, newValues); // Replace all result uses. Also notifies the listener of modifications. - replaceAllUsesWith(op, newValues); + replaceAllOpUsesWith(op, newValues); // Erase op and notify listener. eraseOp(op); @@ -141,7 +141,7 @@ void RewriterBase::replaceOp(Operation *op, Operation *newOp) { rewriteListener->notifyOperationReplaced(op, newOp); // Replace all result uses. Also notifies the listener of modifications. - replaceAllUsesWith(op, newOp->getResults()); + replaceAllOpUsesWith(op, newOp->getResults()); // Erase op and notify listener. eraseOp(op); diff --git a/mlir/lib/Transforms/Utils/RegionUtils.cpp b/mlir/lib/Transforms/Utils/RegionUtils.cpp index eff8acdfb33d..e25867b527b7 100644 --- a/mlir/lib/Transforms/Utils/RegionUtils.cpp +++ b/mlir/lib/Transforms/Utils/RegionUtils.cpp @@ -161,7 +161,7 @@ SmallVector mlir::makeRegionIsolatedFromAbove( rewriter.setInsertionPointToStart(newEntryBlock); for (auto *clonedOp : clonedOperations) { Operation *newOp = rewriter.clone(*clonedOp, map); - rewriter.replaceUsesWithIf(clonedOp, newOp->getResults(), replaceIfFn); + rewriter.replaceOpUsesWithIf(clonedOp, newOp->getResults(), replaceIfFn); } rewriter.mergeBlocks( entryBlock, newEntryBlock, -- GitLab From c9465e4771c93adfbc99ffca5963a48a5334d98d Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Mon, 11 Mar 2024 08:58:59 +0000 Subject: [PATCH 077/953] [DebugInfo][RemoveDIs] Assert if we mix PHIs and debug-info (#84054) A potentially erroneous code construction with the work we've done to remove debug intrinsics, is inserting PHIs into blocks when the position hasn't been "sourced correctly". Specifically, if you have: %foo = PHI #dbg_value %bar = add i32... And plan on inserting a new PHI, you have to use the iterator form of `getFirstNonPHI` or getFirstInsertionPt (or begin()) to acquire an iterator that tells the debug-info maintenance code "this is supposed to be at the start of the block, put it in front of #dbg_value". We can detect call-sites that aren't doing this at runtime, and should do with this assertion. It might invalidate code that's doing something very unexpected, like walking backwards to find a PHI, then going forwards, then inserting: however that's just an inefficient way of calling `getFirstNonPHI`. --- llvm/lib/IR/Instruction.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index ce221758ef79..e863ef3eb8d6 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -149,6 +149,18 @@ void Instruction::insertBefore(BasicBlock &BB, if (!InsertAtHead) { DPMarker *SrcMarker = BB.getMarker(InsertPos); if (SrcMarker && !SrcMarker->empty()) { + // If this assertion fires, the calling code is about to insert a PHI + // after debug-records, which would form a sequence like: + // %0 = PHI + // #dbg_value + // %1 = PHI + // Which is de-normalised and undesired -- hence the assertion. To avoid + // this, you must insert at that position using an iterator, and it must + // be aquired by calling getFirstNonPHIIt / begin or similar methods on + // the block. This will signal to this behind-the-scenes debug-info + // maintenence code that you intend the PHI to be ahead of everything, + // including any debug-info. + assert(!isa(this) && "Inserting PHI after debug-records!"); adoptDbgValues(&BB, InsertPos, false); } } -- GitLab From 0f501c30b9601627c236f9abca8a3befba5dc161 Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Mon, 11 Mar 2024 16:52:18 +0800 Subject: [PATCH 078/953] Revert "[C++20][Coroutines] Lambda-coroutine with operator new in promise_type (#84193)" This reverts commit 35d3b33ba5c9b90443ac985f2521b78f84b611fe. See the comments in https://github.com/llvm/llvm-project/pull/84193 for details --- clang/include/clang/Sema/Sema.h | 12 +---- clang/lib/Sema/SemaCoroutine.cpp | 18 +------- clang/lib/Sema/SemaExprCXX.cpp | 16 ++----- clang/test/SemaCXX/gh84064-1.cpp | 79 -------------------------------- clang/test/SemaCXX/gh84064-2.cpp | 53 --------------------- 5 files changed, 9 insertions(+), 169 deletions(-) delete mode 100644 clang/test/SemaCXX/gh84064-1.cpp delete mode 100644 clang/test/SemaCXX/gh84064-2.cpp diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 00b3f53f5c1c..267c79cc057c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6752,18 +6752,10 @@ public: SourceLocation RParenLoc); //// ActOnCXXThis - Parse 'this' pointer. - /// - /// \param ThisRefersToClosureObject Whether to skip the 'this' check for a - /// lambda because 'this' refers to the closure object. - ExprResult ActOnCXXThis(SourceLocation loc, - bool ThisRefersToClosureObject = false); + ExprResult ActOnCXXThis(SourceLocation loc); /// Build a CXXThisExpr and mark it referenced in the current context. - /// - /// \param ThisRefersToClosureObject Whether to skip the 'this' check for a - /// lambda because 'this' refers to the closure object. - Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit, - bool ThisRefersToClosureObject = false); + Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit); void MarkThisReferenced(CXXThisExpr *This); /// Try to retrieve the type of the 'this' pointer. diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 5206fc7621c7..736632857efc 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -25,7 +25,6 @@ #include "clang/Sema/Initialization.h" #include "clang/Sema/Overload.h" #include "clang/Sema/ScopeInfo.h" -#include "clang/Sema/Sema.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/SmallSet.h" @@ -1291,21 +1290,8 @@ bool CoroutineStmtBuilder::makeReturnOnAllocFailure() { static bool collectPlacementArgs(Sema &S, FunctionDecl &FD, SourceLocation Loc, SmallVectorImpl &PlacementArgs) { if (auto *MD = dyn_cast(&FD)) { - if (MD->isImplicitObjectMemberFunction()) { - ExprResult ThisExpr{}; - - if (isLambdaCallOperator(MD) && !MD->isStatic()) { - Qualifiers ThisQuals = MD->getMethodQualifiers(); - CXXRecordDecl *Record = MD->getParent(); - - Sema::CXXThisScopeRAII ThisScope(S, Record, ThisQuals, - Record != nullptr); - - ThisExpr = S.ActOnCXXThis(Loc, /*ThisRefersToClosureObject=*/true); - } else { - ThisExpr = S.ActOnCXXThis(Loc); - } - + if (MD->isImplicitObjectMemberFunction() && !isLambdaCallOperator(MD)) { + ExprResult ThisExpr = S.ActOnCXXThis(Loc); if (ThisExpr.isInvalid()) return false; ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get()); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 88e3d9ced044..c34a40fa7c81 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1414,8 +1414,7 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, return false; } -ExprResult Sema::ActOnCXXThis(SourceLocation Loc, - bool ThisRefersToClosureObject) { +ExprResult Sema::ActOnCXXThis(SourceLocation Loc) { /// C++ 9.3.2: In the body of a non-static member function, the keyword this /// is a non-lvalue expression whose value is the address of the object for /// which the function is called. @@ -1435,18 +1434,13 @@ ExprResult Sema::ActOnCXXThis(SourceLocation Loc, return Diag(Loc, diag::err_invalid_this_use) << 0; } - return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false, - ThisRefersToClosureObject); + return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false); } -Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit, - bool ThisRefersToClosureObject) { +Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type, + bool IsImplicit) { auto *This = CXXThisExpr::Create(Context, Loc, Type, IsImplicit); - - if (!ThisRefersToClosureObject) { - MarkThisReferenced(This); - } - + MarkThisReferenced(This); return This; } diff --git a/clang/test/SemaCXX/gh84064-1.cpp b/clang/test/SemaCXX/gh84064-1.cpp deleted file mode 100644 index d9c2738a002b..000000000000 --- a/clang/test/SemaCXX/gh84064-1.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -I%S/Inputs -std=c++20 %s - -// expected-no-diagnostics - -#include "std-coroutine.h" - -using size_t = decltype(sizeof(0)); - -struct Generator { - struct promise_type { - int _val{}; - - Generator get_return_object() noexcept - { - return {}; - } - - std::suspend_never initial_suspend() noexcept - { - return {}; - } - - std::suspend_always final_suspend() noexcept - { - return {}; - } - - void return_void() noexcept {} - void unhandled_exception() noexcept {} - - template - static void* - operator new(size_t size, - This&, - TheRest&&...) noexcept - { - return nullptr; - } - - static void operator delete(void*, size_t) - { - } - }; -}; - -struct CapturingThisTest -{ - int x{}; - - void AsPointer() - { - auto lamb = [=,this]() -> Generator { - int y = x; - co_return; - }; - - static_assert(sizeof(decltype(lamb)) == sizeof(void*)); - } - - void AsStarThis() - { - auto lamb = [*this]() -> Generator { - int y = x; - co_return; - }; - - static_assert(sizeof(decltype(lamb)) == sizeof(int)); - } -}; - -int main() -{ - auto lamb = []() -> Generator { - co_return; - }; - - static_assert(sizeof(decltype(lamb)) == 1); -} - diff --git a/clang/test/SemaCXX/gh84064-2.cpp b/clang/test/SemaCXX/gh84064-2.cpp deleted file mode 100644 index 457de43eab6d..000000000000 --- a/clang/test/SemaCXX/gh84064-2.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -I%S/Inputs -std=c++23 %s - -// expected-no-diagnostics - -#include "std-coroutine.h" - -using size_t = decltype(sizeof(0)); - -struct GeneratorStatic { - struct promise_type { - int _val{}; - - GeneratorStatic get_return_object() noexcept - { - return {}; - } - - std::suspend_never initial_suspend() noexcept - { - return {}; - } - - std::suspend_always final_suspend() noexcept - { - return {}; - } - - void return_void() noexcept {} - void unhandled_exception() noexcept {} - - template - static void* - operator new(size_t size, - TheRest&&...) noexcept - { - return nullptr; - } - - static void operator delete(void*, size_t) - { - } - }; -}; - - -int main() -{ - auto lambCpp23 = []() static -> GeneratorStatic { - co_return; - }; - - static_assert(sizeof(decltype(lambCpp23)) == 1); -} -- GitLab From 3b30559c088d679ca8fe491158e6c32db630f223 Mon Sep 17 00:00:00 2001 From: Kareem Ergawy Date: Mon, 11 Mar 2024 10:38:28 +0100 Subject: [PATCH 079/953] [flang][OpenMP] Only use HLFIR base in privatization logic (#84123) Modifies the privatization logic so that the emitted code only used the HLFIR base (i.e. SSA value `#0` returned from `hlfir.declare`). Before that, that emitted privatization logic was a mix of using `#0` and `#1` which leads to some difficulties trying to move to delayed privatization (see the discussion on #84033). --- .../flang/Optimizer/Builder/HLFIRTools.h | 3 +- flang/lib/Lower/Bridge.cpp | 13 ++++--- flang/lib/Optimizer/Builder/HLFIRTools.cpp | 31 +++++++++-------- .../OpenMP/parallel-private-clause-str.f90 | 10 +++--- .../Lower/OpenMP/parallel-private-clause.f90 | 34 +++++++++---------- 5 files changed, 49 insertions(+), 42 deletions(-) diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h index 170e134baef6..ce87941d5382 100644 --- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h +++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h @@ -230,7 +230,8 @@ translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder, /// on the IR. fir::ExtendedValue translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder, - fir::FortranVariableOpInterface fortranVariable); + fir::FortranVariableOpInterface fortranVariable, + bool forceHlfirBase = false); /// Generate declaration for a fir::ExtendedValue in memory. fir::FortranVariableOpInterface diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 8048693119b4..a668ba4116fa 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -618,7 +618,8 @@ public: assert(details && "No host-association found"); const Fortran::semantics::Symbol &hsym = details->symbol(); mlir::Type hSymType = genType(hsym); - Fortran::lower::SymbolBox hsb = lookupSymbol(hsym); + Fortran::lower::SymbolBox hsb = + lookupSymbol(hsym, /*symMap=*/nullptr, /*forceHlfirBase=*/true); auto allocate = [&](llvm::ArrayRef shape, llvm::ArrayRef typeParams) -> mlir::Value { @@ -727,7 +728,8 @@ public: void createHostAssociateVarCloneDealloc( const Fortran::semantics::Symbol &sym) override final { mlir::Location loc = genLocation(sym.name()); - Fortran::lower::SymbolBox hsb = lookupSymbol(sym); + Fortran::lower::SymbolBox hsb = + lookupSymbol(sym, /*symMap=*/nullptr, /*forceHlfirBase=*/true); fir::ExtendedValue hexv = symBoxToExtendedValue(hsb); hexv.match( @@ -960,13 +962,14 @@ private: /// Find the symbol in the local map or return null. Fortran::lower::SymbolBox lookupSymbol(const Fortran::semantics::Symbol &sym, - Fortran::lower::SymMap *symMap = nullptr) { + Fortran::lower::SymMap *symMap = nullptr, + bool forceHlfirBase = false) { symMap = symMap ? symMap : &localSymbols; if (lowerToHighLevelFIR()) { if (std::optional var = symMap->lookupVariableDefinition(sym)) { - auto exv = - hlfir::translateToExtendedValue(toLocation(), *builder, *var); + auto exv = hlfir::translateToExtendedValue(toLocation(), *builder, *var, + forceHlfirBase); return exv.match( [](mlir::Value x) -> Fortran::lower::SymbolBox { return Fortran::lower::SymbolBox::Intrinsic{x}; diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp index 4ffa303f2710..0e0b14e8d690 100644 --- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp +++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp @@ -848,36 +848,38 @@ hlfir::LoopNest hlfir::genLoopNest(mlir::Location loc, static fir::ExtendedValue translateVariableToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder, - hlfir::Entity variable) { + hlfir::Entity variable, + bool forceHlfirBase = false) { assert(variable.isVariable() && "must be a variable"); /// When going towards FIR, use the original base value to avoid /// introducing descriptors at runtime when they are not required. - mlir::Value firBase = variable.getFirBase(); + mlir::Value base = + forceHlfirBase ? variable.getBase() : variable.getFirBase(); if (variable.isMutableBox()) - return fir::MutableBoxValue(firBase, getExplicitTypeParams(variable), + return fir::MutableBoxValue(base, getExplicitTypeParams(variable), fir::MutableProperties{}); - if (firBase.getType().isa()) { + if (base.getType().isa()) { if (!variable.isSimplyContiguous() || variable.isPolymorphic() || variable.isDerivedWithLengthParameters() || variable.isOptional()) { llvm::SmallVector nonDefaultLbounds = getNonDefaultLowerBounds(loc, builder, variable); - return fir::BoxValue(firBase, nonDefaultLbounds, + return fir::BoxValue(base, nonDefaultLbounds, getExplicitTypeParams(variable)); } // Otherwise, the variable can be represented in a fir::ExtendedValue // without the overhead of a fir.box. - firBase = genVariableRawAddress(loc, builder, variable); + base = genVariableRawAddress(loc, builder, variable); } if (variable.isScalar()) { if (variable.isCharacter()) { - if (firBase.getType().isa()) - return genUnboxChar(loc, builder, firBase); + if (base.getType().isa()) + return genUnboxChar(loc, builder, base); mlir::Value len = genCharacterVariableLength(loc, builder, variable); - return fir::CharBoxValue{firBase, len}; + return fir::CharBoxValue{base, len}; } - return firBase; + return base; } llvm::SmallVector extents; llvm::SmallVector nonDefaultLbounds; @@ -893,15 +895,16 @@ translateVariableToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder, } if (variable.isCharacter()) return fir::CharArrayBoxValue{ - firBase, genCharacterVariableLength(loc, builder, variable), extents, + base, genCharacterVariableLength(loc, builder, variable), extents, nonDefaultLbounds}; - return fir::ArrayBoxValue{firBase, extents, nonDefaultLbounds}; + return fir::ArrayBoxValue{base, extents, nonDefaultLbounds}; } fir::ExtendedValue hlfir::translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder, - fir::FortranVariableOpInterface var) { - return translateVariableToExtendedValue(loc, builder, var); + fir::FortranVariableOpInterface var, + bool forceHlfirBase) { + return translateVariableToExtendedValue(loc, builder, var, forceHlfirBase); } std::pair> diff --git a/flang/test/Lower/OpenMP/parallel-private-clause-str.f90 b/flang/test/Lower/OpenMP/parallel-private-clause-str.f90 index f668957624b4..025e51e06617 100644 --- a/flang/test/Lower/OpenMP/parallel-private-clause-str.f90 +++ b/flang/test/Lower/OpenMP/parallel-private-clause-str.f90 @@ -10,7 +10,7 @@ !CHECK: %[[C_DECL:.*]]:2 = hlfir.declare %[[C_BOX_REF]] typeparams %{{.*}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_stringEc"} : (!fir.ref>>>, i32) -> (!fir.ref>>>, !fir.ref>>>) !CHECK: omp.parallel { !CHECK: %[[C_PVT_BOX_REF:.*]] = fir.alloca !fir.box>> {bindc_name = "c", pinned, uniq_name = "_QFtest_allocatable_stringEc"} -!CHECK: %[[C_BOX:.*]] = fir.load %[[C_DECL]]#1 : !fir.ref>>> +!CHECK: %[[C_BOX:.*]] = fir.load %[[C_DECL]]#0 : !fir.ref>>> !CHECK: fir.if %{{.*}} { !CHECK: %[[C_PVT_MEM:.*]] = fir.allocmem !fir.char<1,?>(%{{.*}} : index) {fir.must_be_heap = true, uniq_name = "_QFtest_allocatable_stringEc.alloc"} !CHECK: %[[C_PVT_BOX:.*]] = fir.embox %[[C_PVT_MEM]] typeparams %{{.*}} : (!fir.heap>, index) -> !fir.box>> @@ -18,7 +18,7 @@ !CHECK: } !CHECK: %[[C_PVT_DECL:.*]]:2 = hlfir.declare %[[C_PVT_BOX_REF]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_stringEc"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) !CHECK: fir.if %{{.*}} { -!CHECK: %[[C_PVT_BOX:.*]] = fir.load %[[C_PVT_DECL]]#1 : !fir.ref>>> +!CHECK: %[[C_PVT_BOX:.*]] = fir.load %[[C_PVT_DECL]]#0 : !fir.ref>>> !CHECK: %[[C_PVT_BOX_ADDR:.*]] = fir.box_addr %[[C_PVT_BOX]] : (!fir.box>>) -> !fir.heap> !CHECK: fir.freemem %[[C_PVT_BOX_ADDR]] : !fir.heap> !CHECK: } @@ -38,16 +38,16 @@ end subroutine !CHECK: %[[C_DECL:.*]]:2 = hlfir.declare %[[C_BOX_REF]] typeparams %{{.*}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_string_arrayEc"} : (!fir.ref>>>>, i32) -> (!fir.ref>>>>, !fir.ref>>>>) !CHECK: omp.parallel { !CHECK: %[[C_PVT_BOX_REF:.*]] = fir.alloca !fir.box>>> {bindc_name = "c", pinned, uniq_name = "_QFtest_allocatable_string_arrayEc"} -!CHECK: %{{.*}} = fir.load %[[C_DECL]]#1 : !fir.ref>>>> +!CHECK: %{{.*}} = fir.load %[[C_DECL]]#0 : !fir.ref>>>> !CHECK: fir.if %{{.*}} { !CHECK: %[[C_PVT_ALLOC:.*]] = fir.allocmem !fir.array>(%{{.*}} : index), %{{.*}} {fir.must_be_heap = true, uniq_name = "_QFtest_allocatable_string_arrayEc.alloc"} !CHECK: %[[C_PVT_BOX:.*]] = fir.embox %[[C_PVT_ALLOC]](%{{.*}}) typeparams %{{.*}} : (!fir.heap>>, !fir.shapeshift<1>, index) -> !fir.box>>> !CHECK: fir.store %[[C_PVT_BOX]] to %[[C_PVT_BOX_REF]] : !fir.ref>>>> !CHECK: } !CHECK: %[[C_PVT_DECL:.*]]:2 = hlfir.declare %[[C_PVT_BOX_REF]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_string_arrayEc"} : (!fir.ref>>>>) -> (!fir.ref>>>>, !fir.ref>>>>) -!CHECK: %{{.*}} = fir.load %[[C_PVT_DECL]]#1 : !fir.ref>>>> +!CHECK: %{{.*}} = fir.load %[[C_PVT_DECL]]#0 : !fir.ref>>>> !CHECK: fir.if %{{.*}} { -!CHECK: %[[C_PVT_BOX:.*]] = fir.load %[[C_PVT_DECL]]#1 : !fir.ref>>>> +!CHECK: %[[C_PVT_BOX:.*]] = fir.load %[[C_PVT_DECL]]#0 : !fir.ref>>>> !CHECK: %[[C_PVT_ADDR:.*]] = fir.box_addr %[[C_PVT_BOX]] : (!fir.box>>>) -> !fir.heap>> !CHECK: fir.freemem %[[C_PVT_ADDR]] : !fir.heap>> !CHECK: } diff --git a/flang/test/Lower/OpenMP/parallel-private-clause.f90 b/flang/test/Lower/OpenMP/parallel-private-clause.f90 index 3e46d315f8cc..5578b6710da7 100644 --- a/flang/test/Lower/OpenMP/parallel-private-clause.f90 +++ b/flang/test/Lower/OpenMP/parallel-private-clause.f90 @@ -150,8 +150,8 @@ end subroutine !FIRDialect-DAG: %[[X4_PVT:.*]] = fir.alloca !fir.box>> {bindc_name = "x4", pinned, uniq_name = "{{.*}}Ex4"} !FIRDialect-DAG: %[[X4_PVT_DECL:.*]]:2 = hlfir.declare %[[X4_PVT]] {fortran_attrs = #fir.var_attrs, uniq_name = "{{.*}}Ex4"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) -!FIRDialect-DAG: %[[TMP58:.*]] = fir.load %[[X4_DECL]]#1 : !fir.ref>>> -!FIRDialect-DAG: %[[TMP97:.*]] = fir.load %[[X4_DECL]]#1 : !fir.ref>>> +!FIRDialect-DAG: %[[TMP58:.*]] = fir.load %[[X4_DECL]]#0 : !fir.ref>>> +!FIRDialect-DAG: %[[TMP97:.*]] = fir.load %[[X4_DECL]]#0 : !fir.ref>>> !FIRDialect-DAG: %[[TMP98:.*]]:3 = fir.box_dims %[[TMP97]], {{.*}} : (!fir.box>>, index) -> (index, index, index) !FIRDialect-DAG: %[[TMP101:.*]] = fir.allocmem !fir.array, {{.*}} {fir.must_be_heap = true, uniq_name = "{{.*}}Ex4.alloc"} @@ -192,12 +192,12 @@ end subroutine !FIRDialect-DAG: } !FIRDialect-DAG: %[[X5_PVT_DECL:.*]]:2 = hlfir.declare %[[X5_PVT]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFprivate_clause_real_call_allocatableEx5"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) !FIRDialect-DAG: fir.call @_QFprivate_clause_real_call_allocatablePhelper_private_clause_real_call_allocatable(%[[X5_PVT_DECL]]#0) fastmath : (!fir.ref>>) -> () -!FIRDialect-DAG: %{{.*}} = fir.load %[[X5_PVT_DECL]]#1 : !fir.ref>> +!FIRDialect-DAG: %{{.*}} = fir.load %[[X5_PVT_DECL]]#0 : !fir.ref>> !FIRDialect-DAG: fir.if %{{.*}} { -!FIRDialect-DAG: %{{.*}} = fir.load %[[X5_PVT_DECL]]#1 : !fir.ref>> +!FIRDialect-DAG: %{{.*}} = fir.load %[[X5_PVT_DECL]]#0 : !fir.ref>> -!FIRDialect-DAG: fir.store %{{.*}} to %[[X5_PVT_DECL]]#1 : !fir.ref>> +!FIRDialect-DAG: fir.store %{{.*}} to %[[X5_PVT_DECL]]#0 : !fir.ref>> !FIRDialect-DAG: } !FIRDialect-DAG: omp.terminator !FIRDialect-DAG: } @@ -313,12 +313,12 @@ subroutine simple_loop_1 print*, i end do ! FIRDialect: omp.yield - ! FIRDialect: {{%.*}} = fir.load %[[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: {{%.*}} = fir.load %[[R_DECL]]#0 : !fir.ref>> ! FIRDialect: fir.if {{%.*}} { - ! FIRDialect: [[LD:%.*]] = fir.load %[[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: [[LD:%.*]] = fir.load %[[R_DECL]]#0 : !fir.ref>> ! FIRDialect: [[AD:%.*]] = fir.box_addr [[LD]] : (!fir.box>) -> !fir.heap ! FIRDialect: fir.freemem [[AD]] : !fir.heap - ! FIRDialect: fir.store {{%.*}} to %[[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: fir.store {{%.*}} to %[[R_DECL]]#0 : !fir.ref>> !$OMP END DO ! FIRDialect: omp.terminator !$OMP END PARALLEL @@ -351,12 +351,12 @@ subroutine simple_loop_2 print*, i end do ! FIRDialect: omp.yield - ! FIRDialect: {{%.*}} = fir.load %[[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: {{%.*}} = fir.load %[[R_DECL]]#0 : !fir.ref>> ! FIRDialect: fir.if {{%.*}} { - ! FIRDialect: [[LD:%.*]] = fir.load %[[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: [[LD:%.*]] = fir.load %[[R_DECL]]#0 : !fir.ref>> ! FIRDialect: [[AD:%.*]] = fir.box_addr [[LD]] : (!fir.box>) -> !fir.heap ! FIRDialect: fir.freemem [[AD]] : !fir.heap - ! FIRDialect: fir.store {{%.*}} to %[[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: fir.store {{%.*}} to %[[R_DECL]]#0 : !fir.ref>> !$OMP END DO ! FIRDialect: omp.terminator !$OMP END PARALLEL @@ -388,12 +388,12 @@ subroutine simple_loop_3 print*, i end do ! FIRDialect: omp.yield - ! FIRDialect: {{%.*}} = fir.load [[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: {{%.*}} = fir.load [[R_DECL]]#0 : !fir.ref>> ! FIRDialect: fir.if {{%.*}} { - ! FIRDialect: [[LD:%.*]] = fir.load [[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: [[LD:%.*]] = fir.load [[R_DECL]]#0 : !fir.ref>> ! FIRDialect: [[AD:%.*]] = fir.box_addr [[LD]] : (!fir.box>) -> !fir.heap ! FIRDialect: fir.freemem [[AD]] : !fir.heap - ! FIRDialect: fir.store {{%.*}} to [[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: fir.store {{%.*}} to [[R_DECL]]#0 : !fir.ref>> !$OMP END PARALLEL DO ! FIRDialect: omp.terminator end subroutine @@ -421,10 +421,10 @@ subroutine simd_loop_1 end do !$OMP END SIMD ! FIRDialect: omp.yield - ! FIRDialect: {{%.*}} = fir.load [[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: {{%.*}} = fir.load [[R_DECL]]#0 : !fir.ref>> ! FIRDialect: fir.if {{%.*}} { - ! FIRDialect: [[LD:%.*]] = fir.load [[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: [[LD:%.*]] = fir.load [[R_DECL]]#0 : !fir.ref>> ! FIRDialect: [[AD:%.*]] = fir.box_addr [[LD]] : (!fir.box>) -> !fir.heap ! FIRDialect: fir.freemem [[AD]] : !fir.heap - ! FIRDialect: fir.store {{%.*}} to [[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: fir.store {{%.*}} to [[R_DECL]]#0 : !fir.ref>> end subroutine -- GitLab From 718962f53bfc610f670f1674457a426e01117097 Mon Sep 17 00:00:00 2001 From: Dominik Steenken Date: Mon, 11 Mar 2024 10:40:59 +0100 Subject: [PATCH 080/953] [SystemZ] Provide improved cost estimates (#83873) This commit provides better cost estimates for the llvm.vector.reduce.add intrinsic on SystemZ. These apply to all vector lengths and integer types up to i128. For integer types larger than i128, we fall back to the default cost estimate. This has the effect of lowering the estimated costs of most common instances of the intrinsic. The expected performance impact of this is minimal with a tendency to slightly improve performance of some benchmarks. This commit also provides a test to check the proper computation of the new estimates, as well as the fallback for types larger than i128. --- .../SystemZ/SystemZTargetTransformInfo.cpp | 33 ++++- .../Analysis/CostModel/SystemZ/reduce-add.ll | 128 ++++++++++++++++++ 2 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 llvm/test/Analysis/CostModel/SystemZ/reduce-add.ll diff --git a/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp b/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp index 9370fb51a96c..e4adb7be5649 100644 --- a/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp @@ -20,6 +20,8 @@ #include "llvm/CodeGen/TargetLowering.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/MathExtras.h" + using namespace llvm; #define DEBUG_TYPE "systemztti" @@ -1284,17 +1286,42 @@ InstructionCost SystemZTTIImpl::getInterleavedMemoryOpCost( return NumVectorMemOps + NumPermutes; } -static int getVectorIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy) { +static int +getVectorIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + const SmallVectorImpl &ParamTys) { if (RetTy->isVectorTy() && ID == Intrinsic::bswap) return getNumVectorRegs(RetTy); // VPERM + + if (ID == Intrinsic::vector_reduce_add) { + // Retrieve number and size of elements for the vector op. + auto *VTy = cast(ParamTys.front()); + unsigned NumElements = VTy->getNumElements(); + unsigned ScalarSize = VTy->getScalarSizeInBits(); + // For scalar sizes >128 bits, we fall back to the generic cost estimate. + if (ScalarSize > SystemZ::VectorBits) + return -1; + // A single vector register can hold this many elements. + unsigned MaxElemsPerVector = SystemZ::VectorBits / ScalarSize; + // This many vector regs are needed to represent the input elements (V). + unsigned VectorRegsNeeded = getNumVectorRegs(VTy); + // This many instructions are needed for the final sum of vector elems (S). + unsigned LastVectorHandling = + 2 * Log2_32_Ceil(std::min(NumElements, MaxElemsPerVector)); + // We use vector adds to create a sum vector, which takes + // V/2 + V/4 + ... = V - 1 operations. + // Then, we need S operations to sum up the elements of that sum vector, + // for a total of V + S - 1 operations. + int Cost = VectorRegsNeeded + LastVectorHandling - 1; + return Cost; + } return -1; } InstructionCost SystemZTTIImpl::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) { - InstructionCost Cost = - getVectorIntrinsicInstrCost(ICA.getID(), ICA.getReturnType()); + InstructionCost Cost = getVectorIntrinsicInstrCost( + ICA.getID(), ICA.getReturnType(), ICA.getArgTypes()); if (Cost != -1) return Cost; return BaseT::getIntrinsicInstrCost(ICA, CostKind); diff --git a/llvm/test/Analysis/CostModel/SystemZ/reduce-add.ll b/llvm/test/Analysis/CostModel/SystemZ/reduce-add.ll new file mode 100644 index 000000000000..061e5ece44a4 --- /dev/null +++ b/llvm/test/Analysis/CostModel/SystemZ/reduce-add.ll @@ -0,0 +1,128 @@ +; RUN: opt < %s -mtriple=systemz-unknown -mcpu=z13 -passes="print" -cost-kind=throughput 2>&1 -disable-output | FileCheck %s + +define void @reduce(ptr %src, ptr %dst) { +; CHECK-LABEL: 'reduce' +; CHECK: Cost Model: Found an estimated cost of 2 for instruction: %R2_64 = call i64 @llvm.vector.reduce.add.v2i64(<2 x i64> %V2_64) +; CHECK: Cost Model: Found an estimated cost of 3 for instruction: %R4_64 = call i64 @llvm.vector.reduce.add.v4i64(<4 x i64> %V4_64) +; CHECK: Cost Model: Found an estimated cost of 5 for instruction: %R8_64 = call i64 @llvm.vector.reduce.add.v8i64(<8 x i64> %V8_64) +; CHECK: Cost Model: Found an estimated cost of 9 for instruction: %R16_64 = call i64 @llvm.vector.reduce.add.v16i64(<16 x i64> %V16_64) +; CHECK: Cost Model: Found an estimated cost of 2 for instruction: %R2_32 = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %V2_32) +; CHECK: Cost Model: Found an estimated cost of 4 for instruction: %R4_32 = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %V4_32) +; CHECK: Cost Model: Found an estimated cost of 5 for instruction: %R8_32 = call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> %V8_32) +; CHECK: Cost Model: Found an estimated cost of 7 for instruction: %R16_32 = call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %V16_32) +; CHECK: Cost Model: Found an estimated cost of 2 for instruction: %R2_16 = call i16 @llvm.vector.reduce.add.v2i16(<2 x i16> %V2_16) +; CHECK: Cost Model: Found an estimated cost of 4 for instruction: %R4_16 = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> %V4_16) +; CHECK: Cost Model: Found an estimated cost of 6 for instruction: %R8_16 = call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %V8_16) +; CHECK: Cost Model: Found an estimated cost of 7 for instruction: %R16_16 = call i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %V16_16) +; CHECK: Cost Model: Found an estimated cost of 2 for instruction: %R2_8 = call i8 @llvm.vector.reduce.add.v2i8(<2 x i8> %V2_8) +; CHECK: Cost Model: Found an estimated cost of 4 for instruction: %R4_8 = call i8 @llvm.vector.reduce.add.v4i8(<4 x i8> %V4_8) +; CHECK: Cost Model: Found an estimated cost of 6 for instruction: %R8_8 = call i8 @llvm.vector.reduce.add.v8i8(<8 x i8> %V8_8) +; CHECK: Cost Model: Found an estimated cost of 8 for instruction: %R16_8 = call i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %V16_8) +; +; CHECK: Cost Model: Found an estimated cost of 15 for instruction: %R128_8 = call i8 @llvm.vector.reduce.add.v128i8(<128 x i8> %V128_8) +; CHECK: Cost Model: Found an estimated cost of 20 for instruction: %R4_256 = call i256 @llvm.vector.reduce.add.v4i256(<4 x i256> %V4_256) + + ; REDUCEADD64 + + %V2_64 = load <2 x i64>, ptr %src, align 8 + %R2_64 = call i64 @llvm.vector.reduce.add.v2i64(<2 x i64> %V2_64) + store volatile i64 %R2_64, ptr %dst, align 4 + + %V4_64 = load <4 x i64>, ptr %src, align 8 + %R4_64 = call i64 @llvm.vector.reduce.add.v4i64(<4 x i64> %V4_64) + store volatile i64 %R4_64, ptr %dst, align 4 + + %V8_64 = load <8 x i64>, ptr %src, align 8 + %R8_64 = call i64 @llvm.vector.reduce.add.v8i64(<8 x i64> %V8_64) + store volatile i64 %R8_64, ptr %dst, align 4 + + %V16_64 = load <16 x i64>, ptr %src, align 8 + %R16_64 = call i64 @llvm.vector.reduce.add.v16i64(<16 x i64> %V16_64) + store volatile i64 %R16_64, ptr %dst, align 4 + + ; REDUCEADD32 + + %V2_32 = load <2 x i32>, ptr %src, align 8 + %R2_32 = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %V2_32) + store volatile i32 %R2_32, ptr %dst, align 4 + + %V4_32 = load <4 x i32>, ptr %src, align 8 + %R4_32 = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %V4_32) + store volatile i32 %R4_32, ptr %dst, align 4 + + %V8_32 = load <8 x i32>, ptr %src, align 8 + %R8_32 = call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> %V8_32) + store volatile i32 %R8_32, ptr %dst, align 4 + + %V16_32 = load <16 x i32>, ptr %src, align 8 + %R16_32 = call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %V16_32) + store volatile i32 %R16_32, ptr %dst, align 4 + + ; REDUCEADD16 + + %V2_16 = load <2 x i16>, ptr %src, align 8 + %R2_16 = call i16 @llvm.vector.reduce.add.v2i16(<2 x i16> %V2_16) + store volatile i16 %R2_16, ptr %dst, align 4 + + %V4_16 = load <4 x i16>, ptr %src, align 8 + %R4_16 = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> %V4_16) + store volatile i16 %R4_16, ptr %dst, align 4 + + %V8_16 = load <8 x i16>, ptr %src, align 8 + %R8_16 = call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> %V8_16) + store volatile i16 %R8_16, ptr %dst, align 4 + + %V16_16 = load <16 x i16>, ptr %src, align 8 + %R16_16 = call i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %V16_16) + store volatile i16 %R16_16, ptr %dst, align 4 + + ; REDUCEADD8 + + %V2_8 = load <2 x i8>, ptr %src, align 8 + %R2_8 = call i8 @llvm.vector.reduce.add.v2i8(<2 x i8> %V2_8) + store volatile i8 %R2_8, ptr %dst, align 4 + + %V4_8 = load <4 x i8>, ptr %src, align 8 + %R4_8 = call i8 @llvm.vector.reduce.add.v4i8(<4 x i8> %V4_8) + store volatile i8 %R4_8, ptr %dst, align 4 + + %V8_8 = load <8 x i8>, ptr %src, align 8 + %R8_8 = call i8 @llvm.vector.reduce.add.v8i8(<8 x i8> %V8_8) + store volatile i8 %R8_8, ptr %dst, align 4 + + %V16_8 = load <16 x i8>, ptr %src, align 8 + %R16_8 = call i8 @llvm.vector.reduce.add.v16i8(<16 x i8> %V16_8) + store volatile i8 %R16_8, ptr %dst, align 4 + + ; EXTREME VALUES + + %V128_8 = load <128 x i8>, ptr %src, align 8 + %R128_8 = call i8 @llvm.vector.reduce.add.v128i8(<128 x i8> %V128_8) + store volatile i8 %R128_8, ptr %dst, align 4 + + %V4_256 = load <4 x i256>, ptr %src, align 8 + %R4_256 = call i256 @llvm.vector.reduce.add.v4i256(<4 x i256> %V4_256) + store volatile i256 %R4_256, ptr %dst, align 8 + + ret void +} + +declare i64 @llvm.vector.reduce.add.v2i64(<2 x i64>) +declare i64 @llvm.vector.reduce.add.v4i64(<4 x i64>) +declare i64 @llvm.vector.reduce.add.v8i64(<8 x i64>) +declare i64 @llvm.vector.reduce.add.v16i64(<16 x i64>) +declare i32 @llvm.vector.reduce.add.v2i32(<2 x i32>) +declare i32 @llvm.vector.reduce.add.v4i32(<4 x i32>) +declare i32 @llvm.vector.reduce.add.v8i32(<8 x i32>) +declare i32 @llvm.vector.reduce.add.v16i32(<16 x i32>) +declare i16 @llvm.vector.reduce.add.v2i16(<2 x i16>) +declare i16 @llvm.vector.reduce.add.v4i16(<4 x i16>) +declare i16 @llvm.vector.reduce.add.v8i16(<8 x i16>) +declare i16 @llvm.vector.reduce.add.v16i16(<16 x i16>) +declare i8 @llvm.vector.reduce.add.v2i8(<2 x i8>) +declare i8 @llvm.vector.reduce.add.v4i8(<4 x i8>) +declare i8 @llvm.vector.reduce.add.v8i8(<8 x i8>) +declare i8 @llvm.vector.reduce.add.v16i8(<16 x i8>) + +declare i8 @llvm.vector.reduce.add.v128i8(<128 x i8>) +declare i256 @llvm.vector.reduce.add.v4i256(<4 x i256>) -- GitLab From 58dd59a28293432171c0439eb1ae082f6ea9962f Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Mon, 11 Mar 2024 17:43:02 +0800 Subject: [PATCH 081/953] [RISCV] Don't run combineBinOp_VLToVWBinOp_VL until after legalize types. NFCI (#84125) I noticed this from a discrepancy in fillUpExtensionSupport between how we apparently need to check for legal types for ISD::{ZERO,SIGN}_EXTEND, but we don't need to for RISCVISD::V{Z,S}EXT_VL. Prior to #72340, combineBinOp_VLToVWBinOp_VL only ran after type legalization because it only operated on _VL nodes. _VL nodes are only emitted during op legalization, which takes place **after** type legalization, which is presumably why the existing code didn't need to check for legal types. After #72340 we now handle generic ops like ISD::ADD that exist before op legalization and thus **before** type legalization. This meant that we needed to add extra checks that the narrow type was legal in #76785. I think the easiest thing to do here is to just maintain the invariant that the types are legal and only run the combine after type legalization. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 25 ++++++++++----------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index fa37306a4999..71759fdde9af 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -13657,9 +13657,8 @@ struct NodeExtensionHelper { unsigned ScalarBits = VT.getScalarSizeInBits(); unsigned NarrowScalarBits = NarrowVT.getScalarSizeInBits(); - // Ensure the narrowing element type is legal - if (!Subtarget.getTargetLowering()->isTypeLegal(NarrowElt.getValueType())) - break; + assert( + Subtarget.getTargetLowering()->isTypeLegal(NarrowElt.getValueType())); // Ensure the extension's semantic is equivalent to rvv vzext or vsext. if (ScalarBits != NarrowScalarBits * 2) @@ -13732,14 +13731,11 @@ struct NodeExtensionHelper { } /// Check if \p Root supports any extension folding combines. - static bool isSupportedRoot(const SDNode *Root, const SelectionDAG &DAG) { - const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + static bool isSupportedRoot(const SDNode *Root) { switch (Root->getOpcode()) { case ISD::ADD: case ISD::SUB: case ISD::MUL: { - if (!TLI.isTypeLegal(Root->getValueType(0))) - return false; return Root->getValueType(0).isScalableVector(); } // Vector Widening Integer Add/Sub/Mul Instructions @@ -13756,7 +13752,7 @@ struct NodeExtensionHelper { case RISCVISD::FMUL_VL: case RISCVISD::VFWADD_W_VL: case RISCVISD::VFWSUB_W_VL: - return TLI.isTypeLegal(Root->getValueType(0)); + return true; default: return false; } @@ -13765,9 +13761,10 @@ struct NodeExtensionHelper { /// Build a NodeExtensionHelper for \p Root.getOperand(\p OperandIdx). NodeExtensionHelper(SDNode *Root, unsigned OperandIdx, SelectionDAG &DAG, const RISCVSubtarget &Subtarget) { - assert(isSupportedRoot(Root, DAG) && "Trying to build an helper with an " - "unsupported root"); + assert(isSupportedRoot(Root) && "Trying to build an helper with an " + "unsupported root"); assert(OperandIdx < 2 && "Requesting something else than LHS or RHS"); + assert(DAG.getTargetLoweringInfo().isTypeLegal(Root->getValueType(0))); OrigOperand = Root->getOperand(OperandIdx); unsigned Opc = Root->getOpcode(); @@ -13817,7 +13814,7 @@ struct NodeExtensionHelper { static std::pair getMaskAndVL(const SDNode *Root, SelectionDAG &DAG, const RISCVSubtarget &Subtarget) { - assert(isSupportedRoot(Root, DAG) && "Unexpected root"); + assert(isSupportedRoot(Root) && "Unexpected root"); switch (Root->getOpcode()) { case ISD::ADD: case ISD::SUB: @@ -14117,8 +14114,10 @@ static SDValue combineBinOp_VLToVWBinOp_VL(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const RISCVSubtarget &Subtarget) { SelectionDAG &DAG = DCI.DAG; + if (DCI.isBeforeLegalize()) + return SDValue(); - if (!NodeExtensionHelper::isSupportedRoot(N, DAG)) + if (!NodeExtensionHelper::isSupportedRoot(N)) return SDValue(); SmallVector Worklist; @@ -14129,7 +14128,7 @@ static SDValue combineBinOp_VLToVWBinOp_VL(SDNode *N, while (!Worklist.empty()) { SDNode *Root = Worklist.pop_back_val(); - if (!NodeExtensionHelper::isSupportedRoot(Root, DAG)) + if (!NodeExtensionHelper::isSupportedRoot(Root)) return SDValue(); NodeExtensionHelper LHS(N, 0, DAG, Subtarget); -- GitLab From d3ec8c2a25f43225efe997569925aa57324db0dd Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 11 Mar 2024 10:29:11 +0100 Subject: [PATCH 082/953] Typo: ponit --- compiler-rt/lib/profile/InstrProfilingPlatformWindows.c | 2 +- llvm/unittests/Analysis/LazyCallGraphTest.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c b/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c index 9421f67b768e..741b01faada4 100644 --- a/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c @@ -93,7 +93,7 @@ ValueProfNode *__llvm_profile_end_vnodes(void) { return &VNodesEnd; } ValueProfNode *CurrentVNode = &VNodesStart + 1; ValueProfNode *EndVNode = &VNodesEnd; -/* lld-link provides __buildid symbol which ponits to the 16 bytes build id when +/* lld-link provides __buildid symbol which points to the 16 bytes build id when * using /build-id flag. https://lld.llvm.org/windows_support.html#lld-flags */ #define BUILD_ID_LEN 16 COMPILER_RT_WEAK uint8_t __buildid[BUILD_ID_LEN] = {0}; diff --git a/llvm/unittests/Analysis/LazyCallGraphTest.cpp b/llvm/unittests/Analysis/LazyCallGraphTest.cpp index 6ef31042b600..69af7d92c7cf 100644 --- a/llvm/unittests/Analysis/LazyCallGraphTest.cpp +++ b/llvm/unittests/Analysis/LazyCallGraphTest.cpp @@ -1829,7 +1829,7 @@ TEST(LazyCallGraphTest, InternalRefEdgeToCallBothPartitionAndMerge) { // a cycle. // // Diagram for the graph we want on the left and the graph we use to force - // the ordering on the right. Edges ponit down or right. + // the ordering on the right. Edges point down or right. // // A | A | // / \ | / \ | -- GitLab From 0ef61ed54dca2e974928c55b2144b57d4c4ff621 Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Mon, 11 Mar 2024 18:00:29 +0800 Subject: [PATCH 083/953] [RISCV] Move NodeExtensionHelper assert to getOrCreateExtendedOp. NFC Move the narrow types assert from the ZERO_EXTEND/SIGN_EXTEND case in fillUpExtensionSupport to getOrCreateExtendedOp so we check the other nodes too. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 71759fdde9af..08678a859ae2 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -13490,6 +13490,7 @@ struct NodeExtensionHelper { MVT NarrowVT = getNarrowType(Root, *SupportsExt); SDValue Source = getSource(); + assert(Subtarget.getTargetLowering()->isTypeLegal(Source.getValueType())); if (Source.getValueType() == NarrowVT) return Source; @@ -13657,9 +13658,6 @@ struct NodeExtensionHelper { unsigned ScalarBits = VT.getScalarSizeInBits(); unsigned NarrowScalarBits = NarrowVT.getScalarSizeInBits(); - assert( - Subtarget.getTargetLowering()->isTypeLegal(NarrowElt.getValueType())); - // Ensure the extension's semantic is equivalent to rvv vzext or vsext. if (ScalarBits != NarrowScalarBits * 2) break; -- GitLab From 9277a32305c1083653ffaa7955cd26deffc10988 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Mon, 11 Mar 2024 10:56:37 +0000 Subject: [PATCH 084/953] [VPlan] Funnel recipe insert* through VPBasicBlock::insert (NFCI). This allows relying on VPBasicBlock::insert to make sure insertion is well formed, i.e. by updating the recipe's parent as well as other potential invariants in the future. --- llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp index 40ebec7305b4..d75e322a74cf 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -198,24 +198,21 @@ void VPRecipeBase::insertBefore(VPRecipeBase *InsertPos) { assert(!Parent && "Recipe already in some VPBasicBlock"); assert(InsertPos->getParent() && "Insertion position not in any VPBasicBlock"); - Parent = InsertPos->getParent(); - Parent->getRecipeList().insert(InsertPos->getIterator(), this); + InsertPos->getParent()->insert(this, InsertPos->getIterator()); } void VPRecipeBase::insertBefore(VPBasicBlock &BB, iplist::iterator I) { assert(!Parent && "Recipe already in some VPBasicBlock"); assert(I == BB.end() || I->getParent() == &BB); - Parent = &BB; - BB.getRecipeList().insert(I, this); + BB.insert(this, I); } void VPRecipeBase::insertAfter(VPRecipeBase *InsertPos) { assert(!Parent && "Recipe already in some VPBasicBlock"); assert(InsertPos->getParent() && "Insertion position not in any VPBasicBlock"); - Parent = InsertPos->getParent(); - Parent->getRecipeList().insertAfter(InsertPos->getIterator(), this); + InsertPos->getParent()->insert(this, std::next(InsertPos->getIterator())); } void VPRecipeBase::removeFromParent() { -- GitLab From ec2875ce2690010f7dd894c9b56802297dd6cb84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= Date: Mon, 11 Mar 2024 12:15:11 +0100 Subject: [PATCH 085/953] [clang-repl] Expose RuntimeInterfaceBuilder to allow customization (#83126) RuntimeInterfaceBuilder wires up JITed expressions with the hardcoded Interpreter runtime. It's used only for value printing right now, but it is not limited to that. The default implementation focuses on an evaluation process where the Interpreter has direct access to the memory of JITed expressions (in-process execution or shared memory). We need a different approach to support out-of-process evaluation or variations of the runtime. It seems reasonable to expose a minimal interface for it. The new RuntimeInterfaceBuilder is an abstract base class in the public header. For that, the TypeVisitor had to become a component (instead of inheriting from it). FindRuntimeInterface() was adjusted to return an instance of the RuntimeInterfaceBuilder and it can be overridden from derived classes. --- clang/include/clang/Interpreter/Interpreter.h | 35 ++- clang/lib/Interpreter/Interpreter.cpp | 247 ++++++++++-------- clang/unittests/Interpreter/CMakeLists.txt | 1 + .../Interpreter/InterpreterExtensionsTest.cpp | 79 ++++++ 4 files changed, 253 insertions(+), 109 deletions(-) create mode 100644 clang/unittests/Interpreter/InterpreterExtensionsTest.cpp diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index c8f932e95c47..d972d960dcb7 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -18,6 +18,7 @@ #include "clang/AST/GlobalDecl.h" #include "clang/Interpreter/PartialTranslationUnit.h" #include "clang/Interpreter/Value.h" +#include "clang/Sema/Ownership.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ExecutionEngine/JITSymbol.h" @@ -75,17 +76,26 @@ private: llvm::StringRef CudaSDKPath; }; +/// Generate glue code between the Interpreter's built-in runtime and user code. +class RuntimeInterfaceBuilder { +public: + virtual ~RuntimeInterfaceBuilder() = default; + + using TransformExprFunction = ExprResult(RuntimeInterfaceBuilder *Builder, + Expr *, ArrayRef); + virtual TransformExprFunction *getPrintValueTransformer() = 0; +}; + /// Provides top-level interfaces for incremental compilation and execution. class Interpreter { std::unique_ptr TSCtx; std::unique_ptr IncrParser; std::unique_ptr IncrExecutor; + std::unique_ptr RuntimeIB; // An optional parser for CUDA offloading std::unique_ptr DeviceParser; - Interpreter(std::unique_ptr CI, llvm::Error &Err); - llvm::Error CreateExecutor(); unsigned InitPTUSize = 0; @@ -94,8 +104,25 @@ class Interpreter { // printing happens, it's in an invalid state. Value LastValue; + // Add a call to an Expr to report its result. We query the function from + // RuntimeInterfaceBuilder once and store it as a function pointer to avoid + // frequent virtual function calls. + RuntimeInterfaceBuilder::TransformExprFunction *AddPrintValueCall = nullptr; + +protected: + // Derived classes can make use an extended interface of the Interpreter. + // That's useful for testing and out-of-tree clients. + Interpreter(std::unique_ptr CI, llvm::Error &Err); + + // Lazily construct the RuntimeInterfaceBuilder. The provided instance will be + // used for the entire lifetime of the interpreter. The default implementation + // targets the in-process __clang_Interpreter runtime. Override this to use a + // custom runtime. + virtual std::unique_ptr FindRuntimeInterface(); + public: - ~Interpreter(); + virtual ~Interpreter(); + static llvm::Expected> create(std::unique_ptr CI); static llvm::Expected> @@ -143,8 +170,6 @@ public: private: size_t getEffectivePTUSize() const; - bool FindRuntimeInterface(); - llvm::DenseMap Dtors; llvm::SmallVector ValuePrintingInfo; diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 37696b289764..3485da819668 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -507,9 +507,13 @@ static constexpr llvm::StringRef MagicRuntimeInterface[] = { "__clang_Interpreter_SetValueWithAlloc", "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"}; -bool Interpreter::FindRuntimeInterface() { +static std::unique_ptr +createInProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &Ctx, + Sema &S); + +std::unique_ptr Interpreter::FindRuntimeInterface() { if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; })) - return true; + return nullptr; Sema &S = getCompilerInstance()->getSema(); ASTContext &Ctx = S.getASTContext(); @@ -528,120 +532,34 @@ bool Interpreter::FindRuntimeInterface() { if (!LookupInterface(ValuePrintingInfo[NoAlloc], MagicRuntimeInterface[NoAlloc])) - return false; + return nullptr; if (!LookupInterface(ValuePrintingInfo[WithAlloc], MagicRuntimeInterface[WithAlloc])) - return false; + return nullptr; if (!LookupInterface(ValuePrintingInfo[CopyArray], MagicRuntimeInterface[CopyArray])) - return false; + return nullptr; if (!LookupInterface(ValuePrintingInfo[NewTag], MagicRuntimeInterface[NewTag])) - return false; - return true; + return nullptr; + + return createInProcessRuntimeInterfaceBuilder(*this, Ctx, S); } namespace { -class RuntimeInterfaceBuilder - : public TypeVisitor { - clang::Interpreter &Interp; +class InterfaceKindVisitor + : public TypeVisitor { + friend class InProcessRuntimeInterfaceBuilder; + ASTContext &Ctx; Sema &S; Expr *E; llvm::SmallVector Args; public: - RuntimeInterfaceBuilder(clang::Interpreter &In, ASTContext &C, Sema &SemaRef, - Expr *VE, ArrayRef FixedArgs) - : Interp(In), Ctx(C), S(SemaRef), E(VE) { - // The Interpreter* parameter and the out parameter `OutVal`. - for (Expr *E : FixedArgs) - Args.push_back(E); - - // Get rid of ExprWithCleanups. - if (auto *EWC = llvm::dyn_cast_if_present(E)) - E = EWC->getSubExpr(); - } - - ExprResult getCall() { - QualType Ty = E->getType(); - QualType DesugaredTy = Ty.getDesugaredType(Ctx); - - // For lvalue struct, we treat it as a reference. - if (DesugaredTy->isRecordType() && E->isLValue()) { - DesugaredTy = Ctx.getLValueReferenceType(DesugaredTy); - Ty = Ctx.getLValueReferenceType(Ty); - } - - Expr *TypeArg = - CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)Ty.getAsOpaquePtr()); - // The QualType parameter `OpaqueType`, represented as `void*`. - Args.push_back(TypeArg); - - // We push the last parameter based on the type of the Expr. Note we need - // special care for rvalue struct. - Interpreter::InterfaceKind Kind = Visit(&*DesugaredTy); - switch (Kind) { - case Interpreter::InterfaceKind::WithAlloc: - case Interpreter::InterfaceKind::CopyArray: { - // __clang_Interpreter_SetValueWithAlloc. - ExprResult AllocCall = S.ActOnCallExpr( - /*Scope=*/nullptr, - Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc], - E->getBeginLoc(), Args, E->getEndLoc()); - assert(!AllocCall.isInvalid() && "Can't create runtime interface call!"); - - TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation()); - - // Force CodeGen to emit destructor. - if (auto *RD = Ty->getAsCXXRecordDecl()) { - auto *Dtor = S.LookupDestructor(RD); - Dtor->addAttr(UsedAttr::CreateImplicit(Ctx)); - Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl( - DeclGroupRef(Dtor)); - } - - // __clang_Interpreter_SetValueCopyArr. - if (Kind == Interpreter::InterfaceKind::CopyArray) { - const auto *ConstantArrTy = - cast(DesugaredTy.getTypePtr()); - size_t ArrSize = Ctx.getConstantArrayElementCount(ConstantArrTy); - Expr *ArrSizeExpr = IntegerLiteralExpr(Ctx, ArrSize); - Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr}; - return S.ActOnCallExpr( - /*Scope *=*/nullptr, - Interp - .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray], - SourceLocation(), Args, SourceLocation()); - } - Expr *Args[] = { - AllocCall.get(), - Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]}; - ExprResult CXXNewCall = S.BuildCXXNew( - E->getSourceRange(), - /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args, - /*PlacementRParen=*/SourceLocation(), - /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt, - E->getSourceRange(), E); - - assert(!CXXNewCall.isInvalid() && - "Can't create runtime placement new call!"); - - return S.ActOnFinishFullExpr(CXXNewCall.get(), - /*DiscardedValue=*/false); - } - // __clang_Interpreter_SetValueNoAlloc. - case Interpreter::InterfaceKind::NoAlloc: { - return S.ActOnCallExpr( - /*Scope=*/nullptr, - Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc], - E->getBeginLoc(), Args, E->getEndLoc()); - } - default: - llvm_unreachable("Unhandled Interpreter::InterfaceKind"); - } - } + InterfaceKindVisitor(ASTContext &Ctx, Sema &S, Expr *E) + : Ctx(Ctx), S(S), E(E) {} Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) { return Interpreter::InterfaceKind::WithAlloc; @@ -713,8 +631,124 @@ private: Args.push_back(CastedExpr.get()); } }; + +class InProcessRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder { + Interpreter &Interp; + ASTContext &Ctx; + Sema &S; + +public: + InProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &C, Sema &S) + : Interp(Interp), Ctx(C), S(S) {} + + TransformExprFunction *getPrintValueTransformer() override { + return &transformForValuePrinting; + } + +private: + static ExprResult transformForValuePrinting(RuntimeInterfaceBuilder *Builder, + Expr *E, + ArrayRef FixedArgs) { + auto *B = static_cast(Builder); + + // Get rid of ExprWithCleanups. + if (auto *EWC = llvm::dyn_cast_if_present(E)) + E = EWC->getSubExpr(); + + InterfaceKindVisitor Visitor(B->Ctx, B->S, E); + + // The Interpreter* parameter and the out parameter `OutVal`. + for (Expr *E : FixedArgs) + Visitor.Args.push_back(E); + + QualType Ty = E->getType(); + QualType DesugaredTy = Ty.getDesugaredType(B->Ctx); + + // For lvalue struct, we treat it as a reference. + if (DesugaredTy->isRecordType() && E->isLValue()) { + DesugaredTy = B->Ctx.getLValueReferenceType(DesugaredTy); + Ty = B->Ctx.getLValueReferenceType(Ty); + } + + Expr *TypeArg = CStyleCastPtrExpr(B->S, B->Ctx.VoidPtrTy, + (uintptr_t)Ty.getAsOpaquePtr()); + // The QualType parameter `OpaqueType`, represented as `void*`. + Visitor.Args.push_back(TypeArg); + + // We push the last parameter based on the type of the Expr. Note we need + // special care for rvalue struct. + Interpreter::InterfaceKind Kind = Visitor.Visit(&*DesugaredTy); + switch (Kind) { + case Interpreter::InterfaceKind::WithAlloc: + case Interpreter::InterfaceKind::CopyArray: { + // __clang_Interpreter_SetValueWithAlloc. + ExprResult AllocCall = B->S.ActOnCallExpr( + /*Scope=*/nullptr, + B->Interp + .getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc], + E->getBeginLoc(), Visitor.Args, E->getEndLoc()); + assert(!AllocCall.isInvalid() && "Can't create runtime interface call!"); + + TypeSourceInfo *TSI = + B->Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation()); + + // Force CodeGen to emit destructor. + if (auto *RD = Ty->getAsCXXRecordDecl()) { + auto *Dtor = B->S.LookupDestructor(RD); + Dtor->addAttr(UsedAttr::CreateImplicit(B->Ctx)); + B->Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl( + DeclGroupRef(Dtor)); + } + + // __clang_Interpreter_SetValueCopyArr. + if (Kind == Interpreter::InterfaceKind::CopyArray) { + const auto *ConstantArrTy = + cast(DesugaredTy.getTypePtr()); + size_t ArrSize = B->Ctx.getConstantArrayElementCount(ConstantArrTy); + Expr *ArrSizeExpr = IntegerLiteralExpr(B->Ctx, ArrSize); + Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr}; + return B->S.ActOnCallExpr( + /*Scope *=*/nullptr, + B->Interp + .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray], + SourceLocation(), Args, SourceLocation()); + } + Expr *Args[] = { + AllocCall.get(), + B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]}; + ExprResult CXXNewCall = B->S.BuildCXXNew( + E->getSourceRange(), + /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args, + /*PlacementRParen=*/SourceLocation(), + /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt, + E->getSourceRange(), E); + + assert(!CXXNewCall.isInvalid() && + "Can't create runtime placement new call!"); + + return B->S.ActOnFinishFullExpr(CXXNewCall.get(), + /*DiscardedValue=*/false); + } + // __clang_Interpreter_SetValueNoAlloc. + case Interpreter::InterfaceKind::NoAlloc: { + return B->S.ActOnCallExpr( + /*Scope=*/nullptr, + B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc], + E->getBeginLoc(), Visitor.Args, E->getEndLoc()); + } + default: + llvm_unreachable("Unhandled Interpreter::InterfaceKind"); + } + } +}; } // namespace +static std::unique_ptr +createInProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &Ctx, + Sema &S) { + return std::make_unique(Interp, Ctx, S); +} + // This synthesizes a call expression to a speciall // function that is responsible for generating the Value. // In general, we transform: @@ -733,8 +767,13 @@ Expr *Interpreter::SynthesizeExpr(Expr *E) { Sema &S = getCompilerInstance()->getSema(); ASTContext &Ctx = S.getASTContext(); - if (!FindRuntimeInterface()) - llvm_unreachable("We can't find the runtime iterface for pretty print!"); + if (!RuntimeIB) { + RuntimeIB = FindRuntimeInterface(); + AddPrintValueCall = RuntimeIB->getPrintValueTransformer(); + } + + assert(AddPrintValueCall && + "We don't have a runtime interface for pretty print!"); // Create parameter `ThisInterp`. auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this); @@ -743,9 +782,9 @@ Expr *Interpreter::SynthesizeExpr(Expr *E) { auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue); // Build `__clang_Interpreter_SetValue*` call. - RuntimeInterfaceBuilder Builder(*this, Ctx, S, E, {ThisInterp, OutValue}); + ExprResult Result = + AddPrintValueCall(RuntimeIB.get(), E, {ThisInterp, OutValue}); - ExprResult Result = Builder.getCall(); // It could fail, like printing an array type in C. (not supported) if (Result.isInvalid()) return E; diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt index 0ddedb283e07..046d96ad0ec6 100644 --- a/clang/unittests/Interpreter/CMakeLists.txt +++ b/clang/unittests/Interpreter/CMakeLists.txt @@ -10,6 +10,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalCompilerBuilderTest.cpp IncrementalProcessingTest.cpp InterpreterTest.cpp + InterpreterExtensionsTest.cpp CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC diff --git a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp new file mode 100644 index 000000000000..4e9f2dba210a --- /dev/null +++ b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp @@ -0,0 +1,79 @@ +//===- unittests/Interpreter/InterpreterExtensionsTest.cpp ----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Unit tests for Clang's Interpreter library. +// +//===----------------------------------------------------------------------===// + +#include "clang/Interpreter/Interpreter.h" + +#include "clang/AST/Expr.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Sema.h" + +#include "llvm/Support/Error.h" +#include "llvm/Testing/Support/Error.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include + +using namespace clang; +namespace { + +class RecordRuntimeIBMetrics : public Interpreter { + struct NoopRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder { + NoopRuntimeInterfaceBuilder(Sema &S) : S(S) {} + + TransformExprFunction *getPrintValueTransformer() override { + TransformerQueries += 1; + return &noop; + } + + static ExprResult noop(RuntimeInterfaceBuilder *Builder, Expr *E, + ArrayRef FixedArgs) { + auto *B = static_cast(Builder); + B->TransformedExprs += 1; + return B->S.ActOnFinishFullExpr(E, /*DiscardedValue=*/false); + } + + Sema &S; + size_t TransformedExprs = 0; + size_t TransformerQueries = 0; + }; + +public: + // Inherit with using wouldn't make it public + RecordRuntimeIBMetrics(std::unique_ptr CI, llvm::Error &Err) + : Interpreter(std::move(CI), Err) {} + + std::unique_ptr FindRuntimeInterface() override { + assert(RuntimeIBPtr == nullptr && "We create the builder only once"); + Sema &S = getCompilerInstance()->getSema(); + auto RuntimeIB = std::make_unique(S); + RuntimeIBPtr = RuntimeIB.get(); + return RuntimeIB; + } + + NoopRuntimeInterfaceBuilder *RuntimeIBPtr = nullptr; +}; + +TEST(InterpreterExtensionsTest, FindRuntimeInterface) { + clang::IncrementalCompilerBuilder CB; + llvm::Error ErrOut = llvm::Error::success(); + RecordRuntimeIBMetrics Interp(cantFail(CB.CreateCpp()), ErrOut); + cantFail(std::move(ErrOut)); + cantFail(Interp.Parse("int a = 1; a")); + cantFail(Interp.Parse("int b = 2; b")); + cantFail(Interp.Parse("int c = 3; c")); + EXPECT_EQ(3U, Interp.RuntimeIBPtr->TransformedExprs); + EXPECT_EQ(1U, Interp.RuntimeIBPtr->TransformerQueries); +} + +} // end anonymous namespace -- GitLab From 483c3364fe914280536b1ea0591bac4ba5f6c5de Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Mon, 11 Mar 2024 11:15:22 +0000 Subject: [PATCH 086/953] [gn build] Port ec2875ce2690 --- llvm/utils/gn/secondary/clang/unittests/Interpreter/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/clang/unittests/Interpreter/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/Interpreter/BUILD.gn index a20066436a3b..4107bbc12be2 100644 --- a/llvm/utils/gn/secondary/clang/unittests/Interpreter/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/unittests/Interpreter/BUILD.gn @@ -14,6 +14,7 @@ unittest("ClangReplInterpreterTests") { "CodeCompletionTest.cpp", "IncrementalCompilerBuilderTest.cpp", "IncrementalProcessingTest.cpp", + "InterpreterExtensionsTest.cpp", "InterpreterTest.cpp", ] -- GitLab From 7b90a67fe717338f7ae4e53f6b97d0f29bacde8e Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 11 Mar 2024 11:16:28 +0000 Subject: [PATCH 087/953] [X86] Assert that the supportedVectorShift* helpers are only called with generic shift opcodes. NFC. --- llvm/lib/Target/X86/X86ISelLowering.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index eb249b25374a..a74901958ac0 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -28926,6 +28926,9 @@ SDValue X86TargetLowering::LowerWin64_INT128_TO_FP(SDValue Op, // supported by the Subtarget static bool supportedVectorShiftWithImm(EVT VT, const X86Subtarget &Subtarget, unsigned Opcode) { + assert((Opcode == ISD::SHL || Opcode == ISD::SRA || Opcode == ISD::SRL) && + "Unexpected shift opcode"); + if (!VT.isSimple()) return false; @@ -28959,6 +28962,9 @@ bool supportedVectorShiftWithBaseAmnt(EVT VT, const X86Subtarget &Subtarget, // natively supported by the Subtarget static bool supportedVectorVarShift(EVT VT, const X86Subtarget &Subtarget, unsigned Opcode) { + assert((Opcode == ISD::SHL || Opcode == ISD::SRA || Opcode == ISD::SRL) && + "Unexpected shift opcode"); + if (!VT.isSimple()) return false; -- GitLab From 3149c934cb2602691de40d2aeb238675e8831d57 Mon Sep 17 00:00:00 2001 From: Leandro Lupori Date: Mon, 11 Mar 2024 08:25:41 -0300 Subject: [PATCH 088/953] [flang] Fix Darwin build after 4762c6557d15 (#84478) Select POSIX 2008 standard to avoid including Darwin extensions. Otherwise, Darwin's math.h header defines HUGE, which conflicts with Flang's HUGE function. This started happening after 4762c6557d15 (#82443), that added the "utility" include, which seems to include "math.h". --- flang/CMakeLists.txt | 8 ++++++++ flang/include/flang/Evaluate/integer.h | 4 ---- flang/include/flang/Evaluate/real.h | 4 ---- flang/lib/Evaluate/fold-implementation.h | 4 ---- flang/lib/Evaluate/intrinsics-library.cpp | 4 ++-- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt index 21617aeea021..71141e5efac4 100644 --- a/flang/CMakeLists.txt +++ b/flang/CMakeLists.txt @@ -413,6 +413,14 @@ if (LLVM_COMPILER_IS_GCC_COMPATIBLE) endif() +# Clang on Darwin enables non-POSIX extensions by default, which allows the +# macro HUGE to leak out of even when it is never directly included, +# conflicting with Flang's HUGE symbols. +# Set _POSIX_C_SOURCE to avoid including these extensions. +if (APPLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_POSIX_C_SOURCE=200809") +endif() + list(REMOVE_DUPLICATES CMAKE_CXX_FLAGS) # Determine HOST_LINK_VERSION on Darwin. diff --git a/flang/include/flang/Evaluate/integer.h b/flang/include/flang/Evaluate/integer.h index 2fce4bedfaee..977d35c7eecf 100644 --- a/flang/include/flang/Evaluate/integer.h +++ b/flang/include/flang/Evaluate/integer.h @@ -27,10 +27,6 @@ #include #include -// Some environments, viz. clang on Darwin, allow the macro HUGE -// to leak out of even when it is never directly included. -#undef HUGE - namespace Fortran::evaluate::value { // Implements an integer as an assembly of smaller host integer parts diff --git a/flang/include/flang/Evaluate/real.h b/flang/include/flang/Evaluate/real.h index 62c99cebc316..5266bd0ef64b 100644 --- a/flang/include/flang/Evaluate/real.h +++ b/flang/include/flang/Evaluate/real.h @@ -18,10 +18,6 @@ #include #include -// Some environments, viz. clang on Darwin, allow the macro HUGE -// to leak out of even when it is never directly included. -#undef HUGE - namespace llvm { class raw_ostream; } diff --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h index 798bc5f37f6f..6b3c9416724c 100644 --- a/flang/lib/Evaluate/fold-implementation.h +++ b/flang/lib/Evaluate/fold-implementation.h @@ -39,10 +39,6 @@ #include #include -// Some environments, viz. clang on Darwin, allow the macro HUGE -// to leak out of even when it is never directly included. -#undef HUGE - namespace Fortran::evaluate { // Utilities diff --git a/flang/lib/Evaluate/intrinsics-library.cpp b/flang/lib/Evaluate/intrinsics-library.cpp index e68c5ed3f6a8..7315a7a057b1 100644 --- a/flang/lib/Evaluate/intrinsics-library.cpp +++ b/flang/lib/Evaluate/intrinsics-library.cpp @@ -299,8 +299,8 @@ struct HostRuntimeLibrary, LibraryVersion::Libm> { /// Define libm extensions /// Bessel functions are defined in POSIX.1-2001. -// Remove float bessel functions for AIX as they are not supported -#ifndef _AIX +// Remove float bessel functions for AIX and Darwin as they are not supported +#if !defined(_AIX) && !defined(__APPLE__) template <> struct HostRuntimeLibrary { using F = FuncPointer; using FN = FuncPointer; -- GitLab From 66f0984385fe3d3c1ece0ac22ff338ee348b2862 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 11 Mar 2024 07:35:02 -0400 Subject: [PATCH 089/953] Reorder fields for better packing (#77998) The RelocationEntry's fields are poorly ordered when considering padding. This reordering reduces the size from 56 bytes to 40 bytes (on LP64). --- .../RuntimeDyld/RuntimeDyldImpl.h | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 73e2b365f109..e09c632842d6 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -116,22 +116,22 @@ public: /// linker. class RelocationEntry { public: - /// SectionID - the section this relocation points to. - unsigned SectionID; - /// Offset - offset into the section. uint64_t Offset; - /// RelType - relocation type. - uint32_t RelType; - /// Addend - the relocation addend encoded in the instruction itself. Also /// used to make a relocation section relative instead of symbol relative. int64_t Addend; + /// SectionID - the section this relocation points to. + unsigned SectionID; + + /// RelType - relocation type. + uint32_t RelType; + struct SectionPair { - uint32_t SectionA; - uint32_t SectionB; + uint32_t SectionA; + uint32_t SectionB; }; /// SymOffset - Section offset of the relocation entry's symbol (used for GOT @@ -141,36 +141,36 @@ public: SectionPair Sections; }; - /// True if this is a PCRel relocation (MachO specific). - bool IsPCRel; - /// The size of this relocation (MachO specific). unsigned Size; + /// True if this is a PCRel relocation (MachO specific). + bool IsPCRel : 1; + // ARM (MachO and COFF) specific. - bool IsTargetThumbFunc = false; + bool IsTargetThumbFunc : 1; RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend) - : SectionID(id), Offset(offset), RelType(type), Addend(addend), - SymOffset(0), IsPCRel(false), Size(0), IsTargetThumbFunc(false) {} + : Offset(offset), Addend(addend), SectionID(id), RelType(type), + SymOffset(0), Size(0), IsPCRel(false), IsTargetThumbFunc(false) {} RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, uint64_t symoffset) - : SectionID(id), Offset(offset), RelType(type), Addend(addend), - SymOffset(symoffset), IsPCRel(false), Size(0), + : Offset(offset), Addend(addend), SectionID(id), RelType(type), + SymOffset(symoffset), Size(0), IsPCRel(false), IsTargetThumbFunc(false) {} RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, bool IsPCRel, unsigned Size) - : SectionID(id), Offset(offset), RelType(type), Addend(addend), - SymOffset(0), IsPCRel(IsPCRel), Size(Size), IsTargetThumbFunc(false) {} + : Offset(offset), Addend(addend), SectionID(id), RelType(type), + SymOffset(0), Size(Size), IsPCRel(IsPCRel), IsTargetThumbFunc(false) {} RelocationEntry(unsigned id, uint64_t offset, uint32_t type, int64_t addend, unsigned SectionA, uint64_t SectionAOffset, unsigned SectionB, uint64_t SectionBOffset, bool IsPCRel, unsigned Size) - : SectionID(id), Offset(offset), RelType(type), - Addend(SectionAOffset - SectionBOffset + addend), IsPCRel(IsPCRel), - Size(Size), IsTargetThumbFunc(false) { + : Offset(offset), Addend(SectionAOffset - SectionBOffset + addend), + SectionID(id), RelType(type), Size(Size), IsPCRel(IsPCRel), + IsTargetThumbFunc(false) { Sections.SectionA = SectionA; Sections.SectionB = SectionB; } @@ -179,9 +179,9 @@ public: unsigned SectionA, uint64_t SectionAOffset, unsigned SectionB, uint64_t SectionBOffset, bool IsPCRel, unsigned Size, bool IsTargetThumbFunc) - : SectionID(id), Offset(offset), RelType(type), - Addend(SectionAOffset - SectionBOffset + addend), IsPCRel(IsPCRel), - Size(Size), IsTargetThumbFunc(IsTargetThumbFunc) { + : Offset(offset), Addend(SectionAOffset - SectionBOffset + addend), + SectionID(id), RelType(type), Size(Size), IsPCRel(IsPCRel), + IsTargetThumbFunc(IsTargetThumbFunc) { Sections.SectionA = SectionA; Sections.SectionB = SectionB; } -- GitLab From e77f5fe889909df3508fd929f2636a0ac211877a Mon Sep 17 00:00:00 2001 From: David Spickett Date: Mon, 11 Mar 2024 11:41:56 +0000 Subject: [PATCH 090/953] [lldb][Docs] Add libxml2 to apt install command --- lldb/docs/resources/build.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/docs/resources/build.rst b/lldb/docs/resources/build.rst index 5f4d35ced623..995273a97b65 100644 --- a/lldb/docs/resources/build.rst +++ b/lldb/docs/resources/build.rst @@ -73,7 +73,7 @@ commands below. :: $ yum install libedit-devel libxml2-devel ncurses-devel python-devel swig - $ sudo apt-get install build-essential swig python3-dev libedit-dev libncurses5-dev + $ sudo apt-get install build-essential swig python3-dev libedit-dev libncurses5-dev libxml2-dev $ pkg install swig python libxml2 $ pkgin install swig python36 cmake ninja-build $ brew install swig cmake ninja -- GitLab From a84eb244129f288d609307ad42ab5e6c8e1cc795 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Mon, 11 Mar 2024 11:47:38 +0000 Subject: [PATCH 091/953] [RemoveDIs] Add additional debug-mode verifier checks (#84308) Separated from #83251 --- llvm/lib/IR/Verifier.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index ce090c3b8a74..0e6c01802cfb 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -2691,6 +2691,11 @@ void Verifier::visitFunction(const Function &F) { Check(verifyAttributeCount(Attrs, FT->getNumParams()), "Attribute after last parameter!", &F); + CheckDI(F.IsNewDbgInfoFormat == F.getParent()->IsNewDbgInfoFormat, + "Function debug format should match parent module", &F, + F.IsNewDbgInfoFormat, F.getParent(), + F.getParent()->IsNewDbgInfoFormat); + bool IsIntrinsic = F.isIntrinsic(); // Check function attributes. @@ -3034,6 +3039,11 @@ void Verifier::visitBasicBlock(BasicBlock &BB) { Check(I.getParent() == &BB, "Instruction has bogus parent pointer!"); } + CheckDI(BB.IsNewDbgInfoFormat == BB.getParent()->IsNewDbgInfoFormat, + "BB debug format should match parent function", &BB, + BB.IsNewDbgInfoFormat, BB.getParent(), + BB.getParent()->IsNewDbgInfoFormat); + // Confirm that no issues arise from the debug program. if (BB.IsNewDbgInfoFormat) CheckDI(!BB.getTrailingDPValues(), "Basic Block has trailing DbgRecords!", -- GitLab From 878097dff3ea4bad6b7f50017224a84bbf2af406 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Mon, 11 Mar 2024 12:02:29 +0000 Subject: [PATCH 092/953] [APINotes] Fix failing tests after a PCM logic change This fixes tests that are going to be upstreamed in the near future. Currently they are failing downstream in the Apple open source fork. Failing tests Clang :: APINotes/retain-count-convention.m Clang :: APINotes/types.m Clang :: APINotes/versioned-multi.c Clang :: APINotes/versioned.m Since 2e5af56 got merged, Clang now enables `LangOpts.APINotesModules` when reading a precompiled module that was built with API Notes enabled. This is correct. The logic in APINotesManager needs to be adjusted to handle this. rdar://123526142 --- clang/lib/APINotes/APINotesManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/APINotes/APINotesManager.cpp b/clang/lib/APINotes/APINotesManager.cpp index d3aef09dac91..f60f09e2b3c2 100644 --- a/clang/lib/APINotes/APINotesManager.cpp +++ b/clang/lib/APINotes/APINotesManager.cpp @@ -224,7 +224,7 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule, llvm::SmallVector APINotes; // First, look relative to the module itself. - if (LookInModule) { + if (LookInModule && M->Directory) { // Local function to try loading an API notes file in the given directory. auto tryAPINotes = [&](DirectoryEntryRef Dir, bool WantPublic) { if (auto File = findAPINotesFile(Dir, ModuleName, WantPublic)) { -- GitLab From 5ff672045a97cf7f9d7f3a93d3a02e76994d50fb Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Mon, 11 Mar 2024 12:08:13 +0000 Subject: [PATCH 093/953] [RemoveDIs][NFC] Rename DPValues->DbgRecords in llvm-reduce's ReduceDPValues (#84506) llvm-reduce currently has a file `ReduceDPValues`, which really is concerned with DbgRecords. Therefore, we rename the file and its function accordingly. --- llvm/tools/llvm-reduce/CMakeLists.txt | 2 +- llvm/tools/llvm-reduce/DeltaManager.cpp | 2 +- .../deltas/{ReduceDPValues.cpp => ReduceDbgRecords.cpp} | 8 ++++---- .../deltas/{ReduceDPValues.h => ReduceDbgRecords.h} | 6 +++--- llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) rename llvm/tools/llvm-reduce/deltas/{ReduceDPValues.cpp => ReduceDbgRecords.cpp} (83%) rename llvm/tools/llvm-reduce/deltas/{ReduceDPValues.h => ReduceDbgRecords.h} (80%) diff --git a/llvm/tools/llvm-reduce/CMakeLists.txt b/llvm/tools/llvm-reduce/CMakeLists.txt index 2f1164b04785..a4c605fcd244 100644 --- a/llvm/tools/llvm-reduce/CMakeLists.txt +++ b/llvm/tools/llvm-reduce/CMakeLists.txt @@ -31,7 +31,7 @@ add_llvm_tool(llvm-reduce deltas/ReduceAttributes.cpp deltas/ReduceBasicBlocks.cpp deltas/ReduceDIMetadata.cpp - deltas/ReduceDPValues.cpp + deltas/ReduceDbgRecords.cpp deltas/ReduceFunctionBodies.cpp deltas/ReduceFunctions.cpp deltas/ReduceGlobalObjects.cpp diff --git a/llvm/tools/llvm-reduce/DeltaManager.cpp b/llvm/tools/llvm-reduce/DeltaManager.cpp index fa42920ee912..67fbc2fdc7ad 100644 --- a/llvm/tools/llvm-reduce/DeltaManager.cpp +++ b/llvm/tools/llvm-reduce/DeltaManager.cpp @@ -20,7 +20,7 @@ #include "deltas/ReduceAttributes.h" #include "deltas/ReduceBasicBlocks.h" #include "deltas/ReduceDIMetadata.h" -#include "deltas/ReduceDPValues.h" +#include "deltas/ReduceDbgRecords.h" #include "deltas/ReduceFunctionBodies.h" #include "deltas/ReduceFunctions.h" #include "deltas/ReduceGlobalObjects.h" diff --git a/llvm/tools/llvm-reduce/deltas/ReduceDPValues.cpp b/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.cpp similarity index 83% rename from llvm/tools/llvm-reduce/deltas/ReduceDPValues.cpp rename to llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.cpp index f0d02a78ac6a..94b12eb34cf6 100644 --- a/llvm/tools/llvm-reduce/deltas/ReduceDPValues.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.cpp @@ -1,4 +1,4 @@ -//===- ReduceDPValues.cpp - Specialized Delta Pass ------------------------===// +//===- ReduceDbgRecords.cpp - Specialized Delta Pass ----------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -17,13 +17,13 @@ // //===----------------------------------------------------------------------===// -#include "ReduceDPValues.h" +#include "ReduceDbgRecords.h" #include "Utils.h" #include "llvm/ADT/STLExtras.h" using namespace llvm; -static void extractDPValuesFromModule(Oracle &O, ReducerWorkItem &WorkItem) { +static void extractDbgRecordsFromModule(Oracle &O, ReducerWorkItem &WorkItem) { Module &M = WorkItem.getModule(); for (auto &F : M) @@ -35,5 +35,5 @@ static void extractDPValuesFromModule(Oracle &O, ReducerWorkItem &WorkItem) { } void llvm::reduceDbgRecordDeltaPass(TestRunner &Test) { - runDeltaPass(Test, extractDPValuesFromModule, "Reducing DbgRecords"); + runDeltaPass(Test, extractDbgRecordsFromModule, "Reducing DbgRecords"); } diff --git a/llvm/tools/llvm-reduce/deltas/ReduceDPValues.h b/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.h similarity index 80% rename from llvm/tools/llvm-reduce/deltas/ReduceDPValues.h rename to llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.h index 1d3b8a35daa3..6a8f62155ec3 100644 --- a/llvm/tools/llvm-reduce/deltas/ReduceDPValues.h +++ b/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.h @@ -1,4 +1,4 @@ -//===- ReduceDPValues.h -----------------------------------------*- C++ -*-===// +//===- ReduceDbgRecords.h ---------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEDPVALUES_H -#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEDPVALUES_H +#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEDBGRECORDS_H +#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEDBGRECORDS_H #include "Delta.h" #include "llvm/IR/BasicBlock.h" diff --git a/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn index 02a1db908af3..2f5d159dbb9d 100644 --- a/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/tools/llvm-reduce/BUILD.gn @@ -22,7 +22,7 @@ executable("llvm-reduce") { "deltas/ReduceAttributes.cpp", "deltas/ReduceBasicBlocks.cpp", "deltas/ReduceDIMetadata.cpp", - "deltas/ReduceDPValues.cpp", + "deltas/ReduceDbgRecords.cpp", "deltas/ReduceFunctionBodies.cpp", "deltas/ReduceFunctions.cpp", "deltas/ReduceGlobalObjects.cpp", -- GitLab From 9b2386e82dedafade233c8871637ee76da9ebe0e Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 11 Mar 2024 13:16:58 +0100 Subject: [PATCH 094/953] [clangd] Fix JSON conversion for symbol tags (#84747) The wrong constructor of json::Value got called, making every tag an array instead of a number. --- clang-tools-extra/clangd/Protocol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index 8aa18bb0058a..c6553e00dcae 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -1412,7 +1412,7 @@ bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R, } llvm::json::Value toJSON(SymbolTag Tag) { - return llvm::json::Value{static_cast(Tag)}; + return llvm::json::Value(static_cast(Tag)); } llvm::json::Value toJSON(const CallHierarchyItem &I) { -- GitLab From 702e2da15a1c5e728c042afd094eccf1cb3741f0 Mon Sep 17 00:00:00 2001 From: "Kevin P. Neal" <52762977+kpneal@users.noreply.github.com> Date: Mon, 11 Mar 2024 08:25:23 -0400 Subject: [PATCH 095/953] [HardwareLoops] Add support for strictfp functions. (#84531) This pass was adding new function calls without adding the strictfp attribute as required by the rules laid out in the langref. With this change a make check has 4-5 fewer failing tests with the Verifier changes in D146845. LangRef: https://llvm.org/docs/LangRef.html#constrained-floating-point-intrinsics Test failures found with "https://reviews.llvm.org/D146845". --- llvm/lib/CodeGen/HardwareLoops.cpp | 8 + .../HardwareLoops/scalar-while-strictfp.ll | 428 ++++++++++++++++++ 2 files changed, 436 insertions(+) create mode 100644 llvm/test/Transforms/HardwareLoops/scalar-while-strictfp.ll diff --git a/llvm/lib/CodeGen/HardwareLoops.cpp b/llvm/lib/CodeGen/HardwareLoops.cpp index e7b14d700a44..c536ec9f79d6 100644 --- a/llvm/lib/CodeGen/HardwareLoops.cpp +++ b/llvm/lib/CodeGen/HardwareLoops.cpp @@ -503,6 +503,8 @@ Value *HardwareLoop::InitLoopCount() { Value* HardwareLoop::InsertIterationSetup(Value *LoopCountInit) { IRBuilder<> Builder(BeginBB->getTerminator()); + if (BeginBB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP)) + Builder.setIsFPConstrained(true); Type *Ty = LoopCountInit->getType(); bool UsePhi = UsePHICounter || Opts.ForcePhi; Intrinsic::ID ID = UseLoopGuard @@ -535,6 +537,9 @@ Value* HardwareLoop::InsertIterationSetup(Value *LoopCountInit) { void HardwareLoop::InsertLoopDec() { IRBuilder<> CondBuilder(ExitBranch); + if (ExitBranch->getParent()->getParent()->getAttributes().hasFnAttr( + Attribute::StrictFP)) + CondBuilder.setIsFPConstrained(true); Function *DecFunc = Intrinsic::getDeclaration(M, Intrinsic::loop_decrement, @@ -557,6 +562,9 @@ void HardwareLoop::InsertLoopDec() { Instruction* HardwareLoop::InsertLoopRegDec(Value *EltsRem) { IRBuilder<> CondBuilder(ExitBranch); + if (ExitBranch->getParent()->getParent()->getAttributes().hasFnAttr( + Attribute::StrictFP)) + CondBuilder.setIsFPConstrained(true); Function *DecFunc = Intrinsic::getDeclaration(M, Intrinsic::loop_decrement_reg, diff --git a/llvm/test/Transforms/HardwareLoops/scalar-while-strictfp.ll b/llvm/test/Transforms/HardwareLoops/scalar-while-strictfp.ll new file mode 100644 index 000000000000..951aacc06536 --- /dev/null +++ b/llvm/test/Transforms/HardwareLoops/scalar-while-strictfp.ll @@ -0,0 +1,428 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes +; RUN: opt -passes='hardware-loops' -S %s -o - | FileCheck %s --check-prefix=CHECK-DEC +; RUN: opt -passes='hardware-loops' -S %s -o - | FileCheck %s --check-prefix=CHECK-PHI + +define void @while_lt(i32 %i, i32 %N, ptr nocapture %A) strictfp { +; CHECK-DEC: Function Attrs: strictfp +; CHECK-DEC-LABEL: @while_lt( +; CHECK-DEC-NEXT: entry: +; CHECK-DEC-NEXT: [[CMP4:%.*]] = icmp ult i32 [[I:%.*]], [[N:%.*]] +; CHECK-DEC-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]] +; CHECK-DEC: while.body.preheader: +; CHECK-DEC-NEXT: [[TMP0:%.*]] = sub i32 [[N]], [[I]] +; CHECK-DEC-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP0]]) #[[ATTR0:[0-9]+]] +; CHECK-DEC-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK-DEC: while.body: +; CHECK-DEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ] +; CHECK-DEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[I_ADDR_05]] +; CHECK-DEC-NEXT: store i32 [[I_ADDR_05]], ptr [[ARRAYIDX]], align 4 +; CHECK-DEC-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1 +; CHECK-DEC-NEXT: [[TMP1:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1) #[[ATTR0]] +; CHECK-DEC-NEXT: br i1 [[TMP1]], label [[WHILE_BODY]], label [[WHILE_END]] +; CHECK-DEC: while.end: +; CHECK-DEC-NEXT: ret void +; +; CHECK-PHI: Function Attrs: strictfp +; CHECK-PHI-LABEL: @while_lt( +; CHECK-PHI-NEXT: entry: +; CHECK-PHI-NEXT: [[CMP4:%.*]] = icmp ult i32 [[I:%.*]], [[N:%.*]] +; CHECK-PHI-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]] +; CHECK-PHI: while.body.preheader: +; CHECK-PHI-NEXT: [[TMP0:%.*]] = sub i32 [[N]], [[I]] +; CHECK-PHI-NEXT: [[TMP1:%.*]] = call i32 @llvm.start.loop.iterations.i32(i32 [[TMP0]]) #[[ATTR0:[0-9]+]] +; CHECK-PHI-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK-PHI: while.body: +; CHECK-PHI-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ] +; CHECK-PHI-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP3:%.*]], [[WHILE_BODY]] ] +; CHECK-PHI-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[I_ADDR_05]] +; CHECK-PHI-NEXT: store i32 [[I_ADDR_05]], ptr [[ARRAYIDX]], align 4 +; CHECK-PHI-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1 +; CHECK-PHI-NEXT: [[TMP3]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP2]], i32 1) #[[ATTR0]] +; CHECK-PHI-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP3]], 0 +; CHECK-PHI-NEXT: br i1 [[TMP4]], label [[WHILE_BODY]], label [[WHILE_END]] +; CHECK-PHI: while.end: +; CHECK-PHI-NEXT: ret void +; +entry: + %cmp4 = icmp ult i32 %i, %N + br i1 %cmp4, label %while.body, label %while.end + +while.body: + %i.addr.05 = phi i32 [ %inc, %while.body ], [ %i, %entry ] + %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.addr.05 + store i32 %i.addr.05, ptr %arrayidx, align 4 + %inc = add nuw i32 %i.addr.05, 1 + %exitcond = icmp eq i32 %inc, %N + br i1 %exitcond, label %while.end, label %while.body + +while.end: + ret void +} + +define void @while_gt(i32 %i, i32 %N, ptr nocapture %A) strictfp { +; CHECK-DEC: Function Attrs: strictfp +; CHECK-DEC-LABEL: @while_gt( +; CHECK-DEC-NEXT: entry: +; CHECK-DEC-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[I:%.*]], [[N:%.*]] +; CHECK-DEC-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]] +; CHECK-DEC: while.body.preheader: +; CHECK-DEC-NEXT: [[TMP0:%.*]] = sub i32 [[I]], [[N]] +; CHECK-DEC-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP0]]) #[[ATTR0]] +; CHECK-DEC-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK-DEC: while.body: +; CHECK-DEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ] +; CHECK-DEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[I_ADDR_05]] +; CHECK-DEC-NEXT: store i32 [[I_ADDR_05]], ptr [[ARRAYIDX]], align 4 +; CHECK-DEC-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1 +; CHECK-DEC-NEXT: [[TMP1:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1) #[[ATTR0]] +; CHECK-DEC-NEXT: br i1 [[TMP1]], label [[WHILE_BODY]], label [[WHILE_END]] +; CHECK-DEC: while.end: +; CHECK-DEC-NEXT: ret void +; +; CHECK-PHI: Function Attrs: strictfp +; CHECK-PHI-LABEL: @while_gt( +; CHECK-PHI-NEXT: entry: +; CHECK-PHI-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[I:%.*]], [[N:%.*]] +; CHECK-PHI-NEXT: br i1 [[CMP4]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]] +; CHECK-PHI: while.body.preheader: +; CHECK-PHI-NEXT: [[TMP0:%.*]] = sub i32 [[I]], [[N]] +; CHECK-PHI-NEXT: [[TMP1:%.*]] = call i32 @llvm.start.loop.iterations.i32(i32 [[TMP0]]) #[[ATTR0]] +; CHECK-PHI-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK-PHI: while.body: +; CHECK-PHI-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ] +; CHECK-PHI-NEXT: [[TMP2:%.*]] = phi i32 [ [[TMP1]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP3:%.*]], [[WHILE_BODY]] ] +; CHECK-PHI-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[I_ADDR_05]] +; CHECK-PHI-NEXT: store i32 [[I_ADDR_05]], ptr [[ARRAYIDX]], align 4 +; CHECK-PHI-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1 +; CHECK-PHI-NEXT: [[TMP3]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP2]], i32 1) #[[ATTR0]] +; CHECK-PHI-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP3]], 0 +; CHECK-PHI-NEXT: br i1 [[TMP4]], label [[WHILE_BODY]], label [[WHILE_END]] +; CHECK-PHI: while.end: +; CHECK-PHI-NEXT: ret void +; +entry: + %cmp4 = icmp sgt i32 %i, %N + br i1 %cmp4, label %while.body, label %while.end + +while.body: + %i.addr.05 = phi i32 [ %dec, %while.body ], [ %i, %entry ] + %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.addr.05 + store i32 %i.addr.05, ptr %arrayidx, align 4 + %dec = add nsw i32 %i.addr.05, -1 + %cmp = icmp sgt i32 %dec, %N + br i1 %cmp, label %while.body, label %while.end + +while.end: + ret void +} + +define void @while_gte(i32 %i, i32 %N, ptr nocapture %A) strictfp { +; CHECK-DEC: Function Attrs: strictfp +; CHECK-DEC-LABEL: @while_gte( +; CHECK-DEC-NEXT: entry: +; CHECK-DEC-NEXT: [[CMP4:%.*]] = icmp slt i32 [[I:%.*]], [[N:%.*]] +; CHECK-DEC-NEXT: br i1 [[CMP4]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]] +; CHECK-DEC: while.body.preheader: +; CHECK-DEC-NEXT: [[TMP0:%.*]] = add i32 [[I]], 1 +; CHECK-DEC-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[N]] +; CHECK-DEC-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[TMP1]]) #[[ATTR0]] +; CHECK-DEC-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK-DEC: while.body: +; CHECK-DEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ] +; CHECK-DEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[I_ADDR_05]] +; CHECK-DEC-NEXT: store i32 [[I_ADDR_05]], ptr [[ARRAYIDX]], align 4 +; CHECK-DEC-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1 +; CHECK-DEC-NEXT: [[TMP2:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1) #[[ATTR0]] +; CHECK-DEC-NEXT: br i1 [[TMP2]], label [[WHILE_BODY]], label [[WHILE_END]] +; CHECK-DEC: while.end: +; CHECK-DEC-NEXT: ret void +; +; CHECK-PHI: Function Attrs: strictfp +; CHECK-PHI-LABEL: @while_gte( +; CHECK-PHI-NEXT: entry: +; CHECK-PHI-NEXT: [[CMP4:%.*]] = icmp slt i32 [[I:%.*]], [[N:%.*]] +; CHECK-PHI-NEXT: br i1 [[CMP4]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]] +; CHECK-PHI: while.body.preheader: +; CHECK-PHI-NEXT: [[TMP0:%.*]] = add i32 [[I]], 1 +; CHECK-PHI-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[N]] +; CHECK-PHI-NEXT: [[TMP2:%.*]] = call i32 @llvm.start.loop.iterations.i32(i32 [[TMP1]]) #[[ATTR0]] +; CHECK-PHI-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK-PHI: while.body: +; CHECK-PHI-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[DEC:%.*]], [[WHILE_BODY]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ] +; CHECK-PHI-NEXT: [[TMP3:%.*]] = phi i32 [ [[TMP2]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP4:%.*]], [[WHILE_BODY]] ] +; CHECK-PHI-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[I_ADDR_05]] +; CHECK-PHI-NEXT: store i32 [[I_ADDR_05]], ptr [[ARRAYIDX]], align 4 +; CHECK-PHI-NEXT: [[DEC]] = add nsw i32 [[I_ADDR_05]], -1 +; CHECK-PHI-NEXT: [[TMP4]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP3]], i32 1) #[[ATTR0]] +; CHECK-PHI-NEXT: [[TMP5:%.*]] = icmp ne i32 [[TMP4]], 0 +; CHECK-PHI-NEXT: br i1 [[TMP5]], label [[WHILE_BODY]], label [[WHILE_END]] +; CHECK-PHI: while.end: +; CHECK-PHI-NEXT: ret void +; +entry: + %cmp4 = icmp slt i32 %i, %N + br i1 %cmp4, label %while.end, label %while.body + +while.body: + %i.addr.05 = phi i32 [ %dec, %while.body ], [ %i, %entry ] + %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.addr.05 + store i32 %i.addr.05, ptr %arrayidx, align 4 + %dec = add nsw i32 %i.addr.05, -1 + %cmp = icmp sgt i32 %i.addr.05, %N + br i1 %cmp, label %while.body, label %while.end + +while.end: + ret void +} + +define void @while_ne(i32 %N, ptr nocapture %A) strictfp { +; CHECK-DEC: Function Attrs: strictfp +; CHECK-DEC-LABEL: @while_ne( +; CHECK-DEC-NEXT: entry: +; CHECK-DEC-NEXT: [[CMP:%.*]] = icmp ne i32 [[N:%.*]], 0 +; CHECK-DEC-NEXT: br i1 [[CMP]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]] +; CHECK-DEC: while.body.preheader: +; CHECK-DEC-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]]) #[[ATTR0]] +; CHECK-DEC-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK-DEC: while.body: +; CHECK-DEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ] +; CHECK-DEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[I_ADDR_05]] +; CHECK-DEC-NEXT: store i32 [[I_ADDR_05]], ptr [[ARRAYIDX]], align 4 +; CHECK-DEC-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1 +; CHECK-DEC-NEXT: [[TMP0:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1) #[[ATTR0]] +; CHECK-DEC-NEXT: br i1 [[TMP0]], label [[WHILE_BODY]], label [[WHILE_END]] +; CHECK-DEC: while.end: +; CHECK-DEC-NEXT: ret void +; +; CHECK-PHI: Function Attrs: strictfp +; CHECK-PHI-LABEL: @while_ne( +; CHECK-PHI-NEXT: entry: +; CHECK-PHI-NEXT: [[CMP:%.*]] = icmp ne i32 [[N:%.*]], 0 +; CHECK-PHI-NEXT: br i1 [[CMP]], label [[WHILE_BODY_PREHEADER:%.*]], label [[WHILE_END:%.*]] +; CHECK-PHI: while.body.preheader: +; CHECK-PHI-NEXT: [[TMP0:%.*]] = call i32 @llvm.start.loop.iterations.i32(i32 [[N]]) #[[ATTR0]] +; CHECK-PHI-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK-PHI: while.body: +; CHECK-PHI-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ] +; CHECK-PHI-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP2:%.*]], [[WHILE_BODY]] ] +; CHECK-PHI-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[I_ADDR_05]] +; CHECK-PHI-NEXT: store i32 [[I_ADDR_05]], ptr [[ARRAYIDX]], align 4 +; CHECK-PHI-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1 +; CHECK-PHI-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1) #[[ATTR0]] +; CHECK-PHI-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 +; CHECK-PHI-NEXT: br i1 [[TMP3]], label [[WHILE_BODY]], label [[WHILE_END]] +; CHECK-PHI: while.end: +; CHECK-PHI-NEXT: ret void +; +entry: + %cmp = icmp ne i32 %N, 0 + br i1 %cmp, label %while.body, label %while.end + +while.body: + %i.addr.05 = phi i32 [ %inc, %while.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.addr.05 + store i32 %i.addr.05, ptr %arrayidx, align 4 + %inc = add nuw i32 %i.addr.05, 1 + %exitcond = icmp eq i32 %inc, %N + br i1 %exitcond, label %while.end, label %while.body + +while.end: + ret void +} + +define void @while_eq(i32 %N, ptr nocapture %A) strictfp { +; CHECK-DEC: Function Attrs: strictfp +; CHECK-DEC-LABEL: @while_eq( +; CHECK-DEC-NEXT: entry: +; CHECK-DEC-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0 +; CHECK-DEC-NEXT: br i1 [[CMP]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]] +; CHECK-DEC: while.body.preheader: +; CHECK-DEC-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]]) #[[ATTR0]] +; CHECK-DEC-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK-DEC: while.body: +; CHECK-DEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ] +; CHECK-DEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[I_ADDR_05]] +; CHECK-DEC-NEXT: store i32 [[I_ADDR_05]], ptr [[ARRAYIDX]], align 4 +; CHECK-DEC-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1 +; CHECK-DEC-NEXT: [[TMP0:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1) #[[ATTR0]] +; CHECK-DEC-NEXT: br i1 [[TMP0]], label [[WHILE_BODY]], label [[WHILE_END]] +; CHECK-DEC: while.end: +; CHECK-DEC-NEXT: ret void +; +; CHECK-PHI: Function Attrs: strictfp +; CHECK-PHI-LABEL: @while_eq( +; CHECK-PHI-NEXT: entry: +; CHECK-PHI-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0 +; CHECK-PHI-NEXT: br i1 [[CMP]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]] +; CHECK-PHI: while.body.preheader: +; CHECK-PHI-NEXT: [[TMP0:%.*]] = call i32 @llvm.start.loop.iterations.i32(i32 [[N]]) #[[ATTR0]] +; CHECK-PHI-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK-PHI: while.body: +; CHECK-PHI-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ] +; CHECK-PHI-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP2:%.*]], [[WHILE_BODY]] ] +; CHECK-PHI-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[I_ADDR_05]] +; CHECK-PHI-NEXT: store i32 [[I_ADDR_05]], ptr [[ARRAYIDX]], align 4 +; CHECK-PHI-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1 +; CHECK-PHI-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1) #[[ATTR0]] +; CHECK-PHI-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 +; CHECK-PHI-NEXT: br i1 [[TMP3]], label [[WHILE_BODY]], label [[WHILE_END]] +; CHECK-PHI: while.end: +; CHECK-PHI-NEXT: ret void +; +entry: + %cmp = icmp eq i32 %N, 0 + br i1 %cmp, label %while.end, label %while.body + +while.body: + %i.addr.05 = phi i32 [ %inc, %while.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.addr.05 + store i32 %i.addr.05, ptr %arrayidx, align 4 + %inc = add nuw i32 %i.addr.05, 1 + %exitcond = icmp eq i32 %inc, %N + br i1 %exitcond, label %while.end, label %while.body + +while.end: + ret void +} + +define void @while_preheader_eq(i32 %N, ptr nocapture %A) strictfp { +; CHECK-DEC: Function Attrs: strictfp +; CHECK-DEC-LABEL: @while_preheader_eq( +; CHECK-DEC-NEXT: entry: +; CHECK-DEC-NEXT: br label [[PREHEADER:%.*]] +; CHECK-DEC: preheader: +; CHECK-DEC-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0 +; CHECK-DEC-NEXT: br i1 [[CMP]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]] +; CHECK-DEC: while.body.preheader: +; CHECK-DEC-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]]) #[[ATTR0]] +; CHECK-DEC-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK-DEC: while.body: +; CHECK-DEC-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ] +; CHECK-DEC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[I_ADDR_05]] +; CHECK-DEC-NEXT: store i32 [[I_ADDR_05]], ptr [[ARRAYIDX]], align 4 +; CHECK-DEC-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1 +; CHECK-DEC-NEXT: [[TMP0:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1) #[[ATTR0]] +; CHECK-DEC-NEXT: br i1 [[TMP0]], label [[WHILE_BODY]], label [[WHILE_END]] +; CHECK-DEC: while.end: +; CHECK-DEC-NEXT: ret void +; +; CHECK-PHI: Function Attrs: strictfp +; CHECK-PHI-LABEL: @while_preheader_eq( +; CHECK-PHI-NEXT: entry: +; CHECK-PHI-NEXT: br label [[PREHEADER:%.*]] +; CHECK-PHI: preheader: +; CHECK-PHI-NEXT: [[CMP:%.*]] = icmp eq i32 [[N:%.*]], 0 +; CHECK-PHI-NEXT: br i1 [[CMP]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]] +; CHECK-PHI: while.body.preheader: +; CHECK-PHI-NEXT: [[TMP0:%.*]] = call i32 @llvm.start.loop.iterations.i32(i32 [[N]]) #[[ATTR0]] +; CHECK-PHI-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK-PHI: while.body: +; CHECK-PHI-NEXT: [[I_ADDR_05:%.*]] = phi i32 [ [[INC:%.*]], [[WHILE_BODY]] ], [ 0, [[WHILE_BODY_PREHEADER]] ] +; CHECK-PHI-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[WHILE_BODY_PREHEADER]] ], [ [[TMP2:%.*]], [[WHILE_BODY]] ] +; CHECK-PHI-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[I_ADDR_05]] +; CHECK-PHI-NEXT: store i32 [[I_ADDR_05]], ptr [[ARRAYIDX]], align 4 +; CHECK-PHI-NEXT: [[INC]] = add nuw i32 [[I_ADDR_05]], 1 +; CHECK-PHI-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1) #[[ATTR0]] +; CHECK-PHI-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 +; CHECK-PHI-NEXT: br i1 [[TMP3]], label [[WHILE_BODY]], label [[WHILE_END]] +; CHECK-PHI: while.end: +; CHECK-PHI-NEXT: ret void +; +entry: + br label %preheader + +preheader: + %cmp = icmp eq i32 %N, 0 + br i1 %cmp, label %while.end, label %while.body + +while.body: + %i.addr.05 = phi i32 [ %inc, %while.body ], [ 0, %preheader ] + %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i.addr.05 + store i32 %i.addr.05, ptr %arrayidx, align 4 + %inc = add nuw i32 %i.addr.05, 1 + %exitcond = icmp eq i32 %inc, %N + br i1 %exitcond, label %while.end, label %while.body + +while.end: + ret void +} + +define void @nested(ptr nocapture %A, i32 %N) strictfp { +; CHECK-DEC: Function Attrs: strictfp +; CHECK-DEC-LABEL: @nested( +; CHECK-DEC-NEXT: entry: +; CHECK-DEC-NEXT: [[CMP20:%.*]] = icmp eq i32 [[N:%.*]], 0 +; CHECK-DEC-NEXT: br i1 [[CMP20]], label [[WHILE_END7:%.*]], label [[WHILE_COND1_PREHEADER_US:%.*]] +; CHECK-DEC: while.cond1.preheader.us: +; CHECK-DEC-NEXT: [[I_021_US:%.*]] = phi i32 [ [[INC6_US:%.*]], [[WHILE_COND1_WHILE_END_CRIT_EDGE_US:%.*]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-DEC-NEXT: [[MUL_US:%.*]] = mul i32 [[I_021_US]], [[N]] +; CHECK-DEC-NEXT: call void @llvm.set.loop.iterations.i32(i32 [[N]]) #[[ATTR0]] +; CHECK-DEC-NEXT: br label [[WHILE_BODY3_US:%.*]] +; CHECK-DEC: while.body3.us: +; CHECK-DEC-NEXT: [[J_019_US:%.*]] = phi i32 [ 0, [[WHILE_COND1_PREHEADER_US]] ], [ [[INC_US:%.*]], [[WHILE_BODY3_US]] ] +; CHECK-DEC-NEXT: [[ADD_US:%.*]] = add i32 [[J_019_US]], [[MUL_US]] +; CHECK-DEC-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[ADD_US]] +; CHECK-DEC-NEXT: store i32 [[ADD_US]], ptr [[ARRAYIDX_US]], align 4 +; CHECK-DEC-NEXT: [[INC_US]] = add nuw i32 [[J_019_US]], 1 +; CHECK-DEC-NEXT: [[TMP0:%.*]] = call i1 @llvm.loop.decrement.i32(i32 1) #[[ATTR0]] +; CHECK-DEC-NEXT: br i1 [[TMP0]], label [[WHILE_BODY3_US]], label [[WHILE_COND1_WHILE_END_CRIT_EDGE_US]] +; CHECK-DEC: while.cond1.while.end_crit_edge.us: +; CHECK-DEC-NEXT: [[INC6_US]] = add nuw i32 [[I_021_US]], 1 +; CHECK-DEC-NEXT: [[EXITCOND23:%.*]] = icmp eq i32 [[INC6_US]], [[N]] +; CHECK-DEC-NEXT: br i1 [[EXITCOND23]], label [[WHILE_END7]], label [[WHILE_COND1_PREHEADER_US]] +; CHECK-DEC: while.end7: +; CHECK-DEC-NEXT: ret void +; +; CHECK-PHI: Function Attrs: strictfp +; CHECK-PHI-LABEL: @nested( +; CHECK-PHI-NEXT: entry: +; CHECK-PHI-NEXT: [[CMP20:%.*]] = icmp eq i32 [[N:%.*]], 0 +; CHECK-PHI-NEXT: br i1 [[CMP20]], label [[WHILE_END7:%.*]], label [[WHILE_COND1_PREHEADER_US:%.*]] +; CHECK-PHI: while.cond1.preheader.us: +; CHECK-PHI-NEXT: [[I_021_US:%.*]] = phi i32 [ [[INC6_US:%.*]], [[WHILE_COND1_WHILE_END_CRIT_EDGE_US:%.*]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-PHI-NEXT: [[MUL_US:%.*]] = mul i32 [[I_021_US]], [[N]] +; CHECK-PHI-NEXT: [[TMP0:%.*]] = call i32 @llvm.start.loop.iterations.i32(i32 [[N]]) #[[ATTR0]] +; CHECK-PHI-NEXT: br label [[WHILE_BODY3_US:%.*]] +; CHECK-PHI: while.body3.us: +; CHECK-PHI-NEXT: [[J_019_US:%.*]] = phi i32 [ 0, [[WHILE_COND1_PREHEADER_US]] ], [ [[INC_US:%.*]], [[WHILE_BODY3_US]] ] +; CHECK-PHI-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[WHILE_COND1_PREHEADER_US]] ], [ [[TMP2:%.*]], [[WHILE_BODY3_US]] ] +; CHECK-PHI-NEXT: [[ADD_US:%.*]] = add i32 [[J_019_US]], [[MUL_US]] +; CHECK-PHI-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[ADD_US]] +; CHECK-PHI-NEXT: store i32 [[ADD_US]], ptr [[ARRAYIDX_US]], align 4 +; CHECK-PHI-NEXT: [[INC_US]] = add nuw i32 [[J_019_US]], 1 +; CHECK-PHI-NEXT: [[TMP2]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[TMP1]], i32 1) #[[ATTR0]] +; CHECK-PHI-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 +; CHECK-PHI-NEXT: br i1 [[TMP3]], label [[WHILE_BODY3_US]], label [[WHILE_COND1_WHILE_END_CRIT_EDGE_US]] +; CHECK-PHI: while.cond1.while.end_crit_edge.us: +; CHECK-PHI-NEXT: [[INC6_US]] = add nuw i32 [[I_021_US]], 1 +; CHECK-PHI-NEXT: [[EXITCOND23:%.*]] = icmp eq i32 [[INC6_US]], [[N]] +; CHECK-PHI-NEXT: br i1 [[EXITCOND23]], label [[WHILE_END7]], label [[WHILE_COND1_PREHEADER_US]] +; CHECK-PHI: while.end7: +; CHECK-PHI-NEXT: ret void +; +entry: + %cmp20 = icmp eq i32 %N, 0 + br i1 %cmp20, label %while.end7, label %while.cond1.preheader.us + +while.cond1.preheader.us: + %i.021.us = phi i32 [ %inc6.us, %while.cond1.while.end_crit_edge.us ], [ 0, %entry ] + %mul.us = mul i32 %i.021.us, %N + br label %while.body3.us + +while.body3.us: + %j.019.us = phi i32 [ 0, %while.cond1.preheader.us ], [ %inc.us, %while.body3.us ] + %add.us = add i32 %j.019.us, %mul.us + %arrayidx.us = getelementptr inbounds i32, ptr %A, i32 %add.us + store i32 %add.us, ptr %arrayidx.us, align 4 + %inc.us = add nuw i32 %j.019.us, 1 + %exitcond = icmp eq i32 %inc.us, %N + br i1 %exitcond, label %while.cond1.while.end_crit_edge.us, label %while.body3.us + +while.cond1.while.end_crit_edge.us: + %inc6.us = add nuw i32 %i.021.us, 1 + %exitcond23 = icmp eq i32 %inc6.us, %N + br i1 %exitcond23, label %while.end7, label %while.cond1.preheader.us + +while.end7: + ret void +} -- GitLab From aec92830b79a8c49cdce0d592627d5f18bb6370b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= Date: Mon, 11 Mar 2024 13:39:23 +0100 Subject: [PATCH 096/953] [clang-repl] Refactor locking of runtime PTU stack (NFC) (#84176) The Interpreter locks PTUs that originate from implicit runtime code and initialization to prevent users from undoing them accidentally. The previous implementation seemed hacky, because it required the reader to be familiar with the internal workings of the PTU stack. The concept itself is a pragmatic solution and not very surprising. This patch introduces a function for it and adds a comment. --- clang/include/clang/Interpreter/Interpreter.h | 1 + clang/lib/Interpreter/Interpreter.cpp | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index d972d960dcb7..469ce1fd75bf 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -169,6 +169,7 @@ public: private: size_t getEffectivePTUSize() const; + void markUserCodeStart(); llvm::DenseMap Dtors; diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 3485da819668..e293fefb5249 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -280,15 +280,14 @@ Interpreter::create(std::unique_ptr CI) { if (Err) return std::move(Err); + // Add runtime code and set a marker to hide it from user code. Undo will not + // go through that. auto PTU = Interp->Parse(Runtimes); if (!PTU) return PTU.takeError(); + Interp->markUserCodeStart(); Interp->ValuePrintingInfo.resize(4); - // FIXME: This is a ugly hack. Undo command checks its availability by looking - // at the size of the PTU list. However we have parsed something in the - // beginning of the REPL so we have to mark them as 'Irrevocable'. - Interp->InitPTUSize = Interp->IncrParser->getPTUs().size(); return std::move(Interp); } @@ -345,6 +344,11 @@ const ASTContext &Interpreter::getASTContext() const { return getCompilerInstance()->getASTContext(); } +void Interpreter::markUserCodeStart() { + assert(!InitPTUSize && "We only do this once"); + InitPTUSize = IncrParser->getPTUs().size(); +} + size_t Interpreter::getEffectivePTUSize() const { std::list &PTUs = IncrParser->getPTUs(); assert(PTUs.size() >= InitPTUSize && "empty PTU list?"); -- GitLab From 546f32df26f58fdfe02d99e6d91d681dd9ed6839 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 11 Mar 2024 08:00:18 -0500 Subject: [PATCH 097/953] [flang][CodeGen] Fix use-after-free in BoxedProcedurePass (#84376) Avoid inspecting an operation that has been replaced. This was detected by address sanitizer. --- flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp b/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp index 4cf39716a737..746c275f37ea 100644 --- a/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp +++ b/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp @@ -209,6 +209,7 @@ public: BoxprocTypeRewriter typeConverter(mlir::UnknownLoc::get(context)); mlir::Dialect *firDialect = context->getLoadedDialect("fir"); getModule().walk([&](mlir::Operation *op) { + bool opIsValid = true; typeConverter.setLocation(op->getLoc()); if (auto addr = mlir::dyn_cast(op)) { mlir::Type ty = addr.getVal().getType(); @@ -220,6 +221,7 @@ public: rewriter.setInsertionPoint(addr); rewriter.replaceOpWithNewOp( addr, typeConverter.convertType(addr.getType()), addr.getVal()); + opIsValid = false; } else if (typeConverter.needsConversion(resTy)) { rewriter.startOpModification(op); op->getResult(0).setType(typeConverter.convertType(resTy)); @@ -271,10 +273,12 @@ public: llvm::ArrayRef{tramp}); rewriter.replaceOpWithNewOp(embox, toTy, adjustCall.getResult(0)); + opIsValid = false; } else { // Just forward the function as a pointer. rewriter.replaceOpWithNewOp(embox, toTy, embox.getFunc()); + opIsValid = false; } } else if (auto global = mlir::dyn_cast(op)) { auto ty = global.getType(); @@ -297,6 +301,7 @@ public: rewriter.replaceOpWithNewOp( mem, toTy, uniqName, bindcName, isPinned, mem.getTypeparams(), mem.getShape()); + opIsValid = false; } } else if (auto mem = mlir::dyn_cast(op)) { auto ty = mem.getType(); @@ -310,6 +315,7 @@ public: rewriter.replaceOpWithNewOp( mem, toTy, uniqName, bindcName, mem.getTypeparams(), mem.getShape()); + opIsValid = false; } } else if (auto coor = mlir::dyn_cast(op)) { auto ty = coor.getType(); @@ -321,6 +327,7 @@ public: auto toBaseTy = typeConverter.convertType(baseTy); rewriter.replaceOpWithNewOp(coor, toTy, coor.getRef(), coor.getCoor(), toBaseTy); + opIsValid = false; } } else if (auto index = mlir::dyn_cast(op)) { auto ty = index.getType(); @@ -332,6 +339,7 @@ public: auto toOnTy = typeConverter.convertType(onTy); rewriter.replaceOpWithNewOp( index, toTy, index.getFieldId(), toOnTy, index.getTypeparams()); + opIsValid = false; } } else if (auto index = mlir::dyn_cast(op)) { auto ty = index.getType(); @@ -343,6 +351,7 @@ public: auto toOnTy = typeConverter.convertType(onTy); rewriter.replaceOpWithNewOp( index, toTy, index.getFieldId(), toOnTy, index.getTypeparams()); + opIsValid = false; } } else if (op->getDialect() == firDialect) { rewriter.startOpModification(op); @@ -354,7 +363,7 @@ public: rewriter.finalizeOpModification(op); } // Ensure block arguments are updated if needed. - if (op->getNumRegions() != 0) { + if (opIsValid && op->getNumRegions() != 0) { rewriter.startOpModification(op); for (mlir::Region ®ion : op->getRegions()) for (mlir::Block &block : region.getBlocks()) -- GitLab From 2b8f1daf7878c03d5fac58385fdc3e498a810d8d Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 11 Mar 2024 13:02:37 +0000 Subject: [PATCH 098/953] [X86] Add missing immediate qualifier to the SSE42 (V)PCMPEST/PCMPIST string instruction names --- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 28 ++++++++++++++++--------- llvm/lib/Target/X86/X86InstrSSE.td | 16 +++++++------- llvm/test/TableGen/x86-fold-tables.inc | 16 +++++++------- 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index 5cbd9ab4dc2d..76c6c1645239 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -6133,14 +6133,18 @@ void X86DAGToDAGISel::Select(SDNode *Node) { MachineSDNode *CNode; if (NeedMask) { - unsigned ROpc = Subtarget->hasAVX() ? X86::VPCMPISTRMrr : X86::PCMPISTRMrr; - unsigned MOpc = Subtarget->hasAVX() ? X86::VPCMPISTRMrm : X86::PCMPISTRMrm; + unsigned ROpc = + Subtarget->hasAVX() ? X86::VPCMPISTRMrri : X86::PCMPISTRMrri; + unsigned MOpc = + Subtarget->hasAVX() ? X86::VPCMPISTRMrmi : X86::PCMPISTRMrmi; CNode = emitPCMPISTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node); ReplaceUses(SDValue(Node, 1), SDValue(CNode, 0)); } if (NeedIndex || !NeedMask) { - unsigned ROpc = Subtarget->hasAVX() ? X86::VPCMPISTRIrr : X86::PCMPISTRIrr; - unsigned MOpc = Subtarget->hasAVX() ? X86::VPCMPISTRIrm : X86::PCMPISTRIrm; + unsigned ROpc = + Subtarget->hasAVX() ? X86::VPCMPISTRIrri : X86::PCMPISTRIrri; + unsigned MOpc = + Subtarget->hasAVX() ? X86::VPCMPISTRIrmi : X86::PCMPISTRIrmi; CNode = emitPCMPISTR(ROpc, MOpc, MayFoldLoad, dl, MVT::i32, Node); ReplaceUses(SDValue(Node, 0), SDValue(CNode, 0)); } @@ -6168,15 +6172,19 @@ void X86DAGToDAGISel::Select(SDNode *Node) { MachineSDNode *CNode; if (NeedMask) { - unsigned ROpc = Subtarget->hasAVX() ? X86::VPCMPESTRMrr : X86::PCMPESTRMrr; - unsigned MOpc = Subtarget->hasAVX() ? X86::VPCMPESTRMrm : X86::PCMPESTRMrm; - CNode = emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node, - InGlue); + unsigned ROpc = + Subtarget->hasAVX() ? X86::VPCMPESTRMrri : X86::PCMPESTRMrri; + unsigned MOpc = + Subtarget->hasAVX() ? X86::VPCMPESTRMrmi : X86::PCMPESTRMrmi; + CNode = + emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node, InGlue); ReplaceUses(SDValue(Node, 1), SDValue(CNode, 0)); } if (NeedIndex || !NeedMask) { - unsigned ROpc = Subtarget->hasAVX() ? X86::VPCMPESTRIrr : X86::PCMPESTRIrr; - unsigned MOpc = Subtarget->hasAVX() ? X86::VPCMPESTRIrm : X86::PCMPESTRIrm; + unsigned ROpc = + Subtarget->hasAVX() ? X86::VPCMPESTRIrri : X86::PCMPESTRIrri; + unsigned MOpc = + Subtarget->hasAVX() ? X86::VPCMPESTRIrmi : X86::PCMPESTRIrmi; CNode = emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::i32, Node, InGlue); ReplaceUses(SDValue(Node, 0), SDValue(CNode, 0)); } diff --git a/llvm/lib/Target/X86/X86InstrSSE.td b/llvm/lib/Target/X86/X86InstrSSE.td index fd20090fe097..a572d6f84827 100644 --- a/llvm/lib/Target/X86/X86InstrSSE.td +++ b/llvm/lib/Target/X86/X86InstrSSE.td @@ -6561,12 +6561,12 @@ let Constraints = "$src1 = $dst" in //===----------------------------------------------------------------------===// multiclass pcmpistrm_SS42AI { - def rr : SS42AI<0x62, MRMSrcReg, (outs), + def rri : SS42AI<0x62, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2, u8imm:$src3), !strconcat(asm, "\t{$src3, $src2, $src1|$src1, $src2, $src3}"), []>, Sched<[WritePCmpIStrM]>; let mayLoad = 1 in - def rm :SS42AI<0x62, MRMSrcMem, (outs), + def rmi :SS42AI<0x62, MRMSrcMem, (outs), (ins VR128:$src1, i128mem:$src2, u8imm:$src3), !strconcat(asm, "\t{$src3, $src2, $src1|$src1, $src2, $src3}"), []>, Sched<[WritePCmpIStrM.Folded, WritePCmpIStrM.ReadAfterFold]>; @@ -6579,12 +6579,12 @@ let Defs = [XMM0, EFLAGS], hasSideEffects = 0 in { } multiclass SS42AI_pcmpestrm { - def rr : SS42AI<0x60, MRMSrcReg, (outs), + def rri : SS42AI<0x60, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src3, u8imm:$src5), !strconcat(asm, "\t{$src5, $src3, $src1|$src1, $src3, $src5}"), []>, Sched<[WritePCmpEStrM]>; let mayLoad = 1 in - def rm : SS42AI<0x60, MRMSrcMem, (outs), + def rmi : SS42AI<0x60, MRMSrcMem, (outs), (ins VR128:$src1, i128mem:$src3, u8imm:$src5), !strconcat(asm, "\t{$src5, $src3, $src1|$src1, $src3, $src5}"), []>, Sched<[WritePCmpEStrM.Folded, WritePCmpEStrM.ReadAfterFold]>; @@ -6597,12 +6597,12 @@ let Defs = [XMM0, EFLAGS], Uses = [EAX, EDX], hasSideEffects = 0 in { } multiclass SS42AI_pcmpistri { - def rr : SS42AI<0x63, MRMSrcReg, (outs), + def rri : SS42AI<0x63, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2, u8imm:$src3), !strconcat(asm, "\t{$src3, $src2, $src1|$src1, $src2, $src3}"), []>, Sched<[WritePCmpIStrI]>; let mayLoad = 1 in - def rm : SS42AI<0x63, MRMSrcMem, (outs), + def rmi : SS42AI<0x63, MRMSrcMem, (outs), (ins VR128:$src1, i128mem:$src2, u8imm:$src3), !strconcat(asm, "\t{$src3, $src2, $src1|$src1, $src2, $src3}"), []>, Sched<[WritePCmpIStrI.Folded, WritePCmpIStrI.ReadAfterFold]>; @@ -6615,12 +6615,12 @@ let Defs = [ECX, EFLAGS], hasSideEffects = 0 in { } multiclass SS42AI_pcmpestri { - def rr : SS42AI<0x61, MRMSrcReg, (outs), + def rri : SS42AI<0x61, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src3, u8imm:$src5), !strconcat(asm, "\t{$src5, $src3, $src1|$src1, $src3, $src5}"), []>, Sched<[WritePCmpEStrI]>; let mayLoad = 1 in - def rm : SS42AI<0x61, MRMSrcMem, (outs), + def rmi : SS42AI<0x61, MRMSrcMem, (outs), (ins VR128:$src1, i128mem:$src3, u8imm:$src5), !strconcat(asm, "\t{$src5, $src3, $src1|$src1, $src3, $src5}"), []>, Sched<[WritePCmpEStrI.Folded, WritePCmpEStrI.ReadAfterFold]>; diff --git a/llvm/test/TableGen/x86-fold-tables.inc b/llvm/test/TableGen/x86-fold-tables.inc index d0ae2c474e85..185311f3923e 100644 --- a/llvm/test/TableGen/x86-fold-tables.inc +++ b/llvm/test/TableGen/x86-fold-tables.inc @@ -866,10 +866,10 @@ static const X86FoldTableEntry Table1[] = { {X86::PABSBrr, X86::PABSBrm, TB_ALIGN_16}, {X86::PABSDrr, X86::PABSDrm, TB_ALIGN_16}, {X86::PABSWrr, X86::PABSWrm, TB_ALIGN_16}, - {X86::PCMPESTRIrr, X86::PCMPESTRIrm, 0}, - {X86::PCMPESTRMrr, X86::PCMPESTRMrm, 0}, - {X86::PCMPISTRIrr, X86::PCMPISTRIrm, 0}, - {X86::PCMPISTRMrr, X86::PCMPISTRMrm, 0}, + {X86::PCMPESTRIrri, X86::PCMPESTRIrmi, 0}, + {X86::PCMPESTRMrri, X86::PCMPESTRMrmi, 0}, + {X86::PCMPISTRIrri, X86::PCMPISTRIrmi, 0}, + {X86::PCMPISTRMrri, X86::PCMPISTRMrmi, 0}, {X86::PF2IDrr, X86::PF2IDrm, 0}, {X86::PF2IWrr, X86::PF2IWrm, 0}, {X86::PFRCPrr, X86::PFRCPrm, 0}, @@ -1544,10 +1544,10 @@ static const X86FoldTableEntry Table1[] = { {X86::VPBROADCASTWZ256rr, X86::VPBROADCASTWZ256rm, TB_NO_REVERSE}, {X86::VPBROADCASTWZrr, X86::VPBROADCASTWZrm, TB_NO_REVERSE}, {X86::VPBROADCASTWrr, X86::VPBROADCASTWrm, TB_NO_REVERSE}, - {X86::VPCMPESTRIrr, X86::VPCMPESTRIrm, 0}, - {X86::VPCMPESTRMrr, X86::VPCMPESTRMrm, 0}, - {X86::VPCMPISTRIrr, X86::VPCMPISTRIrm, 0}, - {X86::VPCMPISTRMrr, X86::VPCMPISTRMrm, 0}, + {X86::VPCMPESTRIrri, X86::VPCMPESTRIrmi, 0}, + {X86::VPCMPESTRMrri, X86::VPCMPESTRMrmi, 0}, + {X86::VPCMPISTRIrri, X86::VPCMPISTRIrmi, 0}, + {X86::VPCMPISTRMrri, X86::VPCMPISTRMrmi, 0}, {X86::VPCONFLICTDZ128rr, X86::VPCONFLICTDZ128rm, 0}, {X86::VPCONFLICTDZ256rr, X86::VPCONFLICTDZ256rm, 0}, {X86::VPCONFLICTDZrr, X86::VPCONFLICTDZrm, 0}, -- GitLab From 2a38551457cb2b38dcca35e30e9f2d7fce9ae3e7 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Mon, 11 Mar 2024 14:04:51 +0100 Subject: [PATCH 099/953] [libc++] Remove from (#83183) This moves a utility from `` into an implementation detail header and refactors the selection of the variant index type to use. --- libcxx/include/CMakeLists.txt | 1 + libcxx/include/__tuple/find_index.h | 62 +++++++++++++++++++ libcxx/include/libcxx.imp | 1 + libcxx/include/module.modulemap | 1 + libcxx/include/tuple | 35 +---------- libcxx/include/variant | 31 ++++++---- .../test/libcxx/transitive_includes/cxx23.csv | 1 - .../test/libcxx/transitive_includes/cxx26.csv | 1 - .../variant.variant/variant_size.pass.cpp | 14 ++--- .../tuple.elem/tuple.by.type.verify.cpp | 6 +- .../variant.visit.member/visit.pass.cpp | 1 + .../visit_return_type.pass.cpp | 1 + .../variant/variant.visit/visit.pass.cpp | 1 + .../variant.visit/visit_return_type.pass.cpp | 1 + 14 files changed, 98 insertions(+), 59 deletions(-) create mode 100644 libcxx/include/__tuple/find_index.h diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index e37c4ac4fddd..63adc03fae29 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -701,6 +701,7 @@ set(files __thread/thread.h __thread/timed_backoff_policy.h __tree + __tuple/find_index.h __tuple/make_tuple_types.h __tuple/pair_like.h __tuple/sfinae_helpers.h diff --git a/libcxx/include/__tuple/find_index.h b/libcxx/include/__tuple/find_index.h new file mode 100644 index 000000000000..133b00419d0c --- /dev/null +++ b/libcxx/include/__tuple/find_index.h @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TUPLE_FIND_INDEX_H +#define _LIBCPP___TUPLE_FIND_INDEX_H + +#include <__config> +#include <__type_traits/is_same.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 14 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __find_detail { + +static constexpr size_t __not_found = static_cast(-1); +static constexpr size_t __ambiguous = __not_found - 1; + +inline _LIBCPP_HIDE_FROM_ABI constexpr size_t __find_idx_return(size_t __curr_i, size_t __res, bool __matches) { + return !__matches ? __res : (__res == __not_found ? __curr_i : __ambiguous); +} + +template +inline _LIBCPP_HIDE_FROM_ABI constexpr size_t __find_idx(size_t __i, const bool (&__matches)[_Nx]) { + return __i == _Nx + ? __not_found + : __find_detail::__find_idx_return(__i, __find_detail::__find_idx(__i + 1, __matches), __matches[__i]); +} + +template +struct __find_exactly_one_checked { + static constexpr bool __matches[sizeof...(_Args)] = {is_same<_T1, _Args>::value...}; + static constexpr size_t value = __find_detail::__find_idx(0, __matches); + static_assert(value != __not_found, "type not found in type list"); + static_assert(value != __ambiguous, "type occurs more than once in type list"); +}; + +template +struct __find_exactly_one_checked<_T1> { + static_assert(!is_same<_T1, _T1>::value, "type not in empty type list"); +}; + +} // namespace __find_detail + +template +struct __find_exactly_one_t : public __find_detail::__find_exactly_one_checked<_T1, _Args...> {}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 14 + +#endif // _LIBCPP___TUPLE_FIND_INDEX_H diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp index e02dc8da6ba1..b1e728cde868 100644 --- a/libcxx/include/libcxx.imp +++ b/libcxx/include/libcxx.imp @@ -697,6 +697,7 @@ { include: [ "<__thread/this_thread.h>", "private", "", "public" ] }, { include: [ "<__thread/thread.h>", "private", "", "public" ] }, { include: [ "<__thread/timed_backoff_policy.h>", "private", "", "public" ] }, + { include: [ "<__tuple/find_index.h>", "private", "", "public" ] }, { include: [ "<__tuple/make_tuple_types.h>", "private", "", "public" ] }, { include: [ "<__tuple/pair_like.h>", "private", "", "public" ] }, { include: [ "<__tuple/sfinae_helpers.h>", "private", "", "public" ] }, diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index 98890e890cdb..0bd2831b7f15 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -1799,6 +1799,7 @@ module std_private_thread_thread [system] { } module std_private_thread_timed_backoff_policy [system] { header "__thread/timed_backoff_policy.h" } +module std_private_tuple_find_index [system] { header "__tuple/find_index.h" } module std_private_tuple_make_tuple_types [system] { header "__tuple/make_tuple_types.h" } module std_private_tuple_pair_like [system] { header "__tuple/pair_like.h" diff --git a/libcxx/include/tuple b/libcxx/include/tuple index 8808db6739fb..e63e4e25a7d2 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -213,6 +213,7 @@ template #include <__fwd/tuple.h> #include <__memory/allocator_arg_t.h> #include <__memory/uses_allocator.h> +#include <__tuple/find_index.h> #include <__tuple/make_tuple_types.h> #include <__tuple/sfinae_helpers.h> #include <__tuple/tuple_element.h> @@ -1087,40 +1088,6 @@ get(const tuple<_Tp...>&& __t) _NOEXCEPT { # if _LIBCPP_STD_VER >= 14 -namespace __find_detail { - -static constexpr size_t __not_found = static_cast(-1); -static constexpr size_t __ambiguous = __not_found - 1; - -inline _LIBCPP_HIDE_FROM_ABI constexpr size_t __find_idx_return(size_t __curr_i, size_t __res, bool __matches) { - return !__matches ? __res : (__res == __not_found ? __curr_i : __ambiguous); -} - -template -inline _LIBCPP_HIDE_FROM_ABI constexpr size_t __find_idx(size_t __i, const bool (&__matches)[_Nx]) { - return __i == _Nx - ? __not_found - : __find_detail::__find_idx_return(__i, __find_detail::__find_idx(__i + 1, __matches), __matches[__i]); -} - -template -struct __find_exactly_one_checked { - static constexpr bool __matches[sizeof...(_Args)] = {is_same<_T1, _Args>::value...}; - static constexpr size_t value = __find_detail::__find_idx(0, __matches); - static_assert(value != __not_found, "type not found in type list"); - static_assert(value != __ambiguous, "type occurs more than once in type list"); -}; - -template -struct __find_exactly_one_checked<_T1> { - static_assert(!is_same<_T1, _T1>::value, "type not in empty type list"); -}; - -} // namespace __find_detail - -template -struct __find_exactly_one_t : public __find_detail::__find_exactly_one_checked<_T1, _Args...> {}; - template inline _LIBCPP_HIDE_FROM_ABI constexpr _T1& get(tuple<_Args...>& __tup) noexcept { return std::get<__find_exactly_one_t<_T1, _Args...>::value>(__tup); diff --git a/libcxx/include/variant b/libcxx/include/variant index 5ce99250a8b4..d1eea52f0a93 100644 --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -221,13 +221,18 @@ namespace std { #include <__functional/operations.h> #include <__functional/unary_function.h> #include <__memory/addressof.h> +#include <__tuple/find_index.h> +#include <__tuple/sfinae_helpers.h> #include <__type_traits/add_const.h> #include <__type_traits/add_cv.h> #include <__type_traits/add_pointer.h> #include <__type_traits/add_volatile.h> +#include <__type_traits/common_type.h> #include <__type_traits/dependent_type.h> #include <__type_traits/is_array.h> +#include <__type_traits/is_default_constructible.h> #include <__type_traits/is_destructible.h> +#include <__type_traits/is_nothrow_assignable.h> #include <__type_traits/is_nothrow_move_constructible.h> #include <__type_traits/is_trivially_copy_assignable.h> #include <__type_traits/is_trivially_copy_constructible.h> @@ -242,6 +247,7 @@ namespace std { #include <__utility/forward.h> #include <__utility/forward_like.h> #include <__utility/in_place.h> +#include <__utility/integer_sequence.h> #include <__utility/move.h> #include <__utility/swap.h> #include <__variant/monostate.h> @@ -249,7 +255,6 @@ namespace std { #include #include #include -#include #include // standard-mandated includes @@ -340,21 +345,20 @@ struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, variant<_Types...>> { inline constexpr size_t variant_npos = static_cast(-1); -_LIBCPP_HIDE_FROM_ABI constexpr int __choose_index_type(unsigned int __num_elem) { - if (__num_elem < numeric_limits::max()) - return 0; - if (__num_elem < numeric_limits::max()) - return 1; - return 2; +template +_LIBCPP_HIDE_FROM_ABI constexpr auto __choose_index_type() { +#ifdef _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION + if constexpr (_NumAlternatives < numeric_limits::max()) + return static_cast(0); + else if constexpr (_NumAlternatives < numeric_limits::max()) + return static_cast(0); + else +#endif // _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION + return static_cast(0); } template -using __variant_index_t = -# ifndef _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION - unsigned int; -# else - std::tuple_element_t< __choose_index_type(_NumAlts), std::tuple >; -# endif +using __variant_index_t = decltype(std::__choose_index_type<_NumAlts>()); template constexpr _IndexType __variant_npos = static_cast<_IndexType>(-1); @@ -1625,6 +1629,7 @@ _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include +# include # include # include # include diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv index 043d23d551c5..daa3e17698bb 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx23.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv @@ -661,7 +661,6 @@ variant cstring variant initializer_list variant limits variant new -variant tuple variant version vector array vector cctype diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv index 043d23d551c5..daa3e17698bb 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx26.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv @@ -661,7 +661,6 @@ variant cstring variant initializer_list variant limits variant new -variant tuple variant version vector array vector cctype diff --git a/libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp b/libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp index 9011e61e7880..2f1ea8bffb47 100644 --- a/libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp +++ b/libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp @@ -49,13 +49,13 @@ void test_index_type() { template void test_index_internals() { using Lim = std::numeric_limits; - static_assert(std::__choose_index_type(Lim::max() -1) != - std::__choose_index_type(Lim::max()), ""); - static_assert(std::is_same_v< - std::__variant_index_t, - std::__variant_index_t - > == ExpectEqual, ""); - using IndexT = std::__variant_index_t; +#ifdef _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION + static_assert(!std::is_same_v()), + decltype(std::__choose_index_type())>); +#endif + static_assert( + std::is_same_v, std::__variant_index_t > == ExpectEqual, ""); + using IndexT = std::__variant_index_t; using IndexLim = std::numeric_limits; static_assert(std::__variant_npos == IndexLim::max(), ""); } diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.verify.cpp index 1d05eb5fe76e..00f27c3220d2 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.verify.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.verify.cpp @@ -18,13 +18,13 @@ struct UserType {}; void test_bad_index() { std::tuple t1; - TEST_IGNORE_NODISCARD std::get(t1); // expected-error@tuple:* {{type not found}} + TEST_IGNORE_NODISCARD std::get(t1); // expected-error@*:* {{type not found}} TEST_IGNORE_NODISCARD std::get(t1); // expected-note {{requested here}} TEST_IGNORE_NODISCARD std::get(t1); // expected-note {{requested here}} - // expected-error@tuple:* 2 {{type occurs more than once}} + // expected-error@*:* 2 {{type occurs more than once}} std::tuple<> t0; TEST_IGNORE_NODISCARD std::get(t0); // expected-node {{requested here}} - // expected-error@tuple:* 1 {{type not in empty type list}} + // expected-error@*:* {{type not in empty type list}} } void test_bad_return_type() { diff --git a/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp index 68706d6c32af..50e7fc81387a 100644 --- a/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp index 20472c62fc5f..b005f303bc4b 100644 --- a/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp index 097b784f2bf2..798ce7ded72a 100644 --- a/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/libcxx/test/std/utilities/variant/variant.visit/visit_return_type.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit/visit_return_type.pass.cpp index eb425c07f932..b1189dff656d 100644 --- a/libcxx/test/std/utilities/variant/variant.visit/visit_return_type.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.visit/visit_return_type.pass.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include -- GitLab From 2f1873d11e8853d1ddb801b4c512be3967ffcfc9 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Mon, 11 Mar 2024 13:09:55 +0000 Subject: [PATCH 100/953] Revert "[RemoveDIs] Add additional debug-mode verifier checks" (#84757) Reverts llvm/llvm-project#84308 Failing bots, e.g. https://lab.llvm.org/buildbot/#/builders/16/builds/62432 --- llvm/lib/IR/Verifier.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 0e6c01802cfb..ce090c3b8a74 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -2691,11 +2691,6 @@ void Verifier::visitFunction(const Function &F) { Check(verifyAttributeCount(Attrs, FT->getNumParams()), "Attribute after last parameter!", &F); - CheckDI(F.IsNewDbgInfoFormat == F.getParent()->IsNewDbgInfoFormat, - "Function debug format should match parent module", &F, - F.IsNewDbgInfoFormat, F.getParent(), - F.getParent()->IsNewDbgInfoFormat); - bool IsIntrinsic = F.isIntrinsic(); // Check function attributes. @@ -3039,11 +3034,6 @@ void Verifier::visitBasicBlock(BasicBlock &BB) { Check(I.getParent() == &BB, "Instruction has bogus parent pointer!"); } - CheckDI(BB.IsNewDbgInfoFormat == BB.getParent()->IsNewDbgInfoFormat, - "BB debug format should match parent function", &BB, - BB.IsNewDbgInfoFormat, BB.getParent(), - BB.getParent()->IsNewDbgInfoFormat); - // Confirm that no issues arise from the debug program. if (BB.IsNewDbgInfoFormat) CheckDI(!BB.getTrailingDPValues(), "Basic Block has trailing DbgRecords!", -- GitLab From 6f7e940c2d6711c7be8bc5365a1f4da3a328b2eb Mon Sep 17 00:00:00 2001 From: Jason Eckhardt Date: Mon, 11 Mar 2024 08:13:33 -0500 Subject: [PATCH 101/953] [TableGen] More efficiency improvements for encode/decode emission. (#84647) DecoderEmitter and CodeEmitterGen perform repeated linear walks over the entire instruction list. This patch eliminates two more such walks. The eliminated traversals visit every instruction merely to determine whether the target has variable length encodings. For a target with variable length encodings, the original any_of will terminate quickly. But all targets other than M68k use fixed length encodings and thus any_of must visit the entire instruction list. --- llvm/utils/TableGen/CodeEmitterGen.cpp | 5 +---- llvm/utils/TableGen/CodeGenInstruction.h | 9 +++++++-- llvm/utils/TableGen/CodeGenTarget.cpp | 7 +++++-- llvm/utils/TableGen/CodeGenTarget.h | 4 ++++ llvm/utils/TableGen/DecoderEmitter.cpp | 18 ++++++------------ 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp index 1e80eb6b1ad5..9194c13ccdcb 100644 --- a/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -434,10 +434,7 @@ void CodeEmitterGen::run(raw_ostream &o) { ArrayRef NumberedInstructions = Target.getInstructionsByEnumValue(); - if (any_of(NumberedInstructions, [](const CodeGenInstruction *CGI) { - Record *R = CGI->TheDef; - return R->getValue("Inst") && isa(R->getValueInit("Inst")); - })) { + if (Target.hasVariableLengthEncodings()) { emitVarLenCodeEmitter(Records, o); } else { const CodeGenHwModes &HWM = Target.getHwModes(); diff --git a/llvm/utils/TableGen/CodeGenInstruction.h b/llvm/utils/TableGen/CodeGenInstruction.h index 963c9f0b2592..b658259b4892 100644 --- a/llvm/utils/TableGen/CodeGenInstruction.h +++ b/llvm/utils/TableGen/CodeGenInstruction.h @@ -17,14 +17,13 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/CodeGenTypes/MachineValueType.h" +#include "llvm/TableGen/Record.h" #include #include #include #include namespace llvm { -class Record; -class DagInit; class CodeGenTarget; class CGIOperandList { @@ -333,6 +332,12 @@ public: return isOperandImpl("InOperandList", i, "IsImmediate"); } + /// Return true if the instruction uses a variable length encoding. + bool isVariableLengthEncoding() const { + const RecordVal *RV = TheDef->getValue("Inst"); + return RV && isa(RV->getValue()); + } + private: bool isOperandImpl(StringRef OpListName, unsigned i, StringRef PropertyName) const; diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp index 980c9bdb6367..e1cf33e7f62f 100644 --- a/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/llvm/utils/TableGen/CodeGenTarget.cpp @@ -480,8 +480,11 @@ void CodeGenTarget::ReadInstructions() const { PrintFatalError("No 'Instruction' subclasses defined!"); // Parse the instructions defined in the .td file. - for (unsigned i = 0, e = Insts.size(); i != e; ++i) - Instructions[Insts[i]] = std::make_unique(Insts[i]); + for (Record *R : Insts) { + Instructions[R] = std::make_unique(R); + if (Instructions[R]->isVariableLengthEncoding()) + HasVariableLengthEncodings = true; + } } static const CodeGenInstruction *GetInstByName( diff --git a/llvm/utils/TableGen/CodeGenTarget.h b/llvm/utils/TableGen/CodeGenTarget.h index 2ae3a3a2204d..e109c717dc01 100644 --- a/llvm/utils/TableGen/CodeGenTarget.h +++ b/llvm/utils/TableGen/CodeGenTarget.h @@ -65,6 +65,7 @@ class CodeGenTarget { mutable SmallVector LegalValueTypes; CodeGenHwModes CGH; std::vector MacroFusions; + mutable bool HasVariableLengthEncodings = false; void ReadRegAltNameIndices() const; void ReadInstructions() const; @@ -209,6 +210,9 @@ public: } inst_iterator inst_end() const { return getInstructionsByEnumValue().end(); } + /// Return whether instructions have variable length encodings on this target. + bool hasVariableLengthEncodings() const { return HasVariableLengthEncodings; } + /// isLittleEndianEncoding - are instruction bit patterns defined as [0..n]? /// bool isLittleEndianEncoding() const; diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp index 27ff84bce405..88f245238138 100644 --- a/llvm/utils/TableGen/DecoderEmitter.cpp +++ b/llvm/utils/TableGen/DecoderEmitter.cpp @@ -2499,8 +2499,8 @@ void DecoderEmitter::run(raw_ostream &o) { const auto &NumberedInstructions = Target.getInstructionsByEnumValue(); NumberedEncodings.reserve(NumberedInstructions.size()); for (const auto &NumberedInstruction : NumberedInstructions) { - if (const RecordVal *RV = - NumberedInstruction->TheDef->getValue("EncodingInfos")) { + const Record *InstDef = NumberedInstruction->TheDef; + if (const RecordVal *RV = InstDef->getValue("EncodingInfos")) { if (DefInit *DI = dyn_cast_or_null(RV->getValue())) { EncodingInfoByHwMode EBM(DI->getDef(), HWM); for (auto &KV : EBM) @@ -2513,12 +2513,11 @@ void DecoderEmitter::run(raw_ostream &o) { // This instruction is encoded the same on all HwModes. Emit it for all // HwModes by default, otherwise leave it in a single common table. if (DecoderEmitterSuppressDuplicates) { - NumberedEncodings.emplace_back(NumberedInstruction->TheDef, - NumberedInstruction, "AllModes"); + NumberedEncodings.emplace_back(InstDef, NumberedInstruction, "AllModes"); } else { for (StringRef HwModeName : HwModeNames) - NumberedEncodings.emplace_back(NumberedInstruction->TheDef, - NumberedInstruction, HwModeName); + NumberedEncodings.emplace_back(InstDef, NumberedInstruction, + HwModeName); } } for (const auto &NumberedAlias : @@ -2531,12 +2530,7 @@ void DecoderEmitter::run(raw_ostream &o) { OpcMap; std::map> Operands; std::vector InstrLen; - - bool IsVarLenInst = - any_of(NumberedInstructions, [](const CodeGenInstruction *CGI) { - RecordVal *RV = CGI->TheDef->getValue("Inst"); - return RV && isa(RV->getValue()); - }); + bool IsVarLenInst = Target.hasVariableLengthEncodings(); unsigned MaxInstLen = 0; for (unsigned i = 0; i < NumberedEncodings.size(); ++i) { -- GitLab From facb89ae1228c067b2b14f32e7e70608fe50704b Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 11 Mar 2024 13:15:43 +0000 Subject: [PATCH 102/953] [openmp] __kmp_x86_cpuid fix for i386/PIC builds. (#84626) --- openmp/runtime/src/kmp.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index 6510dd9b3561..48d7124e56c5 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -1404,9 +1404,19 @@ extern void __kmp_query_cpuid(kmp_cpuinfo_t *p); // subleaf is only needed for cache and topology discovery and can be set to // zero in most cases static inline void __kmp_x86_cpuid(int leaf, int subleaf, struct kmp_cpuid *p) { +#if KMP_ARCH_X86 && (defined(__pic__) || defined(__PIC__)) + // on i386 arch, the ebx reg. is used by pic, thus we need to preserve from + // being trashed beforehand + __asm__ __volatile__("mov %%ebx, %%edi\n" + "cpuid\n" + "xchg %%edi, %%ebx\n" + : "=a"(p->eax), "=b"(p->ebx), "=c"(p->ecx), "=d"(p->edx) + : "a"(leaf), "c"(subleaf)); +#else __asm__ __volatile__("cpuid" : "=a"(p->eax), "=b"(p->ebx), "=c"(p->ecx), "=d"(p->edx) : "a"(leaf), "c"(subleaf)); +#endif } // Load p into FPU control word static inline void __kmp_load_x87_fpu_control_word(const kmp_int16 *p) { -- GitLab From 9d30f11b8881d9f9c997bb7e3bf399c70da20b06 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Mon, 11 Mar 2024 08:18:57 -0500 Subject: [PATCH 103/953] [libc] Remove use of `__builtin_modf` in GPU math Summary: This function was not actually supported, see https://godbolt.org/z/MP1j5EeWc. Unsure why we only now begun seeing failures related to it. --- libc/src/math/amdgpu/CMakeLists.txt | 20 -------------------- libc/src/math/amdgpu/modf.cpp | 18 ------------------ libc/src/math/amdgpu/modff.cpp | 18 ------------------ libc/src/math/nvptx/CMakeLists.txt | 20 -------------------- libc/src/math/nvptx/modf.cpp | 18 ------------------ libc/src/math/nvptx/modff.cpp | 18 ------------------ 6 files changed, 112 deletions(-) delete mode 100644 libc/src/math/amdgpu/modf.cpp delete mode 100644 libc/src/math/amdgpu/modff.cpp delete mode 100644 libc/src/math/nvptx/modf.cpp delete mode 100644 libc/src/math/nvptx/modff.cpp diff --git a/libc/src/math/amdgpu/CMakeLists.txt b/libc/src/math/amdgpu/CMakeLists.txt index c300730208d5..93735a556a31 100644 --- a/libc/src/math/amdgpu/CMakeLists.txt +++ b/libc/src/math/amdgpu/CMakeLists.txt @@ -176,26 +176,6 @@ add_entrypoint_object( -O2 ) -add_entrypoint_object( - modf - SRCS - modf.cpp - HDRS - ../modf.h - COMPILE_OPTIONS - -O2 -) - -add_entrypoint_object( - modff - SRCS - modff.cpp - HDRS - ../modff.h - COMPILE_OPTIONS - -O2 -) - add_entrypoint_object( nearbyint SRCS diff --git a/libc/src/math/amdgpu/modf.cpp b/libc/src/math/amdgpu/modf.cpp deleted file mode 100644 index 07dbbd6059c3..000000000000 --- a/libc/src/math/amdgpu/modf.cpp +++ /dev/null @@ -1,18 +0,0 @@ -//===-- Implementation of the GPU modf function ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "src/math/modf.h" -#include "src/__support/common.h" - -namespace LIBC_NAMESPACE { - -LLVM_LIBC_FUNCTION(double, modf, (double x, double *iptr)) { - return __builtin_modf(x, iptr); -} - -} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/amdgpu/modff.cpp b/libc/src/math/amdgpu/modff.cpp deleted file mode 100644 index ad35f9006b51..000000000000 --- a/libc/src/math/amdgpu/modff.cpp +++ /dev/null @@ -1,18 +0,0 @@ -//===-- Implementation of the GPU modff function --------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "src/math/modff.h" -#include "src/__support/common.h" - -namespace LIBC_NAMESPACE { - -LLVM_LIBC_FUNCTION(float, modff, (float x, float *iptr)) { - return __builtin_modff(x, iptr); -} - -} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/nvptx/CMakeLists.txt b/libc/src/math/nvptx/CMakeLists.txt index 56bff1472f13..581e1c6a3044 100644 --- a/libc/src/math/nvptx/CMakeLists.txt +++ b/libc/src/math/nvptx/CMakeLists.txt @@ -177,26 +177,6 @@ add_entrypoint_object( -O2 ) -add_entrypoint_object( - modf - SRCS - modf.cpp - HDRS - ../modf.h - COMPILE_OPTIONS - -O2 -) - -add_entrypoint_object( - modff - SRCS - modff.cpp - HDRS - ../modff.h - COMPILE_OPTIONS - -O2 -) - add_entrypoint_object( nearbyint SRCS diff --git a/libc/src/math/nvptx/modf.cpp b/libc/src/math/nvptx/modf.cpp deleted file mode 100644 index 07dbbd6059c3..000000000000 --- a/libc/src/math/nvptx/modf.cpp +++ /dev/null @@ -1,18 +0,0 @@ -//===-- Implementation of the GPU modf function ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "src/math/modf.h" -#include "src/__support/common.h" - -namespace LIBC_NAMESPACE { - -LLVM_LIBC_FUNCTION(double, modf, (double x, double *iptr)) { - return __builtin_modf(x, iptr); -} - -} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/nvptx/modff.cpp b/libc/src/math/nvptx/modff.cpp deleted file mode 100644 index ad35f9006b51..000000000000 --- a/libc/src/math/nvptx/modff.cpp +++ /dev/null @@ -1,18 +0,0 @@ -//===-- Implementation of the GPU modff function --------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "src/math/modff.h" -#include "src/__support/common.h" - -namespace LIBC_NAMESPACE { - -LLVM_LIBC_FUNCTION(float, modff, (float x, float *iptr)) { - return __builtin_modff(x, iptr); -} - -} // namespace LIBC_NAMESPACE -- GitLab From fcd0dd37936957be27a3583c7daaafa2bf282a90 Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Mon, 11 Mar 2024 13:21:12 +0000 Subject: [PATCH 104/953] [gn build] Port 2a38551457cb --- llvm/utils/gn/secondary/libcxx/include/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn index cb52d99e5b2a..f3d7b1bceb4d 100644 --- a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn +++ b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn @@ -770,6 +770,7 @@ if (current_toolchain == default_toolchain) { "__thread/thread.h", "__thread/timed_backoff_policy.h", "__tree", + "__tuple/find_index.h", "__tuple/make_tuple_types.h", "__tuple/pair_like.h", "__tuple/sfinae_helpers.h", -- GitLab From 0fae9a24b9acf03ab072bb8aca92a467b697a08a Mon Sep 17 00:00:00 2001 From: Zain Jaffal Date: Mon, 11 Mar 2024 13:36:52 +0000 Subject: [PATCH 105/953] [Docs] Fix `llvm-remarkutil` docs (#84661) Code blocks and option points weren't rendered correctly --- llvm/docs/CommandGuide/llvm-remarkutil.rst | 84 ++++++++++++++-------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/llvm/docs/CommandGuide/llvm-remarkutil.rst b/llvm/docs/CommandGuide/llvm-remarkutil.rst index 20f2b34ce008..af7d8eb31c01 100644 --- a/llvm/docs/CommandGuide/llvm-remarkutil.rst +++ b/llvm/docs/CommandGuide/llvm-remarkutil.rst @@ -3,12 +3,12 @@ llvm-remarkutil - Remark utility .. program:: llvm-remarkutil -SYNOPSIS +Synopsis -------- :program:`llvm-remarkutil` [*subcommmand*] [*options*] -DESCRIPTION +Description ----------- Utility for displaying information from, and converting between different @@ -72,12 +72,14 @@ Instruction count remarks require asm-printer remarks. CSV format is as follows: :: + Function,InstructionCount foo,123 if `--use-debug-loc` is passed then the CSV will include the source path, line number and column. :: + Source,Function,InstructionCount path:line:column,foo,3 @@ -101,12 +103,14 @@ Annotation count remarks require AnnotationRemarksPass remarks. CSV format is as follows: :: + Function,Count foo,123 if `--use-debug-loc` is passed then the CSV will include the source path, line number and column. :: + Source,Function,Count path:line:column,foo,3 @@ -115,67 +119,83 @@ if `--use-debug-loc` is passed then the CSV will include the source path, line n count ~~~~~ -..program:: llvm-remarkutil count +.. program:: llvm-remarkutil count USAGE: :program:`llvm-remarkutil` count [*options*] Summary ^^^^^^^ -:program:`llvm-remarkutil count` counts `remarks ` based on specified properties. +:program:`llvm-remarkutil count` counts `remarks `_ based on specified properties. By default the tool counts remarks based on how many occur in a source file or function or total for the generated remark file. The tool also supports collecting count based on specific remark arguments. The specified arguments should have an integer value to be able to report a count. The tool contains utilities to filter the remark count based on remark name, pass name, argument value and remark type. -OPTIONS -------- + +Options +^^^^^^^ .. option:: --parser= Select the type of input remark parser. Required. - * ``yaml``: The tool will parse YAML remarks. - * ``bitstream``: The tool will parse bitstream remarks. -.. option:: --count-by + * ``yaml`` : The tool will parse YAML remarks. + * ``bitstream`` : The tool will parse bitstream remarks. + +.. option:: --count-by= + Select option to collect remarks by. - * ``remark-name``: count how many individual remarks exist. - * ``arg``: count remarks based on specified arguments passed by --(r)args. The argument value must be a number. + + * ``remark-name`` : count how many individual remarks exist. + * ``arg`` : count remarks based on specified arguments passed by --(r)args. The argument value must be a number. .. option:: --group-by= + group count of remarks by property. - * ``source``: Count will be collected per source path. Remarks with no debug location will not be counted. - * ``function``: Count is collected per function. - * ``function-with-loc``: Count is collected per function per source. Remarks with no debug location will not be counted. - * ``Total``: Report a count for the provided remark file. + + * ``source`` : Count will be collected per source path. Remarks with no debug location will not be counted. + * ``function`` : Count is collected per function. + * ``function-with-loc`` : Count is collected per function per source. Remarks with no debug location will not be counted. + * ``Total`` : Report a count for the provided remark file. .. option:: --args[=arguments] + If `count-by` is set to `arg` this flag can be used to collect from specified remark arguments represented as a comma separated string. The arguments must have a numeral value to be able to count remarks by .. option:: --rargs[=arguments] + If `count-by` is set to `arg` this flag can be used to collect from specified remark arguments using regular expression. The arguments must have a numeral value to be able to count remarks by .. option:: --pass-name[=] + Filter count by pass name. .. option:: --rpass-name[=] + Filter count by pass name using regular expressions. .. option:: --remark-name[=] + Filter count by remark name. .. option:: --rremark-name[=] + Filter count by remark name using regular expressions. .. option:: --filter-arg-by[=] + Filter count by argument value. .. option:: --rfilter-arg-by[=] + Filter count by argument value using regular expressions. .. option:: --remark-type= + Filter remarks by type with the following options. + * ``unknown`` * ``passed`` * ``missed`` @@ -210,20 +230,22 @@ compiling a **fixed source** with **differing compilers** or `bitstream `_ remarks. -OPTIONS -------- +Options +^^^^^^^ .. option:: --parser= - Select the type of input remark parser. Required. - * ``yaml``: The tool will parse YAML remarks. - * ``bitstream``: The tool will parse bitstream remarks. +Select the type of input remark parser. Required. + +* ``yaml`` : The tool will parse YAML remarks. +* ``bitstream`` : The tool will parse bitstream remarks. .. option:: --report-style= Output style. - * ``human``: Human-readable textual report. Default option. - * ``json``: JSON report. + + * ``human`` : Human-readable textual report. Default option. + * ``json`` : JSON report. .. option:: --pretty @@ -235,8 +257,8 @@ OPTIONS Output file for the report. Outputs to stdout by default. -HUMAN-READABLE OUTPUT ---------------------- +Human-Readable Output +^^^^^^^^^^^^^^^^^^^^^ The human-readable format for :program:`llvm-remarkutil size-diff` is composed of two sections: @@ -245,7 +267,7 @@ two sections: * A high-level summary of all changes. Changed Function Section -~~~~~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^^^^^ Suppose you are comparing two remark files OLD and NEW. @@ -282,7 +304,7 @@ A breakdown of the format is below: Second file stack byte count - first file stack byte count. Summary Section -~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^ :program:`llvm-remarkutil size-diff` will output a high-level summary after printing all changed functions. @@ -307,10 +329,10 @@ printing all changed functions. file. JSON OUTPUT ------------ +^^^^^^^^^^^^ High-Level view -~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^ Suppose we are comparing two files, OLD and NEW. @@ -352,7 +374,7 @@ Suppose we are comparing two files, OLD and NEW. Functions only present in the second file. Function JSON -~~~~~~~~~~~~~ +^^^^^^^^^^^^^ The ``InBoth``, ``OnlyInA``, and ``OnlyInB`` sections contain size information for each function in the input remark files. @@ -387,7 +409,7 @@ for each function in the input remark files. * ``STACK_BYTES_B``: Stack bytes in NEW. Computing Diffs From Function JSON -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Function JSON does not contain the diffs. Tools consuming JSON output from :program:`llvm-remarkutil size-diff` are responsible for computing the diffs @@ -399,7 +421,7 @@ separately. * Stack byte count diff: ``STACK_BYTES_B - STACK_BYTES_A`` EXIT STATUS ------------ +^^^^^^^^^^^ :program:`llvm-remarkutil size-diff` returns 0 on success, and a non-zero value otherwise. -- GitLab From 1ec5b1f483aa154255d919af9abf5eca2fe8635c Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 11 Mar 2024 13:30:06 +0000 Subject: [PATCH 106/953] [X86] Add missing immediate qualifier to the (V)PCLMULQDQ instruction names --- llvm/lib/Target/X86/X86InstrInfo.cpp | 12 ++--- llvm/lib/Target/X86/X86InstrSSE.td | 44 +++++++++---------- llvm/lib/Target/X86/X86SchedAlderlakeP.td | 2 +- llvm/lib/Target/X86/X86SchedSapphireRapids.td | 4 +- llvm/lib/Target/X86/X86ScheduleBdVer2.td | 4 +- llvm/test/TableGen/x86-fold-tables.inc | 12 ++--- 6 files changed, 39 insertions(+), 39 deletions(-) diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index af0ed071c29a..b65f49527ae5 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -2491,12 +2491,12 @@ MachineInstr *X86InstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI, WorkingMI->removeOperand(3); break; } - case X86::PCLMULQDQrr: - case X86::VPCLMULQDQrr: - case X86::VPCLMULQDQYrr: - case X86::VPCLMULQDQZrr: - case X86::VPCLMULQDQZ128rr: - case X86::VPCLMULQDQZ256rr: { + case X86::PCLMULQDQrri: + case X86::VPCLMULQDQrri: + case X86::VPCLMULQDQYrri: + case X86::VPCLMULQDQZrri: + case X86::VPCLMULQDQZ128rri: + case X86::VPCLMULQDQZ256rri: { // SRC1 64bits = Imm[0] ? SRC1[127:64] : SRC1[63:0] // SRC2 64bits = Imm[4] ? SRC2[127:64] : SRC2[63:0] unsigned Imm = MI.getOperand(3).getImm(); diff --git a/llvm/lib/Target/X86/X86InstrSSE.td b/llvm/lib/Target/X86/X86InstrSSE.td index a572d6f84827..4a542b7e5a1b 100644 --- a/llvm/lib/Target/X86/X86InstrSSE.td +++ b/llvm/lib/Target/X86/X86InstrSSE.td @@ -6917,14 +6917,14 @@ def PCLMULCommuteImm : SDNodeXForm, Sched<[WriteCLMul]>; - def PCLMULQDQrm : PCLMULIi8<0x44, MRMSrcMem, (outs VR128:$dst), + def PCLMULQDQrmi : PCLMULIi8<0x44, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2, u8imm:$src3), "pclmulqdq\t{$src3, $src2, $dst|$dst, $src2, $src3}", [(set VR128:$dst, @@ -6935,7 +6935,7 @@ let Predicates = [NoAVX, HasPCLMUL] in { def : Pat<(int_x86_pclmulqdq (memop addr:$src2), VR128:$src1, (i8 timm:$src3)), - (PCLMULQDQrm VR128:$src1, addr:$src2, + (PCLMULQDQrmi VR128:$src1, addr:$src2, (PCLMULCommuteImm timm:$src3))>; } // Predicates = [NoAVX, HasPCLMUL] @@ -6943,10 +6943,10 @@ let Predicates = [NoAVX, HasPCLMUL] in { foreach HI = ["hq","lq"] in foreach LO = ["hq","lq"] in { def : InstAlias<"pclmul" # HI # LO # "dq\t{$src, $dst|$dst, $src}", - (PCLMULQDQrr VR128:$dst, VR128:$src, + (PCLMULQDQrri VR128:$dst, VR128:$src, !add(!shl(!eq(LO,"hq"),4),!eq(HI,"hq"))), 0>; def : InstAlias<"pclmul" # HI # LO # "dq\t{$src, $dst|$dst, $src}", - (PCLMULQDQrm VR128:$dst, i128mem:$src, + (PCLMULQDQrmi VR128:$dst, i128mem:$src, !add(!shl(!eq(LO,"hq"),4),!eq(HI,"hq"))), 0>; } @@ -6954,25 +6954,25 @@ foreach LO = ["hq","lq"] in { multiclass vpclmulqdq { let isCommutable = 1 in - def rr : PCLMULIi8<0x44, MRMSrcReg, (outs RC:$dst), - (ins RC:$src1, RC:$src2, u8imm:$src3), - "vpclmulqdq\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set RC:$dst, - (IntId RC:$src1, RC:$src2, timm:$src3))]>, - Sched<[WriteCLMul]>; - - def rm : PCLMULIi8<0x44, MRMSrcMem, (outs RC:$dst), - (ins RC:$src1, MemOp:$src2, u8imm:$src3), - "vpclmulqdq\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", - [(set RC:$dst, - (IntId RC:$src1, (LdFrag addr:$src2), timm:$src3))]>, - Sched<[WriteCLMul.Folded, WriteCLMul.ReadAfterFold]>; + def rri : PCLMULIi8<0x44, MRMSrcReg, (outs RC:$dst), + (ins RC:$src1, RC:$src2, u8imm:$src3), + "vpclmulqdq\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", + [(set RC:$dst, + (IntId RC:$src1, RC:$src2, timm:$src3))]>, + Sched<[WriteCLMul]>; + + def rmi : PCLMULIi8<0x44, MRMSrcMem, (outs RC:$dst), + (ins RC:$src1, MemOp:$src2, u8imm:$src3), + "vpclmulqdq\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}", + [(set RC:$dst, + (IntId RC:$src1, (LdFrag addr:$src2), timm:$src3))]>, + Sched<[WriteCLMul.Folded, WriteCLMul.ReadAfterFold]>; // We can commute a load in the first operand by swapping the sources and // rotating the immediate. def : Pat<(IntId (LdFrag addr:$src2), RC:$src1, (i8 timm:$src3)), - (!cast(NAME#"rm") RC:$src1, addr:$src2, - (PCLMULCommuteImm timm:$src3))>; + (!cast(NAME#"rmi") RC:$src1, addr:$src2, + (PCLMULCommuteImm timm:$src3))>; } let Predicates = [HasAVX, NoVLX_Or_NoVPCLMULQDQ, HasPCLMUL] in @@ -6986,10 +6986,10 @@ defm VPCLMULQDQY : vpclmulqdq { def : InstAlias<"vpclmul"#Hi#Lo#"dq\t{$src2, $src1, $dst|$dst, $src1, $src2}", - (!cast(InstStr # "rr") RC:$dst, RC:$src1, RC:$src2, + (!cast(InstStr # "rri") RC:$dst, RC:$src1, RC:$src2, !add(!shl(!eq(Lo,"hq"),4),!eq(Hi,"hq"))), 0>; def : InstAlias<"vpclmul"#Hi#Lo#"dq\t{$src2, $src1, $dst|$dst, $src1, $src2}", - (!cast(InstStr # "rm") RC:$dst, RC:$src1, MemOp:$src2, + (!cast(InstStr # "rmi") RC:$dst, RC:$src1, MemOp:$src2, !add(!shl(!eq(Lo,"hq"),4),!eq(Hi,"hq"))), 0>; } diff --git a/llvm/lib/Target/X86/X86SchedAlderlakeP.td b/llvm/lib/Target/X86/X86SchedAlderlakeP.td index 8e3e55428264..4dc5ea3c8611 100644 --- a/llvm/lib/Target/X86/X86SchedAlderlakeP.td +++ b/llvm/lib/Target/X86/X86SchedAlderlakeP.td @@ -2295,7 +2295,7 @@ def ADLPWriteResGroup263 : SchedWriteRes<[ADLPPort02_03_11, ADLPPort05]> { } def : InstRW<[ADLPWriteResGroup263, ReadAfterVecYLd], (instregex "^VPACK(S|U)S(DW|WB)Yrm$")>; def : InstRW<[ADLPWriteResGroup263, ReadAfterVecYLd], (instrs VPCMPGTQYrm)>; -def : InstRW<[ADLPWriteResGroup263, ReadAfterVecXLd], (instrs VPCLMULQDQYrm)>; +def : InstRW<[ADLPWriteResGroup263, ReadAfterVecXLd], (instrs VPCLMULQDQYrmi)>; def ADLPWriteResGroup264 : SchedWriteRes<[ADLPPort01_05, ADLPPort02_03_11]> { let Latency = 9; diff --git a/llvm/lib/Target/X86/X86SchedSapphireRapids.td b/llvm/lib/Target/X86/X86SchedSapphireRapids.td index 78c5994ee964..3c698d2c9f7a 100644 --- a/llvm/lib/Target/X86/X86SchedSapphireRapids.td +++ b/llvm/lib/Target/X86/X86SchedSapphireRapids.td @@ -2665,8 +2665,8 @@ def : InstRW<[SPRWriteResGroup258, ReadAfterVecYLd], (instregex "^VALIGN(D|Q)Z(( "^VPUNPCK(H|L)(BW|WD)Zrmk(z?)$")>; def : InstRW<[SPRWriteResGroup258, ReadAfterVecYLd], (instrs VPCMPGTQYrm)>; def : InstRW<[SPRWriteResGroup258, ReadAfterVecXLd], (instregex "^VPALIGNRZ128rmik(z?)$", - "^VPCLMULQDQ(Y|Z)rm$")>; -def : InstRW<[SPRWriteResGroup258, ReadAfterVecXLd], (instrs VPCLMULQDQZ256rm)>; + "^VPCLMULQDQ(Y|Z)rmi$")>; +def : InstRW<[SPRWriteResGroup258, ReadAfterVecXLd], (instrs VPCLMULQDQZ256rmi)>; def SPRWriteResGroup259 : SchedWriteRes<[SPRPort00_01_05, SPRPort02_03_11]> { let ReleaseAtCycles = [3, 1]; diff --git a/llvm/lib/Target/X86/X86ScheduleBdVer2.td b/llvm/lib/Target/X86/X86ScheduleBdVer2.td index c9749979576f..296504cfc785 100644 --- a/llvm/lib/Target/X86/X86ScheduleBdVer2.td +++ b/llvm/lib/Target/X86/X86ScheduleBdVer2.td @@ -1275,12 +1275,12 @@ def : InstRW<[WritePHAdd.Folded], (instrs PHADDDrm, PHSUBDrm, defm : PdWriteResXMMPair; -def PdWriteVPCLMULQDQrr : SchedWriteRes<[PdFPU0, PdFPMMA]> { +def PdWriteVPCLMULQDQrri : SchedWriteRes<[PdFPU0, PdFPMMA]> { let Latency = 12; let ReleaseAtCycles = [1, 7]; let NumMicroOps = 6; } -def : InstRW<[PdWriteVPCLMULQDQrr], (instrs VPCLMULQDQrr)>; +def : InstRW<[PdWriteVPCLMULQDQrri], (instrs VPCLMULQDQrri)>; //////////////////////////////////////////////////////////////////////////////// // SSE4A instructions. diff --git a/llvm/test/TableGen/x86-fold-tables.inc b/llvm/test/TableGen/x86-fold-tables.inc index 185311f3923e..e0fccd42e47f 100644 --- a/llvm/test/TableGen/x86-fold-tables.inc +++ b/llvm/test/TableGen/x86-fold-tables.inc @@ -2129,7 +2129,7 @@ static const X86FoldTableEntry Table2[] = { {X86::PAVGWrr, X86::PAVGWrm, TB_ALIGN_16}, {X86::PBLENDVBrr0, X86::PBLENDVBrm0, TB_ALIGN_16}, {X86::PBLENDWrri, X86::PBLENDWrmi, TB_ALIGN_16}, - {X86::PCLMULQDQrr, X86::PCLMULQDQrm, TB_ALIGN_16}, + {X86::PCLMULQDQrri, X86::PCLMULQDQrmi, TB_ALIGN_16}, {X86::PCMPEQBrr, X86::PCMPEQBrm, TB_ALIGN_16}, {X86::PCMPEQDrr, X86::PCMPEQDrm, TB_ALIGN_16}, {X86::PCMPEQQrr, X86::PCMPEQQrm, TB_ALIGN_16}, @@ -3058,11 +3058,11 @@ static const X86FoldTableEntry Table2[] = { {X86::VPBROADCASTWZ128rrkz, X86::VPBROADCASTWZ128rmkz, TB_NO_REVERSE}, {X86::VPBROADCASTWZ256rrkz, X86::VPBROADCASTWZ256rmkz, TB_NO_REVERSE}, {X86::VPBROADCASTWZrrkz, X86::VPBROADCASTWZrmkz, TB_NO_REVERSE}, - {X86::VPCLMULQDQYrr, X86::VPCLMULQDQYrm, 0}, - {X86::VPCLMULQDQZ128rr, X86::VPCLMULQDQZ128rm, 0}, - {X86::VPCLMULQDQZ256rr, X86::VPCLMULQDQZ256rm, 0}, - {X86::VPCLMULQDQZrr, X86::VPCLMULQDQZrm, 0}, - {X86::VPCLMULQDQrr, X86::VPCLMULQDQrm, 0}, + {X86::VPCLMULQDQYrri, X86::VPCLMULQDQYrmi, 0}, + {X86::VPCLMULQDQZ128rri, X86::VPCLMULQDQZ128rmi, 0}, + {X86::VPCLMULQDQZ256rri, X86::VPCLMULQDQZ256rmi, 0}, + {X86::VPCLMULQDQZrri, X86::VPCLMULQDQZrmi, 0}, + {X86::VPCLMULQDQrri, X86::VPCLMULQDQrmi, 0}, {X86::VPCMOVYrrr, X86::VPCMOVYrmr, 0}, {X86::VPCMOVrrr, X86::VPCMOVrmr, 0}, {X86::VPCMPBZ128rri, X86::VPCMPBZ128rmi, 0}, -- GitLab From 02e0b7d405c3ace86e731450c0dd73556f1452d9 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 11 Mar 2024 09:51:59 -0400 Subject: [PATCH 107/953] [libc++] Add missing include in test (#84579) That test is using std::toupper. --- .../format.formatter.spec/formatter.floating_point.pass.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp index 206b0214cf5f..6c507881167f 100644 --- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include -- GitLab From d27c1bed1169a4fc324c70fa60dcd979b86a06d2 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Mon, 11 Mar 2024 09:05:49 -0500 Subject: [PATCH 108/953] [libc] Only enable `LLVM_FULL_BUILD_MODE` by default for GPU targets (#84664) Summary: Currently we have a conditional that turns the full build on by default if it is a default target. This used to work fine when the GPU was the only target that was ever present. However, we've recently changed to allow building multiple of these at the same time. That means we should have the ability to build overlay mode in the CPU mode and full build in the GPU mode. This patch makes some simple adjustments to pass the arguments per-triple. This slightly extends the existing `-DRUNTIMES_` argument support to also transform any extra CMake inputs rather than just the passed CMake variables. --- llvm/CMakeLists.txt | 17 +++++++-------- llvm/runtimes/CMakeLists.txt | 42 +++++++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 111c8cfa15d8..d0e33c29be58 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -173,16 +173,15 @@ endforeach() set(NEED_LIBC_HDRGEN FALSE) if("libc" IN_LIST LLVM_ENABLE_RUNTIMES) set(NEED_LIBC_HDRGEN TRUE) -else() - foreach(_name ${LLVM_RUNTIME_TARGETS}) - if("libc" IN_LIST RUNTIMES_${_name}_LLVM_ENABLE_RUNTIMES) - set(NEED_LIBC_HDRGEN TRUE) - if("${_name}" STREQUAL "amdgcn-amd-amdhsa" OR "${_name}" STREQUAL "nvptx64-nvidia-cuda") - set(LLVM_LIBC_GPU_BUILD ON) - endif() - endif() - endforeach() endif() +foreach(_name ${LLVM_RUNTIME_TARGETS}) + if("libc" IN_LIST RUNTIMES_${_name}_LLVM_ENABLE_RUNTIMES) + set(NEED_LIBC_HDRGEN TRUE) + if("${_name}" STREQUAL "amdgcn-amd-amdhsa" OR "${_name}" STREQUAL "nvptx64-nvidia-cuda") + set(LLVM_LIBC_GPU_BUILD ON) + endif() + endif() +endforeach() if(NEED_LIBC_HDRGEN) # To build the libc runtime, we need to be able to build few libc build # tools from the "libc" project. So, we add it to the list of enabled diff --git a/llvm/runtimes/CMakeLists.txt b/llvm/runtimes/CMakeLists.txt index 9b5e758b6ede..3f3c482adccd 100644 --- a/llvm/runtimes/CMakeLists.txt +++ b/llvm/runtimes/CMakeLists.txt @@ -358,6 +358,14 @@ function(runtime_register_target name) endif() endif() endforeach() + foreach(variable_name ${${name}_extra_args}) + string(FIND "${variable_name}" "-DRUNTIMES_${extra_name}_" out) + if("${out}" EQUAL 0) + string(REPLACE "-DRUNTIMES_${extra_name}_" "" new_name ${variable_name}) + string(REPLACE ";" "|" new_value "${new_name}") + list(APPEND ${name}_extra_args "-D${new_value}") + endif() + endforeach() endforeach() set_enable_per_target_runtime_dir() @@ -438,21 +446,29 @@ if(runtimes) if(NOT hdrgen_exe) message(FATAL_ERROR "libc-hdrgen executable missing") endif() - set(libc_cmake_args "-DLIBC_HDRGEN_EXE=${hdrgen_exe}" - "-DLLVM_LIBC_FULL_BUILD=ON") + list(APPEND libc_cmake_args "-DLIBC_HDRGEN_EXE=${hdrgen_exe}") list(APPEND extra_deps ${hdrgen_deps}) - if(LLVM_LIBC_GPU_BUILD) - list(APPEND libc_cmake_args "-DLLVM_LIBC_GPU_BUILD=ON") - # The `libc` project may require '-DCUDAToolkit_ROOT' in GPU mode. - if(CUDAToolkit_ROOT) - list(APPEND libc_cmake_args "-DCUDAToolkit_ROOT=${CUDAToolkit_ROOT}") - endif() - foreach(dep clang-offload-packager nvptx-arch amdgpu-arch) - if(TARGET ${dep}) - list(APPEND extra_deps ${dep}) - endif() - endforeach() + endif() + if(LLVM_LIBC_GPU_BUILD) + list(APPEND libc_cmake_args "-DLLVM_LIBC_GPU_BUILD=ON") + if("libc" IN_LIST RUNTIMES_amdgcn-amd-amdhsa_LLVM_ENABLE_RUNTIMES) + list(APPEND libc_cmake_args "-DRUNTIMES_amdgcn-amd-amdhsa_LLVM_LIBC_FULL_BUILD=ON") endif() + if("libc" IN_LIST RUNTIMES_nvptx64-nvidia-cuda_LLVM_ENABLE_RUNTIMES) + list(APPEND libc_cmake_args "-DRUNTIMES_nvptx64-nvidia-cuda_LLVM_LIBC_FULL_BUILD=ON") + endif() + # The `libc` project may require '-DCUDAToolkit_ROOT' in GPU mode. + if(CUDAToolkit_ROOT) + list(APPEND libc_cmake_args "-DCUDAToolkit_ROOT=${CUDAToolkit_ROOT}") + endif() + foreach(dep clang-offload-packager nvptx-arch amdgpu-arch) + if(TARGET ${dep}) + list(APPEND extra_deps ${dep}) + endif() + endforeach() + endif() + if(LLVM_LIBC_FULL_BUILD) + list(APPEND libc_cmake_args "-DLLVM_LIBC_FULL_BUILD=ON") endif() if(NOT LLVM_RUNTIME_TARGETS) runtime_default_target( -- GitLab From b1be69f4dbc7e3557e381d413e1b8c31ce974cc8 Mon Sep 17 00:00:00 2001 From: Mark Zhuang Date: Mon, 11 Mar 2024 22:06:30 +0800 Subject: [PATCH 109/953] [NFC] Remove duplicate 'see' in CMake.rst (#84680) --- llvm/docs/CMake.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/docs/CMake.rst b/llvm/docs/CMake.rst index 35c47989a7ee..be5da5652e31 100644 --- a/llvm/docs/CMake.rst +++ b/llvm/docs/CMake.rst @@ -363,7 +363,7 @@ enabled sub-projects. Nearly all of these variable names begin with documentation targets being as part of a normal build. If the ``install`` target is run then this also enables all built documentation targets to be installed. Defaults to OFF. To enable a particular documentation target, see - see LLVM_ENABLE_SPHINX and LLVM_ENABLE_DOXYGEN. + LLVM_ENABLE_SPHINX and LLVM_ENABLE_DOXYGEN. **LLVM_BUILD_EXAMPLES**:BOOL Build LLVM examples. Defaults to OFF. Targets for building each example are -- GitLab From 3f302eaca46ec068879831cae76d4aeda2bf82f8 Mon Sep 17 00:00:00 2001 From: elhewaty Date: Mon, 11 Mar 2024 16:10:40 +0200 Subject: [PATCH 110/953] [InstCombine] Fold usub_sat((sub nuw C1, A), C2) to usub_sat(C1 - C2, A) or 0 (#82280) - Fixes: https://github.com/llvm/llvm-project/issues/82177 - Alive2: https://alive2.llvm.org/ce/z/Q7mMC3 --- .../InstCombine/InstCombineCalls.cpp | 16 +++- .../InstCombine/unsigned_saturated_sub.ll | 89 +++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index d2756b0d4d54..f5f3716d390d 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2164,8 +2164,22 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { } } + // usub_sat((sub nuw C, A), C1) -> usub_sat(usub_sat(C, C1), A) + // which after that: + // usub_sat((sub nuw C, A), C1) -> usub_sat(C - C1, A) if C1 u< C + // usub_sat((sub nuw C, A), C1) -> 0 otherwise + Constant *C, *C1; + Value *A; + if (IID == Intrinsic::usub_sat && + match(Arg0, m_NUWSub(m_ImmConstant(C), m_Value(A))) && + match(Arg1, m_ImmConstant(C1))) { + auto *NewC = Builder.CreateBinaryIntrinsic(Intrinsic::usub_sat, C, C1); + auto *NewSub = + Builder.CreateBinaryIntrinsic(Intrinsic::usub_sat, NewC, A); + return replaceInstUsesWith(*SI, NewSub); + } + // ssub.sat(X, C) -> sadd.sat(X, -C) if C != MIN - Constant *C; if (IID == Intrinsic::ssub_sat && match(Arg1, m_Constant(C)) && C->isNotMinSignedValue()) { Value *NegVal = ConstantExpr::getNeg(C); diff --git a/llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll b/llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll index 5cece931b8d9..ab147584d210 100644 --- a/llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll +++ b/llvm/test/Transforms/InstCombine/unsigned_saturated_sub.ll @@ -8,6 +8,95 @@ declare void @use(i64) declare void @usei32(i32) declare void @usei1(i1) +; usub_sat((sub nuw C1, A), C2) to usub_sat(usub_sat(C1 - C2), A) +define i32 @usub_sat_C1_C2(i32 %a){ +; CHECK-LABEL: @usub_sat_C1_C2( +; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.usub.sat.i32(i32 50, i32 [[A:%.*]]) +; CHECK-NEXT: ret i32 [[COND]] +; + %add = sub nuw i32 64, %a + %cond = call i32 @llvm.usub.sat.i32(i32 %add, i32 14) + ret i32 %cond +} + +define i32 @usub_sat_C1_C2_produce_0(i32 %a){ +; CHECK-LABEL: @usub_sat_C1_C2_produce_0( +; CHECK-NEXT: ret i32 0 +; + %add = sub nuw i32 14, %a + %cond = call i32 @llvm.usub.sat.i32(i32 %add, i32 14) + ret i32 %cond +} + +define i32 @usub_sat_C1_C2_produce_0_too(i32 %a){ +; CHECK-LABEL: @usub_sat_C1_C2_produce_0_too( +; CHECK-NEXT: ret i32 0 +; + %add = sub nuw i32 12, %a + %cond = call i32 @llvm.usub.sat.i32(i32 %add, i32 14) + ret i32 %cond +} + +; vector tests +define <2 x i16> @usub_sat_C1_C2_splat(<2 x i16> %a) { +; CHECK-LABEL: @usub_sat_C1_C2_splat( +; CHECK-NEXT: [[COND:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> , <2 x i16> [[A:%.*]]) +; CHECK-NEXT: ret <2 x i16> [[COND]] +; + %add = sub nuw <2 x i16> , %a + %cond = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %add, <2 x i16> ) + ret <2 x i16> %cond +} + +define <2 x i16> @usub_sat_C1_C2_non_splat(<2 x i16> %a) { +; CHECK-LABEL: @usub_sat_C1_C2_non_splat( +; CHECK-NEXT: [[COND:%.*]] = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> , <2 x i16> [[A:%.*]]) +; CHECK-NEXT: ret <2 x i16> [[COND]] +; + %add = sub nuw <2 x i16> , %a + %cond = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %add, <2 x i16> ) + ret <2 x i16> %cond +} + +define <2 x i16> @usub_sat_C1_C2_splat_produce_0(<2 x i16> %a){ +; CHECK-LABEL: @usub_sat_C1_C2_splat_produce_0( +; CHECK-NEXT: ret <2 x i16> zeroinitializer +; + %add = sub nuw <2 x i16> , %a + %cond = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %add, <2 x i16> ) + ret <2 x i16> %cond +} + +define <2 x i16> @usub_sat_C1_C2_splat_produce_0_too(<2 x i16> %a){ +; CHECK-LABEL: @usub_sat_C1_C2_splat_produce_0_too( +; CHECK-NEXT: ret <2 x i16> zeroinitializer +; + %add = sub nuw <2 x i16> , %a + %cond = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %add, <2 x i16> ) + ret <2 x i16> %cond +} + +define <2 x i16> @usub_sat_C1_C2_non_splat_produce_0_too(<2 x i16> %a){ +; CHECK-LABEL: @usub_sat_C1_C2_non_splat_produce_0_too( +; CHECK-NEXT: ret <2 x i16> zeroinitializer +; + %add = sub nuw <2 x i16> , %a + %cond = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %add, <2 x i16> ) + ret <2 x i16> %cond +} + +; negative tests this souldn't work +define i32 @usub_sat_C1_C2_without_nuw(i32 %a){ +; CHECK-LABEL: @usub_sat_C1_C2_without_nuw( +; CHECK-NEXT: [[ADD:%.*]] = sub i32 12, [[A:%.*]] +; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[ADD]], i32 14) +; CHECK-NEXT: ret i32 [[COND]] +; + %add = sub i32 12, %a + %cond = call i32 @llvm.usub.sat.i32(i32 %add, i32 14) + ret i32 %cond +} + ; (a > b) ? a - b : 0 -> usub.sat(a, b) define i64 @max_sub_ugt(i64 %a, i64 %b) { -- GitLab From 9bc294f9be257eca655807a2d598225dcf4290ee Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Mon, 11 Mar 2024 09:18:47 -0500 Subject: [PATCH 111/953] [libc] Build the GPU during the projects setup like libc-hdrgen (#84667) Summary: The libc build has a few utilties that need to be built before we can do everything in the full build. The one requirement currently is the `libc-hdrgen` binary. If we are doing a full build runtimes mode we first add `libc` to the projects list and then only use the `projects` portion to buld the `libc` portion. We also use utilities for the GPU build, namely the loader utilities. Previously we would build these tools on-demand inside of the cross-build, which tool some hacky workarounds for the dependency finding and target triple. This patch instead just builds them similarly to libc-hdrgen and then passses them in. We now either pass it manually it it was built, or just look it up like we do with the other `clang` tools. Depends on https://github.com/llvm/llvm-project/pull/84664 --- libc/CMakeLists.txt | 9 ++-- .../modules/prepare_libc_gpu_build.cmake | 42 +++++++++++++++---- libc/utils/CMakeLists.txt | 3 -- libc/utils/gpu/CMakeLists.txt | 4 +- libc/utils/gpu/loader/CMakeLists.txt | 34 ++++----------- libc/utils/gpu/loader/amdgpu/CMakeLists.txt | 1 - libc/utils/gpu/loader/nvptx/CMakeLists.txt | 4 +- libc/utils/gpu/server/CMakeLists.txt | 9 ---- llvm/CMakeLists.txt | 4 ++ llvm/runtimes/CMakeLists.txt | 18 +++++--- 10 files changed, 66 insertions(+), 62 deletions(-) diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index b4a2523b7788..6edf5c656193 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -60,6 +60,10 @@ if(LLVM_LIBC_FULL_BUILD OR LLVM_LIBC_GPU_BUILD) message(STATUS "Will use ${LIBC_HDRGEN_EXE} for libc header generation.") endif() endif() +# We will build the GPU utilities if we are not doing a runtimes build. +if(LLVM_LIBC_GPU_BUILD AND NOT LLVM_RUNTIMES_BUILD) + add_subdirectory(utils/gpu) +endif() set(NEED_LIBC_HDRGEN FALSE) if(NOT LLVM_RUNTIMES_BUILD) @@ -79,11 +83,6 @@ if(LIBC_HDRGEN_ONLY OR NEED_LIBC_HDRGEN) # When libc is build as part of the runtimes/bootstrap build's CMake run, we # only need to build the host tools to build the libc. So, we just do enough # to build libc-hdrgen and return. - - # Always make the RPC server availible to other projects for GPU mode. - if(LLVM_LIBC_GPU_BUILD) - add_subdirectory(utils/gpu/server) - endif() return() endif() unset(NEED_LIBC_HDRGEN) diff --git a/libc/cmake/modules/prepare_libc_gpu_build.cmake b/libc/cmake/modules/prepare_libc_gpu_build.cmake index 2de4cb8d82b2..bea6bb016491 100644 --- a/libc/cmake/modules/prepare_libc_gpu_build.cmake +++ b/libc/cmake/modules/prepare_libc_gpu_build.cmake @@ -93,6 +93,41 @@ else() endif() set(LIBC_GPU_TARGET_ARCHITECTURE "${gpu_test_architecture}") +# Identify the GPU loader utility used to run tests. +set(LIBC_GPU_LOADER_EXECUTABLE "" CACHE STRING "Executable for the GPU loader.") +if(LIBC_GPU_LOADER_EXECUTABLE) + set(gpu_loader_executable ${LIBC_GPU_LOADER_EXECUTABLE}) +elseif(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) + find_program(LIBC_AMDHSA_LOADER_EXECUTABLE + NAMES amdhsa-loader NO_DEFAULT_PATH + PATHS ${LLVM_BINARY_DIR}/bin ${compiler_path}) + if(LIBC_AMDHSA_LOADER_EXECUTABLE) + set(gpu_loader_executable ${LIBC_AMDHSA_LOADER_EXECUTABLE}) + endif() +elseif(LIBC_TARGET_ARCHITECTURE_IS_NVPTX) + find_program(LIBC_NVPTX_LOADER_EXECUTABLE + NAMES nvptx-loader NO_DEFAULT_PATH + PATHS ${LLVM_BINARY_DIR}/bin ${compiler_path}) + if(LIBC_NVPTX_LOADER_EXECUTABLE) + set(gpu_loader_executable ${LIBC_NVPTX_LOADER_EXECUTABLE}) + endif() +endif() +if(NOT TARGET libc.utils.gpu.loader AND gpu_loader_executable) + add_custom_target(libc.utils.gpu.loader) + set_target_properties( + libc.utils.gpu.loader + PROPERTIES + EXECUTABLE "${gpu_loader_executable}" + ) +endif() + +if(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) + # The AMDGPU environment uses different code objects to encode the ABI for + # kernel calls and intrinsic functions. We want to specify this manually to + # conform to whatever the test suite was built to handle. + set(LIBC_GPU_CODE_OBJECT_VERSION 5) +endif() + if(LIBC_TARGET_ARCHITECTURE_IS_NVPTX) # FIXME: This is a hack required to keep the CUDA package from trying to find # pthreads. We only link the CUDA driver, so this is unneeded. @@ -103,10 +138,3 @@ if(LIBC_TARGET_ARCHITECTURE_IS_NVPTX) get_filename_component(LIBC_CUDA_ROOT "${CUDAToolkit_BIN_DIR}" DIRECTORY ABSOLUTE) endif() endif() - -if(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) - # The AMDGPU environment uses different code objects to encode the ABI for - # kernel calls and intrinsic functions. We want to specify this manually to - # conform to whatever the test suite was built to handle. - set(LIBC_GPU_CODE_OBJECT_VERSION 5) -endif() diff --git a/libc/utils/CMakeLists.txt b/libc/utils/CMakeLists.txt index 7bf02a4af7de..11f25503cc13 100644 --- a/libc/utils/CMakeLists.txt +++ b/libc/utils/CMakeLists.txt @@ -1,6 +1,3 @@ if(LLVM_INCLUDE_TESTS) add_subdirectory(MPFRWrapper) endif() -if(LIBC_TARGET_OS_IS_GPU) - add_subdirectory(gpu) -endif() diff --git a/libc/utils/gpu/CMakeLists.txt b/libc/utils/gpu/CMakeLists.txt index 4d1ebcfb9f8e..7c15f36052cf 100644 --- a/libc/utils/gpu/CMakeLists.txt +++ b/libc/utils/gpu/CMakeLists.txt @@ -1,4 +1,2 @@ add_subdirectory(server) -if(LIBC_TARGET_OS_IS_GPU) - add_subdirectory(loader) -endif() +add_subdirectory(loader) diff --git a/libc/utils/gpu/loader/CMakeLists.txt b/libc/utils/gpu/loader/CMakeLists.txt index 189460bb02e6..b562cdc521c0 100644 --- a/libc/utils/gpu/loader/CMakeLists.txt +++ b/libc/utils/gpu/loader/CMakeLists.txt @@ -6,37 +6,18 @@ target_include_directories(gpu_loader PUBLIC ${LIBC_SOURCE_DIR} ) -# This utility needs to be compiled for the host system when cross compiling. -if(LLVM_RUNTIMES_TARGET OR LIBC_TARGET_TRIPLE) - target_compile_options(gpu_loader PUBLIC --target=${LLVM_HOST_TRIPLE}) - target_link_libraries(gpu_loader PUBLIC "--target=${LLVM_HOST_TRIPLE}") -endif() - find_package(hsa-runtime64 QUIET 1.2.0 HINTS ${CMAKE_INSTALL_PREFIX} PATHS /opt/rocm) -if(hsa-runtime64_FOUND AND LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) +if(hsa-runtime64_FOUND) add_subdirectory(amdgpu) -elseif(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) - message(STATUS "Skipping HSA loader for gpu target, no HSA was detected") endif() # The CUDA loader requires LLVM to traverse the ELF image for symbols. -find_package(LLVM QUIET) -if(CUDAToolkit_FOUND AND LLVM_FOUND AND LIBC_TARGET_ARCHITECTURE_IS_NVPTX) +find_package(CUDAToolkit 11.2 QUIET) +if(CUDAToolkit_FOUND) add_subdirectory(nvptx) -elseif(LIBC_TARGET_ARCHITECTURE_IS_NVPTX) - message(STATUS "Skipping CUDA loader for gpu target, no CUDA was detected") endif() -# Add a custom target to be used for testing. -set(LIBC_GPU_LOADER_EXECUTABLE "" CACHE STRING "Overriding binary for the GPU loader.") -if(LIBC_GPU_LOADER_EXECUTABLE) - add_custom_target(libc.utils.gpu.loader) - set_target_properties( - libc.utils.gpu.loader - PROPERTIES - EXECUTABLE "${LIBC_GPU_LOADER_EXECUTABLE}" - ) -elseif(TARGET amdhsa-loader AND LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) +if(TARGET amdhsa-loader AND LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) add_custom_target(libc.utils.gpu.loader) add_dependencies(libc.utils.gpu.loader amdhsa-loader) set_target_properties( @@ -56,11 +37,10 @@ elseif(TARGET nvptx-loader AND LIBC_TARGET_ARCHITECTURE_IS_NVPTX) ) endif() -if(TARGET libc.utils.gpu.loader) - get_target_property(gpu_loader_tgt libc.utils.gpu.loader "TARGET") - if(gpu_loader_tgt) +foreach(gpu_loader_tgt amdhsa-loader nvptx-loader) + if(TARGET ${gpu_loader_tgt}) install(TARGETS ${gpu_loader_tgt} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT libc) endif() -endif() +endforeach() diff --git a/libc/utils/gpu/loader/amdgpu/CMakeLists.txt b/libc/utils/gpu/loader/amdgpu/CMakeLists.txt index b99319f50401..97a2de9f8379 100644 --- a/libc/utils/gpu/loader/amdgpu/CMakeLists.txt +++ b/libc/utils/gpu/loader/amdgpu/CMakeLists.txt @@ -1,5 +1,4 @@ add_executable(amdhsa-loader Loader.cpp) -add_dependencies(amdhsa-loader libc.src.__support.RPC.rpc) target_link_libraries(amdhsa-loader PRIVATE diff --git a/libc/utils/gpu/loader/nvptx/CMakeLists.txt b/libc/utils/gpu/loader/nvptx/CMakeLists.txt index e76362a1e8cc..948493959bad 100644 --- a/libc/utils/gpu/loader/nvptx/CMakeLists.txt +++ b/libc/utils/gpu/loader/nvptx/CMakeLists.txt @@ -1,10 +1,10 @@ add_executable(nvptx-loader Loader.cpp) -add_dependencies(nvptx-loader libc.src.__support.RPC.rpc) if(NOT LLVM_ENABLE_RTTI) target_compile_options(nvptx-loader PRIVATE -fno-rtti) endif() -target_include_directories(nvptx-loader PRIVATE ${LLVM_INCLUDE_DIRS}) +target_include_directories(nvptx-loader PRIVATE + ${LLVM_MAIN_INCLUDE_DIR} ${LLVM_BINARY_DIR}/include) target_link_libraries(nvptx-loader PRIVATE gpu_loader diff --git a/libc/utils/gpu/server/CMakeLists.txt b/libc/utils/gpu/server/CMakeLists.txt index 10cfdb45a2c9..6fca72cfae95 100644 --- a/libc/utils/gpu/server/CMakeLists.txt +++ b/libc/utils/gpu/server/CMakeLists.txt @@ -5,21 +5,12 @@ target_include_directories(llvmlibc_rpc_server PRIVATE ${LIBC_SOURCE_DIR}) target_include_directories(llvmlibc_rpc_server PUBLIC ${LIBC_SOURCE_DIR}/include) target_include_directories(llvmlibc_rpc_server PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - # Ignore unsupported clang attributes if we're using GCC. target_compile_options(llvmlibc_rpc_server PUBLIC $<$:-Wno-attributes>) target_compile_definitions(llvmlibc_rpc_server PUBLIC LIBC_NAMESPACE=${LIBC_NAMESPACE}) -# This utility needs to be compiled for the host system when cross compiling. -if(LLVM_RUNTIMES_TARGET OR LIBC_TARGET_TRIPLE) - target_compile_options(llvmlibc_rpc_server PUBLIC - --target=${LLVM_HOST_TRIPLE}) - target_link_libraries(llvmlibc_rpc_server PUBLIC - "--target=${LLVM_HOST_TRIPLE}") -endif() - # Install the server and associated header. install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/llvmlibc_rpc_server.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index d0e33c29be58..494d8abeb64d 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -182,6 +182,10 @@ foreach(_name ${LLVM_RUNTIME_TARGETS}) endif() endif() endforeach() +if("${LIBC_TARGET_TRIPLE}" STREQUAL "amdgcn-amd-amdhsa" OR + "${LIBC_TARGET_TRIPLE}" STREQUAL "nvptx64-nvidia-cuda") + set(LLVM_LIBC_GPU_BUILD ON) +endif() if(NEED_LIBC_HDRGEN) # To build the libc runtime, we need to be able to build few libc build # tools from the "libc" project. So, we add it to the list of enabled diff --git a/llvm/runtimes/CMakeLists.txt b/llvm/runtimes/CMakeLists.txt index 3f3c482adccd..54ec8bd28d4c 100644 --- a/llvm/runtimes/CMakeLists.txt +++ b/llvm/runtimes/CMakeLists.txt @@ -452,20 +452,28 @@ if(runtimes) if(LLVM_LIBC_GPU_BUILD) list(APPEND libc_cmake_args "-DLLVM_LIBC_GPU_BUILD=ON") if("libc" IN_LIST RUNTIMES_amdgcn-amd-amdhsa_LLVM_ENABLE_RUNTIMES) + if(TARGET amdhsa-loader) + list(APPEND libc_cmake_args + "-DRUNTIMES_amdgcn-amd-amdhsa_LIBC_GPU_LOADER_EXECUTABLE=$") + list(APPEND extra_deps amdhsa-loader amdgpu-arch) + endif() list(APPEND libc_cmake_args "-DRUNTIMES_amdgcn-amd-amdhsa_LLVM_LIBC_FULL_BUILD=ON") endif() if("libc" IN_LIST RUNTIMES_nvptx64-nvidia-cuda_LLVM_ENABLE_RUNTIMES) + if(TARGET nvptx-loader) + list(APPEND libc_cmake_args + "-DRUNTIMES_nvptx64-nvidia-cuda_LIBC_GPU_LOADER_EXECUTABLE=$") + list(APPEND extra_deps nvptx-loader nvptx-arch) + endif() list(APPEND libc_cmake_args "-DRUNTIMES_nvptx64-nvidia-cuda_LLVM_LIBC_FULL_BUILD=ON") endif() # The `libc` project may require '-DCUDAToolkit_ROOT' in GPU mode. if(CUDAToolkit_ROOT) list(APPEND libc_cmake_args "-DCUDAToolkit_ROOT=${CUDAToolkit_ROOT}") endif() - foreach(dep clang-offload-packager nvptx-arch amdgpu-arch) - if(TARGET ${dep}) - list(APPEND extra_deps ${dep}) - endif() - endforeach() + if(TARGET clang-offload-packager) + list(APPEND extra_deps clang-offload-packager) + endif() endif() if(LLVM_LIBC_FULL_BUILD) list(APPEND libc_cmake_args "-DLLVM_LIBC_FULL_BUILD=ON") -- GitLab From 5e688f0dbdaaf8ef06c1affa90db985acf401237 Mon Sep 17 00:00:00 2001 From: Sivan Shani Date: Sat, 2 Mar 2024 17:12:42 +0000 Subject: [PATCH 112/953] [llvm][arm] add T1 and T2 assembly options for vlldm and vlstm Re-land 634b0243b8f7acc85af4f16b70e91d86ded4dc83. T1 allow for an optional registers list, the register list must be {d0-d15}. T2 define a mandatory register list, the register list must be {d0-d31}. The requirements for T1/T2 are as follows: T1 T2 Require: v8-M.Main, v8.1-M.Main, secure state secure state 16 D Regs valid valid 32 D Regs UNDEFINED valid No D Regs NOP NOP --- llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp | 53 ++++++++----- llvm/lib/Target/ARM/ARMInstrFormats.td | 31 ++++++++ llvm/lib/Target/ARM/ARMInstrVFP.td | 64 +++++++++++----- .../lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 76 ++++++++++++++++--- .../ARM/Disassembler/ARMDisassembler.cpp | 23 ++++++ .../ARM/MCTargetDesc/ARMInstPrinter.cpp | 32 ++++++++ .../CodeGen/ARM/cmse-vlldm-no-reorder.mir | 5 +- llvm/test/CodeGen/ARM/vlldm-vlstm-uops.mir | 6 +- llvm/test/MC/ARM/thumbv8m.s | 8 +- llvm/test/MC/ARM/vlstm-vlldm-8.1m.s | 11 +++ llvm/test/MC/ARM/vlstm-vlldm-8m.s | 17 +++++ llvm/test/MC/ARM/vlstm-vlldm-diag.s | 61 +++++++++++++++ .../ARM/armv8.1m-vlldm_vlstm-8.1.main.txt | 11 +++ .../ARM/armv8.1m-vlldm_vlstm-8.main.txt | 17 +++++ .../unittests/Target/ARM/MachineInstrTest.cpp | 2 + 15 files changed, 359 insertions(+), 58 deletions(-) create mode 100644 llvm/test/MC/ARM/vlstm-vlldm-8.1m.s create mode 100644 llvm/test/MC/ARM/vlstm-vlldm-8m.s create mode 100644 llvm/test/MC/ARM/vlstm-vlldm-diag.s create mode 100644 llvm/test/MC/Disassembler/ARM/armv8.1m-vlldm_vlstm-8.1.main.txt create mode 100644 llvm/test/MC/Disassembler/ARM/armv8.1m-vlldm_vlstm-8.main.txt diff --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp index f0b69b0b0980..0f7858a3be9f 100644 --- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -1470,13 +1470,19 @@ void ARMExpandPseudo::CMSESaveClearFPRegsV8( // Lazy store all fp registers to the stack. // This executes as NOP in the absence of floating-point support. - MachineInstrBuilder VLSTM = BuildMI(MBB, MBBI, DL, TII->get(ARM::VLSTM)) - .addReg(ARM::SP) - .add(predOps(ARMCC::AL)); - for (auto R : {ARM::VPR, ARM::FPSCR, ARM::FPSCR_NZCV, ARM::Q0, ARM::Q1, - ARM::Q2, ARM::Q3, ARM::Q4, ARM::Q5, ARM::Q6, ARM::Q7}) - VLSTM.addReg(R, RegState::Implicit | - (LiveRegs.contains(R) ? 0 : RegState::Undef)); + MachineInstrBuilder VLSTM = + BuildMI(MBB, MBBI, DL, TII->get(ARM::VLSTM)) + .addReg(ARM::SP) + .add(predOps(ARMCC::AL)) + .addImm(0); // Represents a pseoudo register list, has no effect on + // the encoding. + // Mark non-live registers as undef + for (MachineOperand &MO : VLSTM->implicit_operands()) { + if (MO.isReg() && !MO.isDef()) { + Register Reg = MO.getReg(); + MO.setIsUndef(!LiveRegs.contains(Reg)); + } + } // Restore all arguments for (const auto &Regs : ClearedFPRegs) { @@ -1564,13 +1570,19 @@ void ARMExpandPseudo::CMSESaveClearFPRegsV81(MachineBasicBlock &MBB, .add(predOps(ARMCC::AL)); // Lazy store all FP registers to the stack - MachineInstrBuilder VLSTM = BuildMI(MBB, MBBI, DL, TII->get(ARM::VLSTM)) - .addReg(ARM::SP) - .add(predOps(ARMCC::AL)); - for (auto R : {ARM::VPR, ARM::FPSCR, ARM::FPSCR_NZCV, ARM::Q0, ARM::Q1, - ARM::Q2, ARM::Q3, ARM::Q4, ARM::Q5, ARM::Q6, ARM::Q7}) - VLSTM.addReg(R, RegState::Implicit | - (LiveRegs.contains(R) ? 0 : RegState::Undef)); + MachineInstrBuilder VLSTM = + BuildMI(MBB, MBBI, DL, TII->get(ARM::VLSTM)) + .addReg(ARM::SP) + .add(predOps(ARMCC::AL)) + .addImm(0); // Represents a pseoudo register list, has no effect on + // the encoding. + // Mark non-live registers as undef + for (MachineOperand &MO : VLSTM->implicit_operands()) { + if (MO.isReg() && MO.isImplicit() && !MO.isDef()) { + Register Reg = MO.getReg(); + MO.setIsUndef(!LiveRegs.contains(Reg)); + } + } } else { // Push all the callee-saved registers (s16-s31). MachineInstrBuilder VPUSH = @@ -1673,9 +1685,12 @@ void ARMExpandPseudo::CMSERestoreFPRegsV8( // Lazy load fp regs from stack. // This executes as NOP in the absence of floating-point support. - MachineInstrBuilder VLLDM = BuildMI(MBB, MBBI, DL, TII->get(ARM::VLLDM)) - .addReg(ARM::SP) - .add(predOps(ARMCC::AL)); + MachineInstrBuilder VLLDM = + BuildMI(MBB, MBBI, DL, TII->get(ARM::VLLDM)) + .addReg(ARM::SP) + .add(predOps(ARMCC::AL)) + .addImm(0); // Represents a pseoudo register list, has no effect on + // the encoding. if (STI->fixCMSE_CVE_2021_35465()) { auto Bundler = MIBundleBuilder(MBB, VLLDM); @@ -1757,7 +1772,9 @@ void ARMExpandPseudo::CMSERestoreFPRegsV81( // Load FP registers from stack. BuildMI(MBB, MBBI, DL, TII->get(ARM::VLLDM)) .addReg(ARM::SP) - .add(predOps(ARMCC::AL)); + .add(predOps(ARMCC::AL)) + .addImm(0); // Represents a pseoudo register list, has no effect on the + // encoding. // Pop the stack space BuildMI(MBB, MBBI, DL, TII->get(ARM::tADDspi), ARM::SP) diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td index 14e315534570..404085820a66 100644 --- a/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -1749,6 +1749,37 @@ class AXSI4 + : InstARM { + // Instruction operands. + bits<4> Rn; + bits<13> regs; // Does not affect encoding, for assembly/disassembly only. + list Predicates = [HasVFP2]; + let OutOperandList = (outs); + let InOperandList = (ins GPRnopc:$Rn, pred:$p, dpr_reglist:$regs); + let AsmString = asm; + let Pattern = []; + let DecoderNamespace = "VFP"; + // Encode instruction operands. + let Inst{19-16} = Rn; + let Inst{31-28} = 0b1110; + let Inst{27-25} = 0b110; + let Inst{24} = 0b0; + let Inst{23} = 0b0; + let Inst{22} = 0b0; + let Inst{21} = 0b1; + let Inst{20} = load; // Distinguishes vlldm from vlstm + let Inst{15-12} = 0b0000; + let Inst{11-9} = 0b101; + let Inst{8} = 0; // Single precision + let Inst{7} = et; // encoding type, 0 for T1 and 1 for T2. + let Inst{6-0} = 0b0000000; + let mayLoad = load; + let mayStore = !eq(load, 0); +} + // Double precision, unary class ADuI opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4, bit opcod5, dag oops, dag iops, InstrItinClass itin, string opc, diff --git a/llvm/lib/Target/ARM/ARMInstrVFP.td b/llvm/lib/Target/ARM/ARMInstrVFP.td index 55d3efbd9b9a..3094a4db2b4d 100644 --- a/llvm/lib/Target/ARM/ARMInstrVFP.td +++ b/llvm/lib/Target/ARM/ARMInstrVFP.td @@ -313,29 +313,51 @@ def : MnemonicAlias<"vstm", "vstmia">; //===----------------------------------------------------------------------===// // Lazy load / store multiple Instructions // -def VLLDM : AXSI4<(outs), (ins GPRnopc:$Rn, pred:$p), IndexModeNone, - NoItinerary, "vlldm${p}\t$Rn", "", []>, +// VLLDM and VLSTM: +// 2 encoding options: +// T1 (bit 7 is 0): +// T1 takes an optional dpr_reglist, must be '{d0-d15}' (exactly) +// T1 require v8-M.Main, secure state, target with 16 D registers (or with no D registers - NOP) +// T2 (bit 7 is 1): +// T2 takes a mandatory dpr_reglist, must be '{d0-d31}' (exactly) +// T2 require v8.1-M.Main, secure state, target with 16/32 D registers (or with no D registers - NOP) +// (source: Arm v8-M ARM, DDI0553B.v ID16122022) + +def VLLDM : AXSI4FR<"vlldm${p}\t$Rn, $regs", 0, 1>, Requires<[HasV8MMainline, Has8MSecExt]> { - let Inst{24-23} = 0b00; - let Inst{22} = 0; - let Inst{21} = 1; - let Inst{20} = 1; - let Inst{15-12} = 0; - let Inst{7-0} = 0; - let mayLoad = 1; - let Defs = [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, VPR, FPSCR, FPSCR_NZCV]; -} - -def VLSTM : AXSI4<(outs), (ins GPRnopc:$Rn, pred:$p), IndexModeNone, - NoItinerary, "vlstm${p}\t$Rn", "", []>, + let Defs = [VPR, FPSCR, FPSCR_NZCV, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15]; + let DecoderMethod = "DecodeLazyLoadStoreMul"; +} +// T1: assembly does not contains the register list. +def : InstAlias<"vlldm${p}\t$Rn", (VLLDM GPRnopc:$Rn, pred:$p, 0)>, + Requires<[HasV8MMainline, Has8MSecExt]>; +// T2: assembly must contains the register list. +// The register list has no effect on the encoding, it is for assembly/disassembly purposes only. +def VLLDM_T2 : AXSI4FR<"vlldm${p}\t$Rn, $regs", 1, 1>, + Requires<[HasV8_1MMainline, Has8MSecExt]> { + let Defs = [VPR, FPSCR, FPSCR_NZCV, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, + D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31]; + let DecoderMethod = "DecodeLazyLoadStoreMul"; +} +// T1: assembly contains the register list. +// The register list has no effect on the encoding, it is for assembly/disassembly purposes only. +def VLSTM : AXSI4FR<"vlstm${p}\t$Rn, $regs", 0, 0>, Requires<[HasV8MMainline, Has8MSecExt]> { - let Inst{24-23} = 0b00; - let Inst{22} = 0; - let Inst{21} = 1; - let Inst{20} = 0; - let Inst{15-12} = 0; - let Inst{7-0} = 0; - let mayStore = 1; + let Defs = [VPR, FPSCR, FPSCR_NZCV]; + let Uses = [VPR, FPSCR, FPSCR_NZCV, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15]; + let DecoderMethod = "DecodeLazyLoadStoreMul"; +} +// T1: assembly does not contain the register list. +def : InstAlias<"vlstm${p}\t$Rn", (VLSTM GPRnopc:$Rn, pred:$p, 0)>, + Requires<[HasV8MMainline, Has8MSecExt]>; +// T2: assembly must contain the register list. +// The register list has no effect on the encoding, it is for assembly/disassembly purposes only. +def VLSTM_T2 : AXSI4FR<"vlstm${p}\t$Rn, $regs", 1, 0>, + Requires<[HasV8_1MMainline, Has8MSecExt]> { + let Defs = [VPR, FPSCR, FPSCR_NZCV]; + let Uses = [VPR, FPSCR, FPSCR_NZCV, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, + D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31]; + let DecoderMethod = "DecodeLazyLoadStoreMul"; } def : InstAlias<"vpush${p} $r", (VSTMDDB_UPD SP, pred:$p, dpr_reglist:$r), 0>, diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index efec163c6ed6..c320bf723c88 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -450,11 +450,12 @@ class ARMAsmParser : public MCTargetAsmParser { bool validatetSTMRegList(const MCInst &Inst, const OperandVector &Operands, unsigned ListNo); - int tryParseRegister(); + int tryParseRegister(bool AllowOutofBoundReg = false); bool tryParseRegisterWithWriteBack(OperandVector &); int tryParseShiftRegister(OperandVector &); bool parseRegisterList(OperandVector &, bool EnforceOrder = true, - bool AllowRAAC = false); + bool AllowRAAC = false, + bool AllowOutOfBoundReg = false); bool parseMemory(OperandVector &); bool parseOperand(OperandVector &, StringRef Mnemonic); bool parseImmExpr(int64_t &Out); @@ -4073,7 +4074,7 @@ ParseStatus ARMAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, /// Try to parse a register name. The token must be an Identifier when called, /// and if it is a register name the token is eaten and the register number is /// returned. Otherwise return -1. -int ARMAsmParser::tryParseRegister() { +int ARMAsmParser::tryParseRegister(bool AllowOutOfBoundReg) { MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) return -1; @@ -4117,7 +4118,8 @@ int ARMAsmParser::tryParseRegister() { } // Some FPUs only have 16 D registers, so D16-D31 are invalid - if (!hasD32() && RegNum >= ARM::D16 && RegNum <= ARM::D31) + if (!AllowOutOfBoundReg && !hasD32() && RegNum >= ARM::D16 && + RegNum <= ARM::D31) return -1; Parser.Lex(); // Eat identifier token. @@ -4457,7 +4459,7 @@ insertNoDuplicates(SmallVectorImpl> &Regs, /// Parse a register list. bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder, - bool AllowRAAC) { + bool AllowRAAC, bool AllowOutOfBoundReg) { MCAsmParser &Parser = getParser(); if (Parser.getTok().isNot(AsmToken::LCurly)) return TokError("Token is not a Left Curly Brace"); @@ -4511,7 +4513,7 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder, return Error(RegLoc, "pseudo-register not allowed"); Parser.Lex(); // Eat the minus. SMLoc AfterMinusLoc = Parser.getTok().getLoc(); - int EndReg = tryParseRegister(); + int EndReg = tryParseRegister(AllowOutOfBoundReg); if (EndReg == -1) return Error(AfterMinusLoc, "register expected"); if (EndReg == ARM::RA_AUTH_CODE) @@ -4546,7 +4548,7 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder, RegLoc = Parser.getTok().getLoc(); int OldReg = Reg; const AsmToken RegTok = Parser.getTok(); - Reg = tryParseRegister(); + Reg = tryParseRegister(AllowOutOfBoundReg); if (Reg == -1) return Error(RegLoc, "register expected"); if (!AllowRAAC && Reg == ARM::RA_AUTH_CODE) @@ -6086,8 +6088,11 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { } case AsmToken::LBrac: return parseMemory(Operands); - case AsmToken::LCurly: - return parseRegisterList(Operands, !Mnemonic.starts_with("clr")); + case AsmToken::LCurly: { + bool AllowOutOfBoundReg = Mnemonic == "vlldm" || Mnemonic == "vlstm"; + return parseRegisterList(Operands, !Mnemonic.starts_with("clr"), false, + AllowOutOfBoundReg); + } case AsmToken::Dollar: case AsmToken::Hash: { // #42 -> immediate @@ -7597,6 +7602,33 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, const unsigned Opcode = Inst.getOpcode(); switch (Opcode) { + case ARM::VLLDM: + case ARM::VLLDM_T2: + case ARM::VLSTM: + case ARM::VLSTM_T2: { + // Since in some cases both T1 and T2 are valid, tablegen can not always + // pick the correct instruction. + if (Operands.size() == 4) { // a register list has been provided + ARMOperand &Op = static_cast( + *Operands[3]); // the register list, a dpr_reglist + assert(Op.isDPRRegList()); + auto &RegList = Op.getRegList(); + // T2 requires v8.1-M.Main (cannot be handled by tablegen) + if (RegList.size() == 32 && !hasV8_1MMainline()) { + return Error(Op.getEndLoc(), "T2 version requires v8.1-M.Main"); + } + // When target has 32 D registers, T1 is undefined. + if (hasD32() && RegList.size() != 32) { + return Error(Op.getEndLoc(), "operand must be exactly {d0-d31}"); + } + // When target has 16 D registers, both T1 and T2 are valid. + if (!hasD32() && (RegList.size() != 16 && RegList.size() != 32)) { + return Error(Op.getEndLoc(), + "operand must be exactly {d0-d15} (T1) or {d0-d31} (T2)"); + } + } + return false; + } case ARM::t2IT: { // Encoding is unpredictable if it ever results in a notional 'NV' // predicate. Since we don't parse 'NV' directly this means an 'AL' @@ -8732,6 +8764,32 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, } switch (Inst.getOpcode()) { + case ARM::VLLDM: + case ARM::VLSTM: { + // In some cases both T1 and T2 are valid, causing tablegen pick T1 instead + // of T2 + if (Operands.size() == 4) { // a register list has been provided + ARMOperand &Op = static_cast( + *Operands[3]); // the register list, a dpr_reglist + assert(Op.isDPRRegList()); + auto &RegList = Op.getRegList(); + // When the register list is {d0-d31} the instruction has to be the T2 + // variant + if (RegList.size() == 32) { + const unsigned Opcode = + (Inst.getOpcode() == ARM::VLLDM) ? ARM::VLLDM_T2 : ARM::VLSTM_T2; + MCInst TmpInst; + TmpInst.setOpcode(Opcode); + TmpInst.addOperand(Inst.getOperand(0)); + TmpInst.addOperand(Inst.getOperand(1)); + TmpInst.addOperand(Inst.getOperand(2)); + TmpInst.addOperand(Inst.getOperand(3)); + Inst = TmpInst; + return true; + } + } + return false; + } // Alias for alternate form of 'ldr{,b}t Rt, [Rn], #imm' instruction. case ARM::LDRT_POST: case ARM::LDRBT_POST: { diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index 604f22d71119..705f3cbce12f 100644 --- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -700,6 +700,9 @@ DecodeMVEOverlappingLongShift(MCInst &Inst, unsigned Insn, uint64_t Address, static DecodeStatus DecodeT2AddSubSPImm(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder); +static DecodeStatus DecodeLazyLoadStoreMul(MCInst &Inst, unsigned Insn, + uint64_t Address, + const MCDisassembler *Decoder); #include "ARMGenDisassemblerTables.inc" @@ -7030,3 +7033,23 @@ static DecodeStatus DecodeT2AddSubSPImm(MCInst &Inst, unsigned Insn, return DS; } + +static DecodeStatus DecodeLazyLoadStoreMul(MCInst &Inst, unsigned Insn, + uint64_t Address, + const MCDisassembler *Decoder) { + DecodeStatus S = MCDisassembler::Success; + + const unsigned Rn = fieldFromInstruction(Insn, 16, 4); + // Adding Rn, holding memory location to save/load to/from, the only argument + // that is being encoded. + // '$Rn' in the assembly. + if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))) + return MCDisassembler::Fail; + // An optional predicate, '$p' in the assembly. + DecodePredicateOperand(Inst, ARMCC::AL, Address, Decoder); + // An immediate that represents a floating point registers list. '$regs' in + // the assembly. + Inst.addOperand(MCOperand::createImm(0)); // Arbitrary value, has no effect. + + return S; +} diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp index fbd067d79af0..24e627cd9a4e 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp @@ -91,6 +91,38 @@ void ARMInstPrinter::printInst(const MCInst *MI, uint64_t Address, unsigned Opcode = MI->getOpcode(); switch (Opcode) { + case ARM::VLLDM: { + const MCOperand &Reg = MI->getOperand(0); + O << '\t' << "vlldm" << '\t'; + printRegName(O, Reg.getReg()); + O << ", " + << "{d0 - d15}"; + return; + } + case ARM::VLLDM_T2: { + const MCOperand &Reg = MI->getOperand(0); + O << '\t' << "vlldm" << '\t'; + printRegName(O, Reg.getReg()); + O << ", " + << "{d0 - d31}"; + return; + } + case ARM::VLSTM: { + const MCOperand &Reg = MI->getOperand(0); + O << '\t' << "vlstm" << '\t'; + printRegName(O, Reg.getReg()); + O << ", " + << "{d0 - d15}"; + return; + } + case ARM::VLSTM_T2: { + const MCOperand &Reg = MI->getOperand(0); + O << '\t' << "vlstm" << '\t'; + printRegName(O, Reg.getReg()); + O << ", " + << "{d0 - d31}"; + return; + } // Check for MOVs and print canonical forms, instead. case ARM::MOVsr: { // FIXME: Thumb variants? diff --git a/llvm/test/CodeGen/ARM/cmse-vlldm-no-reorder.mir b/llvm/test/CodeGen/ARM/cmse-vlldm-no-reorder.mir index 2bc4288884f1..3d49fee8fdaf 100644 --- a/llvm/test/CodeGen/ARM/cmse-vlldm-no-reorder.mir +++ b/llvm/test/CodeGen/ARM/cmse-vlldm-no-reorder.mir @@ -89,7 +89,7 @@ body: | # CHECK: $sp = t2STMDB_UPD $sp, 14 /* CC::al */, $noreg, $r4, $r5, $r6, undef $r7, $r8, $r9, $r10, $r11 # CHECK-NEXT: $r0 = t2BICri $r0, 1, 14 /* CC::al */, $noreg, $noreg # CHECK-NEXT: $sp = tSUBspi $sp, 34, 14 /* CC::al */, $noreg -# CHECK-NEXT: VLSTM $sp, 14 /* CC::al */, $noreg, implicit undef $vpr, implicit undef $fpscr, implicit undef $fpscr_nzcv, implicit undef $q0, implicit undef $q1, implicit undef $q2, implicit undef $q3, implicit undef $q4, implicit undef $q5, implicit undef $q6, implicit undef $q7 +# CHECK-NEXT: VLSTM $sp, 14 /* CC::al */, $noreg, 0, implicit-def $vpr, implicit-def $fpscr, implicit-def $fpscr_nzcv, implicit undef $vpr, implicit undef $fpscr, implicit undef $fpscr_nzcv, implicit undef $d0, implicit undef $d1, implicit undef $d2, implicit undef $d3, implicit undef $d4, implicit undef $d5, implicit undef $d6, implicit undef $d7, implicit $d8, implicit $d9, implicit $d10, implicit $d11, implicit $d12, implicit $d13, implicit $d14, implicit $d15 # CHECK-NEXT: $r1 = tMOVr $r0, 14 /* CC::al */, $noreg # CHECK-NEXT: $r2 = tMOVr $r0, 14 /* CC::al */, $noreg # CHECK-NEXT: $r3 = tMOVr $r0, 14 /* CC::al */, $noreg @@ -105,8 +105,7 @@ body: | # CHECK-NEXT: t2MSR_M 3072, $r0, 14 /* CC::al */, $noreg, implicit-def $cpsr # CHECK-NEXT: tBLXNSr 14 /* CC::al */, $noreg, killed $r0, csr_aapcs, implicit-def $lr, implicit $sp, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $s0 # CHECK-NEXT: $r12 = VMOVRS $s0, 14 /* CC::al */, $noreg -# CHECK-NEXT: VLLDM $sp, 14 /* CC::al */, $noreg, implicit-def $q0, implicit-def $q1, implicit-def $q2, implicit-def $q3, implicit-def $q4, implicit-def $q5, implicit-def $q6, implicit-def $q7, implicit-def $vpr, implicit-def $fpscr, implicit-def $fpscr_nzcv +# CHECK-NEXT: VLLDM $sp, 14 /* CC::al */, $noreg, 0, implicit-def $vpr, implicit-def $fpscr, implicit-def $fpscr_nzcv, implicit-def $d0, implicit-def $d1, implicit-def $d2, implicit-def $d3, implicit-def $d4, implicit-def $d5, implicit-def $d6, implicit-def $d7, implicit-def $d8, implicit-def $d9, implicit-def $d10, implicit-def $d11, implicit-def $d12, implicit-def $d13, implicit-def $d14, implicit-def $d15 # CHECK-NEXT: $s0 = VMOVSR $r12, 14 /* CC::al */, $noreg # CHECK-NEXT: $sp = tADDspi $sp, 34, 14 /* CC::al */, $noreg # CHECK-NEXT: $sp = t2LDMIA_UPD $sp, 14 /* CC::al */, $noreg, def $r4, def $r5, def $r6, def $r7, def $r8, def $r9, def $r10, def $r11 - diff --git a/llvm/test/CodeGen/ARM/vlldm-vlstm-uops.mir b/llvm/test/CodeGen/ARM/vlldm-vlstm-uops.mir index 8c49a5316741..8fa9337eae6c 100644 --- a/llvm/test/CodeGen/ARM/vlldm-vlstm-uops.mir +++ b/llvm/test/CodeGen/ARM/vlldm-vlstm-uops.mir @@ -60,9 +60,9 @@ body: | $sp = t2STMDB_UPD $sp, 14, $noreg, $r4, killed $r5, killed $r6, killed $r7, killed $r8, killed $r9, killed $r10, killed $r11 $r4 = t2BICri $r4, 1, 14, $noreg, $noreg $sp = tSUBspi $sp, 34, 14, $noreg - VLSTM $sp, 14, $noreg - tBLXNSr 14, $noreg, killed $r4, csr_aapcs, implicit-def $lr, implicit $sp, implicit-def dead $lr, implicit $sp, implicit-def $sp - VLLDM $sp, 14, $noreg, implicit-def $q0, implicit-def $q1, implicit-def $q2, implicit-def $q3, implicit-def $q4, implicit-def $q5, implicit-def $q6, implicit-def $q7, implicit-def $vpr, implicit-def $fpscr, implicit-def $fpscr_nzcv + VLSTM $sp, 14 /* CC::al */, $noreg, 0, implicit-def $vpr, implicit-def $fpscr, implicit-def $fpscr_nzcv, implicit undef $vpr, implicit undef $fpscr, implicit undef $fpscr_nzcv, implicit undef $d0, implicit undef $d1, implicit undef $d2, implicit undef $d3, implicit undef $d4, implicit undef $d5, implicit undef $d6, implicit undef $d7, implicit $d8, implicit $d9, implicit $d10, implicit $d11, implicit $d12, implicit $d13, implicit $d14, implicit $d15 + tBLXNSr 14, $noreg, killed $r4, csr_aapcs, implicit-def $lr, implicit $sp, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $q0, implicit-def $q1, implicit-def $q2, implicit-def $q3, implicit-def $q4, implicit-def $q5, implicit-def $q6, implicit-def $q7 + VLLDM $sp, 14 /* CC::al */, $noreg, 0, implicit-def $vpr, implicit-def $fpscr, implicit-def $fpscr_nzcv, implicit-def $d0, implicit-def $d1, implicit-def $d2, implicit-def $d3, implicit-def $d4, implicit-def $d5, implicit-def $d6, implicit-def $d7, implicit-def $d8, implicit-def $d9, implicit-def $d10, implicit-def $d11, implicit-def $d12, implicit-def $d13, implicit-def $d14, implicit-def $d15 $sp = tADDspi $sp, 34, 14, $noreg $sp = t2LDMIA_UPD $sp, 14, $noreg, def $r4, def $r5, def $r6, def $r7, def $r8, def $r9, def $r10, def $r11 $sp = t2LDMIA_RET $sp, 14, $noreg, def $r4, def $pc diff --git a/llvm/test/MC/ARM/thumbv8m.s b/llvm/test/MC/ARM/thumbv8m.s index 0e9ab4a9b3bf..f03dd03dae3a 100644 --- a/llvm/test/MC/ARM/thumbv8m.s +++ b/llvm/test/MC/ARM/thumbv8m.s @@ -184,13 +184,13 @@ ttat r0, r1 // 'Lazy Load/Store Multiple' // UNDEF-BASELINE: error: instruction requires: armv8m.main -// CHECK-MAINLINE: vlldm r5 @ encoding: [0x35,0xec,0x00,0x0a] -// CHECK-MAINLINE_DSP: vlldm r5 @ encoding: [0x35,0xec,0x00,0x0a] +// CHECK-MAINLINE: vlldm r5, {d0 - d15} @ encoding: [0x35,0xec,0x00,0x0a] +// CHECK-MAINLINE_DSP: vlldm r5, {d0 - d15} @ encoding: [0x35,0xec,0x00,0x0a] vlldm r5 // UNDEF-BASELINE: error: instruction requires: armv8m.main -// CHECK-MAINLINE: vlstm r10 @ encoding: [0x2a,0xec,0x00,0x0a] -// CHECK-MAINLINE_DSP: vlstm r10 @ encoding: [0x2a,0xec,0x00,0x0a] +// CHECK-MAINLINE: vlstm r10, {d0 - d15} @ encoding: [0x2a,0xec,0x00,0x0a] +// CHECK-MAINLINE_DSP: vlstm r10, {d0 - d15} @ encoding: [0x2a,0xec,0x00,0x0a] vlstm r10 // New SYSm's diff --git a/llvm/test/MC/ARM/vlstm-vlldm-8.1m.s b/llvm/test/MC/ARM/vlstm-vlldm-8.1m.s new file mode 100644 index 000000000000..4e35883ffe43 --- /dev/null +++ b/llvm/test/MC/ARM/vlstm-vlldm-8.1m.s @@ -0,0 +1,11 @@ +// RUN: llvm-mc -triple=armv8.1m.main-arm-none-eabi -mcpu=generic -show-encoding %s \ +// RUN: | FileCheck --check-prefixes=CHECK %s + +// RUN: llvm-mc -triple=thumbv8.1m.main-none-eabi -mcpu=generic -show-encoding %s \ +// RUN: | FileCheck --check-prefixes=CHECK %s + +vlstm r8, {d0 - d31} +// CHECK: vlstm r8, {d0 - d31} @ encoding: [0x28,0xec,0x80,0x0a] + +vlldm r8, {d0 - d31} +// CHECK: vlldm r8, {d0 - d31} @ encoding: [0x38,0xec,0x80,0x0a] diff --git a/llvm/test/MC/ARM/vlstm-vlldm-8m.s b/llvm/test/MC/ARM/vlstm-vlldm-8m.s new file mode 100644 index 000000000000..bbc95318aeb3 --- /dev/null +++ b/llvm/test/MC/ARM/vlstm-vlldm-8m.s @@ -0,0 +1,17 @@ +// RUN: llvm-mc -triple=armv8m.main-arm-none-eabi -mcpu=generic -show-encoding %s \ +// RUN: | FileCheck --check-prefixes=CHECK %s + +// RUN: llvm-mc -triple=thumbv8m.main-none-eabi -mcpu=generic -show-encoding %s \ +// RUN: | FileCheck --check-prefixes=CHECK %s + +vlstm r8, {d0 - d15} +// CHECK: vlstm r8, {d0 - d15} @ encoding: [0x28,0xec,0x00,0x0a] + +vlldm r8, {d0 - d15} +// CHECK: vlldm r8, {d0 - d15} @ encoding: [0x38,0xec,0x00,0x0a] + +vlstm r8 +// CHECK: vlstm r8, {d0 - d15} @ encoding: [0x28,0xec,0x00,0x0a] + +vlldm r8 +// CHECK: vlldm r8, {d0 - d15} @ encoding: [0x38,0xec,0x00,0x0a] diff --git a/llvm/test/MC/ARM/vlstm-vlldm-diag.s b/llvm/test/MC/ARM/vlstm-vlldm-diag.s new file mode 100644 index 000000000000..b57f535c6a25 --- /dev/null +++ b/llvm/test/MC/ARM/vlstm-vlldm-diag.s @@ -0,0 +1,61 @@ +// RUN: not llvm-mc -triple=armv8.1m.main-arm-none-eabi -mcpu=generic -show-encoding %s 2>&1 >/dev/null \ +// RUN: | FileCheck --check-prefixes=ERR %s + +// RUN: not llvm-mc -triple=armv8.1m.main-arm-none-eabi -mcpu=generic -show-encoding %s 2>&1 >/dev/null \ +// RUN: | FileCheck --check-prefixes=ERRT2 %s + +vlstm r8, {d0 - d11} +// ERR: error: operand must be exactly {d0-d15} (T1) or {d0-d31} (T2) +// ERR-NEXT: vlstm r8, {d0 - d11} + +vlldm r8, {d0 - d11} +// ERR: error: operand must be exactly {d0-d15} (T1) or {d0-d31} (T2) +// ERR-NEXT: vlldm r8, {d0 - d11} + +vlstm r8, {d3 - d15} +// ERR: error: operand must be exactly {d0-d15} (T1) or {d0-d31} (T2) +// ERR-NEXT: vlstm r8, {d3 - d15} + +vlldm r8, {d3 - d15} +// ERR: error: operand must be exactly {d0-d15} (T1) or {d0-d31} (T2) +// ERR-NEXT: vlldm r8, {d3 - d15} + +vlstm r8, {d0 - d29} +// ERR: error: operand must be exactly {d0-d15} (T1) or {d0-d31} (T2) +// ERR-NEXT: vlstm r8, {d0 - d29} + +vlldm r8, {d0 - d29} +// ERR: error: operand must be exactly {d0-d15} (T1) or {d0-d31} (T2) +// ERR-NEXT: vlldm r8, {d0 - d29} + +vlstm r8, {d3 - d31} +// ERR: error: operand must be exactly {d0-d15} (T1) or {d0-d31} (T2) +// ERR-NEXT: vlstm r8, {d3 - d31} + +vlldm r8, {d3 - d31} +// ERR: error: operand must be exactly {d0-d15} (T1) or {d0-d31} (T2) +// ERR-NEXT: vlldm r8, {d3 - d31} + +vlstm r8, {d0 - d35} +// ERR: error: register expected +// ERR-NEXT: vlstm r8, {d0 - d35} + +vlldm r8, {d0 - d35} +// ERR: error: register expected +// ERR-NEXT: vlldm r8, {d0 - d35} + +vlstm pc +// ERR: error: operand must be a register in range [r0, r14] +// ERR-NEXT: vlstm pc + +vlldm pc +// ERR: error: operand must be a register in range [r0, r14] +// ERR-NEXT: vlldm pc + +vlstm pc +// ERRT2: error: operand must be a register in range [r0, r14] +// ERRT2-NEXT: vlstm pc + +vlldm pc +// ERRT2: error: operand must be a register in range [r0, r14] +// ERRT2-NEXT: vlldm pc \ No newline at end of file diff --git a/llvm/test/MC/Disassembler/ARM/armv8.1m-vlldm_vlstm-8.1.main.txt b/llvm/test/MC/Disassembler/ARM/armv8.1m-vlldm_vlstm-8.1.main.txt new file mode 100644 index 000000000000..6b9882454c06 --- /dev/null +++ b/llvm/test/MC/Disassembler/ARM/armv8.1m-vlldm_vlstm-8.1.main.txt @@ -0,0 +1,11 @@ +// RUN: llvm-mc -triple=armv8.1m.main-arm-none-eabi -mcpu=generic -show-encoding -disassemble %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-DISS + +// RUN: llvm-mc -triple=thumbv8.1m.main-none-eabi -mcpu=generic -show-encoding -disassemble %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-DISS + +[0x28,0xec,0x80,0x0a] +// CHECK-DISS: vlstm r8, {d0 - d31} @ encoding: [0x28,0xec,0x80,0x0a] + +[0x38,0xec,0x80,0x0a] +// CHECK-DISS: vlldm r8, {d0 - d31} @ encoding: [0x38,0xec,0x80,0x0a] \ No newline at end of file diff --git a/llvm/test/MC/Disassembler/ARM/armv8.1m-vlldm_vlstm-8.main.txt b/llvm/test/MC/Disassembler/ARM/armv8.1m-vlldm_vlstm-8.main.txt new file mode 100644 index 000000000000..1e28d5284c5b --- /dev/null +++ b/llvm/test/MC/Disassembler/ARM/armv8.1m-vlldm_vlstm-8.main.txt @@ -0,0 +1,17 @@ +// RUN: llvm-mc -triple=armv8m.main-arm-none-eabi -mcpu=generic -show-encoding -disassemble %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-DISS + +// RUN: llvm-mc -triple=thumbv8m.main-none-eabi -mcpu=generic -show-encoding -disassemble %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-DISS + +[0x28,0xec,0x00,0x0a] +// CHECK-DISS: vlstm r8, {d0 - d15} @ encoding: [0x28,0xec,0x00,0x0a] + +[0x38,0xec,0x00,0x0a] +// CHECK-DISS: vlldm r8, {d0 - d15} @ encoding: [0x38,0xec,0x00,0x0a] + +[0x28,0xec,0x00,0x0a] +// CHECK-DISS: vlstm r8, {d0 - d15} @ encoding: [0x28,0xec,0x00,0x0a] + +[0x38,0xec,0x00,0x0a] +// CHECK-DISS: vlldm r8, {d0 - d15} @ encoding: [0x38,0xec,0x00,0x0a] \ No newline at end of file diff --git a/llvm/unittests/Target/ARM/MachineInstrTest.cpp b/llvm/unittests/Target/ARM/MachineInstrTest.cpp index aeb25bf012d0..3a76054ca4f3 100644 --- a/llvm/unittests/Target/ARM/MachineInstrTest.cpp +++ b/llvm/unittests/Target/ARM/MachineInstrTest.cpp @@ -1126,7 +1126,9 @@ TEST(MachineInstr, HasSideEffects) { VLDR_VPR_post, VLDR_VPR_pre, VLLDM, + VLLDM_T2, VLSTM, + VLSTM_T2, VMRS, VMRS_FPCXTNS, VMRS_FPCXTS, -- GitLab From 769eab47194c2a67a5939bb6a077bf48b0ba9ddb Mon Sep 17 00:00:00 2001 From: Krzysztof Drewniak Date: Mon, 11 Mar 2024 09:34:50 -0500 Subject: [PATCH 113/953] [NFC][AMDGPU] Fix redundant assignment from #77952 (#84586) Someone pointed out a typo (Value* RsrcRes = RsrcRes = ...) in PR the address space 7 lowering, this commit fixes it. --- llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp index 34fcb9aec38f..544231cad280 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp @@ -1671,7 +1671,7 @@ PtrParts SplitPtrStructs::visitSelectInst(SelectInst &SI) { auto [TrueRsrc, TrueOff] = getPtrParts(True); auto [FalseRsrc, FalseOff] = getPtrParts(False); - Value *RsrcRes = RsrcRes = + Value *RsrcRes = IRB.CreateSelect(Cond, TrueRsrc, FalseRsrc, SI.getName() + ".rsrc", &SI); copyMetadata(RsrcRes, &SI); Conditionals.push_back(&SI); -- GitLab From d0117b71193787ebfd92d96a4ecc261f0aaeac86 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Sun, 10 Mar 2024 20:46:37 +0000 Subject: [PATCH 114/953] [RemoveDIs] Copy debug mode to new functions in amdgpu-lower-buffer-fat-pointers Fixes failing tests after https://github.com/llvm/llvm-project/pull/84308 LLVM :: CodeGen/AMDGPU/GlobalISel/irtranslator-non-integral-address-spaces-vectors.ll LLVM :: CodeGen/AMDGPU/GlobalISel/irtranslator-non-integral-address-spaces.ll LLVM :: CodeGen/AMDGPU/lower-buffer-fat-pointers-calls.ll LLVM :: CodeGen/AMDGPU/lower-buffer-fat-pointers-constants.ll LLVM :: CodeGen/AMDGPU/lower-buffer-fat-pointers-pointer-ops.ll LLVM :: CodeGen/AMDGPU/pal-metadata-3.0.ll Buildbots: https://lab.llvm.org/buildbot/#/builders/121/builds/39855 --- llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp index 544231cad280..2cfd1de93a04 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp @@ -1841,6 +1841,7 @@ static Function *moveFunctionAdaptingType(Function *OldF, FunctionType *NewTy, bool IsIntrinsic = OldF->isIntrinsic(); Function *NewF = Function::Create(NewTy, OldF->getLinkage(), OldF->getAddressSpace()); + NewF->IsNewDbgInfoFormat = OldF->IsNewDbgInfoFormat; NewF->copyAttributesFrom(OldF); NewF->copyMetadata(OldF, 0); NewF->takeName(OldF); -- GitLab From 538aeb180bcdf82cd86a46b44d6622a1c13d2877 Mon Sep 17 00:00:00 2001 From: Emma Pilkington Date: Mon, 11 Mar 2024 10:36:38 -0400 Subject: [PATCH 115/953] [AMDGPU] Use a consistent DwarfEH register flavour (#84513) Previously, we always used the wave64 encodings for EH registers regardless of whether we were compiling for wave32, which seems wrong. We don't seem to use the EH registers, so this commit is mostly just about papering over code that converts from non-EH dwarf registers to LLVM registers while claiming they are EH dwarf registers. That kind of code should be okay on any non-darwin target (since darwin is the only target that uses a different encoding for EH registers). --- llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCTargetDesc.cpp | 2 +- llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp | 5 +++-- llvm/unittests/MC/AMDGPU/DwarfRegMappings.cpp | 2 ++ llvm/unittests/Target/AMDGPU/DwarfRegMappings.cpp | 2 ++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCTargetDesc.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCTargetDesc.cpp index a6a01479b5b1..4700a984770b 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCTargetDesc.cpp +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCTargetDesc.cpp @@ -70,7 +70,7 @@ static MCRegisterInfo *createAMDGPUMCRegisterInfo(const Triple &TT) { MCRegisterInfo *llvm::createGCNMCRegisterInfo(AMDGPUDwarfFlavour DwarfFlavour) { MCRegisterInfo *X = new MCRegisterInfo(); - InitAMDGPUMCRegisterInfo(X, AMDGPU::PC_REG, DwarfFlavour); + InitAMDGPUMCRegisterInfo(X, AMDGPU::PC_REG, DwarfFlavour, DwarfFlavour); return X; } diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp index 3664535b3259..5c64c6bcd196 100644 --- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp +++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp @@ -318,8 +318,9 @@ struct SGPRSpillBuilder { } // namespace llvm SIRegisterInfo::SIRegisterInfo(const GCNSubtarget &ST) - : AMDGPUGenRegisterInfo(AMDGPU::PC_REG, ST.getAMDGPUDwarfFlavour()), ST(ST), - SpillSGPRToVGPR(EnableSpillSGPRToVGPR), isWave32(ST.isWave32()) { + : AMDGPUGenRegisterInfo(AMDGPU::PC_REG, ST.getAMDGPUDwarfFlavour(), + ST.getAMDGPUDwarfFlavour()), + ST(ST), SpillSGPRToVGPR(EnableSpillSGPRToVGPR), isWave32(ST.isWave32()) { assert(getSubRegIndexLaneMask(AMDGPU::sub0).getAsInteger() == 3 && getSubRegIndexLaneMask(AMDGPU::sub31).getAsInteger() == (3ULL << 62) && diff --git a/llvm/unittests/MC/AMDGPU/DwarfRegMappings.cpp b/llvm/unittests/MC/AMDGPU/DwarfRegMappings.cpp index e1acb8677a04..7f7a3720cf7c 100644 --- a/llvm/unittests/MC/AMDGPU/DwarfRegMappings.cpp +++ b/llvm/unittests/MC/AMDGPU/DwarfRegMappings.cpp @@ -55,6 +55,7 @@ TEST(AMDGPUDwarfRegMappingTests, TestWave64DwarfRegMapping) { for (int llvmReg : {16, 17, 32, 95, 1088, 1129, 2560, 2815, 3072, 3327}) { MCRegister PCReg(*MRI->getLLVMRegNum(llvmReg, false)); EXPECT_EQ(llvmReg, MRI->getDwarfRegNum(PCReg, false)); + EXPECT_EQ(llvmReg, MRI->getDwarfRegNum(PCReg, true)); } } } @@ -73,6 +74,7 @@ TEST(AMDGPUDwarfRegMappingTests, TestWave32DwarfRegMapping) { for (int llvmReg : {16, 1, 32, 95, 1088, 1129, 1536, 1791, 2048, 2303}) { MCRegister PCReg(*MRI->getLLVMRegNum(llvmReg, false)); EXPECT_EQ(llvmReg, MRI->getDwarfRegNum(PCReg, false)); + EXPECT_EQ(llvmReg, MRI->getDwarfRegNum(PCReg, true)); } } } diff --git a/llvm/unittests/Target/AMDGPU/DwarfRegMappings.cpp b/llvm/unittests/Target/AMDGPU/DwarfRegMappings.cpp index 620835c5dfc5..56da4ce7b43a 100644 --- a/llvm/unittests/Target/AMDGPU/DwarfRegMappings.cpp +++ b/llvm/unittests/Target/AMDGPU/DwarfRegMappings.cpp @@ -29,6 +29,7 @@ TEST(AMDGPU, TestWave64DwarfRegMapping) { {16, 17, 32, 95, 1088, 1129, 2560, 2815, 3072, 3327}) { MCRegister PCReg(*MRI->getLLVMRegNum(llvmReg, false)); EXPECT_EQ(llvmReg, MRI->getDwarfRegNum(PCReg, false)); + EXPECT_EQ(llvmReg, MRI->getDwarfRegNum(PCReg, true)); } } } @@ -52,6 +53,7 @@ TEST(AMDGPU, TestWave32DwarfRegMapping) { {16, 1, 32, 95, 1088, 1129, 1536, 1791, 2048, 2303}) { MCRegister PCReg(*MRI->getLLVMRegNum(llvmReg, false)); EXPECT_EQ(llvmReg, MRI->getDwarfRegNum(PCReg, false)); + EXPECT_EQ(llvmReg, MRI->getDwarfRegNum(PCReg, true)); } } } -- GitLab From 2953d9c8b07e07d1344b979ebd831a68b07d0e8f Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Sun, 10 Mar 2024 20:53:25 +0000 Subject: [PATCH 116/953] Reapply "[RemoveDIs] Add additional debug-mode verifier checks" (#84757) Test failures fixed in d0117b71193787ebfd92d96a4ecc261f0aaeac86 --- llvm/lib/IR/Verifier.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index ce090c3b8a74..0e6c01802cfb 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -2691,6 +2691,11 @@ void Verifier::visitFunction(const Function &F) { Check(verifyAttributeCount(Attrs, FT->getNumParams()), "Attribute after last parameter!", &F); + CheckDI(F.IsNewDbgInfoFormat == F.getParent()->IsNewDbgInfoFormat, + "Function debug format should match parent module", &F, + F.IsNewDbgInfoFormat, F.getParent(), + F.getParent()->IsNewDbgInfoFormat); + bool IsIntrinsic = F.isIntrinsic(); // Check function attributes. @@ -3034,6 +3039,11 @@ void Verifier::visitBasicBlock(BasicBlock &BB) { Check(I.getParent() == &BB, "Instruction has bogus parent pointer!"); } + CheckDI(BB.IsNewDbgInfoFormat == BB.getParent()->IsNewDbgInfoFormat, + "BB debug format should match parent function", &BB, + BB.IsNewDbgInfoFormat, BB.getParent(), + BB.getParent()->IsNewDbgInfoFormat); + // Confirm that no issues arise from the debug program. if (BB.IsNewDbgInfoFormat) CheckDI(!BB.getTrailingDPValues(), "Basic Block has trailing DbgRecords!", -- GitLab From f14224d92b0e43aa508c8d800db57f8f674e1c7b Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Mon, 11 Mar 2024 07:52:28 -0700 Subject: [PATCH 117/953] [RISCV] Rename schedule classes for vmv.s.x, vmv.x.s, vfmv.s.f, and vfmv.f.s [nfc] (#84563) The prior naming scheme is incredibly hard to make sense out of. I suspect the usage was actually backwards from intent - though that didn't matter for any in tree schedule model. --- llvm/lib/Target/RISCV/RISCVInstrInfoV.td | 8 ++-- .../Target/RISCV/RISCVInstrInfoVPseudos.td | 8 ++-- llvm/lib/Target/RISCV/RISCVSchedSiFive7.td | 20 ++++----- llvm/lib/Target/RISCV/RISCVScheduleV.td | 42 +++++++++---------- 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoV.td index d2d824da9c78..d7807c120378 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoV.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoV.td @@ -1637,11 +1637,11 @@ def VID_V : RVInstV<0b010100, 0b10001, OPMVV, (outs VR:$vd), let vm = 1, RVVConstraint = NoConstraint in { def VMV_X_S : RVInstV<0b010000, 0b00000, OPMVV, (outs GPR:$vd), (ins VR:$vs2), "vmv.x.s", "$vd, $vs2">, - Sched<[WriteVIMovVX, ReadVIMovVX]>; + Sched<[WriteVMovXS, ReadVMovXS]>; let Constraints = "$vd = $vd_wb" in def VMV_S_X : RVInstV2<0b010000, 0b00000, OPMVX, (outs VR:$vd_wb), (ins VR:$vd, GPR:$rs1), "vmv.s.x", "$vd, $rs1">, - Sched<[WriteVIMovXV, ReadVIMovXV, ReadVIMovXX]>; + Sched<[WriteVMovSX, ReadVMovSX_V, ReadVMovSX_X]>; } } // hasSideEffects = 0, mayLoad = 0, mayStore = 0 @@ -1655,11 +1655,11 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, vm = 1, // Floating-Point Scalar Move Instructions def VFMV_F_S : RVInstV<0b010000, 0b00000, OPFVV, (outs FPR32:$vd), (ins VR:$vs2), "vfmv.f.s", "$vd, $vs2">, - Sched<[WriteVFMovVF, ReadVFMovVF]>; + Sched<[WriteVMovFS, ReadVMovFS]>; let Constraints = "$vd = $vd_wb" in def VFMV_S_F : RVInstV2<0b010000, 0b00000, OPFVF, (outs VR:$vd_wb), (ins VR:$vd, FPR32:$rs1), "vfmv.s.f", "$vd, $rs1">, - Sched<[WriteVFMovFV, ReadVFMovFV, ReadVFMovFX]>; + Sched<[WriteVMovSF, ReadVMovSF_V, ReadVMovSF_F]>; } // hasSideEffects = 0, mayLoad = 0, mayStore = 0, vm = 1 diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td index 48cf48e8af58..ae93bf694875 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -6767,14 +6767,14 @@ let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in { let HasSEWOp = 1, BaseInstr = VMV_X_S in def PseudoVMV_X_S: Pseudo<(outs GPR:$rd), (ins VR:$rs2, ixlenimm:$sew), []>, - Sched<[WriteVIMovVX, ReadVIMovVX]>, + Sched<[WriteVMovXS, ReadVMovXS]>, RISCVVPseudo; let HasVLOp = 1, HasSEWOp = 1, BaseInstr = VMV_S_X, Constraints = "$rd = $rs1" in def PseudoVMV_S_X: Pseudo<(outs VR:$rd), (ins VR:$rs1, GPR:$rs2, AVL:$vl, ixlenimm:$sew), []>, - Sched<[WriteVIMovXV, ReadVIMovXV, ReadVIMovXX]>, + Sched<[WriteVMovSX, ReadVMovSX_V, ReadVMovSX_X]>, RISCVVPseudo; } } // Predicates = [HasVInstructions] @@ -6793,7 +6793,7 @@ let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in { def "PseudoVFMV_" # f.FX # "_S_" # mx : Pseudo<(outs f.fprclass:$rd), (ins m.vrclass:$rs2, ixlenimm:$sew), []>, - Sched<[WriteVFMovVF, ReadVFMovVF]>, + Sched<[WriteVMovFS, ReadVMovFS]>, RISCVVPseudo; let HasVLOp = 1, HasSEWOp = 1, BaseInstr = VFMV_S_F, Constraints = "$rd = $rs1" in @@ -6802,7 +6802,7 @@ let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in { (ins m.vrclass:$rs1, f.fprclass:$rs2, AVL:$vl, ixlenimm:$sew), []>, - Sched<[WriteVFMovFV, ReadVFMovFV, ReadVFMovFX]>, + Sched<[WriteVMovSF, ReadVMovSF_V, ReadVMovSF_F]>, RISCVVPseudo; } } diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td index b21a56bdcdd2..240d170bfcf6 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td @@ -887,10 +887,10 @@ foreach mx = SchedMxList in { // 16. Vector Permutation Instructions let Latency = 4, AcquireAtCycles = [0, 1], ReleaseAtCycles = [1, !add(1, 1)] in { - def : WriteRes; - def : WriteRes; - def : WriteRes; - def : WriteRes; + def : WriteRes; + def : WriteRes; + def : WriteRes; + def : WriteRes; } foreach mx = SchedMxList in { defvar Cycles = SiFive7GetCyclesDefault.c; @@ -1190,12 +1190,12 @@ defm "" : LMULReadAdvance<"ReadVMSFSV", 0>; defm "" : LMULReadAdvance<"ReadVIotaV", 0>; // 17. Vector Permutation Instructions -def : ReadAdvance; -def : ReadAdvance; -def : ReadAdvance; -def : ReadAdvance; -def : ReadAdvance; -def : ReadAdvance; +def : ReadAdvance; +def : ReadAdvance; +def : ReadAdvance; +def : ReadAdvance; +def : ReadAdvance; +def : ReadAdvance; defm "" : LMULReadAdvance<"ReadVISlideV", 0>; defm "" : LMULReadAdvance<"ReadVISlideX", 0>; defm "" : LMULReadAdvance<"ReadVFSlideV", 0>; diff --git a/llvm/lib/Target/RISCV/RISCVScheduleV.td b/llvm/lib/Target/RISCV/RISCVScheduleV.td index 0be681de3daf..379622d4ca83 100644 --- a/llvm/lib/Target/RISCV/RISCVScheduleV.td +++ b/llvm/lib/Target/RISCV/RISCVScheduleV.td @@ -196,7 +196,7 @@ multiclass LMULSEWReadAdvanceImpl writes // by the ReadAdvance. For example: // ``` // defm "" : LMULReadAdvance<"ReadVIALUX", 1, -// LMULSchedWriteList<["WriteVIMovVX"]>.value>; +// LMULSchedWriteList<["WriteVMovSX"]>.value>; // ``` class LMULSchedWriteListImpl names, list MxList> { list value = !foldl([], @@ -484,11 +484,11 @@ defm "" : LMULSchedWrites<"WriteVIdxV">; // 16. Vector Permutation Instructions // 16.1. Integer Scalar Move Instructions -def WriteVIMovVX : SchedWrite; -def WriteVIMovXV : SchedWrite; +def WriteVMovSX : SchedWrite; +def WriteVMovXS : SchedWrite; // 16.2. Floating-Point Scalar Move Instructions -def WriteVFMovVF : SchedWrite; -def WriteVFMovFV : SchedWrite; +def WriteVMovSF : SchedWrite; +def WriteVMovFS : SchedWrite; // 16.3. Vector Slide Instructions defm "" : LMULSchedWrites<"WriteVISlideX">; defm "" : LMULSchedWrites<"WriteVISlideI">; @@ -709,13 +709,13 @@ defm "" : LMULSchedReads<"ReadVIotaV">; // 16. Vector Permutation Instructions // 16.1. Integer Scalar Move Instructions -def ReadVIMovVX : SchedRead; -def ReadVIMovXV : SchedRead; -def ReadVIMovXX : SchedRead; +def ReadVMovXS : SchedRead; +def ReadVMovSX_V : SchedRead; +def ReadVMovSX_X : SchedRead; // 16.2. Floating-Point Scalar Move Instructions -def ReadVFMovVF : SchedRead; -def ReadVFMovFV : SchedRead; -def ReadVFMovFX : SchedRead; +def ReadVMovFS : SchedRead; +def ReadVMovSF_V : SchedRead; +def ReadVMovSF_F : SchedRead; // 16.3. Vector Slide Instructions defm "" : LMULSchedReads<"ReadVISlideV">; defm "" : LMULSchedReads<"ReadVISlideX">; @@ -921,10 +921,10 @@ defm "" : LMULWriteRes<"WriteVIotaV", []>; defm "" : LMULWriteRes<"WriteVIdxV", []>; // 16. Vector Permutation Instructions -def : WriteRes; -def : WriteRes; -def : WriteRes; -def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; defm "" : LMULWriteRes<"WriteVISlideX", []>; defm "" : LMULWriteRes<"WriteVISlideI", []>; defm "" : LMULWriteRes<"WriteVISlide1X", []>; @@ -1082,12 +1082,12 @@ defm "" : LMULReadAdvance<"ReadVMSFSV", 0>; defm "" : LMULReadAdvance<"ReadVIotaV", 0>; // 16. Vector Permutation Instructions -def : ReadAdvance; -def : ReadAdvance; -def : ReadAdvance; -def : ReadAdvance; -def : ReadAdvance; -def : ReadAdvance; +def : ReadAdvance; +def : ReadAdvance; +def : ReadAdvance; +def : ReadAdvance; +def : ReadAdvance; +def : ReadAdvance; defm "" : LMULReadAdvance<"ReadVISlideV", 0>; defm "" : LMULReadAdvance<"ReadVISlideX", 0>; defm "" : LMULReadAdvance<"ReadVFSlideV", 0>; -- GitLab From 63ae5099b7339e87e6ce67fc7da63d26b8e7cb27 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Mon, 11 Mar 2024 22:55:16 +0800 Subject: [PATCH 118/953] [libc++][test] Don't include `test_format_context.h` in `parse.pass.cpp` (#83734) The `parse.pass.cpp` tests doen't need to call `test_format_context_create` to create a `basic_format_context`, so they shouldn't include `test_format_context.h`. The `to_address` mechanism works around the iterator debugging mechanisms of MSVC STL. Related to [LWG3989](https://cplusplus.github.io/LWG/issue3989). Discovered when implementing `formatter` in MSVC STL. With the inclusion removed, `std/utilities/format/format.tuple/parse.pass.cpp` when using enhanced MSVC STL (and `/utf-8` option for MSVC). --- .../container.adaptors.format/parse.pass.cpp | 5 +++-- .../sequences/vector.bool/vector.bool.fmt/parse.pass.cpp | 5 +++-- .../thread.thread.class/thread.thread.id/parse.pass.cpp | 5 +++-- .../format.formatter.spec/formatter.bool.pass.cpp | 4 +++- .../format.formatter.spec/formatter.c_string.pass.cpp | 4 +++- .../format.formatter.spec/formatter.char.pass.cpp | 4 +++- .../format.formatter.spec/formatter.char_array.pass.cpp | 4 +++- .../format.formatter.spec/formatter.floating_point.pass.cpp | 4 +++- .../format.formatter.spec/formatter.handle.pass.cpp | 4 +++- .../format.formatter.spec/formatter.pointer.pass.cpp | 4 +++- .../format.formatter.spec/formatter.signed_integral.pass.cpp | 4 +++- .../format.formatter.spec/formatter.string.pass.cpp | 4 +++- .../formatter.unsigned_integral.pass.cpp | 4 +++- .../format/format.range/format.range.fmtdef/parse.pass.cpp | 5 +++-- .../format/format.range/format.range.fmtmap/parse.pass.cpp | 5 +++-- .../format/format.range/format.range.fmtset/parse.pass.cpp | 5 +++-- .../format/format.range/format.range.fmtstr/parse.pass.cpp | 5 +++-- .../format.range/format.range.formatter/parse.pass.cpp | 5 +++-- libcxx/test/std/utilities/format/format.tuple/parse.pass.cpp | 5 +++-- 19 files changed, 57 insertions(+), 28 deletions(-) diff --git a/libcxx/test/std/containers/container.adaptors/container.adaptors.format/parse.pass.cpp b/libcxx/test/std/containers/container.adaptors/container.adaptors.format/parse.pass.cpp index 136910b90c90..c47fb188c865 100644 --- a/libcxx/test/std/containers/container.adaptors/container.adaptors.format/parse.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/container.adaptors.format/parse.pass.cpp @@ -27,10 +27,10 @@ #include #include #include +#include #include #include -#include "test_format_context.h" #include "test_macros.h" #include "make_string.h" @@ -44,7 +44,8 @@ constexpr void test_parse(StringViewT fmt, std::size_t offset) { static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); } template diff --git a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/parse.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/parse.pass.cpp index c76103944219..abae40d78b23 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/parse.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/vector.bool.fmt/parse.pass.cpp @@ -25,9 +25,9 @@ #include #include #include +#include #include -#include "test_format_context.h" #include "test_macros.h" #include "make_string.h" @@ -41,7 +41,8 @@ constexpr void test_parse(StringViewT fmt, std::size_t offset) { static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); } template diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/parse.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/parse.pass.cpp index 8523bc894971..2e75606832b4 100644 --- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/parse.pass.cpp +++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.id/parse.pass.cpp @@ -24,9 +24,9 @@ #include #include +#include #include -#include "test_format_context.h" #include "test_macros.h" #include "make_string.h" @@ -40,7 +40,8 @@ constexpr void test_parse(StringViewT fmt, std::size_t offset) { static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); } template diff --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.bool.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.bool.pass.cpp index efea2889ce3b..116f78e63be0 100644 --- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.bool.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.bool.pass.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "test_format_context.h" @@ -38,7 +39,8 @@ void test(StringT expected, StringViewT fmt, bool arg, std::size_t offset) { static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); StringT result; auto out = std::back_inserter(result); diff --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.c_string.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.c_string.pass.cpp index f363bc303200..3125dd8b60bb 100644 --- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.c_string.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.c_string.pass.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "test_format_context.h" @@ -38,7 +39,8 @@ void test(StringT expected, StringViewT fmt, const CharT* a, std::size_t offset) static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); StringT result; auto out = std::back_inserter(result); diff --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char.pass.cpp index 554def930020..0723547c2df2 100644 --- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char.pass.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "test_format_context.h" @@ -39,7 +40,8 @@ void test(StringT expected, StringViewT fmt, ArgumentT arg, std::size_t offset) static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); StringT result; auto out = std::back_inserter(result); diff --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char_array.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char_array.pass.cpp index 295ba7f67bbc..b0ee399a1c19 100644 --- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char_array.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char_array.pass.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "test_format_context.h" @@ -51,7 +52,8 @@ struct Tester { static_assert(std::semiregular); std::same_as::iterator> auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); std::basic_string result; auto out = std::back_inserter(result); diff --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp index 6c507881167f..263dc1d8d851 100644 --- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -50,7 +51,8 @@ void test(std::basic_string_view fmt, ArithmeticT arg, std::basic_string< static_assert(std::semiregular); std::same_as::iterator> auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); std::basic_string result; auto out = std::back_inserter(result); diff --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.handle.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.handle.pass.cpp index e2b3d6b3d237..5921cc6efcec 100644 --- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.handle.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.handle.pass.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -43,7 +44,8 @@ void test(std::string expected, std::string_view fmt, color arg, std::size_t off static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); std::string result; auto out = std::back_inserter(result); diff --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.pointer.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.pointer.pass.cpp index aa10f34c95b7..408168e033bb 100644 --- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.pointer.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.pointer.pass.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -44,7 +45,8 @@ void test(StringT expected, StringViewT fmt, PointerT arg, std::size_t offset) { static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); StringT result; auto out = std::back_inserter(result); diff --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.signed_integral.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.signed_integral.pass.cpp index e5db5dac0c56..cdd56d1b882a 100644 --- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.signed_integral.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.signed_integral.pass.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "test_format_context.h" @@ -46,7 +47,8 @@ void test(StringT expected, StringViewT fmt, ArithmeticT arg, std::size_t offset static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); StringT result; auto out = std::back_inserter(result); diff --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.string.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.string.pass.cpp index 73df7464dcb7..49f54dae2647 100644 --- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.string.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.string.pass.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "make_string.h" @@ -46,7 +47,8 @@ void test(StringT expected, StringViewT fmt, StringT a, std::size_t offset) { static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); StringT result; auto out = std::back_inserter(result); diff --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.unsigned_integral.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.unsigned_integral.pass.cpp index eb70115bf5de..a9537465faf9 100644 --- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.unsigned_integral.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.unsigned_integral.pass.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "test_format_context.h" @@ -46,7 +47,8 @@ void test(StringT expected, StringViewT fmt, ArithmeticT arg, std::size_t offset static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); StringT result; auto out = std::back_inserter(result); diff --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtdef/parse.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.fmtdef/parse.pass.cpp index 9f9b4d4545a8..0eb984cc2c01 100644 --- a/libcxx/test/std/utilities/format/format.range/format.range.fmtdef/parse.pass.cpp +++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtdef/parse.pass.cpp @@ -22,8 +22,8 @@ #include #include #include +#include -#include "test_format_context.h" #include "test_macros.h" #include "make_string.h" @@ -37,7 +37,8 @@ constexpr void test_parse(StringViewT fmt, std::size_t offset) { static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); } template diff --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/parse.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/parse.pass.cpp index daa92214845b..99d6aa7452a0 100644 --- a/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/parse.pass.cpp +++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtmap/parse.pass.cpp @@ -25,8 +25,8 @@ #include #include #include +#include -#include "test_format_context.h" #include "test_macros.h" #include "make_string.h" @@ -40,7 +40,8 @@ constexpr void test_parse(StringViewT fmt, std::size_t offset) { static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); } template diff --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/parse.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/parse.pass.cpp index 843855f4e6d0..182beff4bd16 100644 --- a/libcxx/test/std/utilities/format/format.range/format.range.fmtset/parse.pass.cpp +++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtset/parse.pass.cpp @@ -24,9 +24,9 @@ #include #include #include +#include #include -#include "test_format_context.h" #include "test_macros.h" #include "make_string.h" @@ -40,7 +40,8 @@ constexpr void test_parse(StringViewT fmt, std::size_t offset) { static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); } template diff --git a/libcxx/test/std/utilities/format/format.range/format.range.fmtstr/parse.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.fmtstr/parse.pass.cpp index 7acee9cb9dc5..3354de347219 100644 --- a/libcxx/test/std/utilities/format/format.range/format.range.fmtstr/parse.pass.cpp +++ b/libcxx/test/std/utilities/format/format.range/format.range.fmtstr/parse.pass.cpp @@ -23,9 +23,9 @@ #include #include #include +#include #include "format.functions.tests.h" -#include "test_format_context.h" #include "test_macros.h" template @@ -36,7 +36,8 @@ constexpr void test_parse(StringViewT fmt, std::size_t offset) { static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); } template diff --git a/libcxx/test/std/utilities/format/format.range/format.range.formatter/parse.pass.cpp b/libcxx/test/std/utilities/format/format.range/format.range.formatter/parse.pass.cpp index 87774c262087..2d0cef11feb8 100644 --- a/libcxx/test/std/utilities/format/format.range/format.range.formatter/parse.pass.cpp +++ b/libcxx/test/std/utilities/format/format.range/format.range.formatter/parse.pass.cpp @@ -25,8 +25,8 @@ #include #include #include +#include -#include "test_format_context.h" #include "test_macros.h" #include "make_string.h" @@ -40,7 +40,8 @@ constexpr void test_parse(StringViewT fmt, std::size_t offset) { static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); } template diff --git a/libcxx/test/std/utilities/format/format.tuple/parse.pass.cpp b/libcxx/test/std/utilities/format/format.tuple/parse.pass.cpp index 5cabbda63dd0..8653c282bfe1 100644 --- a/libcxx/test/std/utilities/format/format.tuple/parse.pass.cpp +++ b/libcxx/test/std/utilities/format/format.tuple/parse.pass.cpp @@ -24,10 +24,10 @@ #include #include #include +#include #include #include -#include "test_format_context.h" #include "test_macros.h" #include "make_string.h" @@ -41,7 +41,8 @@ constexpr void test(StringViewT fmt, std::size_t offset) { static_assert(std::semiregular); std::same_as auto it = formatter.parse(parse_ctx); - assert(it == fmt.end() - offset); + // std::to_address works around LWG3989 and MSVC STL's iterator debugging mechanism. + assert(std::to_address(it) == std::to_address(fmt.end()) - offset); } template -- GitLab From 63c77d84756793ad38e3a5b830a27b400308fe7a Mon Sep 17 00:00:00 2001 From: Pierre van Houtryve Date: Mon, 11 Mar 2024 15:56:17 +0100 Subject: [PATCH 119/953] [AMDGPU] Make generic versioning docs easier to find (#84761) --- llvm/docs/AMDGPUUsage.rst | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst index 7f39f69cae60..f5f37d9e8a3b 100644 --- a/llvm/docs/AMDGPUUsage.rst +++ b/llvm/docs/AMDGPUUsage.rst @@ -525,16 +525,7 @@ it supports. Such code objects may not perform as well as those for the non-gene Generic processors are only available on code object V6 and above (see :ref:`amdgpu-elf-code-object`). -Generic processor code objects are versioned (see :ref:`amdgpu-elf-header-e_flags-table-v6-onwards`) between 1 and 255. -The version of non-generic code objects is always set to 0. - -For a generic code object, adding a new supported processor may require the code generated for the generic target to be changed -so it can continue to execute on the previously supported processors as well as on the new one. -When this happens, the generic code object version number is incremented at the same time as the generic target is updated. - -Each supported processor of a generic target is mapped to the version it was introduced in. -A generic code object can execute on a supported processor if the version of the code object being loaded is -greater than or equal to the version in which the processor was added to the generic target. +Generic processor code objects are versioned. See :ref:`amdgpu-generic-processor-versioning` for more information on how versioning works. .. table:: AMDGPU Generic Processors :name: amdgpu-generic-processor-table @@ -621,6 +612,21 @@ greater than or equal to the version in which the processor was added to the gen - ``gfx1151`` ==================== ============== ================= ================== ================= ================================= +.. _amdgpu-generic-processor-versioning: + +Generic Processor Versioning +---------------------------- + +Generic processor (see :ref:`amdgpu-generic-processor-table`) code objects are versioned (see :ref:`amdgpu-elf-header-e_flags-table-v6-onwards`) between 1 and 255. +The version of non-generic code objects is always set to 0. + +For a generic code object, adding a new supported processor may require the code generated for the generic target to be changed +so it can continue to execute on the previously supported processors as well as on the new one. +When this happens, the generic code object version number is incremented at the same time as the generic target is updated. + +Each supported processor of a generic target is mapped to the version it was introduced in. +A generic code object can execute on a supported processor if the version of the code object being loaded is +greater than or equal to the version in which the processor was added to the generic target. .. _amdgpu-target-features: @@ -1803,7 +1809,7 @@ The AMDGPU backend uses the following ELF header: mask. This is a value between 1 and 255, stored in the most significant byte of EFLAGS. - See :ref:`amdgpu-generic-processor-table` + See :ref:`amdgpu-generic-processor-versioning` ============================================ ========== ========================================= .. table:: AMDGPU ``EF_AMDGPU_MACH`` Values -- GitLab From 63af8584fc7ea81ef6f2176e0ada0533a3495745 Mon Sep 17 00:00:00 2001 From: itrofimow Date: Mon, 11 Mar 2024 18:59:05 +0400 Subject: [PATCH 120/953] [libc++] Only forward-declare ABI-functions in exception_ptr.h if they are meant to be used (#84707) This patch fixes the unconditional forward-declarations of ABI-functions in exception_ptr.h, and makes it dependent on the availability macro, as it should've been from the beginning. The declarations being unconditional break the build with libcxxrt before 045c52ce8 [1], now they are opt-out. [1]: https://github.com/libcxxrt/libcxxrt/commit/045c52ce821388f4ae4d119fe4fb75f1eb547b85 --- libcxx/include/__exception/exception_ptr.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h index 53e2f718bc1b..c9027de9238c 100644 --- a/libcxx/include/__exception/exception_ptr.h +++ b/libcxx/include/__exception/exception_ptr.h @@ -26,6 +26,8 @@ #ifndef _LIBCPP_ABI_MICROSOFT +# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION + namespace __cxxabiv1 { extern "C" { @@ -37,14 +39,16 @@ _LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception* __cxa_init_primary_exception( void*, std::type_info*, void( -# if defined(_WIN32) +# if defined(_WIN32) __thiscall -# endif +# endif *)(void*)) throw(); } } // namespace __cxxabiv1 +# endif + #endif namespace std { // purposefully not using versioning namespace -- GitLab From b05c15259bcbe3eba353b77ca4fc9ec2a81dd3fb Mon Sep 17 00:00:00 2001 From: Krzysztof Drewniak Date: Mon, 11 Mar 2024 10:06:49 -0500 Subject: [PATCH 121/953] [mlir][AMDGPU] Improve amdgpu.lds_barrier, add warnings (#77942) On some architectures (currently gfx90a, gfx94*, and gfx10**), we can implement an LDS barrier using compiler intrinsics instead of inline assembly, improving optimization possibilities and decreasing the fragility of the underlying code. Other AMDGPU chipsets continue to require inline assembly to implement this barrier, as, by the default, the LLVM backend will insert waits on global memory (s_waintcnt vmcnt(0)) before barriers in order to ensure memory watchpoints set by debuggers work correctly. Use of amdgpu.lds_barrier, on these architectures, imposes a tradeoff between debugability and performance. The documentation, as well as the generated inline assembly, have been updated to explicitly call attention to this fact. For chipsets that did not require the inline assembly hack, we move to the s.waitcnt and s.barrier intrinsics, which have been added to the ROCDL dialect. The magic constants used as an argument to the waitcnt intrinsic can be derived from llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp --- mlir/include/mlir/Dialect/AMDGPU/IR/AMDGPU.td | 5 ++ mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td | 17 +++++ .../AMDGPUToROCDL/AMDGPUToROCDL.cpp | 62 ++++++++++++++----- .../AMDGPUToROCDL/amdgpu-to-rocdl.mlir | 52 ++++++++++------ mlir/test/Dialect/LLVMIR/rocdl.mlir | 13 ++++ mlir/test/Target/LLVMIR/rocdl.mlir | 16 +++++ 6 files changed, 132 insertions(+), 33 deletions(-) diff --git a/mlir/include/mlir/Dialect/AMDGPU/IR/AMDGPU.td b/mlir/include/mlir/Dialect/AMDGPU/IR/AMDGPU.td index b4bf1b519123..21942b179a00 100644 --- a/mlir/include/mlir/Dialect/AMDGPU/IR/AMDGPU.td +++ b/mlir/include/mlir/Dialect/AMDGPU/IR/AMDGPU.td @@ -441,6 +441,11 @@ def AMDGPU_LDSBarrierOp : AMDGPU_Op<"lds_barrier"> { to complete before execution continues. Therefore, it should be used when operations on global memory can be issued far in advance of when their results are used (for example, by writing them to LDS). + + WARNING: On architectures that do not support the BackOffBarrier feature, + (those which will implement this barrier by emitting inline assembly), + use of this operation will impede the usabiliity of memory watches (including + breakpoints set on variables) when debugging. }]; let assemblyFormat = "attr-dict"; } diff --git a/mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td b/mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td index 53e9f2dc6a99..32b5a1c016b6 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td @@ -194,6 +194,23 @@ def ROCDL_GridDimZOp : ROCDL_DeviceFunctionOp<"grid.dim.z", //===----------------------------------------------------------------------===// // Synchronization primitives +// Emits the waintcnt instruction. The bitfield's semantics depend +// on the target chipset +def ROCDL_WaitcntOp : ROCDL_Op<"waitcnt">, Arguments<(ins I32Attr:$bitfield)> { + string llvmBuilder = [{ + createIntrinsicCall(builder, llvm::Intrinsic::amdgcn_s_waitcnt, + {builder.getInt32($bitfield)}); + }]; + let assemblyFormat = "attr-dict $bitfield"; +} + +def ROCDL_SBarrierOp : ROCDL_Op<"s.barrier"> { + string llvmBuilder = [{ + createIntrinsicCall(builder, llvm::Intrinsic::amdgcn_s_barrier); + }]; + let assemblyFormat = "attr-dict"; +} + def ROCDL_BarrierOp : ROCDL_Op<"barrier"> { string llvmBuilder = [{ llvm::LLVMContext &llvmContext = builder.getContext(); diff --git a/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp b/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp index 12d2462061dc..7e073bae75c0 100644 --- a/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp +++ b/mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp @@ -270,21 +270,54 @@ struct RawBufferOpLowering : public ConvertOpToLLVMPattern { }; struct LDSBarrierOpLowering : public ConvertOpToLLVMPattern { - using ConvertOpToLLVMPattern::ConvertOpToLLVMPattern; + LDSBarrierOpLowering(LLVMTypeConverter &converter, Chipset chipset) + : ConvertOpToLLVMPattern(converter), chipset(chipset) {} + + Chipset chipset; LogicalResult matchAndRewrite(LDSBarrierOp op, LDSBarrierOp::Adaptor adaptor, ConversionPatternRewriter &rewriter) const override { - auto asmDialectAttr = LLVM::AsmDialectAttr::get(rewriter.getContext(), - LLVM::AsmDialect::AD_ATT); - const char *asmStr = "s_waitcnt lgkmcnt(0)\ns_barrier"; - const char *constraints = ""; - rewriter.replaceOpWithNewOp( - op, - /*resultTypes=*/TypeRange(), /*operands=*/ValueRange(), - /*asm_string=*/asmStr, constraints, /*has_side_effects=*/true, - /*is_align_stack=*/false, /*asm_dialect=*/asmDialectAttr, - /*operand_attrs=*/ArrayAttr()); + bool requiresInlineAsm = + chipset.majorVersion < 9 || + (chipset.majorVersion == 9 && chipset.minorVersion < 0x0a) || + (chipset.majorVersion == 11); + + if (requiresInlineAsm) { + auto asmDialectAttr = LLVM::AsmDialectAttr::get(rewriter.getContext(), + LLVM::AsmDialect::AD_ATT); + const char *asmStr = + ";;;WARNING: BREAKS DEBUG WATCHES\ns_waitcnt lgkmcnt(0)\ns_barrier"; + const char *constraints = ""; + rewriter.replaceOpWithNewOp( + op, + /*resultTypes=*/TypeRange(), /*operands=*/ValueRange(), + /*asm_string=*/asmStr, constraints, /*has_side_effects=*/true, + /*is_align_stack=*/false, /*asm_dialect=*/asmDialectAttr, + /*operand_attrs=*/ArrayAttr()); + return success(); + } + constexpr int32_t ldsOnlyBitsGfx6789 = ~(0x1f << 8); + constexpr int32_t ldsOnlyBitsGfx10 = ~(0x3f << 8); + // Left in place in case someone disables the inline ASM path or future + // chipsets use the same bit pattern. + constexpr int32_t ldsOnlyBitsGfx11 = ~(0x3f << 4); + + int32_t ldsOnlyBits; + if (chipset.majorVersion == 11) + ldsOnlyBits = ldsOnlyBitsGfx11; + else if (chipset.majorVersion == 10) + ldsOnlyBits = ldsOnlyBitsGfx10; + else if (chipset.majorVersion <= 9) + ldsOnlyBits = ldsOnlyBitsGfx6789; + else + return op.emitOpError( + "don't know how to lower this for chipset major version") + << chipset.majorVersion; + + Location loc = op->getLoc(); + rewriter.create(loc, ldsOnlyBits); + rewriter.replaceOpWithNewOp(op); return success(); } }; @@ -834,7 +867,6 @@ void mlir::populateAMDGPUToROCDLConversionPatterns(LLVMTypeConverter &converter, return converter.convertType(t.clone(IntegerType::get(t.getContext(), 16))); }); - patterns.add(converter); patterns .add, RawBufferOpLowering, @@ -848,9 +880,9 @@ void mlir::populateAMDGPUToROCDLConversionPatterns(LLVMTypeConverter &converter, ROCDL::RawPtrBufferAtomicUminOp>, RawBufferOpLowering, - MFMAOpLowering, WMMAOpLowering, ExtPackedFp8OpLowering, - PackedTrunc2xFp8OpLowering, PackedStochRoundFp8OpLowering>(converter, - chipset); + LDSBarrierOpLowering, MFMAOpLowering, WMMAOpLowering, + ExtPackedFp8OpLowering, PackedTrunc2xFp8OpLowering, + PackedStochRoundFp8OpLowering>(converter, chipset); } std::unique_ptr mlir::createConvertAMDGPUToROCDLPass() { diff --git a/mlir/test/Conversion/AMDGPUToROCDL/amdgpu-to-rocdl.mlir b/mlir/test/Conversion/AMDGPUToROCDL/amdgpu-to-rocdl.mlir index 76e427913234..bb1cedaa276b 100644 --- a/mlir/test/Conversion/AMDGPUToROCDL/amdgpu-to-rocdl.mlir +++ b/mlir/test/Conversion/AMDGPUToROCDL/amdgpu-to-rocdl.mlir @@ -1,12 +1,13 @@ -// RUN: mlir-opt %s -convert-amdgpu-to-rocdl=chipset=gfx908 | FileCheck %s -// RUN: mlir-opt %s -convert-amdgpu-to-rocdl=chipset=gfx1030 | FileCheck %s --check-prefix=RDNA -// RUN: mlir-opt %s -convert-amdgpu-to-rocdl=chipset=gfx1100 | FileCheck %s --check-prefix=RDNA +// RUN: mlir-opt %s -convert-amdgpu-to-rocdl=chipset=gfx908 | FileCheck %s --check-prefixes=CHECK,GFX9,GFX908 +// RUN: mlir-opt %s -convert-amdgpu-to-rocdl=chipset=gfx90a | FileCheck %s --check-prefixes=CHECK,GFX9,GFX90A +// RUN: mlir-opt %s -convert-amdgpu-to-rocdl=chipset=gfx1030 | FileCheck %s --check-prefixes=CHECK,GFX10,RDNA +// RUN: mlir-opt %s -convert-amdgpu-to-rocdl=chipset=gfx1100 | FileCheck %s --check-prefixes=CHECK,GFX11,RDNA // CHECK-LABEL: func @gpu_gcn_raw_buffer_load_scalar_i32 func.func @gpu_gcn_raw_buffer_load_scalar_i32(%buf: memref) -> i32 { // CHECK: %[[stride:.*]] = llvm.mlir.constant(0 : i16) // CHECK: %[[numRecords:.*]] = llvm.mlir.constant(4 : i32) - // CHECK: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // GFX9: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) // RDNA: %[[flags:.*]] = llvm.mlir.constant(822243328 : i32) // CHECK: %[[resource:.*]] = rocdl.make.buffer.rsrc %{{.*}}, %[[stride]], %[[numRecords]], %[[flags]] : !llvm.ptr to <8> // CHECK: %[[ret:.*]] = rocdl.raw.ptr.buffer.load %[[resource]], %{{.*}}, %{{.*}}, %{{.*}} : i32 @@ -19,7 +20,7 @@ func.func @gpu_gcn_raw_buffer_load_scalar_i32(%buf: memref) -> i32 { func.func @gpu_gcn_raw_buffer_load_i32(%buf: memref<64xi32>, %idx: i32) -> i32 { // CHECK: %[[stride:.*]] = llvm.mlir.constant(0 : i16) // CHECK: %[[numRecords:.*]] = llvm.mlir.constant(256 : i32) - // CHECK: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // GFX9: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) // RDNA: %[[flags:.*]] = llvm.mlir.constant(822243328 : i32) // CHECK: %[[resource:.*]] = rocdl.make.buffer.rsrc %{{.*}}, %[[stride]], %[[numRecords]], %[[flags]] : !llvm.ptr to <8> // CHECK: %[[ret:.*]] = rocdl.raw.ptr.buffer.load %[[resource]], %{{.*}}, %{{.*}}, %{{.*}} : i32 @@ -30,11 +31,11 @@ func.func @gpu_gcn_raw_buffer_load_i32(%buf: memref<64xi32>, %idx: i32) -> i32 { // CHECK-LABEL: func @gpu_gcn_raw_buffer_load_i32_oob_off func.func @gpu_gcn_raw_buffer_load_i32_oob_off(%buf: memref<64xi32>, %idx: i32) -> i32 { - // CHECK: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // GFX9: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) // RDNA: %[[flags:.*]] = llvm.mlir.constant(553807872 : i32) - // RDNA: %[[resource:.*]] = rocdl.make.buffer.rsrc %{{.*}}, %{{.*}}, %{{.*}}, %[[flags]] - // RDNA: %[[ret:.*]] = rocdl.raw.ptr.buffer.load %[[resource]], %{{.*}}, %{{.*}}, %{{.*}} : i32 - // RDNA: return %[[ret]] + // CHECK: %[[resource:.*]] = rocdl.make.buffer.rsrc %{{.*}}, %{{.*}}, %{{.*}}, %[[flags]] + // CHECK: %[[ret:.*]] = rocdl.raw.ptr.buffer.load %[[resource]], %{{.*}}, %{{.*}}, %{{.*}} : i32 + // CHECK: return %[[ret]] %0 = amdgpu.raw_buffer_load {boundsCheck = false} %buf[%idx] : memref<64xi32>, i32 -> i32 func.return %0 : i32 } @@ -103,7 +104,8 @@ func.func @gpu_gcn_raw_buffer_load_4xf8E4M3FNUZ(%buf: memref<64xf8E4M3FNUZ>, %id // Since the lowering logic is shared with loads, only bitcasts need to be rechecked // CHECK-LABEL: func @gpu_gcn_raw_buffer_store_scalar_i32 func.func @gpu_gcn_raw_buffer_store_scalar_i32(%value: i32, %buf: memref) { - // CHECK: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // GFX9: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // RDNA: %[[flags:.*]] = llvm.mlir.constant(822243328 : i32) // CHECK: %[[resource:.*]] = rocdl.make.buffer.rsrc %{{.*}}, %{{.*}}, %{{.*}}, %[[flags]] // CHECK: rocdl.raw.ptr.buffer.store %{{.*}}, %[[resource]], %{{.*}}, %{{.*}}, %{{.*}} : i32 amdgpu.raw_buffer_store {boundsCheck = true} %value -> %buf[] : i32 -> memref @@ -113,7 +115,8 @@ func.func @gpu_gcn_raw_buffer_store_scalar_i32(%value: i32, %buf: memref) { // CHECK-LABEL: func @gpu_gcn_raw_buffer_store_i32 func.func @gpu_gcn_raw_buffer_store_i32(%value: i32, %buf: memref<64xi32>, %idx: i32) { // CHECK: %[[numRecords:.*]] = llvm.mlir.constant(256 : i32) - // CHECK: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // GFX9: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // RDNA: %[[flags:.*]] = llvm.mlir.constant(822243328 : i32) // CHECK: %[[resource:.*]] = rocdl.make.buffer.rsrc %{{.*}}, %{{.*}}, %[[numRecords]], %[[flags]] // CHECK: rocdl.raw.ptr.buffer.store %{{.*}}, %[[resource]], %{{.*}}, %{{.*}}, %{{.*}} : i32 amdgpu.raw_buffer_store {boundsCheck = true} %value -> %buf[%idx] : i32 -> memref<64xi32>, i32 @@ -140,7 +143,8 @@ func.func @gpu_gcn_raw_buffer_store_16xi8(%value: vector<16xi8>, %buf: memref<64 // CHECK-LABEL: func @gpu_gcn_raw_buffer_atomic_fadd_f32 func.func @gpu_gcn_raw_buffer_atomic_fadd_f32(%value: f32, %buf: memref<64xf32>, %idx: i32) { // CHECK: %[[numRecords:.*]] = llvm.mlir.constant(256 : i32) - // CHECK: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // GFX9: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // RDNA: %[[flags:.*]] = llvm.mlir.constant(822243328 : i32) // CHECK: %[[resource:.*]] = rocdl.make.buffer.rsrc %{{.*}}, %{{.*}}, %[[numRecords]], %[[flags]] // CHECK: rocdl.raw.ptr.buffer.atomic.fadd %{{.*}}, %[[resource]], %{{.*}}, %{{.*}}, %{{.*}} : f32 amdgpu.raw_buffer_atomic_fadd {boundsCheck = true} %value -> %buf[%idx] : f32 -> memref<64xf32>, i32 @@ -150,7 +154,8 @@ func.func @gpu_gcn_raw_buffer_atomic_fadd_f32(%value: f32, %buf: memref<64xf32>, // CHECK-LABEL: func @gpu_gcn_raw_buffer_atomic_fmax_f32 func.func @gpu_gcn_raw_buffer_atomic_fmax_f32(%value: f32, %buf: memref<64xf32>, %idx: i32) { // CHECK: %[[numRecords:.*]] = llvm.mlir.constant(256 : i32) - // CHECK: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // GFX9: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // RDNA: %[[flags:.*]] = llvm.mlir.constant(822243328 : i32) // CHECK: %[[resource:.*]] = rocdl.make.buffer.rsrc %{{.*}}, %{{.*}}, %[[numRecords]], %[[flags]] // CHECK: rocdl.raw.ptr.buffer.atomic.fmax %{{.*}}, %[[resource]], %{{.*}}, %{{.*}}, %{{.*}} : f32 amdgpu.raw_buffer_atomic_fmax {boundsCheck = true} %value -> %buf[%idx] : f32 -> memref<64xf32>, i32 @@ -160,7 +165,8 @@ func.func @gpu_gcn_raw_buffer_atomic_fmax_f32(%value: f32, %buf: memref<64xf32>, // CHECK-LABEL: func @gpu_gcn_raw_buffer_atomic_smax_i32 func.func @gpu_gcn_raw_buffer_atomic_smax_i32(%value: i32, %buf: memref<64xi32>, %idx: i32) { // CHECK: %[[numRecords:.*]] = llvm.mlir.constant(256 : i32) - // CHECK: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // GFX9: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // RDNA: %[[flags:.*]] = llvm.mlir.constant(822243328 : i32) // CHECK: %[[resource:.*]] = rocdl.make.buffer.rsrc %{{.*}}, %{{.*}}, %[[numRecords]], %[[flags]] // CHECK: rocdl.raw.ptr.buffer.atomic.smax %{{.*}} %[[resource]], %{{.*}}, %{{.*}}, %{{.*}} : i32 amdgpu.raw_buffer_atomic_smax {boundsCheck = true} %value -> %buf[%idx] : i32 -> memref<64xi32>, i32 @@ -170,7 +176,8 @@ func.func @gpu_gcn_raw_buffer_atomic_smax_i32(%value: i32, %buf: memref<64xi32>, // CHECK-LABEL: func @gpu_gcn_raw_buffer_atomic_umin_i32 func.func @gpu_gcn_raw_buffer_atomic_umin_i32(%value: i32, %buf: memref<64xi32>, %idx: i32) { // CHECK: %[[numRecords:.*]] = llvm.mlir.constant(256 : i32) - // CHECK: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // GFX9: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // RDNA: %[[flags:.*]] = llvm.mlir.constant(822243328 : i32) // CHECK: %[[resource:.*]] = rocdl.make.buffer.rsrc %{{.*}}, %{{.*}}, %[[numRecords]], %[[flags]] // CHECK: rocdl.raw.ptr.buffer.atomic.umin %{{.*}} %[[resource]], %{{.*}}, %{{.*}}, %{{.*}} : i32 amdgpu.raw_buffer_atomic_umin {boundsCheck = true} %value -> %buf[%idx] : i32 -> memref<64xi32>, i32 @@ -183,7 +190,8 @@ func.func @amdgpu_raw_buffer_atomic_cmpswap_f32(%src : f32, %cmp : f32, %buf : m // CHECK: %[[srcCast:.*]] = llvm.bitcast %[[src]] : f32 to i32 // CHECK: %[[cmpCast:.*]] = llvm.bitcast %[[cmp]] : f32 to i32 // CHECK: %[[numRecords:.*]] = llvm.mlir.constant(256 : i32) - // CHECK: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // GFX9: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // RDNA: %[[flags:.*]] = llvm.mlir.constant(822243328 : i32) // CHECK: %[[resource:.*]] = rocdl.make.buffer.rsrc %{{.*}}, %{{.*}}, %[[numRecords]], %[[flags]] // CHECK: %[[dst:.*]] = rocdl.raw.ptr.buffer.atomic.cmpswap %[[srcCast]], %[[cmpCast]], %[[resource]], %{{.*}}, %{{.*}}, %{{.*}} : i32 // CHECK: %[[dstCast:.*]] = llvm.bitcast %[[dst]] : i32 to f32 @@ -196,7 +204,8 @@ func.func @amdgpu_raw_buffer_atomic_cmpswap_f32(%src : f32, %cmp : f32, %buf : m // CHECK-SAME: (%[[src:.*]]: i64, %[[cmp:.*]]: i64, {{.*}}) func.func @amdgpu_raw_buffer_atomic_cmpswap_i64(%src : i64, %cmp : i64, %buf : memref<64xi64>, %idx: i32) -> i64 { // CHECK: %[[numRecords:.*]] = llvm.mlir.constant(512 : i32) - // CHECK: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // GFX9: %[[flags:.*]] = llvm.mlir.constant(159744 : i32) + // RDNA: %[[flags:.*]] = llvm.mlir.constant(822243328 : i32) // CHECK: %[[resource:.*]] = rocdl.make.buffer.rsrc %{{.*}}, %{{.*}}, %[[numRecords]], %[[flags]] // CHECK: %[[dst:.*]] = rocdl.raw.ptr.buffer.atomic.cmpswap %[[src]], %[[cmp]], %[[resource]], %{{.*}}, %{{.*}}, %{{.*}} : i64 // CHECK: return %[[dst]] @@ -206,7 +215,14 @@ func.func @amdgpu_raw_buffer_atomic_cmpswap_i64(%src : i64, %cmp : i64, %buf : m // CHECK-LABEL: func @lds_barrier func.func @lds_barrier() { - // CHECK: llvm.inline_asm has_side_effects asm_dialect = att "s_waitcnt lgkmcnt(0)\0As_barrier" + // GFX908: llvm.inline_asm has_side_effects asm_dialect = att + // GFX908-SAME: ";;;WARNING: BREAKS DEBUG WATCHES\0As_waitcnt lgkmcnt(0)\0As_barrier" + // GFX90A: rocdl.waitcnt -7937 + // GFX90A-NEXT: rocdl.s.barrier + // GFX10: rocdl.waitcnt -16129 + // GFX10-NEXT: rocdl.s.barrier + // GFX11: llvm.inline_asm has_side_effects asm_dialect = att + // GFX11-SAME: ";;;WARNING: BREAKS DEBUG WATCHES\0As_waitcnt lgkmcnt(0)\0As_barrier" amdgpu.lds_barrier func.return } diff --git a/mlir/test/Dialect/LLVMIR/rocdl.mlir b/mlir/test/Dialect/LLVMIR/rocdl.mlir index 89e8e7836c3a..6519186d2cfd 100644 --- a/mlir/test/Dialect/LLVMIR/rocdl.mlir +++ b/mlir/test/Dialect/LLVMIR/rocdl.mlir @@ -363,6 +363,19 @@ llvm.func @rocdl_8bit_floats(%source: i32, %stoch: i32) -> i32 { llvm.return %source5 : i32 } +llvm.func @rocdl.waitcnt() { + // CHECK-LABEL: rocdl.waitcnt + // CHECK: rocdl.waitcnt 0 + rocdl.waitcnt 0 + llvm.return +} + +llvm.func @rocdl.s.barrier() { + // CHECK-LABEL: rocdl.s.barrier + // CHECK: rocdl.s.barrier + rocdl.s.barrier + llvm.return +} // ----- // expected-error@below {{attribute attached to unexpected op}} diff --git a/mlir/test/Target/LLVMIR/rocdl.mlir b/mlir/test/Target/LLVMIR/rocdl.mlir index 3ea6292c679d..d35acb0475e6 100644 --- a/mlir/test/Target/LLVMIR/rocdl.mlir +++ b/mlir/test/Target/LLVMIR/rocdl.mlir @@ -88,7 +88,23 @@ llvm.func @rocdl.bpermute(%src : i32) -> i32 { llvm.return %0 : i32 } +llvm.func @rocdl.waitcnt() { + // CHECK-LABEL: rocdl.waitcnt + // CHECK-NEXT: call void @llvm.amdgcn.s.waitcnt(i32 0) + rocdl.waitcnt 0 + llvm.return +} + +llvm.func @rocdl.s.barrier() { + // CHECK-LABEL: rocdl.s.barrier + // CHECK-NEXT: call void @llvm.amdgcn.s.barrier() + rocdl.s.barrier + llvm.return +} + + llvm.func @rocdl.barrier() { + // CHECK-LABEL: rocdl.barrier // CHECK: fence syncscope("workgroup") release // CHECK-NEXT: call void @llvm.amdgcn.s.barrier() // CHECK-NEXT: fence syncscope("workgroup") acquire -- GitLab From b4e39ad1176aa7fc1528aa3f7b447bf27350549f Mon Sep 17 00:00:00 2001 From: Jonathan Peyton Date: Mon, 11 Mar 2024 10:26:53 -0500 Subject: [PATCH 122/953] [OpenMP] Remove dead code of checking int > INT_MAX (#83305) --- openmp/runtime/src/kmp_settings.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/openmp/runtime/src/kmp_settings.cpp b/openmp/runtime/src/kmp_settings.cpp index ec86ee07472c..abca4d2d7525 100644 --- a/openmp/runtime/src/kmp_settings.cpp +++ b/openmp/runtime/src/kmp_settings.cpp @@ -4889,9 +4889,6 @@ static void __kmp_stg_parse_spin_backoff_params(const char *name, if (num <= 0) { // The number of retries should be > 0 msg = KMP_I18N_STR(ValueTooSmall); num = 1; - } else if (num > KMP_INT_MAX) { - msg = KMP_I18N_STR(ValueTooLarge); - num = KMP_INT_MAX; } if (msg != NULL) { // Message is not empty. Print warning. @@ -4988,9 +4985,6 @@ static void __kmp_stg_parse_adaptive_lock_props(const char *name, if (num < 0) { // The number of retries should be >= 0 msg = KMP_I18N_STR(ValueTooSmall); num = 1; - } else if (num > KMP_INT_MAX) { - msg = KMP_I18N_STR(ValueTooLarge); - num = KMP_INT_MAX; } if (msg != NULL) { // Message is not empty. Print warning. -- GitLab From 1ed463d9617324c37d7efe117233f68f794ac619 Mon Sep 17 00:00:00 2001 From: Jonathan Peyton Date: Mon, 11 Mar 2024 10:27:31 -0500 Subject: [PATCH 123/953] [OpenMP] Make sure ptr is used after NULL check (#83304) --- openmp/runtime/src/kmp_settings.cpp | 4 ++-- openmp/runtime/src/kmp_threadprivate.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/openmp/runtime/src/kmp_settings.cpp b/openmp/runtime/src/kmp_settings.cpp index abca4d2d7525..b9c8289b5c51 100644 --- a/openmp/runtime/src/kmp_settings.cpp +++ b/openmp/runtime/src/kmp_settings.cpp @@ -4373,8 +4373,8 @@ static void __kmp_stg_parse_omp_schedule(char const *name, char const *value, void *data) { size_t length; const char *ptr = value; - SKIP_WS(ptr); - if (value) { + if (ptr) { + SKIP_WS(ptr); length = KMP_STRLEN(value); if (length) { if (value[length - 1] == '"' || value[length - 1] == '\'') diff --git a/openmp/runtime/src/kmp_threadprivate.cpp b/openmp/runtime/src/kmp_threadprivate.cpp index b79ac7d6d2b2..c4a1ec6e1023 100644 --- a/openmp/runtime/src/kmp_threadprivate.cpp +++ b/openmp/runtime/src/kmp_threadprivate.cpp @@ -248,16 +248,16 @@ void __kmp_common_destroy_gtid(int gtid) { if (d_tn->is_vec) { if (d_tn->dt.dtorv != 0) { (void)(*d_tn->dt.dtorv)(tn->par_addr, d_tn->vec_len); - } - if (d_tn->obj_init != 0) { - (void)(*d_tn->dt.dtorv)(d_tn->obj_init, d_tn->vec_len); + if (d_tn->obj_init != 0) { + (void)(*d_tn->dt.dtorv)(d_tn->obj_init, d_tn->vec_len); + } } } else { if (d_tn->dt.dtor != 0) { (void)(*d_tn->dt.dtor)(tn->par_addr); - } - if (d_tn->obj_init != 0) { - (void)(*d_tn->dt.dtor)(d_tn->obj_init); + if (d_tn->obj_init != 0) { + (void)(*d_tn->dt.dtor)(d_tn->obj_init); + } } } } -- GitLab From de4d7015d05ee3d140298207bb09c239884a71f7 Mon Sep 17 00:00:00 2001 From: Jonathan Peyton Date: Mon, 11 Mar 2024 10:27:53 -0500 Subject: [PATCH 124/953] [OpenMP] Remove unnecessary check of ap (#83303) --- openmp/runtime/src/kmp_runtime.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp index ce775ff49f4d..a60bdb968371 100644 --- a/openmp/runtime/src/kmp_runtime.cpp +++ b/openmp/runtime/src/kmp_runtime.cpp @@ -1743,14 +1743,8 @@ __kmp_serial_fork_call(ident_t *loc, int gtid, enum fork_context_e call_context, __kmp_alloc_argv_entries(argc, team, TRUE); team->t.t_argc = argc; argv = (void **)team->t.t_argv; - if (ap) { - for (i = argc - 1; i >= 0; --i) - *argv++ = va_arg(kmp_va_deref(ap), void *); - } else { - for (i = 0; i < argc; ++i) - // Get args from parent team for teams construct - argv[i] = parent_team->t.t_argv[i]; - } + for (i = argc - 1; i >= 0; --i) + *argv++ = va_arg(kmp_va_deref(ap), void *); // AC: revert change made in __kmpc_serialized_parallel() // because initial code in teams should have level=0 team->t.t_level--; -- GitLab From 9b1c496898cbefdce74eb1cf1a0911eb3230d65b Mon Sep 17 00:00:00 2001 From: Jonathan Peyton Date: Mon, 11 Mar 2024 10:28:12 -0500 Subject: [PATCH 125/953] [OpenMP] Fixup while loops to avoid bad NULL check (#83302) --- openmp/runtime/src/kmp_affinity.cpp | 11 +++-------- openmp/runtime/src/kmp_tasking.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/openmp/runtime/src/kmp_affinity.cpp b/openmp/runtime/src/kmp_affinity.cpp index ae0b6459d79e..b79b57eafd6a 100644 --- a/openmp/runtime/src/kmp_affinity.cpp +++ b/openmp/runtime/src/kmp_affinity.cpp @@ -1829,14 +1829,8 @@ static bool __kmp_affinity_create_hwloc_map(kmp_i18n_id_t *const msg_id) { // Figure out the depth and types in the topology depth = 0; - pu = hwloc_get_pu_obj_by_os_index(tp, __kmp_affin_fullMask->begin()); - KMP_ASSERT(pu); - obj = pu; - types[depth] = KMP_HW_THREAD; - hwloc_types[depth] = obj->type; - depth++; - while (obj != root && obj != NULL) { - obj = obj->parent; + obj = hwloc_get_pu_obj_by_os_index(tp, __kmp_affin_fullMask->begin()); + while (obj && obj != root) { #if HWLOC_API_VERSION >= 0x00020000 if (obj->memory_arity) { hwloc_obj_t memory; @@ -1858,6 +1852,7 @@ static bool __kmp_affinity_create_hwloc_map(kmp_i18n_id_t *const msg_id) { hwloc_types[depth] = obj->type; depth++; } + obj = obj->parent; } KMP_ASSERT(depth > 0); diff --git a/openmp/runtime/src/kmp_tasking.cpp b/openmp/runtime/src/kmp_tasking.cpp index 6e8b948efa06..155e17ba7ec8 100644 --- a/openmp/runtime/src/kmp_tasking.cpp +++ b/openmp/runtime/src/kmp_tasking.cpp @@ -2662,8 +2662,8 @@ void *__kmpc_task_reduction_get_th_data(int gtid, void *tskgrp, void *data) { if (tg == NULL) tg = thread->th.th_current_task->td_taskgroup; KMP_ASSERT(tg != NULL); - kmp_taskred_data_t *arr = (kmp_taskred_data_t *)(tg->reduce_data); - kmp_int32 num = tg->reduce_num_data; + kmp_taskred_data_t *arr; + kmp_int32 num; kmp_int32 tid = thread->th.th_info.ds.ds_tid; #if OMPX_TASKGRAPH @@ -2680,6 +2680,8 @@ void *__kmpc_task_reduction_get_th_data(int gtid, void *tskgrp, void *data) { KMP_ASSERT(data != NULL); while (tg != NULL) { + arr = (kmp_taskred_data_t *)(tg->reduce_data); + num = tg->reduce_num_data; for (int i = 0; i < num; ++i) { if (!arr[i].flags.lazy_priv) { if (data == arr[i].reduce_shar || @@ -2713,8 +2715,6 @@ void *__kmpc_task_reduction_get_th_data(int gtid, void *tskgrp, void *data) { } KMP_ASSERT(tg->parent); tg = tg->parent; - arr = (kmp_taskred_data_t *)(tg->reduce_data); - num = tg->reduce_num_data; } KMP_ASSERT2(0, "Unknown task reduction item"); return NULL; // ERROR, this line never executed -- GitLab From cd5504637beb1aafeeec08fd339e0e920386eea1 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 11 Mar 2024 10:29:46 -0500 Subject: [PATCH 126/953] [flang][unittests] Use malloc when memory will be deallcated with free (#84380) Runtime unit tests used `new[]` to allocate memory, which then was released using `free`. This was detected by address sanitizer. --- flang/unittests/Runtime/Ragged.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flang/unittests/Runtime/Ragged.cpp b/flang/unittests/Runtime/Ragged.cpp index 4b261b14789c..5049bc83405f 100644 --- a/flang/unittests/Runtime/Ragged.cpp +++ b/flang/unittests/Runtime/Ragged.cpp @@ -14,7 +14,7 @@ using namespace Fortran::runtime; TEST(Ragged, RaggedArrayAllocateDeallocateTest) { struct RaggedArrayHeader header; unsigned rank = 2; - int64_t *extents = new int64_t[2]; + int64_t *extents = reinterpret_cast(malloc(2 * sizeof(int64_t))); extents[0] = 10; extents[1] = 100; RaggedArrayHeader *ret = (RaggedArrayHeader *)_FortranARaggedArrayAllocate( -- GitLab From 63a5dc4aedaf8a4b26e536afb22612b4d69100bf Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Mon, 11 Mar 2024 15:35:05 +0000 Subject: [PATCH 127/953] [CodeGen] Do not pass MF into MachineRegisterInfo methods. NFC. (#84770) MachineRegisterInfo already knows the MF so there is no need to pass it in as an argument. --- .../llvm/CodeGen/MachineRegisterInfo.h | 9 ++++----- llvm/lib/CodeGen/MIRParser/MIRParser.cpp | 2 +- llvm/lib/CodeGen/MachineOutliner.cpp | 2 +- llvm/lib/CodeGen/MachineRegisterInfo.cpp | 19 ++++++++----------- llvm/lib/CodeGen/RegAllocBase.cpp | 2 +- llvm/lib/CodeGen/RegAllocFast.cpp | 2 +- llvm/lib/CodeGen/RegAllocPBQP.cpp | 2 +- llvm/lib/CodeGen/TargetLoweringBase.cpp | 2 +- .../AArch64LowerHomogeneousPrologEpilog.cpp | 2 +- .../Target/AMDGPU/SIPreAllocateWWMRegs.cpp | 2 +- llvm/tools/llvm-exegesis/lib/Assembler.cpp | 2 +- llvm/tools/llvm-reduce/ReducerWorkItem.cpp | 2 +- 12 files changed, 22 insertions(+), 26 deletions(-) diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h index 257643c109ba..3f0fc160f9ea 100644 --- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -244,14 +244,13 @@ public: bool isUpdatedCSRsInitialized() const { return IsUpdatedCSRsInitialized; } /// Returns true if a register can be used as an argument to a function. - bool isArgumentRegister(const MachineFunction &MF, MCRegister Reg) const; + bool isArgumentRegister(MCRegister Reg) const; /// Returns true if a register is a fixed register. - bool isFixedRegister(const MachineFunction &MF, MCRegister Reg) const; + bool isFixedRegister(MCRegister Reg) const; /// Returns true if a register is a general purpose register. - bool isGeneralPurposeRegister(const MachineFunction &MF, - MCRegister Reg) const; + bool isGeneralPurposeRegister(MCRegister Reg) const; /// Disables the register from the list of CSRs. /// I.e. the register will not appear as part of the CSR mask. @@ -930,7 +929,7 @@ public: /// freezeReservedRegs - Called by the register allocator to freeze the set /// of reserved registers before allocation begins. - void freezeReservedRegs(const MachineFunction&); + void freezeReservedRegs(); /// reserveReg -- Mark a register as reserved so checks like isAllocatable /// will not suggest using it. This should not be used during the middle diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp index 54f55623131b..e09318a48695 100644 --- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp @@ -574,7 +574,7 @@ MIRParserImpl::initializeMachineFunction(const yaml::MachineFunction &YamlMF, // FIXME: This is a temporary workaround until the reserved registers can be // serialized. MachineRegisterInfo &MRI = MF.getRegInfo(); - MRI.freezeReservedRegs(MF); + MRI.freezeReservedRegs(); computeFunctionProperties(MF); diff --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp index b8d3b2e30e6e..dc2f5ef15206 100644 --- a/llvm/lib/CodeGen/MachineOutliner.cpp +++ b/llvm/lib/CodeGen/MachineOutliner.cpp @@ -759,7 +759,7 @@ MachineFunction *MachineOutliner::createOutlinedFunction( MF.getProperties().set(MachineFunctionProperties::Property::NoPHIs); MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs); MF.getProperties().set(MachineFunctionProperties::Property::TracksLiveness); - MF.getRegInfo().freezeReservedRegs(MF); + MF.getRegInfo().freezeReservedRegs(); // Compute live-in set for outlined fn const MachineRegisterInfo &MRI = MF.getRegInfo(); diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp index e88487fcc9f9..55d7c8370e9c 100644 --- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp +++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp @@ -517,8 +517,8 @@ LLVM_DUMP_METHOD void MachineRegisterInfo::dumpUses(Register Reg) const { } #endif -void MachineRegisterInfo::freezeReservedRegs(const MachineFunction &MF) { - ReservedRegs = getTargetRegisterInfo()->getReservedRegs(MF); +void MachineRegisterInfo::freezeReservedRegs() { + ReservedRegs = getTargetRegisterInfo()->getReservedRegs(*MF); assert(ReservedRegs.size() == getTargetRegisterInfo()->getNumRegs() && "Invalid ReservedRegs vector from target"); } @@ -660,17 +660,14 @@ bool MachineRegisterInfo::isReservedRegUnit(unsigned Unit) const { return false; } -bool MachineRegisterInfo::isArgumentRegister(const MachineFunction &MF, - MCRegister Reg) const { - return getTargetRegisterInfo()->isArgumentRegister(MF, Reg); +bool MachineRegisterInfo::isArgumentRegister(MCRegister Reg) const { + return getTargetRegisterInfo()->isArgumentRegister(*MF, Reg); } -bool MachineRegisterInfo::isFixedRegister(const MachineFunction &MF, - MCRegister Reg) const { - return getTargetRegisterInfo()->isFixedRegister(MF, Reg); +bool MachineRegisterInfo::isFixedRegister(MCRegister Reg) const { + return getTargetRegisterInfo()->isFixedRegister(*MF, Reg); } -bool MachineRegisterInfo::isGeneralPurposeRegister(const MachineFunction &MF, - MCRegister Reg) const { - return getTargetRegisterInfo()->isGeneralPurposeRegister(MF, Reg); +bool MachineRegisterInfo::isGeneralPurposeRegister(MCRegister Reg) const { + return getTargetRegisterInfo()->isGeneralPurposeRegister(*MF, Reg); } diff --git a/llvm/lib/CodeGen/RegAllocBase.cpp b/llvm/lib/CodeGen/RegAllocBase.cpp index 900f0e9079d6..d0dec372f689 100644 --- a/llvm/lib/CodeGen/RegAllocBase.cpp +++ b/llvm/lib/CodeGen/RegAllocBase.cpp @@ -61,7 +61,7 @@ void RegAllocBase::init(VirtRegMap &vrm, LiveIntervals &lis, VRM = &vrm; LIS = &lis; Matrix = &mat; - MRI->freezeReservedRegs(vrm.getMachineFunction()); + MRI->freezeReservedRegs(); RegClassInfo.runOnMachineFunction(vrm.getMachineFunction()); } diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp index e81d47930136..6740e1f0edb4 100644 --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -1740,7 +1740,7 @@ bool RegAllocFast::runOnMachineFunction(MachineFunction &MF) { TRI = STI.getRegisterInfo(); TII = STI.getInstrInfo(); MFI = &MF.getFrameInfo(); - MRI->freezeReservedRegs(MF); + MRI->freezeReservedRegs(); RegClassInfo.runOnMachineFunction(MF); unsigned NumRegUnits = TRI->getNumRegUnits(); UsedInInstr.clear(); diff --git a/llvm/lib/CodeGen/RegAllocPBQP.cpp b/llvm/lib/CodeGen/RegAllocPBQP.cpp index b8ee5dc0f849..aea927880579 100644 --- a/llvm/lib/CodeGen/RegAllocPBQP.cpp +++ b/llvm/lib/CodeGen/RegAllocPBQP.cpp @@ -809,7 +809,7 @@ bool RegAllocPBQP::runOnMachineFunction(MachineFunction &MF) { std::unique_ptr VRegSpiller( createInlineSpiller(*this, MF, VRM, DefaultVRAI)); - MF.getRegInfo().freezeReservedRegs(MF); + MF.getRegInfo().freezeReservedRegs(); LLVM_DEBUG(dbgs() << "PBQP Register Allocating for " << MF.getName() << "\n"); diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp index a2aeb66835b2..8ac55ee6a5d0 100644 --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -2336,7 +2336,7 @@ bool TargetLoweringBase::isLoadBitCastBeneficial( } void TargetLoweringBase::finalizeLowering(MachineFunction &MF) const { - MF.getRegInfo().freezeReservedRegs(MF); + MF.getRegInfo().freezeReservedRegs(); } MachineMemOperand::Flags TargetLoweringBase::getLoadMemOperandFlags( diff --git a/llvm/lib/Target/AArch64/AArch64LowerHomogeneousPrologEpilog.cpp b/llvm/lib/Target/AArch64/AArch64LowerHomogeneousPrologEpilog.cpp index 4afc678abaca..d21aa59659a2 100644 --- a/llvm/lib/Target/AArch64/AArch64LowerHomogeneousPrologEpilog.cpp +++ b/llvm/lib/Target/AArch64/AArch64LowerHomogeneousPrologEpilog.cpp @@ -183,7 +183,7 @@ static MachineFunction &createFrameHelperMachineFunction(Module *M, MF.getProperties().reset(MachineFunctionProperties::Property::TracksLiveness); MF.getProperties().reset(MachineFunctionProperties::Property::IsSSA); MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs); - MF.getRegInfo().freezeReservedRegs(MF); + MF.getRegInfo().freezeReservedRegs(); // Create entry block. BasicBlock *EntryBB = BasicBlock::Create(C, "entry", F); diff --git a/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp b/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp index 0c57110b4eb1..398f870a9f53 100644 --- a/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp +++ b/llvm/lib/Target/AMDGPU/SIPreAllocateWWMRegs.cpp @@ -156,7 +156,7 @@ void SIPreAllocateWWMRegs::rewriteRegs(MachineFunction &MF) { RegsToRewrite.clear(); // Update the set of reserved registers to include WWM ones. - MRI->freezeReservedRegs(MF); + MRI->freezeReservedRegs(); } #ifndef NDEBUG diff --git a/llvm/tools/llvm-exegesis/lib/Assembler.cpp b/llvm/tools/llvm-exegesis/lib/Assembler.cpp index 3aad91359789..92ab3a96d91e 100644 --- a/llvm/tools/llvm-exegesis/lib/Assembler.cpp +++ b/llvm/tools/llvm-exegesis/lib/Assembler.cpp @@ -305,7 +305,7 @@ Error assembleToStream(const ExegesisTarget &ET, // prologue/epilogue pass needs the reserved registers to be frozen, this // is usually done by the SelectionDAGISel pass. - MF.getRegInfo().freezeReservedRegs(MF); + MF.getRegInfo().freezeReservedRegs(); // We create the pass manager, run the passes to populate AsmBuffer. MCContext &MCContext = MMIWP->getMMI().getContext(); diff --git a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp index 353216766717..78e6f72d7032 100644 --- a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp +++ b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp @@ -414,7 +414,7 @@ static std::unique_ptr cloneMF(MachineFunction *SrcMF, if (!DstMF->cloneInfoFrom(*SrcMF, Src2DstMBB)) report_fatal_error("target does not implement MachineFunctionInfo cloning"); - DstMRI->freezeReservedRegs(*DstMF); + DstMRI->freezeReservedRegs(); DstMF->verify(nullptr, "", /*AbortOnError=*/true); return DstMF; -- GitLab From d99bb01422a984e50043588a6bfafd2c6ce0b7e7 Mon Sep 17 00:00:00 2001 From: lntue <35648136+lntue@users.noreply.github.com> Date: Mon, 11 Mar 2024 11:38:39 -0400 Subject: [PATCH 128/953] [libc][NFC] Clean up test/src/math/differential_testing folder, renaming it to performance_testing. (#84646) Removing all the diff tests. --- libc/docs/math/index.rst | 4 +- libc/src/math/docs/add_math_function.md | 8 +- libc/test/src/math/CMakeLists.txt | 2 +- .../math/differential_testing/ceilf_diff.cpp | 16 -- .../math/differential_testing/cosf_diff.cpp | 16 -- .../math/differential_testing/exp2f_diff.cpp | 16 -- .../math/differential_testing/expf_diff.cpp | 16 -- .../math/differential_testing/expm1f_diff.cpp | 16 -- .../math/differential_testing/fabsf_diff.cpp | 16 -- .../math/differential_testing/floorf_diff.cpp | 16 -- .../math/differential_testing/fmod_diff.cpp | 16 -- .../math/differential_testing/fmodf_diff.cpp | 16 -- .../math/differential_testing/hypot_diff.cpp | 16 -- .../math/differential_testing/hypotf_diff.cpp | 16 -- .../math/differential_testing/log2f_diff.cpp | 16 -- .../math/differential_testing/logbf_diff.cpp | 16 -- .../math/differential_testing/logf_diff.cpp | 16 -- .../differential_testing/nearbyintf_diff.cpp | 16 -- .../math/differential_testing/rintf_diff.cpp | 16 -- .../math/differential_testing/roundf_diff.cpp | 16 -- .../math/differential_testing/sinf_diff.cpp | 16 -- .../math/differential_testing/sqrtf_diff.cpp | 16 -- .../math/differential_testing/truncf_diff.cpp | 16 -- .../BinaryOpSingleOutputPerf.h} | 55 +--- .../CMakeLists.txt | 268 +++--------------- .../SingleInputSingleOutputPerf.h} | 47 +-- .../Timer.cpp | 0 .../Timer.h | 6 +- .../ceilf_perf.cpp | 2 +- .../cosf_perf.cpp | 2 +- .../exp2f_perf.cpp | 2 +- .../expf_perf.cpp | 2 +- .../expm1f_perf.cpp | 2 +- .../fabsf_perf.cpp | 2 +- .../floorf_perf.cpp | 2 +- .../fmod_perf.cpp | 2 +- .../fmodf_perf.cpp | 2 +- .../hypot_perf.cpp | 2 +- .../hypotf_perf.cpp | 2 +- .../log10f_perf.cpp | 2 +- .../log1pf_perf.cpp | 2 +- .../log2f_perf.cpp | 2 +- .../logbf_perf.cpp | 2 +- .../logf_perf.cpp | 2 +- .../nearbyintf_perf.cpp | 2 +- .../rintf_perf.cpp | 2 +- .../roundf_perf.cpp | 2 +- .../sinf_perf.cpp | 2 +- .../sqrtf_perf.cpp | 2 +- .../truncf_perf.cpp | 2 +- 50 files changed, 88 insertions(+), 666 deletions(-) delete mode 100644 libc/test/src/math/differential_testing/ceilf_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/cosf_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/exp2f_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/expf_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/expm1f_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/fabsf_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/floorf_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/fmod_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/fmodf_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/hypot_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/hypotf_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/log2f_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/logbf_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/logf_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/nearbyintf_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/rintf_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/roundf_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/sinf_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/sqrtf_diff.cpp delete mode 100644 libc/test/src/math/differential_testing/truncf_diff.cpp rename libc/test/src/math/{differential_testing/BinaryOpSingleOutputDiff.h => performance_testing/BinaryOpSingleOutputPerf.h} (70%) rename libc/test/src/math/{differential_testing => performance_testing}/CMakeLists.txt (56%) rename libc/test/src/math/{differential_testing/SingleInputSingleOutputDiff.h => performance_testing/SingleInputSingleOutputPerf.h} (64%) rename libc/test/src/math/{differential_testing => performance_testing}/Timer.cpp (100%) rename libc/test/src/math/{differential_testing => performance_testing}/Timer.h (77%) rename libc/test/src/math/{differential_testing => performance_testing}/ceilf_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/cosf_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/exp2f_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/expf_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/expm1f_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/fabsf_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/floorf_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/fmod_perf.cpp (93%) rename libc/test/src/math/{differential_testing => performance_testing}/fmodf_perf.cpp (93%) rename libc/test/src/math/{differential_testing => performance_testing}/hypot_perf.cpp (93%) rename libc/test/src/math/{differential_testing => performance_testing}/hypotf_perf.cpp (93%) rename libc/test/src/math/{differential_testing => performance_testing}/log10f_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/log1pf_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/log2f_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/logbf_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/logf_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/nearbyintf_perf.cpp (93%) rename libc/test/src/math/{differential_testing => performance_testing}/rintf_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/roundf_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/sinf_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/sqrtf_perf.cpp (92%) rename libc/test/src/math/{differential_testing => performance_testing}/truncf_perf.cpp (92%) diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst index 7f2a1b2f3e28..b22ed5127c17 100644 --- a/libc/docs/math/index.rst +++ b/libc/docs/math/index.rst @@ -567,13 +567,13 @@ Legends: Performance =========== -* Simple performance testings are located at: `libc/test/src/math/differential_testing `_. +* Simple performance testings are located at: `libc/test/src/math/performance_testing `_. * We also use the *perf* tool from the `CORE-MATH `_ project: `link `_. The performance results from the CORE-MATH's perf tool are reported in the table below, using the system library as reference (such as the `GNU C library `_ - on Linux). Fmod performance results obtained with "differential_testing". + on Linux). Fmod performance results obtained with "performance_testing". +--------------+-------------------------------+-------------------------------+-------------------------------------+----------------------------------------------------------------------+ | | Reciprocal throughput (clk) | Latency (clk) | Testing ranges | Testing configuration | diff --git a/libc/src/math/docs/add_math_function.md b/libc/src/math/docs/add_math_function.md index 6f08bf037c57..f8bc8a3bdd8b 100644 --- a/libc/src/math/docs/add_math_function.md +++ b/libc/src/math/docs/add_math_function.md @@ -129,11 +129,11 @@ implementation (which is very often glibc). - Add a performance test to: ``` - libc/test/src/math/differential_testing/_perf.cpp + libc/test/src/math/performance_testing/_perf.cpp ``` - Add the corresponding entry point to: ``` - libc/test/src/math/differential_testing/CMakeLists.txt + libc/test/src/math/performance_testing/CMakeLists.txt ``` ## Build and Run @@ -189,8 +189,8 @@ implementation (which is very often glibc). - Build and Run performance test: ``` - $ ninja libc.test.src.math.differential_testing._perf - $ projects/libc/test/src/math/differential_testing/libc.test.src.math.differential_testing._perf + $ ninja libc.test.src.math.performance_testing._perf + $ projects/libc/test/src/math/performance_testing/libc.test.src.math.performance_testing._perf $ cat _perf.log ``` diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt index ad7dfdb3dfd9..b8a4aafcd97a 100644 --- a/libc/test/src/math/CMakeLists.txt +++ b/libc/test/src/math/CMakeLists.txt @@ -1721,5 +1721,5 @@ add_subdirectory(smoke) if(NOT LLVM_LIBC_FULL_BUILD) add_subdirectory(exhaustive) - add_subdirectory(differential_testing) + add_subdirectory(performance_testing) endif() diff --git a/libc/test/src/math/differential_testing/ceilf_diff.cpp b/libc/test/src/math/differential_testing/ceilf_diff.cpp deleted file mode 100644 index 7c0bb1e95a03..000000000000 --- a/libc/test/src/math/differential_testing/ceilf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for ceilf----------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/ceilf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::ceilf, ::ceilf, - "ceilf_diff.log") diff --git a/libc/test/src/math/differential_testing/cosf_diff.cpp b/libc/test/src/math/differential_testing/cosf_diff.cpp deleted file mode 100644 index ee3102384a8e..000000000000 --- a/libc/test/src/math/differential_testing/cosf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for cosf ----------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/cosf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::cosf, ::cosf, - "cosf_diff.log") diff --git a/libc/test/src/math/differential_testing/exp2f_diff.cpp b/libc/test/src/math/differential_testing/exp2f_diff.cpp deleted file mode 100644 index 545c6de320fc..000000000000 --- a/libc/test/src/math/differential_testing/exp2f_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for exp2f----------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/exp2f.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::exp2f, ::exp2f, - "exp2f_diff.log") diff --git a/libc/test/src/math/differential_testing/expf_diff.cpp b/libc/test/src/math/differential_testing/expf_diff.cpp deleted file mode 100644 index 7c2e90744bc9..000000000000 --- a/libc/test/src/math/differential_testing/expf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for expf ----------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/expf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::expf, ::expf, - "expf_diff.log") diff --git a/libc/test/src/math/differential_testing/expm1f_diff.cpp b/libc/test/src/math/differential_testing/expm1f_diff.cpp deleted file mode 100644 index 3cbd8a99690f..000000000000 --- a/libc/test/src/math/differential_testing/expm1f_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for expm1f --------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/expm1f.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::expm1f, ::expm1f, - "expm1f_diff.log") diff --git a/libc/test/src/math/differential_testing/fabsf_diff.cpp b/libc/test/src/math/differential_testing/fabsf_diff.cpp deleted file mode 100644 index 9bf9eff888fb..000000000000 --- a/libc/test/src/math/differential_testing/fabsf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for fabsf----------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/fabsf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::fabsf, ::fabsf, - "fabsf_diff.log") diff --git a/libc/test/src/math/differential_testing/floorf_diff.cpp b/libc/test/src/math/differential_testing/floorf_diff.cpp deleted file mode 100644 index 6d72927b5010..000000000000 --- a/libc/test/src/math/differential_testing/floorf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for floorf---------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/floorf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::floorf, ::floorf, - "floorf_diff.log") diff --git a/libc/test/src/math/differential_testing/fmod_diff.cpp b/libc/test/src/math/differential_testing/fmod_diff.cpp deleted file mode 100644 index 026e529c6cae..000000000000 --- a/libc/test/src/math/differential_testing/fmod_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for fmod ----------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "BinaryOpSingleOutputDiff.h" - -#include "src/math/fmod.h" - -#include - -BINARY_OP_SINGLE_OUTPUT_DIFF(double, LIBC_NAMESPACE::fmod, ::fmod, - "fmod_diff.log") diff --git a/libc/test/src/math/differential_testing/fmodf_diff.cpp b/libc/test/src/math/differential_testing/fmodf_diff.cpp deleted file mode 100644 index 7029b1ee42cd..000000000000 --- a/libc/test/src/math/differential_testing/fmodf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for fmodf ---------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "BinaryOpSingleOutputDiff.h" - -#include "src/math/fmodf.h" - -#include - -BINARY_OP_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::fmodf, ::fmodf, - "fmodf_diff.log") diff --git a/libc/test/src/math/differential_testing/hypot_diff.cpp b/libc/test/src/math/differential_testing/hypot_diff.cpp deleted file mode 100644 index c61e589bdb2d..000000000000 --- a/libc/test/src/math/differential_testing/hypot_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for hypot ---------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "BinaryOpSingleOutputDiff.h" - -#include "src/math/hypot.h" - -#include - -BINARY_OP_SINGLE_OUTPUT_DIFF(double, LIBC_NAMESPACE::hypot, ::hypot, - "hypot_diff.log") diff --git a/libc/test/src/math/differential_testing/hypotf_diff.cpp b/libc/test/src/math/differential_testing/hypotf_diff.cpp deleted file mode 100644 index d1c70fc2b6ed..000000000000 --- a/libc/test/src/math/differential_testing/hypotf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for hypotf --------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "BinaryOpSingleOutputDiff.h" - -#include "src/math/hypotf.h" - -#include - -BINARY_OP_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::hypotf, ::hypotf, - "hypotf_diff.log") diff --git a/libc/test/src/math/differential_testing/log2f_diff.cpp b/libc/test/src/math/differential_testing/log2f_diff.cpp deleted file mode 100644 index aef431dce487..000000000000 --- a/libc/test/src/math/differential_testing/log2f_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for log2f ---------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/log2f.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::log2f, ::log2f, - "log2f_diff.log") diff --git a/libc/test/src/math/differential_testing/logbf_diff.cpp b/libc/test/src/math/differential_testing/logbf_diff.cpp deleted file mode 100644 index 37441eb40a4d..000000000000 --- a/libc/test/src/math/differential_testing/logbf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for logbf----------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/logbf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::logbf, ::logbf, - "logbf_diff.log") diff --git a/libc/test/src/math/differential_testing/logf_diff.cpp b/libc/test/src/math/differential_testing/logf_diff.cpp deleted file mode 100644 index 4ed1307f7120..000000000000 --- a/libc/test/src/math/differential_testing/logf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for logf ----------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/logf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::logf, ::logf, - "logf_diff.log") diff --git a/libc/test/src/math/differential_testing/nearbyintf_diff.cpp b/libc/test/src/math/differential_testing/nearbyintf_diff.cpp deleted file mode 100644 index 14200116883d..000000000000 --- a/libc/test/src/math/differential_testing/nearbyintf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for nearbyintf-----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/nearbyintf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::nearbyintf, ::nearbyintf, - "nearbyintf_diff.log") diff --git a/libc/test/src/math/differential_testing/rintf_diff.cpp b/libc/test/src/math/differential_testing/rintf_diff.cpp deleted file mode 100644 index e60f66085e5d..000000000000 --- a/libc/test/src/math/differential_testing/rintf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for rintf----------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/rintf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::rintf, ::rintf, - "rintf_diff.log") diff --git a/libc/test/src/math/differential_testing/roundf_diff.cpp b/libc/test/src/math/differential_testing/roundf_diff.cpp deleted file mode 100644 index e1401a01af35..000000000000 --- a/libc/test/src/math/differential_testing/roundf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for roundf---------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/roundf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::roundf, ::roundf, - "roundf_diff.log") diff --git a/libc/test/src/math/differential_testing/sinf_diff.cpp b/libc/test/src/math/differential_testing/sinf_diff.cpp deleted file mode 100644 index cb4557e6796b..000000000000 --- a/libc/test/src/math/differential_testing/sinf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for sinf ----------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/sinf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::sinf, ::sinf, - "sinf_diff.log") diff --git a/libc/test/src/math/differential_testing/sqrtf_diff.cpp b/libc/test/src/math/differential_testing/sqrtf_diff.cpp deleted file mode 100644 index 22ddeaac9caf..000000000000 --- a/libc/test/src/math/differential_testing/sqrtf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for sqrtf----------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/sqrtf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::sqrtf, ::sqrtf, - "sqrtf_diff.log") diff --git a/libc/test/src/math/differential_testing/truncf_diff.cpp b/libc/test/src/math/differential_testing/truncf_diff.cpp deleted file mode 100644 index 7f6ac4e6a926..000000000000 --- a/libc/test/src/math/differential_testing/truncf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for truncf---------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/truncf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::truncf, ::truncf, - "truncf_diff.log") diff --git a/libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h b/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h similarity index 70% rename from libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h rename to libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h index 48572e78e515..68d37b46b77c 100644 --- a/libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h +++ b/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h @@ -7,14 +7,14 @@ //===----------------------------------------------------------------------===// #include "src/__support/FPUtil/FPBits.h" -#include "test/src/math/differential_testing/Timer.h" +#include "test/src/math/performance_testing/Timer.h" #include namespace LIBC_NAMESPACE { namespace testing { -template class BinaryOpSingleOutputDiff { +template class BinaryOpSingleOutputPerf { using FPBits = fputil::FPBits; using StorageType = typename FPBits::StorageType; static constexpr StorageType UIntMax = @@ -23,40 +23,6 @@ template class BinaryOpSingleOutputDiff { public: typedef T Func(T, T); - static uint64_t run_diff_in_range(Func myFunc, Func otherFunc, - StorageType startingBit, - StorageType endingBit, StorageType N, - std::ofstream &log) { - uint64_t result = 0; - if (endingBit < startingBit) { - return result; - } - - StorageType step = (endingBit - startingBit) / N; - for (StorageType bitsX = startingBit, bitsY = endingBit;; - bitsX += step, bitsY -= step) { - T x = T(FPBits(bitsX)); - T y = T(FPBits(bitsY)); - FPBits myBits = FPBits(myFunc(x, y)); - FPBits otherBits = FPBits(otherFunc(x, y)); - if (myBits.uintval() != otherBits.uintval()) { - result++; - log << " Input: " << bitsX << ", " << bitsY << " (" << x << ", " - << y << ")\n" - << " My result: " << myBits.uintval() << " (" << myBits.get_val() - << ")\n" - << "Other result: " << otherBits.uintval() << " (" - << otherBits.get_val() << ")\n" - << '\n'; - } - - if (endingBit - bitsX < step) { - break; - } - } - return result; - } - static void run_perf_in_range(Func myFunc, Func otherFunc, StorageType startingBit, StorageType endingBit, StorageType N, std::ofstream &log) { @@ -69,8 +35,8 @@ public: StorageType step = (endingBit - startingBit) / N; for (StorageType bitsX = startingBit, bitsY = endingBit;; bitsX += step, bitsY -= step) { - T x = T(FPBits(bitsX)); - T y = T(FPBits(bitsY)); + T x = FPBits(bitsX).get_val(); + T y = FPBits(bitsY).get_val(); result = func(x, y); if (endingBit - bitsX < step) { break; @@ -110,12 +76,12 @@ public: log << " Performance tests with inputs in denormal range:\n"; run_perf_in_range(myFunc, otherFunc, /* startingBit= */ StorageType(0), /* endingBit= */ FPBits::max_subnormal().uintval(), - 1'000'001, log); + 10'000'001, log); log << "\n Performance tests with inputs in normal range:\n"; run_perf_in_range(myFunc, otherFunc, /* startingBit= */ FPBits::min_normal().uintval(), /* endingBit= */ FPBits::max_normal().uintval(), - 100'000'001, log); + 10'000'001, log); log << "\n Performance tests with inputs in normal range with exponents " "close to each other:\n"; run_perf_in_range( @@ -148,16 +114,9 @@ public: } // namespace testing } // namespace LIBC_NAMESPACE -#define BINARY_OP_SINGLE_OUTPUT_DIFF(T, myFunc, otherFunc, filename) \ - int main() { \ - LIBC_NAMESPACE::testing::BinaryOpSingleOutputDiff::run_diff( \ - &myFunc, &otherFunc, filename); \ - return 0; \ - } - #define BINARY_OP_SINGLE_OUTPUT_PERF(T, myFunc, otherFunc, filename) \ int main() { \ - LIBC_NAMESPACE::testing::BinaryOpSingleOutputDiff::run_perf( \ + LIBC_NAMESPACE::testing::BinaryOpSingleOutputPerf::run_perf( \ &myFunc, &otherFunc, filename); \ return 0; \ } diff --git a/libc/test/src/math/differential_testing/CMakeLists.txt b/libc/test/src/math/performance_testing/CMakeLists.txt similarity index 56% rename from libc/test/src/math/differential_testing/CMakeLists.txt rename to libc/test/src/math/performance_testing/CMakeLists.txt index 878f81f1d573..d20c2eb303a7 100644 --- a/libc/test/src/math/differential_testing/CMakeLists.txt +++ b/libc/test/src/math/performance_testing/CMakeLists.txt @@ -4,28 +4,28 @@ add_library( Timer.h ) -# A convenience target to build all differential tests. -add_custom_target(libc-math-differential-tests) +# A convenience target to build all performance tests. +add_custom_target(libc-math-performance-tests) -function(add_diff_binary target_name) +function(add_perf_binary target_name) cmake_parse_arguments( - "DIFF" + "PERF" "" # No optional arguments "SUITE;CXX_STANDARD" # Single value arguments "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS" # Multi-value arguments ${ARGN} ) - if(NOT DIFF_SRCS) - message(FATAL_ERROR "'add_diff_binary' target requires a SRCS list of .cpp " + if(NOT PERF_SRCS) + message(FATAL_ERROR "'add_perf_binary' target requires a SRCS list of .cpp " "files.") endif() - if(NOT DIFF_DEPENDS) - message(FATAL_ERROR "'add_diff_binary' target requires a DEPENDS list of " + if(NOT PERF_DEPENDS) + message(FATAL_ERROR "'add_perf_binary' target requires a DEPENDS list of " "'add_entrypoint_object' targets.") endif() get_fq_target_name(${target_name} fq_target_name) - get_fq_deps_list(fq_deps_list ${DIFF_DEPENDS}) + get_fq_deps_list(fq_deps_list ${PERF_DEPENDS}) get_object_files_for_test( link_object_files skipped_entrypoints_list ${fq_deps_list}) if(skipped_entrypoints_list) @@ -40,18 +40,18 @@ function(add_diff_binary target_name) add_executable( ${fq_target_name} EXCLUDE_FROM_ALL - ${DIFF_SRCS} - ${DIFF_HDRS} + ${PERF_SRCS} + ${PERF_HDRS} ) target_include_directories( ${fq_target_name} PRIVATE ${LIBC_SOURCE_DIR} ) - if(DIFF_COMPILE_OPTIONS) + if(PERF_COMPILE_OPTIONS) target_compile_options( ${fq_target_name} - PRIVATE ${DIFF_COMPILE_OPTIONS} + PRIVATE ${PERF_COMPILE_OPTIONS} ) endif() @@ -62,11 +62,11 @@ function(add_diff_binary target_name) set_target_properties(${fq_target_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - if(DIFF_CXX_STANDARD) + if(PERF_CXX_STANDARD) set_target_properties( ${fq_target_name} PROPERTIES - CXX_STANDARD ${DIFF_CXX_STANDARD} + CXX_STANDARD ${PERF_CXX_STANDARD} ) endif() @@ -75,31 +75,22 @@ function(add_diff_binary target_name) libc.src.__support.FPUtil.fp_bits ${fq_deps_list} ) - add_dependencies(libc-math-differential-tests ${fq_target_name}) + add_dependencies(libc-math-performance-tests ${fq_target_name}) endfunction() add_header_library( single_input_single_output_diff HDRS - SingleInputSingleOutputDiff.h + SingleInputSingleOutputPerf.h ) add_header_library( binary_op_single_output_diff HDRS - BinaryOpSingleOutputDiff.h + BinaryOpSingleOutputPerf.h ) -add_diff_binary( - sinf_diff - SRCS - sinf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.sinf -) - -add_diff_binary( +add_perf_binary( sinf_perf SRCS sinf_perf.cpp @@ -110,16 +101,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - cosf_diff - SRCS - cosf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.cosf -) - -add_diff_binary( +add_perf_binary( cosf_perf SRCS cosf_perf.cpp @@ -130,16 +112,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - expm1f_diff - SRCS - expm1f_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.expm1f -) - -add_diff_binary( +add_perf_binary( expm1f_perf SRCS expm1f_perf.cpp @@ -150,16 +123,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - ceilf_diff - SRCS - ceilf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.ceilf -) - -add_diff_binary( +add_perf_binary( ceilf_perf SRCS ceilf_perf.cpp @@ -170,16 +134,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - exp2f_diff - SRCS - exp2f_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.exp2f -) - -add_diff_binary( +add_perf_binary( exp2f_perf SRCS exp2f_perf.cpp @@ -190,16 +145,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - expf_diff - SRCS - expf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.expf -) - -add_diff_binary( +add_perf_binary( expf_perf SRCS expf_perf.cpp @@ -210,16 +156,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - fabsf_diff - SRCS - fabsf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.fabsf -) - -add_diff_binary( +add_perf_binary( fabsf_perf SRCS fabsf_perf.cpp @@ -230,16 +167,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - floorf_diff - SRCS - floorf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.floorf -) - -add_diff_binary( +add_perf_binary( floorf_perf SRCS floorf_perf.cpp @@ -250,7 +178,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( +add_perf_binary( log10f_perf SRCS log10f_perf.cpp @@ -261,7 +189,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( +add_perf_binary( log1pf_perf SRCS log1pf_perf.cpp @@ -272,18 +200,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - log2f_diff - SRCS - log2f_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.log2f - COMPILE_OPTIONS - -fno-builtin -) - -add_diff_binary( +add_perf_binary( log2f_perf SRCS log2f_perf.cpp @@ -294,18 +211,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - logf_diff - SRCS - logf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.logf - COMPILE_OPTIONS - -fno-builtin -) - -add_diff_binary( +add_perf_binary( logf_perf SRCS logf_perf.cpp @@ -316,16 +222,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - logbf_diff - SRCS - logbf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.logbf -) - -add_diff_binary( +add_perf_binary( logbf_perf SRCS logbf_perf.cpp @@ -336,16 +233,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - nearbyintf_diff - SRCS - nearbyintf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.nearbyintf -) - -add_diff_binary( +add_perf_binary( nearbyintf_perf SRCS nearbyintf_perf.cpp @@ -356,16 +244,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - rintf_diff - SRCS - rintf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.rintf -) - -add_diff_binary( +add_perf_binary( rintf_perf SRCS rintf_perf.cpp @@ -376,16 +255,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - roundf_diff - SRCS - roundf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.roundf -) - -add_diff_binary( +add_perf_binary( roundf_perf SRCS roundf_perf.cpp @@ -396,16 +266,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - sqrtf_diff - SRCS - sqrtf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.sqrtf -) - -add_diff_binary( +add_perf_binary( sqrtf_perf SRCS sqrtf_perf.cpp @@ -416,16 +277,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - truncf_diff - SRCS - truncf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.truncf -) - -add_diff_binary( +add_perf_binary( truncf_perf SRCS truncf_perf.cpp @@ -436,18 +288,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - hypotf_diff - SRCS - hypotf_diff.cpp - DEPENDS - .binary_op_single_output_diff - libc.src.math.hypotf - COMPILE_OPTIONS - -fno-builtin -) - -add_diff_binary( +add_perf_binary( hypotf_perf SRCS hypotf_perf.cpp @@ -458,18 +299,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - hypot_diff - SRCS - hypot_diff.cpp - DEPENDS - .binary_op_single_output_diff - libc.src.math.hypot - COMPILE_OPTIONS - -fno-builtin -) - -add_diff_binary( +add_perf_binary( hypot_perf SRCS hypot_perf.cpp @@ -480,16 +310,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - fmodf_diff - SRCS - fmodf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.fmodf -) - -add_diff_binary( +add_perf_binary( fmodf_perf SRCS fmodf_perf.cpp @@ -500,16 +321,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - fmod_diff - SRCS - fmod_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.fmod -) - -add_diff_binary( +add_perf_binary( fmod_perf SRCS fmod_perf.cpp diff --git a/libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h b/libc/test/src/math/performance_testing/SingleInputSingleOutputPerf.h similarity index 64% rename from libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h rename to libc/test/src/math/performance_testing/SingleInputSingleOutputPerf.h index 5e8310e889dc..b5b38313a69c 100644 --- a/libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h +++ b/libc/test/src/math/performance_testing/SingleInputSingleOutputPerf.h @@ -7,14 +7,14 @@ //===----------------------------------------------------------------------===// #include "src/__support/FPUtil/FPBits.h" -#include "test/src/math/differential_testing/Timer.h" +#include "test/src/math/performance_testing/Timer.h" #include namespace LIBC_NAMESPACE { namespace testing { -template class SingleInputSingleOutputDiff { +template class SingleInputSingleOutputPerf { using FPBits = fputil::FPBits; using StorageType = typename FPBits::StorageType; static constexpr StorageType UIntMax = @@ -23,40 +23,18 @@ template class SingleInputSingleOutputDiff { public: typedef T Func(T); - static void runDiff(Func myFunc, Func otherFunc, const char *logFile) { - StorageType diffCount = 0; - std::ofstream log(logFile); - log << "Starting diff for values from 0 to " << UIntMax << '\n' - << "Only differing results will be logged.\n\n"; - for (StorageType bits = 0;; ++bits) { - T x = T(FPBits(bits)); - T myResult = myFunc(x); - T otherResult = otherFunc(x); - StorageType myBits = FPBits(myResult).uintval(); - StorageType otherBits = FPBits(otherResult).uintval(); - if (myBits != otherBits) { - ++diffCount; - log << " Input: " << bits << " (" << x << ")\n" - << " My result: " << myBits << " (" << myResult << ")\n" - << "Other result: " << otherBits << " (" << otherResult << ")\n" - << '\n'; - } - if (bits == UIntMax) - break; - } - log << "Total number of differing results: " << diffCount << '\n'; - } - static void runPerfInRange(Func myFunc, Func otherFunc, StorageType startingBit, StorageType endingBit, std::ofstream &log) { auto runner = [=](Func func) { + constexpr StorageType N = 10'010'001; + StorageType step = (endingBit - startingBit) / N; + if (step == 0) + step = 1; volatile T result; - for (StorageType bits = startingBit;; ++bits) { - T x = T(FPBits(bits)); + for (StorageType bits = startingBit; bits < endingBit; bits += step) { + T x = FPBits(bits).get_val(); result = func(x); - if (bits == endingBit) - break; } }; @@ -104,16 +82,9 @@ public: } // namespace testing } // namespace LIBC_NAMESPACE -#define SINGLE_INPUT_SINGLE_OUTPUT_DIFF(T, myFunc, otherFunc, filename) \ - int main() { \ - LIBC_NAMESPACE::testing::SingleInputSingleOutputDiff::runDiff( \ - &myFunc, &otherFunc, filename); \ - return 0; \ - } - #define SINGLE_INPUT_SINGLE_OUTPUT_PERF(T, myFunc, otherFunc, filename) \ int main() { \ - LIBC_NAMESPACE::testing::SingleInputSingleOutputDiff::runPerf( \ + LIBC_NAMESPACE::testing::SingleInputSingleOutputPerf::runPerf( \ &myFunc, &otherFunc, filename); \ return 0; \ } diff --git a/libc/test/src/math/differential_testing/Timer.cpp b/libc/test/src/math/performance_testing/Timer.cpp similarity index 100% rename from libc/test/src/math/differential_testing/Timer.cpp rename to libc/test/src/math/performance_testing/Timer.cpp diff --git a/libc/test/src/math/differential_testing/Timer.h b/libc/test/src/math/performance_testing/Timer.h similarity index 77% rename from libc/test/src/math/differential_testing/Timer.h rename to libc/test/src/math/performance_testing/Timer.h index 0d9518c37d9e..2327ede260ab 100644 --- a/libc/test/src/math/differential_testing/Timer.h +++ b/libc/test/src/math/performance_testing/Timer.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_TEST_SRC_MATH_DIFFERENTIAL_TESTING_TIMER_H -#define LLVM_LIBC_TEST_SRC_MATH_DIFFERENTIAL_TESTING_TIMER_H +#ifndef LLVM_LIBC_TEST_SRC_MATH_PERFORMACE_TESTING_TIMER_H +#define LLVM_LIBC_TEST_SRC_MATH_PERFORMACE_TESTING_TIMER_H #include @@ -30,4 +30,4 @@ public: } // namespace testing } // namespace LIBC_NAMESPACE -#endif // LLVM_LIBC_TEST_SRC_MATH_DIFFERENTIAL_TESTING_TIMER_H +#endif // LLVM_LIBC_TEST_SRC_MATH_PERFORMANCE_TESTING_TIMER_H diff --git a/libc/test/src/math/differential_testing/ceilf_perf.cpp b/libc/test/src/math/performance_testing/ceilf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/ceilf_perf.cpp rename to libc/test/src/math/performance_testing/ceilf_perf.cpp index c304231e0678..04e96f6fb2dc 100644 --- a/libc/test/src/math/differential_testing/ceilf_perf.cpp +++ b/libc/test/src/math/performance_testing/ceilf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/ceilf.h" diff --git a/libc/test/src/math/differential_testing/cosf_perf.cpp b/libc/test/src/math/performance_testing/cosf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/cosf_perf.cpp rename to libc/test/src/math/performance_testing/cosf_perf.cpp index 981a94133b80..1501b8bf2540 100644 --- a/libc/test/src/math/differential_testing/cosf_perf.cpp +++ b/libc/test/src/math/performance_testing/cosf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/cosf.h" diff --git a/libc/test/src/math/differential_testing/exp2f_perf.cpp b/libc/test/src/math/performance_testing/exp2f_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/exp2f_perf.cpp rename to libc/test/src/math/performance_testing/exp2f_perf.cpp index 4aae5220e6a5..19a70ac6569a 100644 --- a/libc/test/src/math/differential_testing/exp2f_perf.cpp +++ b/libc/test/src/math/performance_testing/exp2f_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/exp2f.h" diff --git a/libc/test/src/math/differential_testing/expf_perf.cpp b/libc/test/src/math/performance_testing/expf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/expf_perf.cpp rename to libc/test/src/math/performance_testing/expf_perf.cpp index c34173b21b4f..4b743514023d 100644 --- a/libc/test/src/math/differential_testing/expf_perf.cpp +++ b/libc/test/src/math/performance_testing/expf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/expf.h" diff --git a/libc/test/src/math/differential_testing/expm1f_perf.cpp b/libc/test/src/math/performance_testing/expm1f_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/expm1f_perf.cpp rename to libc/test/src/math/performance_testing/expm1f_perf.cpp index 3c25ef81d480..128ab351d86d 100644 --- a/libc/test/src/math/differential_testing/expm1f_perf.cpp +++ b/libc/test/src/math/performance_testing/expm1f_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/expm1f.h" diff --git a/libc/test/src/math/differential_testing/fabsf_perf.cpp b/libc/test/src/math/performance_testing/fabsf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/fabsf_perf.cpp rename to libc/test/src/math/performance_testing/fabsf_perf.cpp index f9f9cea72c6d..b6c6add75d23 100644 --- a/libc/test/src/math/differential_testing/fabsf_perf.cpp +++ b/libc/test/src/math/performance_testing/fabsf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/fabsf.h" diff --git a/libc/test/src/math/differential_testing/floorf_perf.cpp b/libc/test/src/math/performance_testing/floorf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/floorf_perf.cpp rename to libc/test/src/math/performance_testing/floorf_perf.cpp index abd1cd7885ff..0f1087b3c823 100644 --- a/libc/test/src/math/differential_testing/floorf_perf.cpp +++ b/libc/test/src/math/performance_testing/floorf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/floorf.h" diff --git a/libc/test/src/math/differential_testing/fmod_perf.cpp b/libc/test/src/math/performance_testing/fmod_perf.cpp similarity index 93% rename from libc/test/src/math/differential_testing/fmod_perf.cpp rename to libc/test/src/math/performance_testing/fmod_perf.cpp index 219ee7860a24..fa9b4c6b4128 100644 --- a/libc/test/src/math/differential_testing/fmod_perf.cpp +++ b/libc/test/src/math/performance_testing/fmod_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "BinaryOpSingleOutputDiff.h" +#include "BinaryOpSingleOutputPerf.h" #include "src/math/fmod.h" diff --git a/libc/test/src/math/differential_testing/fmodf_perf.cpp b/libc/test/src/math/performance_testing/fmodf_perf.cpp similarity index 93% rename from libc/test/src/math/differential_testing/fmodf_perf.cpp rename to libc/test/src/math/performance_testing/fmodf_perf.cpp index c2927bb1ea9d..f13f02e2439d 100644 --- a/libc/test/src/math/differential_testing/fmodf_perf.cpp +++ b/libc/test/src/math/performance_testing/fmodf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "BinaryOpSingleOutputDiff.h" +#include "BinaryOpSingleOutputPerf.h" #include "src/math/fmodf.h" diff --git a/libc/test/src/math/differential_testing/hypot_perf.cpp b/libc/test/src/math/performance_testing/hypot_perf.cpp similarity index 93% rename from libc/test/src/math/differential_testing/hypot_perf.cpp rename to libc/test/src/math/performance_testing/hypot_perf.cpp index 01a72e6fbc3d..393697b75403 100644 --- a/libc/test/src/math/differential_testing/hypot_perf.cpp +++ b/libc/test/src/math/performance_testing/hypot_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "BinaryOpSingleOutputDiff.h" +#include "BinaryOpSingleOutputPerf.h" #include "src/math/hypot.h" diff --git a/libc/test/src/math/differential_testing/hypotf_perf.cpp b/libc/test/src/math/performance_testing/hypotf_perf.cpp similarity index 93% rename from libc/test/src/math/differential_testing/hypotf_perf.cpp rename to libc/test/src/math/performance_testing/hypotf_perf.cpp index ed57b186f889..f711729377da 100644 --- a/libc/test/src/math/differential_testing/hypotf_perf.cpp +++ b/libc/test/src/math/performance_testing/hypotf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "BinaryOpSingleOutputDiff.h" +#include "BinaryOpSingleOutputPerf.h" #include "src/math/hypotf.h" diff --git a/libc/test/src/math/differential_testing/log10f_perf.cpp b/libc/test/src/math/performance_testing/log10f_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/log10f_perf.cpp rename to libc/test/src/math/performance_testing/log10f_perf.cpp index 60c1161a31cf..32a31b932528 100644 --- a/libc/test/src/math/differential_testing/log10f_perf.cpp +++ b/libc/test/src/math/performance_testing/log10f_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/log10f.h" diff --git a/libc/test/src/math/differential_testing/log1pf_perf.cpp b/libc/test/src/math/performance_testing/log1pf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/log1pf_perf.cpp rename to libc/test/src/math/performance_testing/log1pf_perf.cpp index 5cd523d82184..18c168423b87 100644 --- a/libc/test/src/math/differential_testing/log1pf_perf.cpp +++ b/libc/test/src/math/performance_testing/log1pf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/log1pf.h" diff --git a/libc/test/src/math/differential_testing/log2f_perf.cpp b/libc/test/src/math/performance_testing/log2f_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/log2f_perf.cpp rename to libc/test/src/math/performance_testing/log2f_perf.cpp index ee899394c421..c4c4dbf4d9f5 100644 --- a/libc/test/src/math/differential_testing/log2f_perf.cpp +++ b/libc/test/src/math/performance_testing/log2f_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/log2f.h" diff --git a/libc/test/src/math/differential_testing/logbf_perf.cpp b/libc/test/src/math/performance_testing/logbf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/logbf_perf.cpp rename to libc/test/src/math/performance_testing/logbf_perf.cpp index 89d5bd13f931..eefd64b8ae91 100644 --- a/libc/test/src/math/differential_testing/logbf_perf.cpp +++ b/libc/test/src/math/performance_testing/logbf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/logbf.h" diff --git a/libc/test/src/math/differential_testing/logf_perf.cpp b/libc/test/src/math/performance_testing/logf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/logf_perf.cpp rename to libc/test/src/math/performance_testing/logf_perf.cpp index f1b3f986bd40..53f4f50e09ef 100644 --- a/libc/test/src/math/differential_testing/logf_perf.cpp +++ b/libc/test/src/math/performance_testing/logf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/logf.h" diff --git a/libc/test/src/math/differential_testing/nearbyintf_perf.cpp b/libc/test/src/math/performance_testing/nearbyintf_perf.cpp similarity index 93% rename from libc/test/src/math/differential_testing/nearbyintf_perf.cpp rename to libc/test/src/math/performance_testing/nearbyintf_perf.cpp index 9c5736fb4ab0..ae708dd21324 100644 --- a/libc/test/src/math/differential_testing/nearbyintf_perf.cpp +++ b/libc/test/src/math/performance_testing/nearbyintf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/nearbyintf.h" diff --git a/libc/test/src/math/differential_testing/rintf_perf.cpp b/libc/test/src/math/performance_testing/rintf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/rintf_perf.cpp rename to libc/test/src/math/performance_testing/rintf_perf.cpp index 432e5da77f37..6347ac9149af 100644 --- a/libc/test/src/math/differential_testing/rintf_perf.cpp +++ b/libc/test/src/math/performance_testing/rintf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/rintf.h" diff --git a/libc/test/src/math/differential_testing/roundf_perf.cpp b/libc/test/src/math/performance_testing/roundf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/roundf_perf.cpp rename to libc/test/src/math/performance_testing/roundf_perf.cpp index 091c7b2b8680..36becacba07c 100644 --- a/libc/test/src/math/differential_testing/roundf_perf.cpp +++ b/libc/test/src/math/performance_testing/roundf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/roundf.h" diff --git a/libc/test/src/math/differential_testing/sinf_perf.cpp b/libc/test/src/math/performance_testing/sinf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/sinf_perf.cpp rename to libc/test/src/math/performance_testing/sinf_perf.cpp index 7247bca2853d..43ba60e1ef76 100644 --- a/libc/test/src/math/differential_testing/sinf_perf.cpp +++ b/libc/test/src/math/performance_testing/sinf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/sinf.h" diff --git a/libc/test/src/math/differential_testing/sqrtf_perf.cpp b/libc/test/src/math/performance_testing/sqrtf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/sqrtf_perf.cpp rename to libc/test/src/math/performance_testing/sqrtf_perf.cpp index 5ae586ba3126..71325518533b 100644 --- a/libc/test/src/math/differential_testing/sqrtf_perf.cpp +++ b/libc/test/src/math/performance_testing/sqrtf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/sqrtf.h" diff --git a/libc/test/src/math/differential_testing/truncf_perf.cpp b/libc/test/src/math/performance_testing/truncf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/truncf_perf.cpp rename to libc/test/src/math/performance_testing/truncf_perf.cpp index e07db1320fdd..ff74c6b4eb64 100644 --- a/libc/test/src/math/differential_testing/truncf_perf.cpp +++ b/libc/test/src/math/performance_testing/truncf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/truncf.h" -- GitLab From 818af71b72219d149174faf9420dfc00f2c03470 Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Mon, 11 Mar 2024 16:40:57 +0100 Subject: [PATCH 129/953] [mlir][emitc] Add ArrayType (#83386) This models a one or multi-dimensional C/C++ array. The type implements the `ShapedTypeInterface` and prints similar to memref/tensor: ``` %arg0: !emitc.array<1xf32>, %arg1: !emitc.array<10x20x30xi32>, %arg2: !emitc.array<30x!emitc.ptr>, %arg3: !emitc.array<30x!emitc.opaque<"int">> ``` It can be translated to a C array type when used as function parameter or as `emitc.variable` type. --- .../mlir/Dialect/EmitC/IR/EmitCTypes.td | 52 ++++++++++++- mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 73 +++++++++++++++++++ mlir/lib/Target/Cpp/TranslateToCpp.cpp | 54 ++++++++++++-- mlir/test/Dialect/EmitC/invalid_ops.mlir | 32 ++++++++ mlir/test/Dialect/EmitC/invalid_types.mlir | 70 ++++++++++++++++++ mlir/test/Dialect/EmitC/types.mlir | 14 ++++ mlir/test/Target/Cpp/common-cpp.mlir | 5 ++ mlir/test/Target/Cpp/declare_func.mlir | 8 ++ mlir/test/Target/Cpp/func.mlir | 3 + mlir/test/Target/Cpp/invalid.mlir | 28 +++++++ .../Cpp/invalid_declare_variables_at_top.mlir | 9 +++ mlir/test/Target/Cpp/variable.mlir | 6 ++ 12 files changed, 346 insertions(+), 8 deletions(-) create mode 100644 mlir/test/Target/Cpp/invalid_declare_variables_at_top.mlir diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td index 8818c049ed77..1ff41022eba8 100644 --- a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td +++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td @@ -16,16 +16,64 @@ include "mlir/IR/AttrTypeBase.td" include "mlir/Dialect/EmitC/IR/EmitCBase.td" +include "mlir/IR/BuiltinTypeInterfaces.td" //===----------------------------------------------------------------------===// // EmitC type definitions //===----------------------------------------------------------------------===// -class EmitC_Type - : TypeDef { +class EmitC_Type traits = []> + : TypeDef { let mnemonic = typeMnemonic; } +def EmitC_ArrayType : EmitC_Type<"Array", "array", [ShapedTypeInterface]> { + let summary = "EmitC array type"; + + let description = [{ + An array data type. + + Example: + + ```mlir + // Array emitted as `int32_t[10]` + !emitc.array<10xi32> + // Array emitted as `float[10][20]` + !emitc.ptr<10x20xf32> + ``` + }]; + + let parameters = (ins + ArrayRefParameter<"int64_t">:$shape, + "Type":$elementType + ); + + let builders = [ + TypeBuilderWithInferredContext<(ins + "ArrayRef":$shape, + "Type":$elementType + ), [{ + return $_get(elementType.getContext(), shape, elementType); + }]> + ]; + let extraClassDeclaration = [{ + /// Returns if this type is ranked (always true). + bool hasRank() const { return true; } + + /// Clone this array type with the given shape and element type. If the + /// provided shape is `std::nullopt`, the current shape of the type is used. + ArrayType cloneWith(std::optional> shape, + Type elementType) const; + + static bool isValidElementType(Type type) { + return type.isIntOrIndexOrFloat() || + llvm::isa(type); + } + }]; + let genVerifyDecl = 1; + let hasCustomAssemblyFormat = 1; +} + def EmitC_OpaqueType : EmitC_Type<"Opaque", "opaque"> { let summary = "EmitC opaque type"; diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp index 07ee1d394287..9426bbbe2370 100644 --- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp +++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp @@ -141,6 +141,8 @@ LogicalResult emitc::AssignOp::verify() { return emitOpError() << "requires value's type (" << value.getType() << ") to match variable's type (" << variable.getType() << ")"; + if (isa(variable.getType())) + return emitOpError() << "cannot assign to array type"; return success(); } @@ -192,6 +194,11 @@ LogicalResult emitc::CallOpaqueOp::verify() { } } + if (llvm::any_of(getResultTypes(), + [](Type type) { return isa(type); })) { + return emitOpError() << "cannot return array type"; + } + return success(); } @@ -456,6 +463,9 @@ LogicalResult FuncOp::verify() { return emitOpError("requires zero or exactly one result, but has ") << getNumResults(); + if (getNumResults() == 1 && isa(getResultTypes()[0])) + return emitOpError("cannot return array type"); + return success(); } @@ -763,6 +773,69 @@ LogicalResult emitc::YieldOp::verify() { #define GET_TYPEDEF_CLASSES #include "mlir/Dialect/EmitC/IR/EmitCTypes.cpp.inc" +//===----------------------------------------------------------------------===// +// ArrayType +//===----------------------------------------------------------------------===// + +Type emitc::ArrayType::parse(AsmParser &parser) { + if (parser.parseLess()) + return Type(); + + SmallVector dimensions; + if (parser.parseDimensionList(dimensions, /*allowDynamic=*/false, + /*withTrailingX=*/true)) + return Type(); + // Parse the element type. + auto typeLoc = parser.getCurrentLocation(); + Type elementType; + if (parser.parseType(elementType)) + return Type(); + + // Check that array is formed from allowed types. + if (!isValidElementType(elementType)) + return parser.emitError(typeLoc, "invalid array element type"), Type(); + if (parser.parseGreater()) + return Type(); + return parser.getChecked(dimensions, elementType); +} + +void emitc::ArrayType::print(AsmPrinter &printer) const { + printer << "<"; + for (int64_t dim : getShape()) { + printer << dim << 'x'; + } + printer.printType(getElementType()); + printer << ">"; +} + +LogicalResult emitc::ArrayType::verify( + ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError, + ::llvm::ArrayRef shape, Type elementType) { + if (shape.empty()) + return emitError() << "shape must not be empty"; + + for (int64_t dim : shape) { + if (dim <= 0) + return emitError() << "dimensions must have positive size"; + } + + if (!elementType) + return emitError() << "element type must not be none"; + + if (!isValidElementType(elementType)) + return emitError() << "invalid array element type"; + + return success(); +} + +emitc::ArrayType +emitc::ArrayType::cloneWith(std::optional> shape, + Type elementType) const { + if (!shape) + return emitc::ArrayType::get(getShape(), elementType); + return emitc::ArrayType::get(*shape, elementType); +} + //===----------------------------------------------------------------------===// // OpaqueType //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp index 3d71b4a3e315..3cf137c1d07c 100644 --- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp +++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp @@ -139,6 +139,10 @@ struct CppEmitter { LogicalResult emitVariableDeclaration(OpResult result, bool trailingSemicolon); + /// Emits a declaration of a variable with the given type and name. + LogicalResult emitVariableDeclaration(Location loc, Type type, + StringRef name); + /// Emits the variable declaration and assignment prefix for 'op'. /// - emits separate variable followed by std::tie for multi-valued operation; /// - emits single type followed by variable for single result; @@ -870,10 +874,8 @@ static LogicalResult printFunctionArgs(CppEmitter &emitter, return (interleaveCommaWithError( arguments, os, [&](BlockArgument arg) -> LogicalResult { - if (failed(emitter.emitType(functionOp->getLoc(), arg.getType()))) - return failure(); - os << " " << emitter.getOrCreateName(arg); - return success(); + return emitter.emitVariableDeclaration( + functionOp->getLoc(), arg.getType(), emitter.getOrCreateName(arg)); })); } @@ -917,6 +919,9 @@ static LogicalResult printFunctionBody(CppEmitter &emitter, if (emitter.hasValueInScope(arg)) return functionOp->emitOpError(" block argument #") << arg.getArgNumber() << " is out of scope"; + if (isa(arg.getType())) + return functionOp->emitOpError("cannot emit block argument #") + << arg.getArgNumber() << " with array type"; if (failed( emitter.emitType(block.getParentOp()->getLoc(), arg.getType()))) { return failure(); @@ -960,6 +965,11 @@ static LogicalResult printOperation(CppEmitter &emitter, "with multiple blocks needs variables declared at top"); } + if (llvm::any_of(functionOp.getResultTypes(), + [](Type type) { return isa(type); })) { + return functionOp.emitOpError() << "cannot emit array type as result type"; + } + CppEmitter::Scope scope(emitter); raw_indented_ostream &os = emitter.ostream(); if (failed(emitter.emitTypes(functionOp.getLoc(), @@ -1306,9 +1316,10 @@ LogicalResult CppEmitter::emitVariableDeclaration(OpResult result, return result.getDefiningOp()->emitError( "result variable for the operation already declared"); } - if (failed(emitType(result.getOwner()->getLoc(), result.getType()))) + if (failed(emitVariableDeclaration(result.getOwner()->getLoc(), + result.getType(), + getOrCreateName(result)))) return failure(); - os << " " << getOrCreateName(result); if (trailingSemicolon) os << ";\n"; return success(); @@ -1403,6 +1414,23 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) { return success(); } +LogicalResult CppEmitter::emitVariableDeclaration(Location loc, Type type, + StringRef name) { + if (auto arrType = dyn_cast(type)) { + if (failed(emitType(loc, arrType.getElementType()))) + return failure(); + os << " " << name; + for (auto dim : arrType.getShape()) { + os << "[" << dim << "]"; + } + return success(); + } + if (failed(emitType(loc, type))) + return failure(); + os << " " << name; + return success(); +} + LogicalResult CppEmitter::emitType(Location loc, Type type) { if (auto iType = dyn_cast(type)) { switch (iType.getWidth()) { @@ -1438,6 +1466,8 @@ LogicalResult CppEmitter::emitType(Location loc, Type type) { if (!tType.hasStaticShape()) return emitError(loc, "cannot emit tensor type with non static shape"); os << "Tensor<"; + if (isa(tType.getElementType())) + return emitError(loc, "cannot emit tensor of array type ") << type; if (failed(emitType(loc, tType.getElementType()))) return failure(); auto shape = tType.getShape(); @@ -1454,7 +1484,16 @@ LogicalResult CppEmitter::emitType(Location loc, Type type) { os << oType.getValue(); return success(); } + if (auto aType = dyn_cast(type)) { + if (failed(emitType(loc, aType.getElementType()))) + return failure(); + for (auto dim : aType.getShape()) + os << "[" << dim << "]"; + return success(); + } if (auto pType = dyn_cast(type)) { + if (isa(pType.getPointee())) + return emitError(loc, "cannot emit pointer to array type ") << type; if (failed(emitType(loc, pType.getPointee()))) return failure(); os << "*"; @@ -1476,6 +1515,9 @@ LogicalResult CppEmitter::emitTypes(Location loc, ArrayRef types) { } LogicalResult CppEmitter::emitTupleType(Location loc, ArrayRef types) { + if (llvm::any_of(types, [](Type type) { return isa(type); })) { + return emitError(loc, "cannot emit tuple of array type"); + } os << "std::tuple<"; if (failed(interleaveCommaWithError( types, os, [&](Type type) { return emitType(loc, type); }))) diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir index 5f64b535d684..58b3a11ed93e 100644 --- a/mlir/test/Dialect/EmitC/invalid_ops.mlir +++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir @@ -80,6 +80,14 @@ func.func @dense_template_argument(%arg : i32) { // ----- +func.func @array_result() { + // expected-error @+1 {{'emitc.call_opaque' op cannot return array type}} + emitc.call_opaque "array_result"() : () -> !emitc.array<4xi32> + return +} + +// ----- + func.func @empty_operator(%arg : i32) { // expected-error @+1 {{'emitc.apply' op applicable operator must not be empty}} %2 = emitc.apply ""(%arg) : (i32) -> !emitc.ptr @@ -129,6 +137,14 @@ func.func @cast_tensor(%arg : tensor) { // ----- +func.func @cast_array(%arg : !emitc.array<4xf32>) { + // expected-error @+1 {{'emitc.cast' op operand type '!emitc.array<4xf32>' and result type '!emitc.array<4xf32>' are cast incompatible}} + %1 = emitc.cast %arg: !emitc.array<4xf32> to !emitc.array<4xf32> + return +} + +// ----- + func.func @add_two_pointers(%arg0: !emitc.ptr, %arg1: !emitc.ptr) { // expected-error @+1 {{'emitc.add' op requires that at most one operand is a pointer}} %1 = "emitc.add" (%arg0, %arg1) : (!emitc.ptr, !emitc.ptr) -> !emitc.ptr @@ -235,6 +251,15 @@ func.func @test_assign_type_mismatch(%arg1: f32) { // ----- +func.func @test_assign_to_array(%arg1: !emitc.array<4xi32>) { + %v = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4xi32> + // expected-error @+1 {{'emitc.assign' op cannot assign to array type}} + emitc.assign %arg1 : !emitc.array<4xi32> to %v : !emitc.array<4xi32> + return +} + +// ----- + func.func @test_expression_no_yield() -> i32 { // expected-error @+1 {{'emitc.expression' op must yield a value at termination}} %r = emitc.expression : i32 { @@ -313,6 +338,13 @@ emitc.func @return_type_mismatch() -> i32 { // ----- +// expected-error@+1 {{'emitc.func' op cannot return array type}} +emitc.func @return_type_array(%arg : !emitc.array<4xi32>) -> !emitc.array<4xi32> { + emitc.return %arg : !emitc.array<4xi32> +} + +// ----- + func.func @return_inside_func.func(%0: i32) -> (i32) { // expected-error@+1 {{'emitc.return' op expects parent op 'emitc.func'}} emitc.return %0 : i32 diff --git a/mlir/test/Dialect/EmitC/invalid_types.mlir b/mlir/test/Dialect/EmitC/invalid_types.mlir index 54e3775ddb8e..079371b39b9d 100644 --- a/mlir/test/Dialect/EmitC/invalid_types.mlir +++ b/mlir/test/Dialect/EmitC/invalid_types.mlir @@ -11,3 +11,73 @@ func.func @illegal_opaque_type_2() { // expected-error @+1 {{pointer not allowed as outer type with !emitc.opaque, use !emitc.ptr instead}} %1 = "emitc.variable"(){value = "nullptr" : !emitc.opaque<"int32_t*">} : () -> !emitc.opaque<"int32_t*"> } + +// ----- + +func.func @illegal_array_missing_spec( + // expected-error @+1 {{expected non-function type}} + %arg0: !emitc.array<>) { +} + +// ----- + +func.func @illegal_array_missing_shape( + // expected-error @+1 {{shape must not be empty}} + %arg9: !emitc.array) { +} + +// ----- + +func.func @illegal_array_missing_x( + // expected-error @+1 {{expected 'x' in dimension list}} + %arg0: !emitc.array<10> +) { +} + +// ----- + +func.func @illegal_array_non_positive_dimenson( + // expected-error @+1 {{dimensions must have positive size}} + %arg0: !emitc.array<0xi32> +) { +} + +// ----- + +func.func @illegal_array_missing_type( + // expected-error @+1 {{expected non-function type}} + %arg0: !emitc.array<10x> +) { +} + +// ----- + +func.func @illegal_array_dynamic_shape( + // expected-error @+1 {{expected static shape}} + %arg0: !emitc.array<10x?xi32> +) { +} + +// ----- + +func.func @illegal_array_unranked( + // expected-error @+1 {{expected non-function type}} + %arg0: !emitc.array<*xi32> +) { +} + +// ----- + +func.func @illegal_array_with_array_element_type( + // expected-error @+1 {{invalid array element type}} + %arg0: !emitc.array<4x!emitc.array<4xi32>> +) { +} + +// ----- + +func.func @illegal_array_with_tensor_element_type( + // expected-error @+1 {{invalid array element type}} + %arg0: !emitc.array<4xtensor<4xi32>> +) { +} diff --git a/mlir/test/Dialect/EmitC/types.mlir b/mlir/test/Dialect/EmitC/types.mlir index 26d6f43a5824..752f2c10c17b 100644 --- a/mlir/test/Dialect/EmitC/types.mlir +++ b/mlir/test/Dialect/EmitC/types.mlir @@ -2,6 +2,20 @@ // check parser // RUN: mlir-opt -verify-diagnostics %s | mlir-opt -verify-diagnostics | FileCheck %s +// CHECK-LABEL: func @array_types( +func.func @array_types( + // CHECK-SAME: !emitc.array<1xf32>, + %arg0: !emitc.array<1xf32>, + // CHECK-SAME: !emitc.array<10x20x30xi32>, + %arg1: !emitc.array<10x20x30xi32>, + // CHECK-SAME: !emitc.array<30x!emitc.ptr>, + %arg2: !emitc.array<30x!emitc.ptr>, + // CHECK-SAME: !emitc.array<30x!emitc.opaque<"int">> + %arg3: !emitc.array<30x!emitc.opaque<"int">> +) { + return +} + // CHECK-LABEL: func @opaque_types() { func.func @opaque_types() { // CHECK-NEXT: !emitc.opaque<"int"> diff --git a/mlir/test/Target/Cpp/common-cpp.mlir b/mlir/test/Target/Cpp/common-cpp.mlir index b537e7098deb..a87b33a10844 100644 --- a/mlir/test/Target/Cpp/common-cpp.mlir +++ b/mlir/test/Target/Cpp/common-cpp.mlir @@ -89,3 +89,8 @@ func.func @apply(%arg0: i32) -> !emitc.ptr { %1 = emitc.apply "*"(%0) : (!emitc.ptr) -> (i32) return %0 : !emitc.ptr } + +// CHECK: void array_type(int32_t v1[3], float v2[10][20]) +func.func @array_type(%arg0: !emitc.array<3xi32>, %arg1: !emitc.array<10x20xf32>) { + return +} diff --git a/mlir/test/Target/Cpp/declare_func.mlir b/mlir/test/Target/Cpp/declare_func.mlir index 72c087a3388e..00680d71824a 100644 --- a/mlir/test/Target/Cpp/declare_func.mlir +++ b/mlir/test/Target/Cpp/declare_func.mlir @@ -14,3 +14,11 @@ emitc.declare_func @foo emitc.func @foo(%arg0: i32) -> i32 attributes {specifiers = ["static","inline"]} { emitc.return %arg0 : i32 } + + +// CHECK: void array_arg(int32_t [[V2:[^ ]*]][3]); +emitc.declare_func @array_arg +// CHECK: void array_arg(int32_t [[V2:[^ ]*]][3]) { +emitc.func @array_arg(%arg0: !emitc.array<3xi32>) { + emitc.return +} diff --git a/mlir/test/Target/Cpp/func.mlir b/mlir/test/Target/Cpp/func.mlir index a639cae6f623..9c9ea55bfc4e 100644 --- a/mlir/test/Target/Cpp/func.mlir +++ b/mlir/test/Target/Cpp/func.mlir @@ -40,3 +40,6 @@ emitc.func @emitc_call() -> i32 { emitc.func private @extern_func(i32) attributes {specifiers = ["extern"]} // CPP-DEFAULT: extern void extern_func(int32_t); + +emitc.func private @array_arg(!emitc.array<3xi32>) attributes {specifiers = ["extern"]} +// CPP-DEFAULT: extern void array_arg(int32_t[3]); diff --git a/mlir/test/Target/Cpp/invalid.mlir b/mlir/test/Target/Cpp/invalid.mlir index 18dabb915586..552c04a9b07f 100644 --- a/mlir/test/Target/Cpp/invalid.mlir +++ b/mlir/test/Target/Cpp/invalid.mlir @@ -57,3 +57,31 @@ func.func @non_static_shape(%arg0 : tensor) { func.func @unranked_tensor(%arg0 : tensor<*xf32>) { return } + +// ----- + +// expected-error@+1 {{cannot emit tensor of array type}} +func.func @tensor_of_array(%arg0 : tensor<4x!emitc.array<4xf32>>) { + return +} + +// ----- + +// expected-error@+1 {{cannot emit pointer to array type}} +func.func @pointer_to_array(%arg0 : !emitc.ptr>) { + return +} + +// ----- + +// expected-error@+1 {{cannot emit array type as result type}} +func.func @array_as_result(%arg: !emitc.array<4xi8>) -> (!emitc.array<4xi8>) { + return %arg : !emitc.array<4xi8> +} + +// ----- +func.func @ptr_to_array() { + // expected-error@+1 {{cannot emit pointer to array type '!emitc.ptr>'}} + %v = "emitc.variable"(){value = #emitc.opaque<"NULL">} : () -> !emitc.ptr> + return +} diff --git a/mlir/test/Target/Cpp/invalid_declare_variables_at_top.mlir b/mlir/test/Target/Cpp/invalid_declare_variables_at_top.mlir new file mode 100644 index 000000000000..844fe03bad4a --- /dev/null +++ b/mlir/test/Target/Cpp/invalid_declare_variables_at_top.mlir @@ -0,0 +1,9 @@ +// RUN: mlir-translate -split-input-file -declare-variables-at-top -mlir-to-cpp -verify-diagnostics %s + +// expected-error@+1 {{'func.func' op cannot emit block argument #0 with array type}} +func.func @array_as_block_argument(!emitc.array<4xi8>) { +^bb0(%arg0 : !emitc.array<4xi8>): + cf.br ^bb1(%arg0 : !emitc.array<4xi8>) +^bb1(%a : !emitc.array<4xi8>): + return +} diff --git a/mlir/test/Target/Cpp/variable.mlir b/mlir/test/Target/Cpp/variable.mlir index 77a060a32f9d..126dd384b47a 100644 --- a/mlir/test/Target/Cpp/variable.mlir +++ b/mlir/test/Target/Cpp/variable.mlir @@ -9,6 +9,8 @@ func.func @emitc_variable() { %c4 = "emitc.variable"(){value = 255 : ui8} : () -> ui8 %c5 = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.ptr %c6 = "emitc.variable"(){value = #emitc.opaque<"NULL">} : () -> !emitc.ptr + %c7 = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.array<3x7xi32> + %c8 = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.array<5x!emitc.ptr> return } // CPP-DEFAULT: void emitc_variable() { @@ -19,6 +21,8 @@ func.func @emitc_variable() { // CPP-DEFAULT-NEXT: uint8_t [[V4:[^ ]*]] = 255; // CPP-DEFAULT-NEXT: int32_t* [[V5:[^ ]*]]; // CPP-DEFAULT-NEXT: int32_t* [[V6:[^ ]*]] = NULL; +// CPP-DEFAULT-NEXT: int32_t [[V7:[^ ]*]][3][7]; +// CPP-DEFAULT-NEXT: int8_t* [[V8:[^ ]*]][5]; // CPP-DECLTOP: void emitc_variable() { // CPP-DECLTOP-NEXT: int32_t [[V0:[^ ]*]]; @@ -28,6 +32,8 @@ func.func @emitc_variable() { // CPP-DECLTOP-NEXT: uint8_t [[V4:[^ ]*]]; // CPP-DECLTOP-NEXT: int32_t* [[V5:[^ ]*]]; // CPP-DECLTOP-NEXT: int32_t* [[V6:[^ ]*]]; +// CPP-DECLTOP-NEXT: int32_t [[V7:[^ ]*]][3][7]; +// CPP-DECLTOP-NEXT: int8_t* [[V8:[^ ]*]][5]; // CPP-DECLTOP-NEXT: ; // CPP-DECLTOP-NEXT: [[V1]] = 42; // CPP-DECLTOP-NEXT: [[V2]] = -1; -- GitLab From 575ca6744b755f75799c1d092f56953e776a80a6 Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Mon, 11 Mar 2024 15:36:22 +0000 Subject: [PATCH 130/953] [CodeGen] Remove unused MachineRegisterInfo methods --- llvm/include/llvm/CodeGen/MachineRegisterInfo.h | 9 --------- llvm/lib/CodeGen/MachineRegisterInfo.cpp | 12 ------------ 2 files changed, 21 deletions(-) diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h index 3f0fc160f9ea..09d9a0b4ec40 100644 --- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -243,15 +243,6 @@ public: /// Returns true if the updated CSR list was initialized and false otherwise. bool isUpdatedCSRsInitialized() const { return IsUpdatedCSRsInitialized; } - /// Returns true if a register can be used as an argument to a function. - bool isArgumentRegister(MCRegister Reg) const; - - /// Returns true if a register is a fixed register. - bool isFixedRegister(MCRegister Reg) const; - - /// Returns true if a register is a general purpose register. - bool isGeneralPurposeRegister(MCRegister Reg) const; - /// Disables the register from the list of CSRs. /// I.e. the register will not appear as part of the CSR mask. /// \see UpdatedCalleeSavedRegs. diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp index 55d7c8370e9c..b0c1838b3ff0 100644 --- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp +++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp @@ -659,15 +659,3 @@ bool MachineRegisterInfo::isReservedRegUnit(unsigned Unit) const { } return false; } - -bool MachineRegisterInfo::isArgumentRegister(MCRegister Reg) const { - return getTargetRegisterInfo()->isArgumentRegister(*MF, Reg); -} - -bool MachineRegisterInfo::isFixedRegister(MCRegister Reg) const { - return getTargetRegisterInfo()->isFixedRegister(*MF, Reg); -} - -bool MachineRegisterInfo::isGeneralPurposeRegister(MCRegister Reg) const { - return getTargetRegisterInfo()->isGeneralPurposeRegister(*MF, Reg); -} -- GitLab From a924da6d4b8733e5bf08098b18dd7ad1a5ba5f46 Mon Sep 17 00:00:00 2001 From: Marius Brehler Date: Mon, 11 Mar 2024 16:47:06 +0100 Subject: [PATCH 131/953] [mlir][IR] Add `isInteger()` (without width) (#84467) For the singless and signed integers overloads exist, so that the width does not need to be specified as an argument. This adds the same for integers without checking for signedness. --- mlir/include/mlir/IR/Types.h | 3 ++- mlir/lib/IR/Types.cpp | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/mlir/include/mlir/IR/Types.h b/mlir/include/mlir/IR/Types.h index 46bb733101c1..a89e13b625bf 100644 --- a/mlir/include/mlir/IR/Types.h +++ b/mlir/include/mlir/IR/Types.h @@ -133,7 +133,8 @@ public: bool isF80() const; bool isF128() const; - /// Return true if this is an integer type with the specified width. + /// Return true if this is an integer type (with the specified width). + bool isInteger() const; bool isInteger(unsigned width) const; /// Return true if this is a signless integer type (with the specified width). bool isSignlessInteger() const; diff --git a/mlir/lib/IR/Types.cpp b/mlir/lib/IR/Types.cpp index 32dfef9e8104..1d1ba6df4db2 100644 --- a/mlir/lib/IR/Types.cpp +++ b/mlir/lib/IR/Types.cpp @@ -55,6 +55,8 @@ bool Type::isF128() const { return llvm::isa(*this); } bool Type::isIndex() const { return llvm::isa(*this); } +bool Type::isInteger() const { return llvm::isa(*this); } + /// Return true if this is an integer type with the specified width. bool Type::isInteger(unsigned width) const { if (auto intTy = llvm::dyn_cast(*this)) -- GitLab From 0858c906db008e02163e159158c082d9fc82dcca Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 11 Mar 2024 14:18:58 +0000 Subject: [PATCH 132/953] [X86] Add missing register qualifier to the VBLENDVPD/VBLENDVPS/VPBLENDVB instruction names Matches the SSE variants (which has a 0 qualifier to indicate the xmm0 explicit dependency) --- llvm/lib/Target/X86/X86FastISel.cpp | 2 +- llvm/lib/Target/X86/X86InstrSSE.td | 48 +++++++++---------- llvm/lib/Target/X86/X86SchedAlderlakeP.td | 8 ++-- llvm/lib/Target/X86/X86SchedSapphireRapids.td | 14 +++--- llvm/test/TableGen/x86-fold-tables.inc | 12 ++--- 5 files changed, 42 insertions(+), 42 deletions(-) diff --git a/llvm/lib/Target/X86/X86FastISel.cpp b/llvm/lib/Target/X86/X86FastISel.cpp index 9f0b5f32df20..48d3b68b1823 100644 --- a/llvm/lib/Target/X86/X86FastISel.cpp +++ b/llvm/lib/Target/X86/X86FastISel.cpp @@ -2230,7 +2230,7 @@ bool X86FastISel::X86FastEmitSSESelect(MVT RetVT, const Instruction *I) { unsigned CmpOpcode = (RetVT == MVT::f32) ? X86::VCMPSSrri : X86::VCMPSDrri; unsigned BlendOpcode = - (RetVT == MVT::f32) ? X86::VBLENDVPSrr : X86::VBLENDVPDrr; + (RetVT == MVT::f32) ? X86::VBLENDVPSrrr : X86::VBLENDVPDrrr; Register CmpReg = fastEmitInst_rri(CmpOpcode, RC, CmpLHSReg, CmpRHSReg, CC); diff --git a/llvm/lib/Target/X86/X86InstrSSE.td b/llvm/lib/Target/X86/X86InstrSSE.td index 4a542b7e5a1b..69d45366a1db 100644 --- a/llvm/lib/Target/X86/X86InstrSSE.td +++ b/llvm/lib/Target/X86/X86InstrSSE.td @@ -6266,27 +6266,27 @@ multiclass SS41I_quaternary_avx opc, string OpcodeStr, RegisterClass RC, X86MemOperand x86memop, ValueType VT, PatFrag mem_frag, SDNode OpNode, X86FoldableSchedWrite sched> { - def rr : Ii8Reg, TA, PD, VEX, VVVV, - Sched<[sched]>; + def rrr : Ii8Reg, TA, PD, VEX, VVVV, + Sched<[sched]>; - def rm : Ii8Reg, TA, PD, VEX, VVVV, - Sched<[sched.Folded, sched.ReadAfterFold, - // x86memop:$src2 - ReadDefault, ReadDefault, ReadDefault, ReadDefault, - ReadDefault, - // RC::$src3 - sched.ReadAfterFold]>; + def rmr : Ii8Reg, TA, PD, VEX, VVVV, + Sched<[sched.Folded, sched.ReadAfterFold, + // x86memop:$src2 + ReadDefault, ReadDefault, ReadDefault, ReadDefault, + ReadDefault, + // RC::$src3 + sched.ReadAfterFold]>; } let Predicates = [HasAVX] in { @@ -6320,16 +6320,16 @@ defm VPBLENDVBY : SS41I_quaternary_avx<0x4C, "vpblendvb", VR256, i256mem, let Predicates = [HasAVX] in { def : Pat<(v4i32 (X86Blendv (v4i32 VR128:$mask), (v4i32 VR128:$src1), (v4i32 VR128:$src2))), - (VBLENDVPSrr VR128:$src2, VR128:$src1, VR128:$mask)>; + (VBLENDVPSrrr VR128:$src2, VR128:$src1, VR128:$mask)>; def : Pat<(v2i64 (X86Blendv (v2i64 VR128:$mask), (v2i64 VR128:$src1), (v2i64 VR128:$src2))), - (VBLENDVPDrr VR128:$src2, VR128:$src1, VR128:$mask)>; + (VBLENDVPDrrr VR128:$src2, VR128:$src1, VR128:$mask)>; def : Pat<(v8i32 (X86Blendv (v8i32 VR256:$mask), (v8i32 VR256:$src1), (v8i32 VR256:$src2))), - (VBLENDVPSYrr VR256:$src2, VR256:$src1, VR256:$mask)>; + (VBLENDVPSYrrr VR256:$src2, VR256:$src1, VR256:$mask)>; def : Pat<(v4i64 (X86Blendv (v4i64 VR256:$mask), (v4i64 VR256:$src1), (v4i64 VR256:$src2))), - (VBLENDVPDYrr VR256:$src2, VR256:$src1, VR256:$mask)>; + (VBLENDVPDYrrr VR256:$src2, VR256:$src1, VR256:$mask)>; } // Prefer a movss or movsd over a blendps when optimizing for size. these were diff --git a/llvm/lib/Target/X86/X86SchedAlderlakeP.td b/llvm/lib/Target/X86/X86SchedAlderlakeP.td index 4dc5ea3c8611..6f9d2cf7ffdf 100644 --- a/llvm/lib/Target/X86/X86SchedAlderlakeP.td +++ b/llvm/lib/Target/X86/X86SchedAlderlakeP.td @@ -2158,16 +2158,16 @@ def ADLPWriteResGroup244 : SchedWriteRes<[ADLPPort00_01_05, ADLPPort02_03_11]> { let Latency = 9; let NumMicroOps = 4; } -def : InstRW<[ADLPWriteResGroup244, ReadAfterVecXLd, ReadAfterVecXLd, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault], (instregex "^VBLENDVP(D|S)rm$")>; -def : InstRW<[ADLPWriteResGroup244, ReadAfterVecXLd, ReadAfterVecXLd, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault], (instrs VPBLENDVBrm)>; +def : InstRW<[ADLPWriteResGroup244, ReadAfterVecXLd, ReadAfterVecXLd, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault], (instregex "^VBLENDVP(D|S)rmr$")>; +def : InstRW<[ADLPWriteResGroup244, ReadAfterVecXLd, ReadAfterVecXLd, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault], (instrs VPBLENDVBrmr)>; def ADLPWriteResGroup245 : SchedWriteRes<[ADLPPort00_01_05]> { let ReleaseAtCycles = [3]; let Latency = 3; let NumMicroOps = 3; } -def : InstRW<[ADLPWriteResGroup245], (instregex "^VBLENDVP(D|S)rr$")>; -def : InstRW<[ADLPWriteResGroup245], (instrs VPBLENDVBrr)>; +def : InstRW<[ADLPWriteResGroup245], (instregex "^VBLENDVP(D|S)rrr$")>; +def : InstRW<[ADLPWriteResGroup245], (instrs VPBLENDVBrrr)>; def ADLPWriteResGroup246 : SchedWriteRes<[ADLPPort00, ADLPPort01, ADLPPort02_03_11]> { let ReleaseAtCycles = [6, 7, 18]; diff --git a/llvm/lib/Target/X86/X86SchedSapphireRapids.td b/llvm/lib/Target/X86/X86SchedSapphireRapids.td index 3c698d2c9f7a..88bb9ad8f1d7 100644 --- a/llvm/lib/Target/X86/X86SchedSapphireRapids.td +++ b/llvm/lib/Target/X86/X86SchedSapphireRapids.td @@ -2673,25 +2673,25 @@ def SPRWriteResGroup259 : SchedWriteRes<[SPRPort00_01_05, SPRPort02_03_11]> { let Latency = 10; let NumMicroOps = 4; } -def : InstRW<[SPRWriteResGroup259, ReadAfterVecYLd, ReadAfterVecYLd, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault], (instregex "^VBLENDVP(D|S)Yrm$")>; -def : InstRW<[SPRWriteResGroup259, ReadAfterVecYLd, ReadAfterVecYLd, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault], (instrs VPBLENDVBYrm)>; +def : InstRW<[SPRWriteResGroup259, ReadAfterVecYLd, ReadAfterVecYLd, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault], (instregex "^VBLENDVP(D|S)Yrmr$")>; +def : InstRW<[SPRWriteResGroup259, ReadAfterVecYLd, ReadAfterVecYLd, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault], (instrs VPBLENDVBYrmr)>; def SPRWriteResGroup260 : SchedWriteRes<[SPRPort00_01_05]> { let ReleaseAtCycles = [3]; let Latency = 3; let NumMicroOps = 3; } -def : InstRW<[SPRWriteResGroup260], (instregex "^VBLENDVP(S|DY)rr$", - "^VBLENDVP(D|SY)rr$", - "^VPBLENDVB(Y?)rr$")>; +def : InstRW<[SPRWriteResGroup260], (instregex "^VBLENDVP(S|DY)rrr$", + "^VBLENDVP(D|SY)rrr$", + "^VPBLENDVB(Y?)rrr$")>; def SPRWriteResGroup261 : SchedWriteRes<[SPRPort00_01_05, SPRPort02_03_11]> { let ReleaseAtCycles = [3, 1]; let Latency = 9; let NumMicroOps = 4; } -def : InstRW<[SPRWriteResGroup261, ReadAfterVecXLd, ReadAfterVecXLd, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault], (instregex "^VBLENDVP(D|S)rm$")>; -def : InstRW<[SPRWriteResGroup261, ReadAfterVecXLd, ReadAfterVecXLd, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault], (instrs VPBLENDVBrm)>; +def : InstRW<[SPRWriteResGroup261, ReadAfterVecXLd, ReadAfterVecXLd, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault], (instregex "^VBLENDVP(D|S)rmr$")>; +def : InstRW<[SPRWriteResGroup261, ReadAfterVecXLd, ReadAfterVecXLd, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault], (instrs VPBLENDVBrmr)>; def SPRWriteResGroup262 : SchedWriteRes<[SPRPort00_01_05, SPRPort02_03_11]> { let Latency = 9; diff --git a/llvm/test/TableGen/x86-fold-tables.inc b/llvm/test/TableGen/x86-fold-tables.inc index e0fccd42e47f..eea4f87cae9c 100644 --- a/llvm/test/TableGen/x86-fold-tables.inc +++ b/llvm/test/TableGen/x86-fold-tables.inc @@ -2363,10 +2363,10 @@ static const X86FoldTableEntry Table2[] = { {X86::VBLENDPDrri, X86::VBLENDPDrmi, 0}, {X86::VBLENDPSYrri, X86::VBLENDPSYrmi, 0}, {X86::VBLENDPSrri, X86::VBLENDPSrmi, 0}, - {X86::VBLENDVPDYrr, X86::VBLENDVPDYrm, 0}, - {X86::VBLENDVPDrr, X86::VBLENDVPDrm, 0}, - {X86::VBLENDVPSYrr, X86::VBLENDVPSYrm, 0}, - {X86::VBLENDVPSrr, X86::VBLENDVPSrm, 0}, + {X86::VBLENDVPDYrrr, X86::VBLENDVPDYrmr, 0}, + {X86::VBLENDVPDrrr, X86::VBLENDVPDrmr, 0}, + {X86::VBLENDVPSYrrr, X86::VBLENDVPSYrmr, 0}, + {X86::VBLENDVPSrrr, X86::VBLENDVPSrmr, 0}, {X86::VBROADCASTF32X2Z256rrkz, X86::VBROADCASTF32X2Z256rmkz, TB_NO_REVERSE}, {X86::VBROADCASTF32X2Zrrkz, X86::VBROADCASTF32X2Zrmkz, TB_NO_REVERSE}, {X86::VBROADCASTI32X2Z128rrkz, X86::VBROADCASTI32X2Z128rmkz, TB_NO_REVERSE}, @@ -3042,8 +3042,8 @@ static const X86FoldTableEntry Table2[] = { {X86::VPBLENDMWZ128rr, X86::VPBLENDMWZ128rm, 0}, {X86::VPBLENDMWZ256rr, X86::VPBLENDMWZ256rm, 0}, {X86::VPBLENDMWZrr, X86::VPBLENDMWZrm, 0}, - {X86::VPBLENDVBYrr, X86::VPBLENDVBYrm, 0}, - {X86::VPBLENDVBrr, X86::VPBLENDVBrm, 0}, + {X86::VPBLENDVBYrrr, X86::VPBLENDVBYrmr, 0}, + {X86::VPBLENDVBrrr, X86::VPBLENDVBrmr, 0}, {X86::VPBLENDWYrri, X86::VPBLENDWYrmi, 0}, {X86::VPBLENDWrri, X86::VPBLENDWrmi, 0}, {X86::VPBROADCASTBZ128rrkz, X86::VPBROADCASTBZ128rmkz, TB_NO_REVERSE}, -- GitLab From ad8c8281363261929b53b0a519cd20e9e2445343 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 11 Mar 2024 14:36:46 +0000 Subject: [PATCH 133/953] [X86] (V)MPSADBW instructions can run on Port1 or Port5 for one uop stage When we copied the IceLake model from the SkylakeServer model we missed this diff Confirmed with uops.info and Agner --- llvm/lib/Target/X86/X86SchedIceLake.td | 6 +++--- .../tools/llvm-mca/X86/IceLakeServer/resources-avx1.s | 10 +++++----- .../tools/llvm-mca/X86/IceLakeServer/resources-avx2.s | 10 +++++----- .../tools/llvm-mca/X86/IceLakeServer/resources-sse41.s | 10 +++++----- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/llvm/lib/Target/X86/X86SchedIceLake.td b/llvm/lib/Target/X86/X86SchedIceLake.td index c9ae9901ed5b..3981279abc36 100644 --- a/llvm/lib/Target/X86/X86SchedIceLake.td +++ b/llvm/lib/Target/X86/X86SchedIceLake.td @@ -402,9 +402,9 @@ defm : ICXWriteResPair; defm : ICXWriteResPair; // Vector variable blends. defm : ICXWriteResPair; defm : ICXWriteResPair; -defm : ICXWriteResPair; // Vector MPSAD. -defm : ICXWriteResPair; -defm : ICXWriteResPair; +defm : ICXWriteResPair; // Vector MPSAD. +defm : ICXWriteResPair; +defm : ICXWriteResPair; defm : ICXWriteResPair; // Vector PSADBW. defm : ICXWriteResPair; defm : ICXWriteResPair; diff --git a/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx1.s b/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx1.s index e467c4e48ebd..f184d5579d06 100644 --- a/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx1.s +++ b/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx1.s @@ -1337,8 +1337,8 @@ vzeroupper # CHECK-NEXT: 1 1 0.33 vmovups %ymm0, %ymm2 # CHECK-NEXT: 2 1 0.50 * vmovups %ymm0, (%rax) # CHECK-NEXT: 1 7 0.50 * vmovups (%rax), %ymm2 -# CHECK-NEXT: 2 4 2.00 vmpsadbw $1, %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 10 2.00 * vmpsadbw $1, (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 4 1.00 vmpsadbw $1, %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: 3 10 1.00 * vmpsadbw $1, (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 4 0.50 vmulpd %xmm0, %xmm1, %xmm2 # CHECK-NEXT: 2 10 0.50 * vmulpd (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 4 0.50 vmulpd %ymm0, %ymm1, %ymm2 @@ -1738,7 +1738,7 @@ vzeroupper # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] -# CHECK-NEXT: - 126.00 322.92 232.92 160.50 160.50 19.00 296.92 6.25 19.00 19.00 19.00 +# CHECK-NEXT: - 126.00 322.92 233.92 160.50 160.50 19.00 295.92 6.25 19.00 19.00 19.00 # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] Instructions: @@ -2049,8 +2049,8 @@ vzeroupper # CHECK-NEXT: - - 0.33 0.33 - - - 0.33 - - - - vmovups %ymm0, %ymm2 # CHECK-NEXT: - - - - - - 0.50 - - 0.50 0.50 0.50 vmovups %ymm0, (%rax) # CHECK-NEXT: - - - - 0.50 0.50 - - - - - - vmovups (%rax), %ymm2 -# CHECK-NEXT: - - - - - - - 2.00 - - - - vmpsadbw $1, %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - - - vmpsadbw $1, (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - - 0.50 - - - 1.50 - - - - vmpsadbw $1, %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: - - - 0.50 0.50 0.50 - 1.50 - - - - vmpsadbw $1, (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vmulpd %xmm0, %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vmulpd (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vmulpd %ymm0, %ymm1, %ymm2 diff --git a/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx2.s b/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx2.s index 97f0d052f455..dcf883445ba4 100644 --- a/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx2.s +++ b/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx2.s @@ -476,8 +476,8 @@ vpxor (%rax), %ymm1, %ymm2 # CHECK-NEXT: 1 3 1.00 vinserti128 $1, %xmm0, %ymm1, %ymm2 # CHECK-NEXT: 2 7 0.50 * vinserti128 $1, (%rax), %ymm1, %ymm2 # CHECK-NEXT: 1 7 0.50 * vmovntdqa (%rax), %ymm0 -# CHECK-NEXT: 2 4 2.00 vmpsadbw $1, %ymm0, %ymm1, %ymm2 -# CHECK-NEXT: 3 11 2.00 * vmpsadbw $1, (%rax), %ymm1, %ymm2 +# CHECK-NEXT: 2 4 1.00 vmpsadbw $1, %ymm0, %ymm1, %ymm2 +# CHECK-NEXT: 3 11 1.00 * vmpsadbw $1, (%rax), %ymm1, %ymm2 # CHECK-NEXT: 1 1 0.50 vpabsb %ymm0, %ymm2 # CHECK-NEXT: 2 8 0.50 * vpabsb (%rax), %ymm2 # CHECK-NEXT: 1 1 0.50 vpabsd %ymm0, %ymm2 @@ -778,7 +778,7 @@ vpxor (%rax), %ymm1, %ymm2 # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] -# CHECK-NEXT: - - 110.33 103.33 98.00 98.00 2.50 150.33 - 2.50 2.50 2.50 +# CHECK-NEXT: - - 110.33 104.33 98.00 98.00 2.50 149.33 - 2.50 2.50 2.50 # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] Instructions: @@ -798,8 +798,8 @@ vpxor (%rax), %ymm1, %ymm2 # CHECK-NEXT: - - - - - - - 1.00 - - - - vinserti128 $1, %xmm0, %ymm1, %ymm2 # CHECK-NEXT: - - 0.33 0.33 0.50 0.50 - 0.33 - - - - vinserti128 $1, (%rax), %ymm1, %ymm2 # CHECK-NEXT: - - - - 0.50 0.50 - - - - - - vmovntdqa (%rax), %ymm0 -# CHECK-NEXT: - - - - - - - 2.00 - - - - vmpsadbw $1, %ymm0, %ymm1, %ymm2 -# CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - - - vmpsadbw $1, (%rax), %ymm1, %ymm2 +# CHECK-NEXT: - - - 0.50 - - - 1.50 - - - - vmpsadbw $1, %ymm0, %ymm1, %ymm2 +# CHECK-NEXT: - - - 0.50 0.50 0.50 - 1.50 - - - - vmpsadbw $1, (%rax), %ymm1, %ymm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vpabsb %ymm0, %ymm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpabsb (%rax), %ymm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vpabsd %ymm0, %ymm2 diff --git a/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-sse41.s b/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-sse41.s index 554d7aad54ba..05c208b1c622 100644 --- a/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-sse41.s +++ b/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-sse41.s @@ -172,8 +172,8 @@ roundss $1, (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 insertps $1, %xmm0, %xmm2 # CHECK-NEXT: 2 7 1.00 * insertps $1, (%rax), %xmm2 # CHECK-NEXT: 1 6 0.50 * movntdqa (%rax), %xmm2 -# CHECK-NEXT: 2 4 2.00 mpsadbw $1, %xmm0, %xmm2 -# CHECK-NEXT: 3 10 2.00 * mpsadbw $1, (%rax), %xmm2 +# CHECK-NEXT: 2 4 1.00 mpsadbw $1, %xmm0, %xmm2 +# CHECK-NEXT: 3 10 1.00 * mpsadbw $1, (%rax), %xmm2 # CHECK-NEXT: 1 3 1.00 packusdw %xmm0, %xmm2 # CHECK-NEXT: 2 10 1.00 * packusdw (%rax), %xmm2 # CHECK-NEXT: 2 2 0.67 pblendvb %xmm0, %xmm0, %xmm2 @@ -268,7 +268,7 @@ roundss $1, (%rax), %xmm2 # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] -# CHECK-NEXT: - - 36.67 41.67 22.00 22.00 2.50 53.67 - 2.50 2.50 2.50 +# CHECK-NEXT: - - 36.67 42.67 22.00 22.00 2.50 52.67 - 2.50 2.50 2.50 # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] Instructions: @@ -289,8 +289,8 @@ roundss $1, (%rax), %xmm2 # CHECK-NEXT: - - - - - - - 1.00 - - - - insertps $1, %xmm0, %xmm2 # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - - - insertps $1, (%rax), %xmm2 # CHECK-NEXT: - - - - 0.50 0.50 - - - - - - movntdqa (%rax), %xmm2 -# CHECK-NEXT: - - - - - - - 2.00 - - - - mpsadbw $1, %xmm0, %xmm2 -# CHECK-NEXT: - - - - 0.50 0.50 - 2.00 - - - - mpsadbw $1, (%rax), %xmm2 +# CHECK-NEXT: - - - 0.50 - - - 1.50 - - - - mpsadbw $1, %xmm0, %xmm2 +# CHECK-NEXT: - - - 0.50 0.50 0.50 - 1.50 - - - - mpsadbw $1, (%rax), %xmm2 # CHECK-NEXT: - - - - - - - 1.00 - - - - packusdw %xmm0, %xmm2 # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - - - packusdw (%rax), %xmm2 # CHECK-NEXT: - - 0.67 0.67 - - - 0.67 - - - - pblendvb %xmm0, %xmm0, %xmm2 -- GitLab From 2c93beccdf8e026534a737eddaf8f5f26f3a23c3 Mon Sep 17 00:00:00 2001 From: Cyndy Ishida Date: Mon, 11 Mar 2024 09:02:43 -0700 Subject: [PATCH 134/953] [InstallAPI] Collect C++ Decls (#84403) This includes capturing symbols for global variables, functions, classes, and templated defintions. As pre-determing what symbols are generated from C++ declarations can be non-trivial, InstallAPI only parses select declarations for symbol generation when parsing c++. For example, installapi only looks at explicit template instantiations or full template specializations, instead of general function or class templates, for symbol emittion. --- clang/include/clang/InstallAPI/Visitor.h | 14 + clang/lib/InstallAPI/Frontend.cpp | 4 +- clang/lib/InstallAPI/Visitor.cpp | 426 +++++++++++++++++- clang/test/InstallAPI/cpp.test | 530 +++++++++++++++++++++++ clang/tools/clang-installapi/Options.cpp | 33 +- clang/tools/clang-installapi/Options.h | 7 + 6 files changed, 1008 insertions(+), 6 deletions(-) create mode 100644 clang/test/InstallAPI/cpp.test diff --git a/clang/include/clang/InstallAPI/Visitor.h b/clang/include/clang/InstallAPI/Visitor.h index 71d4d9894f42..9ac948ded3e3 100644 --- a/clang/include/clang/InstallAPI/Visitor.h +++ b/clang/include/clang/InstallAPI/Visitor.h @@ -21,6 +21,7 @@ #include "llvm/ADT/Twine.h" namespace clang { +struct AvailabilityInfo; namespace installapi { /// ASTVisitor for collecting declarations that represent global symbols. @@ -33,6 +34,7 @@ public: MC(ItaniumMangleContext::create(ASTCtx, ASTCtx.getDiagnostics())), Layout(ASTCtx.getTargetInfo().getDataLayoutString()) {} void HandleTranslationUnit(ASTContext &ASTCtx) override; + bool shouldVisitTemplateInstantiations() const { return true; } /// Collect global variables. bool VisitVarDecl(const VarDecl *D); @@ -51,9 +53,19 @@ public: /// is therefore itself not collected. bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D); + /// Collect global c++ declarations. + bool VisitCXXRecordDecl(const CXXRecordDecl *D); + private: std::string getMangledName(const NamedDecl *D) const; std::string getBackendMangledName(llvm::Twine Name) const; + std::string getMangledCXXVTableName(const CXXRecordDecl *D) const; + std::string getMangledCXXThunk(const GlobalDecl &D, + const ThunkInfo &Thunk) const; + std::string getMangledCXXRTTI(const CXXRecordDecl *D) const; + std::string getMangledCXXRTTIName(const CXXRecordDecl *D) const; + std::string getMangledCtorDtor(const CXXMethodDecl *D, int Type) const; + std::optional getAccessForDecl(const NamedDecl *D) const; void recordObjCInstanceVariables( const ASTContext &ASTCtx, llvm::MachO::ObjCContainerRecord *Record, @@ -61,6 +73,8 @@ private: const llvm::iterator_range< DeclContext::specific_decl_iterator> Ivars); + void emitVTableSymbols(const CXXRecordDecl *D, const AvailabilityInfo &Avail, + const HeaderType Access, bool EmittedVTable = false); InstallAPIContext &Ctx; SourceManager &SrcMgr; diff --git a/clang/lib/InstallAPI/Frontend.cpp b/clang/lib/InstallAPI/Frontend.cpp index 1edbdf5bb983..0d526fe1da66 100644 --- a/clang/lib/InstallAPI/Frontend.cpp +++ b/clang/lib/InstallAPI/Frontend.cpp @@ -137,9 +137,9 @@ std::unique_ptr createInputBuffer(InstallAPIContext &Ctx) { else OS << "#import "; if (H.useIncludeName()) - OS << "<" << H.getIncludeName() << ">"; + OS << "<" << H.getIncludeName() << ">\n"; else - OS << "\"" << H.getPath() << "\""; + OS << "\"" << H.getPath() << "\"\n"; Ctx.addKnownHeader(H); } diff --git a/clang/lib/InstallAPI/Visitor.cpp b/clang/lib/InstallAPI/Visitor.cpp index 1f2ef08e5aa2..aded94f7a94a 100644 --- a/clang/lib/InstallAPI/Visitor.cpp +++ b/clang/lib/InstallAPI/Visitor.cpp @@ -7,7 +7,9 @@ //===----------------------------------------------------------------------===// #include "clang/InstallAPI/Visitor.h" +#include "clang/AST/Availability.h" #include "clang/AST/ParentMapContext.h" +#include "clang/AST/VTableBuilder.h" #include "clang/Basic/Linkage.h" #include "clang/InstallAPI/Frontend.h" #include "llvm/ADT/SmallString.h" @@ -18,6 +20,15 @@ using namespace llvm; using namespace llvm::MachO; +namespace { +enum class CXXLinkage { + ExternalLinkage, + LinkOnceODRLinkage, + WeakODRLinkage, + PrivateLinkage, +}; +} + namespace clang::installapi { // Exported NamedDecl needs to have external linkage and @@ -53,7 +64,7 @@ static bool isInlined(const FunctionDecl *D) { return true; } -static SymbolFlags getFlags(bool WeakDef, bool ThreadLocal) { +static SymbolFlags getFlags(bool WeakDef, bool ThreadLocal = false) { SymbolFlags Result = SymbolFlags::None; if (WeakDef) Result |= SymbolFlags::WeakDefined; @@ -277,8 +288,417 @@ bool InstallAPIVisitor::VisitFunctionDecl(const FunctionDecl *D) { ? RecordLinkage::Internal : RecordLinkage::Exported; Ctx.Slice->addGlobal(Name, Linkage, GlobalRecord::Kind::Function, Avail, D, - *Access, getFlags(WeakDef, /*ThreadLocal=*/false), - Inlined); + *Access, getFlags(WeakDef), Inlined); + return true; +} + +static bool hasVTable(const CXXRecordDecl *D) { + // Check if vtable symbols should be emitted, only dynamic classes need + // vtables. + if (!D->hasDefinition() || !D->isDynamicClass()) + return false; + + assert(D->isExternallyVisible() && "Should be externally visible"); + assert(D->isCompleteDefinition() && "Only works on complete definitions"); + + const CXXMethodDecl *KeyFunctionD = + D->getASTContext().getCurrentKeyFunction(D); + // If this class has a key function, then there is a vtable, possibly internal + // though. + if (KeyFunctionD) { + switch (KeyFunctionD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + case TSK_ImplicitInstantiation: + case TSK_ExplicitInstantiationDefinition: + return true; + case TSK_ExplicitInstantiationDeclaration: + llvm_unreachable( + "Unexpected TemplateSpecializationKind for key function"); + } + } else if (D->isAbstract()) { + // If the class is abstract and it doesn't have a key function, it is a + // 'pure' virtual class. It doesn't need a vtable. + return false; + } + + switch (D->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + case TSK_ImplicitInstantiation: + return false; + + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + return true; + } + + llvm_unreachable("Invalid TemplateSpecializationKind!"); +} + +static CXXLinkage getVTableLinkage(const CXXRecordDecl *D) { + assert((D->hasDefinition() && D->isDynamicClass()) && "Record has no vtable"); + assert(D->isExternallyVisible() && "Record should be externally visible"); + if (D->getVisibility() == HiddenVisibility) + return CXXLinkage::PrivateLinkage; + + const CXXMethodDecl *KeyFunctionD = + D->getASTContext().getCurrentKeyFunction(D); + if (KeyFunctionD) { + // If this class has a key function, use that to determine the + // linkage of the vtable. + switch (KeyFunctionD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + if (isInlined(KeyFunctionD)) + return CXXLinkage::LinkOnceODRLinkage; + return CXXLinkage::ExternalLinkage; + case TSK_ImplicitInstantiation: + llvm_unreachable("No external vtable for implicit instantiations"); + case TSK_ExplicitInstantiationDefinition: + return CXXLinkage::WeakODRLinkage; + case TSK_ExplicitInstantiationDeclaration: + llvm_unreachable( + "Unexpected TemplateSpecializationKind for key function"); + } + } + + switch (D->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + case TSK_ImplicitInstantiation: + return CXXLinkage::LinkOnceODRLinkage; + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + return CXXLinkage::WeakODRLinkage; + } + + llvm_unreachable("Invalid TemplateSpecializationKind!"); +} + +static bool isRTTIWeakDef(const CXXRecordDecl *D) { + if (D->hasAttr()) + return true; + + if (D->isAbstract() && D->getASTContext().getCurrentKeyFunction(D) == nullptr) + return true; + + if (D->isDynamicClass()) + return getVTableLinkage(D) != CXXLinkage::ExternalLinkage; + + return false; +} + +static bool hasRTTI(const CXXRecordDecl *D) { + if (!D->getASTContext().getLangOpts().RTTI) + return false; + + if (!D->hasDefinition()) + return false; + + if (!D->isDynamicClass()) + return false; + + // Don't emit weak-def RTTI information. InstallAPI cannot reliably determine + // if the final binary will have those weak defined RTTI symbols. This depends + // on the optimization level and if the class has been instantiated and used. + // + // Luckily, the Apple static linker doesn't need those weak defined RTTI + // symbols for linking. They are only needed by the runtime linker. That means + // they can be safely dropped. + if (isRTTIWeakDef(D)) + return false; + + return true; +} + +std::string +InstallAPIVisitor::getMangledCXXRTTIName(const CXXRecordDecl *D) const { + SmallString<256> Name; + raw_svector_ostream NameStream(Name); + MC->mangleCXXRTTIName(QualType(D->getTypeForDecl(), 0), NameStream); + + return getBackendMangledName(Name); +} + +std::string InstallAPIVisitor::getMangledCXXRTTI(const CXXRecordDecl *D) const { + SmallString<256> Name; + raw_svector_ostream NameStream(Name); + MC->mangleCXXRTTI(QualType(D->getTypeForDecl(), 0), NameStream); + + return getBackendMangledName(Name); +} + +std::string +InstallAPIVisitor::getMangledCXXVTableName(const CXXRecordDecl *D) const { + SmallString<256> Name; + raw_svector_ostream NameStream(Name); + MC->mangleCXXVTable(D, NameStream); + + return getBackendMangledName(Name); +} + +std::string +InstallAPIVisitor::getMangledCXXThunk(const GlobalDecl &D, + const ThunkInfo &Thunk) const { + SmallString<256> Name; + raw_svector_ostream NameStream(Name); + const auto *Method = cast(D.getDecl()); + if (const auto *Dtor = dyn_cast(Method)) + MC->mangleCXXDtorThunk(Dtor, D.getDtorType(), Thunk.This, NameStream); + else + MC->mangleThunk(Method, Thunk, NameStream); + + return getBackendMangledName(Name); +} + +std::string InstallAPIVisitor::getMangledCtorDtor(const CXXMethodDecl *D, + int Type) const { + SmallString<256> Name; + raw_svector_ostream NameStream(Name); + GlobalDecl GD; + if (const auto *Ctor = dyn_cast(D)) + GD = GlobalDecl(Ctor, CXXCtorType(Type)); + else { + const auto *Dtor = cast(D); + GD = GlobalDecl(Dtor, CXXDtorType(Type)); + } + MC->mangleName(GD, NameStream); + return getBackendMangledName(Name); +} + +void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D, + const AvailabilityInfo &Avail, + const HeaderType Access, + bool EmittedVTable) { + if (hasVTable(D)) { + EmittedVTable = true; + const CXXLinkage VTableLinkage = getVTableLinkage(D); + if (VTableLinkage == CXXLinkage::ExternalLinkage || + VTableLinkage == CXXLinkage::WeakODRLinkage) { + const std::string Name = getMangledCXXVTableName(D); + const bool WeakDef = VTableLinkage == CXXLinkage::WeakODRLinkage; + Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Variable, Avail, D, Access, + getFlags(WeakDef)); + if (!D->getDescribedClassTemplate() && !D->isInvalidDecl()) { + VTableContextBase *VTable = D->getASTContext().getVTableContext(); + auto AddThunk = [&](GlobalDecl GD) { + const ItaniumVTableContext::ThunkInfoVectorTy *Thunks = + VTable->getThunkInfo(GD); + if (!Thunks) + return; + + for (const auto &Thunk : *Thunks) { + const std::string Name = getMangledCXXThunk(GD, Thunk); + Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Function, Avail, + GD.getDecl(), Access); + } + }; + + for (const auto *Method : D->methods()) { + if (isa(Method) || !Method->isVirtual()) + continue; + + if (auto Dtor = dyn_cast(Method)) { + // Skip default destructor. + if (Dtor->isDefaulted()) + continue; + AddThunk({Dtor, Dtor_Deleting}); + AddThunk({Dtor, Dtor_Complete}); + } else + AddThunk(Method); + } + } + } + } + + if (!EmittedVTable) + return; + + if (hasRTTI(D)) { + std::string Name = getMangledCXXRTTI(D); + Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Variable, Avail, D, Access); + + Name = getMangledCXXRTTIName(D); + Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Variable, Avail, D, Access); + } + + for (const auto &It : D->bases()) { + const CXXRecordDecl *Base = + cast(It.getType()->castAs()->getDecl()); + const auto BaseAccess = getAccessForDecl(Base); + if (!BaseAccess) + continue; + const AvailabilityInfo BaseAvail = AvailabilityInfo::createFromDecl(Base); + emitVTableSymbols(Base, BaseAvail, *BaseAccess, /*EmittedVTable=*/true); + } +} + +bool InstallAPIVisitor::VisitCXXRecordDecl(const CXXRecordDecl *D) { + if (!D->isCompleteDefinition()) + return true; + + // Skip templated classes. + if (D->getDescribedClassTemplate() != nullptr) + return true; + + // Skip partial templated classes too. + if (isa(D)) + return true; + + auto Access = getAccessForDecl(D); + if (!Access) + return true; + const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D); + + // Check whether to emit the vtable/rtti symbols. + if (isExported(D)) + emitVTableSymbols(D, Avail, *Access); + + TemplateSpecializationKind ClassSK = TSK_Undeclared; + bool KeepInlineAsWeak = false; + if (auto *Templ = dyn_cast(D)) { + ClassSK = Templ->getTemplateSpecializationKind(); + if (ClassSK == TSK_ExplicitInstantiationDeclaration) + KeepInlineAsWeak = true; + } + + // Record the class methods. + for (const auto *M : D->methods()) { + // Inlined methods are usually not emitted, except when it comes from a + // specialized template. + bool WeakDef = false; + if (isInlined(M)) { + if (!KeepInlineAsWeak) + continue; + + WeakDef = true; + } + + if (!isExported(M)) + continue; + + switch (M->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + break; + case TSK_ImplicitInstantiation: + continue; + case TSK_ExplicitInstantiationDeclaration: + if (ClassSK == TSK_ExplicitInstantiationDeclaration) + WeakDef = true; + break; + case TSK_ExplicitInstantiationDefinition: + WeakDef = true; + break; + } + + if (!M->isUserProvided()) + continue; + + // Methods that are deleted are not exported. + if (M->isDeleted()) + continue; + + const auto Access = getAccessForDecl(M); + if (!Access) + return true; + const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(M); + + if (const auto *Ctor = dyn_cast(M)) { + // Defaulted constructors are not exported. + if (Ctor->isDefaulted()) + continue; + + std::string Name = getMangledCtorDtor(M, Ctor_Base); + Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Function, Avail, D, *Access, + getFlags(WeakDef)); + + if (!D->isAbstract()) { + std::string Name = getMangledCtorDtor(M, Ctor_Complete); + Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Function, Avail, D, *Access, + getFlags(WeakDef)); + } + + continue; + } + + if (const auto *Dtor = dyn_cast(M)) { + // Defaulted destructors are not exported. + if (Dtor->isDefaulted()) + continue; + + std::string Name = getMangledCtorDtor(M, Dtor_Base); + Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Function, Avail, D, *Access, + getFlags(WeakDef)); + + Name = getMangledCtorDtor(M, Dtor_Complete); + Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Function, Avail, D, *Access, + getFlags(WeakDef)); + + if (Dtor->isVirtual()) { + Name = getMangledCtorDtor(M, Dtor_Deleting); + Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Function, Avail, D, *Access, + getFlags(WeakDef)); + } + + continue; + } + + // Though abstract methods can map to exports, this is generally unexpected. + // Except in the case of destructors. Only ignore pure virtuals after + // checking if the member function was a destructor. + if (M->isPureVirtual()) + continue; + + std::string Name = getMangledName(M); + Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Function, Avail, D, *Access, + getFlags(WeakDef)); + } + + if (auto *Templ = dyn_cast(D)) { + if (!Templ->isExplicitInstantiationOrSpecialization()) + return true; + } + + using var_iter = CXXRecordDecl::specific_decl_iterator; + using var_range = iterator_range; + for (const auto *Var : var_range(D->decls())) { + // Skip const static member variables. + // \code + // struct S { + // static const int x = 0; + // }; + // \endcode + if (Var->isStaticDataMember() && Var->hasInit()) + continue; + + // Skip unexported var decls. + if (!isExported(Var)) + continue; + + const std::string Name = getMangledName(Var); + const auto Access = getAccessForDecl(Var); + if (!Access) + return true; + const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(Var); + const bool WeakDef = Var->hasAttr() || KeepInlineAsWeak; + + Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Variable, Avail, D, *Access, + getFlags(WeakDef)); + } + return true; } diff --git a/clang/test/InstallAPI/cpp.test b/clang/test/InstallAPI/cpp.test new file mode 100644 index 000000000000..481789909530 --- /dev/null +++ b/clang/test/InstallAPI/cpp.test @@ -0,0 +1,530 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json + +// Invoke C++ with no-rtti. +// RUN: clang-installapi -target arm64-apple-macos13.1 \ +// RUN: -I%t/usr/include -I%t/usr/local/include -x c++ \ +// RUN: -install_name @rpath/lib/libcpp.dylib -fno-rtti \ +// RUN: %t/inputs.json -o %t/no-rtti.tbd 2>&1 | FileCheck %s --allow-empty + +// RUN: llvm-readtapi -compare %t/no-rtti.tbd \ +// RUN: %t/expected-no-rtti.tbd 2>&1 | FileCheck %s --allow-empty + +// Invoke C++ with rtti. +// RUN: clang-installapi -target arm64-apple-macos13.1 \ +// RUN: -I%t/usr/include -I%t/usr/local/include -x c++ \ +// RUN: -install_name @rpath/lib/libcpp.dylib -frtti \ +// RUN: %t/inputs.json -o %t/rtti.tbd 2>&1 | FileCheck %s --allow-empty +// RUN: llvm-readtapi -compare %t/rtti.tbd \ +// RUN: %t/expected-rtti.tbd 2>&1 | FileCheck %s --allow-empty + +// CHECK-NOT: error: +// CHECK-NOT: warning: + +//--- usr/include/basic.h +#ifndef CPP_H +#define CPP_H + +inline int foo(int x) { return x + 1; } + +extern int bar(int x) { return x + 1; } + +inline int baz(int x) { + static const int a[] = {1, 2, 3}; + return a[x]; +} + +extern "C" { + int cFunc(const char*); +} + +class Bar { +public: + static const int x = 0; + static int y; + + inline int func1(int x) { return x + 2; } + inline int func2(int x); + int func3(int x); +}; + +class __attribute__((visibility("hidden"))) BarI { + static const int x = 0; + static int y; + + inline int func1(int x) { return x + 2; } + inline int func2(int x); + int func3(int x); +}; + +int Bar::func2(int x) { return x + 3; } +inline int Bar::func3(int x) { return x + 4; } + +int BarI::func2(int x) { return x + 3; } +inline int BarI::func3(int x) { return x + 4; } +#endif + +//--- usr/local/include/vtable.h +// Simple test class with no virtual functions. There should be no vtable or +// RTTI. +namespace test1 { +class Simple { +public: + void run(); +}; +} // end namespace test1 + +// Simple test class with virtual function. There should be an external vtable +// and RTTI. +namespace test2 { +class Simple { +public: + virtual void run(); +}; +} // end namespace test2 + +// Abstract class with no sub classes. There should be no vtable or RTTI. +namespace test3 { +class Abstract { +public: + virtual ~Abstract() {} + virtual void run() = 0; +}; +} // end namespace test3 + +// Abstract base class with a sub class. There should be weak-def RTTI for the +// abstract base class. +// The sub-class should have vtable and RTTI. +namespace test4 { +class Base { +public: + virtual ~Base() {} + virtual void run() = 0; +}; + +class Sub : public Base { +public: + void run() override; +}; +} // end namespace test4 + +// Abstract base class with a sub class. Same as above, but with a user defined +// inlined destructor. +namespace test5 { +class Base { +public: + virtual ~Base() {} + virtual void run() = 0; +}; + +class Sub : public Base { +public: + virtual ~Sub() {} + void run() override; +}; +} // end namespace test5 + +// Abstract base class with a sub class. Same as above, but with a different +// inlined key method. +namespace test6 { +class Base { +public: + virtual ~Base() {} + virtual void run() = 0; +}; + +class Sub : public Base { +public: + virtual void foo() {} + void run() override; +}; +} // end namespace test6 + +// Abstract base class with a sub class. Overloaded method is implemented +// inline. No vtable or RTTI. +namespace test7 { +class Base { +public: + virtual ~Base() {} + virtual bool run() = 0; +}; + +class Sub : public Base { +public: + bool run() override { return true; } +}; +} // end namespace test7 + +// Abstract base class with a sub class. Overloaded method has no inline +// attribute and is recognized as key method, +// but is later implemented inline. Weak-def RTTI only. +namespace test8 { +class Base { +public: + virtual ~Base() {} + virtual void run() = 0; +}; + +class Sub : public Base { +public: + void run() override; +}; + +inline void Sub::run() {} +} // end namespace test8 + +namespace test9 { +class Base { +public: + virtual ~Base() {} + virtual void run1() = 0; + virtual void run2() = 0; +}; + +class Sub : public Base { +public: + void run1() override {} + void run2() override; +}; + +inline void Sub::run2() {} +} // end namespace test9 + +namespace test10 { +class Base { +public: + virtual ~Base() {} + virtual void run1() = 0; + virtual void run2() = 0; +}; + +class Sub : public Base { +public: + void run1() override {} + inline void run2() override; +}; + +void Sub::run2() {} +} // end namespace test10 + +namespace test11 { +class Base { +public: + virtual ~Base() {} + virtual void run1() = 0; + virtual void run2() = 0; + virtual void run3() = 0; +}; + +class Sub : public Base { +public: + void run1() override {} + void run2() override; + void run3() override; +}; + +inline void Sub::run2() {} +} // end namespace test11 + +namespace test12 { +template class Simple { +public: + virtual void foo() {} +}; +extern template class Simple; +} // end namespace test12 + +namespace test13 { +class Base { +public: + virtual ~Base() {} + virtual void run1() = 0; + virtual void run2() {}; + virtual void run3(); // key function. +}; + +class Sub : public Base { +public: + void run1() override {} + void run2() override {} +}; + +} // end namespace test13 + +namespace test14 { + +class __attribute__((visibility("hidden"))) Base +{ +public: + Base() {} + virtual ~Base(); // keyfunction. + virtual void run1() const = 0; +}; + +class Sub : public Base +{ +public: + Sub(); + virtual ~Sub(); + virtual void run1() const; + void run2() const {} +}; + +} // end namespace test14 + +namespace test15 { + +class Base { +public: + virtual ~Base() {} + virtual void run() {}; +}; + +class Base1 { +public: + virtual ~Base1() {} + virtual void run1() {}; +}; + +class Sub : public Base, public Base1 { +public: + Sub() {} + ~Sub(); + void run() override; + void run1() override; +}; + +class Sub1 : public Base, public Base1 { +public: + Sub1() {} + ~Sub1() = default; + void run() override; + void run1() override; +}; + +} // end namespace test15 + +//--- usr/local/include/templates.h +#ifndef TEMPLATES_H +#define TEMPLATES_H + +namespace templates { + +// Full specialization. +template int foo1(T a) { return 1; } +template <> int foo1(int a); +extern template int foo1(short a); + +template int foo2(T a); + +// Partial specialization. +template class Partial { + static int run(A a, B b) { return a + b; } +}; + +template class Partial { + static int run(A a, int b) { return a - b; } +}; + +template class Foo { +public: + Foo(); + ~Foo(); +}; + +template class Bar { +public: + Bar(); + ~Bar() {} + + inline int bazinga() { return 7; } +}; + +extern template class Bar; + +class Bazz { +public: + Bazz() {} + + template int buzz(T a); + + float implicit() const { return foo1(0.0f); } +}; + +template int Bazz::buzz(T a) { return sizeof(T); } + +template struct S { static int x; }; + +template int S::x = 0; + +} // end namespace templates. + +#endif + + +//--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/usr/include/basic.h", + "type" : "public" + }, + { + "path" : "DSTROOT/usr/local/include/vtable.h", + "type" : "private" + }, + { + "path" : "DSTROOT/usr/local/include/templates.h", + "type" : "private" + } + ], + "version": "3" +} + +//--- expected-no-rtti.tbd +{ + "main_library": { + "compatibility_versions": [ + { + "version": "0" + } + ], + "current_versions": [ + { + "version": "0" + } + ], + "exported_symbols": [ + { + "data": { + "global": [ + "__ZTVN6test143SubE", "__ZTVN6test113SubE", "__ZTVN5test26SimpleE", + "__ZTVN5test53SubE", "__ZTVN6test154Sub1E", "__ZTVN6test153SubE", + "__ZN3Bar1yE", "__ZTVN5test43SubE", "__ZTVN5test63SubE", + "__ZTVN6test134BaseE" + ], + "weak": [ + "__ZTVN6test126SimpleIiEE" + ] + }, + "text": { + "global": [ + "__ZN6test153Sub3runEv", "__ZN6test154Sub13runEv", + "__Z3bari", "__ZThn8_N6test153SubD1Ev", + "__ZNK6test143Sub4run1Ev", "__ZN6test154Sub14run1Ev", + "__ZThn8_N6test153Sub4run1Ev", "__ZN6test143SubD1Ev", + "__ZN6test134Base4run3Ev", "__ZN5test16Simple3runEv", + "__ZN5test43Sub3runEv", "__ZN6test113Sub4run3Ev", "__ZN6test153SubD2Ev", + "__ZN5test53Sub3runEv", "__ZN6test153SubD1Ev", "__ZN6test143SubC1Ev", + "__ZN9templates4foo1IiEEiT_", "__ZN6test143SubC2Ev", "__ZN5test63Sub3runEv", + "__ZN5test26Simple3runEv", "__ZN6test153SubD0Ev", + "__ZN6test143SubD2Ev", "__ZN6test153Sub4run1Ev", "__ZN6test143SubD0Ev", + "__ZThn8_N6test153SubD0Ev", "__ZThn8_N6test154Sub14run1Ev", "_cFunc" + ], + "weak": [ + "__ZN9templates3BarIiED2Ev", "__ZN9templates3BarIiEC2Ev", + "__ZN9templates3BarIiEC1Ev", "__ZN9templates3BarIiED1Ev", + "__ZN6test126SimpleIiE3fooEv", "__ZN9templates3BarIiE7bazingaEv", + "__ZN9templates4foo1IsEEiT_" + ] + } + } + ], + "flags": [ + { + "attributes": [ + "not_app_extension_safe" + ] + } + ], + "install_names": [ + { + "name": "@rpath/lib/libcpp.dylib" + } + ], + "target_info": [ + { + "min_deployment": "13.1", + "target": "arm64-macos" + } + ] + }, + "tapi_tbd_version": 5 +} + +//--- expected-rtti.tbd +{ + "main_library": { + "compatibility_versions": [ + { + "version": "0" + } + ], + "current_versions": [ + { + "version": "0" + } + ], + "exported_symbols": [ + { + "data": { + "global": [ + "__ZTVN6test143SubE", "__ZTIN5test63SubE", "__ZTSN5test26SimpleE", + "__ZTIN6test153SubE", "__ZTVN6test113SubE", "__ZTIN5test43SubE", + "__ZTIN6test134BaseE", "__ZTVN5test26SimpleE", "__ZTIN5test26SimpleE", + "__ZTSN6test134BaseE", "__ZTVN6test154Sub1E", "__ZTVN5test43SubE", + "__ZTVN5test63SubE", "__ZTSN5test43SubE", "__ZTSN6test113SubE", + "__ZTIN6test154Sub1E", "__ZTSN6test153SubE", "__ZTSN5test63SubE", + "__ZTSN6test154Sub1E", "__ZTIN6test113SubE", "__ZTSN6test143SubE", + "__ZTVN5test53SubE", "__ZTIN6test143SubE", "__ZTVN6test153SubE", + "__ZTIN5test53SubE", "__ZN3Bar1yE", "__ZTVN6test134BaseE", + "__ZTSN5test53SubE" + ], + "weak": [ + "__ZTVN6test126SimpleIiEE" + ] + }, + "text": { + "global": [ + "__ZN6test154Sub13runEv", "__ZN6test153Sub3runEv", "__ZNK6test143Sub4run1Ev", + "__ZN6test134Base4run3Ev", "__ZN5test16Simple3runEv", "__ZN6test153SubD2Ev", + "__ZN6test143SubC2Ev", "__ZN5test63Sub3runEv", "__ZN6test153SubD0Ev", + "__ZN6test143SubD2Ev", "__ZThn8_N6test154Sub14run1Ev", + "__ZThn8_N6test153SubD0Ev", "__Z3bari", "__ZThn8_N6test153SubD1Ev", + "__ZN6test154Sub14run1Ev", "__ZThn8_N6test153Sub4run1Ev", + "__ZN6test143SubD1Ev", "__ZN5test43Sub3runEv", + "__ZN6test113Sub4run3Ev", "__ZN5test53Sub3runEv", "__ZN6test143SubC1Ev", + "__ZN6test153SubD1Ev", "__ZN9templates4foo1IiEEiT_", "__ZN5test26Simple3runEv", + "__ZN6test153Sub4run1Ev", "__ZN6test143SubD0Ev", "_cFunc" + ], + "weak": [ + "__ZN9templates3BarIiEC2Ev", "__ZN9templates3BarIiEC1Ev", + "__ZN9templates3BarIiED1Ev", "__ZN6test126SimpleIiE3fooEv", + "__ZN9templates4foo1IsEEiT_", "__ZN9templates3BarIiED2Ev", + "__ZN9templates3BarIiE7bazingaEv" + ] + } + } + ], + "flags": [ + { + "attributes": [ + "not_app_extension_safe" + ] + } + ], + "install_names": [ + { + "name": "@rpath/lib/libcpp.dylib" + } + ], + "target_info": [ + { + "min_deployment": "13.1", + "target": "arm64-macos" + } + ] + }, + "tapi_tbd_version": 5 +} + diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp index b9c36eab2ad3..701ab81c57c3 100644 --- a/clang/tools/clang-installapi/Options.cpp +++ b/clang/tools/clang-installapi/Options.cpp @@ -99,6 +99,33 @@ bool Options::processLinkerOptions(InputArgList &Args) { return true; } +bool Options::processFrontendOptions(InputArgList &Args) { + // Do not claim any arguments, as they will be passed along for CC1 + // invocations. + if (auto *A = Args.getLastArgNoClaim(OPT_x)) { + FEOpts.LangMode = llvm::StringSwitch(A->getValue()) + .Case("c", clang::Language::C) + .Case("c++", clang::Language::CXX) + .Case("objective-c", clang::Language::ObjC) + .Case("objective-c++", clang::Language::ObjCXX) + .Default(clang::Language::Unknown); + + if (FEOpts.LangMode == clang::Language::Unknown) { + Diags->Report(clang::diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + return false; + } + } + for (auto *A : Args.filtered(OPT_ObjC, OPT_ObjCXX)) { + if (A->getOption().matches(OPT_ObjC)) + FEOpts.LangMode = clang::Language::ObjC; + else + FEOpts.LangMode = clang::Language::ObjCXX; + } + + return true; +} + Options::Options(DiagnosticsEngine &Diag, FileManager *FM, InputArgList &ArgList) : Diags(&Diag), FM(FM) { @@ -108,7 +135,10 @@ Options::Options(DiagnosticsEngine &Diag, FileManager *FM, if (!processLinkerOptions(ArgList)) return; - /// Any remaining arguments should be handled by invoking the clang frontend. + if (!processFrontendOptions(ArgList)) + return; + + /// Any unclaimed arguments should be handled by invoking the clang frontend. for (const Arg *A : ArgList) { if (A->isClaimed()) continue; @@ -132,6 +162,7 @@ InstallAPIContext Options::createContext() { Ctx.BA.AppExtensionSafe = LinkerOpts.AppExtensionSafe; Ctx.FT = DriverOpts.OutFT; Ctx.OutputLoc = DriverOpts.OutputPath; + Ctx.LangMode = FEOpts.LangMode; // Process inputs. for (const std::string &ListPath : DriverOpts.FileLists) { diff --git a/clang/tools/clang-installapi/Options.h b/clang/tools/clang-installapi/Options.h index f68addf19728..9d4d841284fd 100644 --- a/clang/tools/clang-installapi/Options.h +++ b/clang/tools/clang-installapi/Options.h @@ -62,15 +62,22 @@ struct LinkerOptions { bool IsDylib = false; }; +struct FrontendOptions { + /// \brief The language mode to parse headers in. + Language LangMode = Language::ObjC; +}; + class Options { private: bool processDriverOptions(llvm::opt::InputArgList &Args); bool processLinkerOptions(llvm::opt::InputArgList &Args); + bool processFrontendOptions(llvm::opt::InputArgList &Args); public: /// The various options grouped together. DriverOptions DriverOpts; LinkerOptions LinkerOpts; + FrontendOptions FEOpts; Options() = delete; -- GitLab From 34acdb3ec2113265ea221fb20747ecbffb4f6a2d Mon Sep 17 00:00:00 2001 From: annamthomas Date: Mon, 11 Mar 2024 12:16:52 -0400 Subject: [PATCH 135/953] Precommit testcase for pr81872 (#84782) Testcase shows miscompile when dropping disjoint flag from disjoint or during vectorization. --- .../Transforms/LoopVectorize/X86/pr81872.ll | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 llvm/test/Transforms/LoopVectorize/X86/pr81872.ll diff --git a/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll b/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll new file mode 100644 index 000000000000..c6b1944b2009 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll @@ -0,0 +1,109 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -passes=loop-vectorize < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@global = external global ptr addrspace(1), align 8 + +; PR 81872 explains the issue. + +; If we vectorize, we have a miscompile where array IV and thereby value stored in (arr[99], +; arr[98]) is calculated incorrectly since disjoint or was only disjoint because +; of dominating conditions. Dropping the disjoint to avoid poison still changes +; the behaviour since now the or is no longer equivalent to the add. +; Function Attrs: uwtable +define void @test(ptr noundef align 8 dereferenceable_or_null(16) %arr) #0 { +; CHECK-LABEL: define void @test( +; CHECK-SAME: ptr noundef align 8 dereferenceable_or_null(16) [[ARR:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: bb5: +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]], !prof [[PROF0:![0-9]+]] +; CHECK: vector.ph: +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i64> [ , [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = sub i64 99, [[INDEX]] +; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[OFFSET_IDX]], 0 +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i64> poison, i64 [[INDEX]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT]], <4 x i64> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[VEC_IV:%.*]] = add <4 x i64> [[BROADCAST_SPLAT]], +; CHECK-NEXT: [[TMP1:%.*]] = icmp ule <4 x i64> [[VEC_IV]], +; CHECK-NEXT: [[TMP2:%.*]] = and <4 x i64> [[VEC_IND]], +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <4 x i64> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = select <4 x i1> [[TMP1]], <4 x i1> [[TMP3]], <4 x i1> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = or i64 [[TMP0]], 1 +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i64, ptr [[ARR]], i64 [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i64, ptr [[TMP6]], i32 0 +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i64, ptr [[TMP7]], i32 -3 +; CHECK-NEXT: [[REVERSE:%.*]] = shufflevector <4 x i1> [[TMP4]], <4 x i1> poison, <4 x i32> +; CHECK-NEXT: call void @llvm.masked.store.v4i64.p0(<4 x i64> , ptr [[TMP8]], i32 8, <4 x i1> [[REVERSE]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 +; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], +; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], 12 +; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !prof [[PROF1:![0-9]+]], !llvm.loop [[LOOP2:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: br i1 true, label [[BB6:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 87, [[MIDDLE_BLOCK]] ], [ 99, [[BB5:%.*]] ] +; CHECK-NEXT: br label [[BB15:%.*]] +; CHECK: bb15: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[BB20:%.*]] ] +; CHECK-NEXT: [[AND:%.*]] = and i64 [[IV]], 1 +; CHECK-NEXT: [[ICMP17:%.*]] = icmp eq i64 [[AND]], 0 +; CHECK-NEXT: br i1 [[ICMP17]], label [[BB18:%.*]], label [[BB20]], !prof [[PROF5:![0-9]+]] +; CHECK: bb18: +; CHECK-NEXT: [[OR:%.*]] = or disjoint i64 [[IV]], 1 +; CHECK-NEXT: [[GETELEMENTPTR19:%.*]] = getelementptr inbounds i64, ptr [[ARR]], i64 [[OR]] +; CHECK-NEXT: store i64 1, ptr [[GETELEMENTPTR19]], align 8 +; CHECK-NEXT: br label [[BB20]] +; CHECK: bb20: +; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], -1 +; CHECK-NEXT: [[ICMP22:%.*]] = icmp eq i64 [[IV_NEXT]], 90 +; CHECK-NEXT: br i1 [[ICMP22]], label [[BB6]], label [[BB15]], !prof [[PROF6:![0-9]+]], !llvm.loop [[LOOP7:![0-9]+]] +; CHECK: bb6: +; CHECK-NEXT: ret void +; +bb5: + br label %bb15 + +bb15: ; preds = %bb20, %bb8 + %iv = phi i64 [ 99, %bb5 ], [ %iv.next, %bb20 ] + %and = and i64 %iv, 1 + %icmp17 = icmp eq i64 %and, 0 + br i1 %icmp17, label %bb18, label %bb20, !prof !21 + +bb18: ; preds = %bb15 + %or = or disjoint i64 %iv, 1 + %getelementptr19 = getelementptr inbounds i64, ptr %arr, i64 %or + store i64 1, ptr %getelementptr19, align 8 + br label %bb20 + +bb20: ; preds = %bb18, %bb15 + %iv.next = add nsw i64 %iv, -1 + %icmp22 = icmp eq i64 %iv.next, 90 + br i1 %icmp22, label %bb6, label %bb15, !prof !22 + +bb6: + ret void +} + +attributes #0 = {"target-cpu"="haswell" "target-features"="+avx2" } + +!4 = !{} +!10 = !{i32 1} +!16 = !{i64 864} +!17 = !{i64 8} +!21 = !{!"branch_weights", i32 1, i32 1} +!22 = !{!"branch_weights", i32 1, i32 95} + + +;. +; CHECK: [[PROF0]] = !{!"branch_weights", i32 1, i32 127} +; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 23} +; CHECK: [[LOOP2]] = distinct !{[[LOOP2]], [[META3:![0-9]+]], [[META4:![0-9]+]]} +; CHECK: [[META3]] = !{!"llvm.loop.isvectorized", i32 1} +; CHECK: [[META4]] = !{!"llvm.loop.unroll.runtime.disable"} +; CHECK: [[PROF5]] = !{!"branch_weights", i32 1, i32 1} +; CHECK: [[PROF6]] = !{!"branch_weights", i32 0, i32 0} +; CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[META4]], [[META3]]} +;. -- GitLab From 7dc4d5f6a0012d6a2485640f6c3c9ca388a02433 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 11 Mar 2024 16:22:18 +0000 Subject: [PATCH 136/953] [X86] Add AVX512 (x86-64-v4) coverage to generic shift combines tests --- llvm/test/CodeGen/X86/combine-shl.ll | 248 +++++++++++++++++---------- llvm/test/CodeGen/X86/combine-sra.ll | 79 ++++++--- llvm/test/CodeGen/X86/combine-srl.ll | 108 ++++++++---- 3 files changed, 293 insertions(+), 142 deletions(-) diff --git a/llvm/test/CodeGen/X86/combine-shl.ll b/llvm/test/CodeGen/X86/combine-shl.ll index b485a9b10f26..5472e1e6c083 100644 --- a/llvm/test/CodeGen/X86/combine-shl.ll +++ b/llvm/test/CodeGen/X86/combine-shl.ll @@ -1,9 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefixes=CHECK,SSE,SSE2 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.1 | FileCheck %s --check-prefixes=CHECK,SSE,SSE41 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=CHECK,AVX,AVX-SLOW -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-crosslane-shuffle,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX-FAST-ALL -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX-FAST-PERLANE +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-SLOW +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-crosslane-shuffle,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-FAST-ALL +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-FAST-PERLANE +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=x86-64-v4 | FileCheck %s --check-prefixes=CHECK,AVX,AVX512 ; fold (shl 0, x) -> 0 define <4 x i32> @combine_vec_shl_zero(<4 x i32> %x) { @@ -137,32 +138,40 @@ define <4 x i32> @combine_vec_shl_trunc_and(<4 x i32> %x, <4 x i64> %y) { ; SSE41-NEXT: pmulld %xmm1, %xmm0 ; SSE41-NEXT: retq ; -; AVX-SLOW-LABEL: combine_vec_shl_trunc_and: -; AVX-SLOW: # %bb.0: -; AVX-SLOW-NEXT: vextractf128 $1, %ymm1, %xmm2 -; AVX-SLOW-NEXT: vshufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] -; AVX-SLOW-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 -; AVX-SLOW-NEXT: vpsllvd %xmm1, %xmm0, %xmm0 -; AVX-SLOW-NEXT: vzeroupper -; AVX-SLOW-NEXT: retq -; -; AVX-FAST-ALL-LABEL: combine_vec_shl_trunc_and: -; AVX-FAST-ALL: # %bb.0: -; AVX-FAST-ALL-NEXT: vpmovsxbd {{.*#+}} ymm2 = [0,2,4,6,0,0,0,0] -; AVX-FAST-ALL-NEXT: vpermd %ymm1, %ymm2, %ymm1 -; AVX-FAST-ALL-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 -; AVX-FAST-ALL-NEXT: vpsllvd %xmm1, %xmm0, %xmm0 -; AVX-FAST-ALL-NEXT: vzeroupper -; AVX-FAST-ALL-NEXT: retq -; -; AVX-FAST-PERLANE-LABEL: combine_vec_shl_trunc_and: -; AVX-FAST-PERLANE: # %bb.0: -; AVX-FAST-PERLANE-NEXT: vextractf128 $1, %ymm1, %xmm2 -; AVX-FAST-PERLANE-NEXT: vshufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] -; AVX-FAST-PERLANE-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 -; AVX-FAST-PERLANE-NEXT: vpsllvd %xmm1, %xmm0, %xmm0 -; AVX-FAST-PERLANE-NEXT: vzeroupper -; AVX-FAST-PERLANE-NEXT: retq +; AVX2-SLOW-LABEL: combine_vec_shl_trunc_and: +; AVX2-SLOW: # %bb.0: +; AVX2-SLOW-NEXT: vextractf128 $1, %ymm1, %xmm2 +; AVX2-SLOW-NEXT: vshufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; AVX2-SLOW-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 +; AVX2-SLOW-NEXT: vpsllvd %xmm1, %xmm0, %xmm0 +; AVX2-SLOW-NEXT: vzeroupper +; AVX2-SLOW-NEXT: retq +; +; AVX2-FAST-ALL-LABEL: combine_vec_shl_trunc_and: +; AVX2-FAST-ALL: # %bb.0: +; AVX2-FAST-ALL-NEXT: vpmovsxbd {{.*#+}} ymm2 = [0,2,4,6,0,0,0,0] +; AVX2-FAST-ALL-NEXT: vpermd %ymm1, %ymm2, %ymm1 +; AVX2-FAST-ALL-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 +; AVX2-FAST-ALL-NEXT: vpsllvd %xmm1, %xmm0, %xmm0 +; AVX2-FAST-ALL-NEXT: vzeroupper +; AVX2-FAST-ALL-NEXT: retq +; +; AVX2-FAST-PERLANE-LABEL: combine_vec_shl_trunc_and: +; AVX2-FAST-PERLANE: # %bb.0: +; AVX2-FAST-PERLANE-NEXT: vextractf128 $1, %ymm1, %xmm2 +; AVX2-FAST-PERLANE-NEXT: vshufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; AVX2-FAST-PERLANE-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 +; AVX2-FAST-PERLANE-NEXT: vpsllvd %xmm1, %xmm0, %xmm0 +; AVX2-FAST-PERLANE-NEXT: vzeroupper +; AVX2-FAST-PERLANE-NEXT: retq +; +; AVX512-LABEL: combine_vec_shl_trunc_and: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovqd %ymm1, %xmm1 +; AVX512-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 +; AVX512-NEXT: vpsllvd %xmm1, %xmm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq %1 = and <4 x i64> %y, %2 = trunc <4 x i64> %1 to <4 x i32> %3 = shl <4 x i32> %x, %2 @@ -353,11 +362,17 @@ define <8 x i32> @combine_vec_shl_zext_lshr0(<8 x i16> %x) { ; SSE41-NEXT: punpckhwd {{.*#+}} xmm1 = xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7] ; SSE41-NEXT: retq ; -; AVX-LABEL: combine_vec_shl_zext_lshr0: -; AVX: # %bb.0: -; AVX-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 -; AVX-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_shl_zext_lshr0: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_shl_zext_lshr0: +; AVX512: # %bb.0: +; AVX512-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm0 +; AVX512-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX512-NEXT: retq %1 = lshr <8 x i16> %x, %2 = zext <8 x i16> %1 to <8 x i32> %3 = shl <8 x i32> %2, @@ -504,12 +519,18 @@ define <4 x i32> @combine_vec_shl_gt_lshr0(<4 x i32> %x) { ; SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; SSE-NEXT: retq ; -; AVX-LABEL: combine_vec_shl_gt_lshr0: -; AVX: # %bb.0: -; AVX-NEXT: vpslld $2, %xmm0, %xmm0 -; AVX-NEXT: vpbroadcastd {{.*#+}} xmm1 = [4294967264,4294967264,4294967264,4294967264] -; AVX-NEXT: vpand %xmm1, %xmm0, %xmm0 -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_shl_gt_lshr0: +; AVX2: # %bb.0: +; AVX2-NEXT: vpslld $2, %xmm0, %xmm0 +; AVX2-NEXT: vpbroadcastd {{.*#+}} xmm1 = [4294967264,4294967264,4294967264,4294967264] +; AVX2-NEXT: vpand %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_shl_gt_lshr0: +; AVX512: # %bb.0: +; AVX512-NEXT: vpslld $2, %xmm0, %xmm0 +; AVX512-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm0 +; AVX512-NEXT: retq %1 = lshr <4 x i32> %x, %2 = shl <4 x i32> %1, ret <4 x i32> %2 @@ -540,12 +561,18 @@ define <4 x i32> @combine_vec_shl_le_lshr0(<4 x i32> %x) { ; SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; SSE-NEXT: retq ; -; AVX-LABEL: combine_vec_shl_le_lshr0: -; AVX: # %bb.0: -; AVX-NEXT: vpsrld $2, %xmm0, %xmm0 -; AVX-NEXT: vpbroadcastd {{.*#+}} xmm1 = [1073741816,1073741816,1073741816,1073741816] -; AVX-NEXT: vpand %xmm1, %xmm0, %xmm0 -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_shl_le_lshr0: +; AVX2: # %bb.0: +; AVX2-NEXT: vpsrld $2, %xmm0, %xmm0 +; AVX2-NEXT: vpbroadcastd {{.*#+}} xmm1 = [1073741816,1073741816,1073741816,1073741816] +; AVX2-NEXT: vpand %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_shl_le_lshr0: +; AVX512: # %bb.0: +; AVX512-NEXT: vpsrld $2, %xmm0, %xmm0 +; AVX512-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm0 +; AVX512-NEXT: retq %1 = lshr <4 x i32> %x, %2 = shl <4 x i32> %1, ret <4 x i32> %2 @@ -587,11 +614,16 @@ define <4 x i32> @combine_vec_shl_ashr0(<4 x i32> %x) { ; SSE-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; SSE-NEXT: retq ; -; AVX-LABEL: combine_vec_shl_ashr0: -; AVX: # %bb.0: -; AVX-NEXT: vbroadcastss {{.*#+}} xmm1 = [4294967264,4294967264,4294967264,4294967264] -; AVX-NEXT: vandps %xmm1, %xmm0, %xmm0 -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_shl_ashr0: +; AVX2: # %bb.0: +; AVX2-NEXT: vbroadcastss {{.*#+}} xmm1 = [4294967264,4294967264,4294967264,4294967264] +; AVX2-NEXT: vandps %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_shl_ashr0: +; AVX512: # %bb.0: +; AVX512-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm0 +; AVX512-NEXT: retq %1 = ashr <4 x i32> %x, %2 = shl <4 x i32> %1, ret <4 x i32> %2 @@ -620,12 +652,18 @@ define <4 x i32> @combine_vec_shl_add0(<4 x i32> %x) { ; SSE-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; SSE-NEXT: retq ; -; AVX-LABEL: combine_vec_shl_add0: -; AVX: # %bb.0: -; AVX-NEXT: vpslld $2, %xmm0, %xmm0 -; AVX-NEXT: vpbroadcastd {{.*#+}} xmm1 = [20,20,20,20] -; AVX-NEXT: vpaddd %xmm1, %xmm0, %xmm0 -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_shl_add0: +; AVX2: # %bb.0: +; AVX2-NEXT: vpslld $2, %xmm0, %xmm0 +; AVX2-NEXT: vpbroadcastd {{.*#+}} xmm1 = [20,20,20,20] +; AVX2-NEXT: vpaddd %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_shl_add0: +; AVX512: # %bb.0: +; AVX512-NEXT: vpslld $2, %xmm0, %xmm0 +; AVX512-NEXT: vpaddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm0 +; AVX512-NEXT: retq %1 = add <4 x i32> %x, %2 = shl <4 x i32> %1, ret <4 x i32> %2 @@ -667,12 +705,18 @@ define <4 x i32> @combine_vec_shl_or0(<4 x i32> %x) { ; SSE-NEXT: por {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; SSE-NEXT: retq ; -; AVX-LABEL: combine_vec_shl_or0: -; AVX: # %bb.0: -; AVX-NEXT: vpslld $2, %xmm0, %xmm0 -; AVX-NEXT: vpbroadcastd {{.*#+}} xmm1 = [20,20,20,20] -; AVX-NEXT: vpor %xmm1, %xmm0, %xmm0 -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_shl_or0: +; AVX2: # %bb.0: +; AVX2-NEXT: vpslld $2, %xmm0, %xmm0 +; AVX2-NEXT: vpbroadcastd {{.*#+}} xmm1 = [20,20,20,20] +; AVX2-NEXT: vpor %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_shl_or0: +; AVX512: # %bb.0: +; AVX512-NEXT: vpslld $2, %xmm0, %xmm0 +; AVX512-NEXT: vpord {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm0 +; AVX512-NEXT: retq %1 = or <4 x i32> %x, %2 = shl <4 x i32> %1, ret <4 x i32> %2 @@ -724,11 +768,16 @@ define <4 x i32> @combine_vec_shl_mul0(<4 x i32> %x) { ; SSE41-NEXT: pmulld {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; SSE41-NEXT: retq ; -; AVX-LABEL: combine_vec_shl_mul0: -; AVX: # %bb.0: -; AVX-NEXT: vpbroadcastd {{.*#+}} xmm1 = [20,20,20,20] -; AVX-NEXT: vpmulld %xmm1, %xmm0, %xmm0 -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_shl_mul0: +; AVX2: # %bb.0: +; AVX2-NEXT: vpbroadcastd {{.*#+}} xmm1 = [20,20,20,20] +; AVX2-NEXT: vpmulld %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_shl_mul0: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmulld {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm0 +; AVX512-NEXT: retq %1 = mul <4 x i32> %x, %2 = shl <4 x i32> %1, ret <4 x i32> %2 @@ -778,12 +827,18 @@ define <4 x i32> @combine_vec_add_shl_nonsplat(<4 x i32> %a0) { ; SSE41-NEXT: por {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; SSE41-NEXT: retq ; -; AVX-LABEL: combine_vec_add_shl_nonsplat: -; AVX: # %bb.0: -; AVX-NEXT: vpsllvd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 -; AVX-NEXT: vpbroadcastd {{.*#+}} xmm1 = [3,3,3,3] -; AVX-NEXT: vpor %xmm1, %xmm0, %xmm0 -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_add_shl_nonsplat: +; AVX2: # %bb.0: +; AVX2-NEXT: vpsllvd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX2-NEXT: vpbroadcastd {{.*#+}} xmm1 = [3,3,3,3] +; AVX2-NEXT: vpor %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_add_shl_nonsplat: +; AVX512: # %bb.0: +; AVX512-NEXT: vpsllvd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX512-NEXT: vpord {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm0 +; AVX512-NEXT: retq %1 = shl <4 x i32> %a0, %2 = add <4 x i32> %1, ret <4 x i32> %2 @@ -812,14 +867,22 @@ define <4 x i32> @combine_vec_add_shl_and_nonsplat(<4 x i32> %a0) { ; SSE41-NEXT: por {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; SSE41-NEXT: retq ; -; AVX-LABEL: combine_vec_add_shl_and_nonsplat: -; AVX: # %bb.0: -; AVX-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX-NEXT: vpblendw {{.*#+}} xmm0 = xmm1[0],xmm0[1],xmm1[2],xmm0[3],xmm1[4],xmm0[5],xmm1[6],xmm0[7] -; AVX-NEXT: vpsllvd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 -; AVX-NEXT: vpbroadcastd {{.*#+}} xmm1 = [15,15,15,15] -; AVX-NEXT: vpor %xmm1, %xmm0, %xmm0 -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_add_shl_and_nonsplat: +; AVX2: # %bb.0: +; AVX2-NEXT: vpxor %xmm1, %xmm1, %xmm1 +; AVX2-NEXT: vpblendw {{.*#+}} xmm0 = xmm1[0],xmm0[1],xmm1[2],xmm0[3],xmm1[4],xmm0[5],xmm1[6],xmm0[7] +; AVX2-NEXT: vpsllvd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX2-NEXT: vpbroadcastd {{.*#+}} xmm1 = [15,15,15,15] +; AVX2-NEXT: vpor %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_add_shl_and_nonsplat: +; AVX512: # %bb.0: +; AVX512-NEXT: vpxor %xmm1, %xmm1, %xmm1 +; AVX512-NEXT: vpblendw {{.*#+}} xmm0 = xmm1[0],xmm0[1],xmm1[2],xmm0[3],xmm1[4],xmm0[5],xmm1[6],xmm0[7] +; AVX512-NEXT: vpsllvd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX512-NEXT: vpord {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm0 +; AVX512-NEXT: retq %1 = and <4 x i32> %a0, %2 = shl <4 x i32> %1, %3 = add <4 x i32> %2, @@ -847,13 +910,20 @@ define <4 x i32> @combine_vec_add_shuffle_shl(<4 x i32> %a0) { ; SSE41-NEXT: por {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; SSE41-NEXT: retq ; -; AVX-LABEL: combine_vec_add_shuffle_shl: -; AVX: # %bb.0: -; AVX-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[0,1,1,0] -; AVX-NEXT: vpsllvd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 -; AVX-NEXT: vpbroadcastd {{.*#+}} xmm1 = [3,3,3,3] -; AVX-NEXT: vpor %xmm1, %xmm0, %xmm0 -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_add_shuffle_shl: +; AVX2: # %bb.0: +; AVX2-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[0,1,1,0] +; AVX2-NEXT: vpsllvd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX2-NEXT: vpbroadcastd {{.*#+}} xmm1 = [3,3,3,3] +; AVX2-NEXT: vpor %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_add_shuffle_shl: +; AVX512: # %bb.0: +; AVX512-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[0,1,1,0] +; AVX512-NEXT: vpsllvd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX512-NEXT: vpord {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm0 +; AVX512-NEXT: retq %1 = shl <4 x i32> %a0, %2 = shufflevector <4 x i32> %1, <4 x i32> undef, <4 x i32> %3 = add <4 x i32> %2, diff --git a/llvm/test/CodeGen/X86/combine-sra.ll b/llvm/test/CodeGen/X86/combine-sra.ll index cc0ed2b8268c..0aac99457d7d 100644 --- a/llvm/test/CodeGen/X86/combine-sra.ll +++ b/llvm/test/CodeGen/X86/combine-sra.ll @@ -1,8 +1,9 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.1 | FileCheck %s --check-prefixes=CHECK,SSE -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=CHECK,AVX,AVX2-SLOW -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-crosslane-shuffle,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX2-FAST-ALL -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX2-FAST-PERLANE +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-SLOW +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-crosslane-shuffle,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-FAST-ALL +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-FAST-PERLANE +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=x86-64-v4 | FileCheck %s --check-prefixes=CHECK,AVX,AVX512 ; fold (sra 0, x) -> 0 define <4 x i32> @combine_vec_ashr_zero(<4 x i32> %x) { @@ -193,6 +194,14 @@ define <4 x i32> @combine_vec_ashr_trunc_and(<4 x i32> %x, <4 x i64> %y) { ; AVX2-FAST-PERLANE-NEXT: vpsravd %xmm1, %xmm0, %xmm0 ; AVX2-FAST-PERLANE-NEXT: vzeroupper ; AVX2-FAST-PERLANE-NEXT: retq +; +; AVX512-LABEL: combine_vec_ashr_trunc_and: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovqd %ymm1, %xmm1 +; AVX512-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 +; AVX512-NEXT: vpsravd %xmm1, %xmm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq %1 = and <4 x i64> %y, %2 = trunc <4 x i64> %1 to <4 x i32> %3 = ashr <4 x i32> %x, %2 @@ -237,6 +246,14 @@ define <4 x i32> @combine_vec_ashr_trunc_lshr(<4 x i64> %x) { ; AVX2-FAST-PERLANE-NEXT: vpsravd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 ; AVX2-FAST-PERLANE-NEXT: vzeroupper ; AVX2-FAST-PERLANE-NEXT: retq +; +; AVX512-LABEL: combine_vec_ashr_trunc_lshr: +; AVX512: # %bb.0: +; AVX512-NEXT: vpsrlq $32, %ymm0, %ymm0 +; AVX512-NEXT: vpmovqd %ymm0, %xmm0 +; AVX512-NEXT: vpsravd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq %1 = lshr <4 x i64> %x, %2 = trunc <4 x i64> %1 to <4 x i32> %3 = ashr <4 x i32> %2, @@ -255,16 +272,23 @@ define <16 x i8> @combine_vec_ashr_trunc_lshr_splat(<16 x i32> %x) { ; SSE-NEXT: packsswb %xmm2, %xmm0 ; SSE-NEXT: retq ; -; AVX-LABEL: combine_vec_ashr_trunc_lshr_splat: -; AVX: # %bb.0: -; AVX-NEXT: vpsrad $26, %ymm1, %ymm1 -; AVX-NEXT: vpsrad $26, %ymm0, %ymm0 -; AVX-NEXT: vpackssdw %ymm1, %ymm0, %ymm0 -; AVX-NEXT: vextracti128 $1, %ymm0, %xmm1 -; AVX-NEXT: vpacksswb %xmm1, %xmm0, %xmm0 -; AVX-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[0,2,1,3] -; AVX-NEXT: vzeroupper -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_ashr_trunc_lshr_splat: +; AVX2: # %bb.0: +; AVX2-NEXT: vpsrad $26, %ymm1, %ymm1 +; AVX2-NEXT: vpsrad $26, %ymm0, %ymm0 +; AVX2-NEXT: vpackssdw %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 +; AVX2-NEXT: vpacksswb %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[0,2,1,3] +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_ashr_trunc_lshr_splat: +; AVX512: # %bb.0: +; AVX512-NEXT: vpsrad $26, %zmm0, %zmm0 +; AVX512-NEXT: vpmovdb %zmm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq %1 = lshr <16 x i32> %x, %2 = trunc <16 x i32> %1 to <16 x i8> %3 = ashr <16 x i8> %2, @@ -309,6 +333,14 @@ define <4 x i32> @combine_vec_ashr_trunc_ashr(<4 x i64> %x) { ; AVX2-FAST-PERLANE-NEXT: vpsravd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 ; AVX2-FAST-PERLANE-NEXT: vzeroupper ; AVX2-FAST-PERLANE-NEXT: retq +; +; AVX512-LABEL: combine_vec_ashr_trunc_ashr: +; AVX512: # %bb.0: +; AVX512-NEXT: vpsrlq $32, %ymm0, %ymm0 +; AVX512-NEXT: vpmovqd %ymm0, %xmm0 +; AVX512-NEXT: vpsravd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq %1 = ashr <4 x i64> %x, %2 = trunc <4 x i64> %1 to <4 x i32> %3 = ashr <4 x i32> %2, @@ -323,13 +355,20 @@ define <8 x i16> @combine_vec_ashr_trunc_ashr_splat(<8 x i32> %x) { ; SSE-NEXT: packssdw %xmm1, %xmm0 ; SSE-NEXT: retq ; -; AVX-LABEL: combine_vec_ashr_trunc_ashr_splat: -; AVX: # %bb.0: -; AVX-NEXT: vpsrad $19, %ymm0, %ymm0 -; AVX-NEXT: vextracti128 $1, %ymm0, %xmm1 -; AVX-NEXT: vpackssdw %xmm1, %xmm0, %xmm0 -; AVX-NEXT: vzeroupper -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_ashr_trunc_ashr_splat: +; AVX2: # %bb.0: +; AVX2-NEXT: vpsrad $19, %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 +; AVX2-NEXT: vpackssdw %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_ashr_trunc_ashr_splat: +; AVX512: # %bb.0: +; AVX512-NEXT: vpsrad $19, %ymm0, %ymm0 +; AVX512-NEXT: vpmovdw %ymm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq %1 = ashr <8 x i32> %x, %2 = trunc <8 x i32> %1 to <8 x i16> %3 = ashr <8 x i16> %2, diff --git a/llvm/test/CodeGen/X86/combine-srl.ll b/llvm/test/CodeGen/X86/combine-srl.ll index b38ab5d26281..79c86a6b012e 100644 --- a/llvm/test/CodeGen/X86/combine-srl.ll +++ b/llvm/test/CodeGen/X86/combine-srl.ll @@ -1,8 +1,9 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.1 | FileCheck %s --check-prefixes=CHECK,SSE -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=CHECK,AVX,AVX2-SLOW -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-crosslane-shuffle,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX2-FAST-ALL -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX2-FAST-PERLANE +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-SLOW +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-crosslane-shuffle,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-FAST-ALL +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-FAST-PERLANE +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=x86-64-v4 | FileCheck %s --check-prefixes=CHECK,AVX,AVX512 ; fold (srl 0, x) -> 0 define <4 x i32> @combine_vec_lshr_zero(<4 x i32> %x) { @@ -188,6 +189,13 @@ define <4 x i32> @combine_vec_lshr_trunc_lshr0(<4 x i64> %x) { ; AVX2-FAST-PERLANE-NEXT: vpackusdw %xmm1, %xmm0, %xmm0 ; AVX2-FAST-PERLANE-NEXT: vzeroupper ; AVX2-FAST-PERLANE-NEXT: retq +; +; AVX512-LABEL: combine_vec_lshr_trunc_lshr0: +; AVX512: # %bb.0: +; AVX512-NEXT: vpsrlq $48, %ymm0, %ymm0 +; AVX512-NEXT: vpmovqd %ymm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq %1 = lshr <4 x i64> %x, %2 = trunc <4 x i64> %1 to <4 x i32> %3 = lshr <4 x i32> %2, @@ -243,6 +251,14 @@ define <4 x i32> @combine_vec_lshr_trunc_lshr1(<4 x i64> %x) { ; AVX2-FAST-PERLANE-NEXT: vpsrlvd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 ; AVX2-FAST-PERLANE-NEXT: vzeroupper ; AVX2-FAST-PERLANE-NEXT: retq +; +; AVX512-LABEL: combine_vec_lshr_trunc_lshr1: +; AVX512: # %bb.0: +; AVX512-NEXT: vpsrlvq {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; AVX512-NEXT: vpmovqd %ymm0, %xmm0 +; AVX512-NEXT: vpsrlvd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq %1 = lshr <4 x i64> %x, %2 = trunc <4 x i64> %1 to <4 x i32> %3 = lshr <4 x i32> %2, @@ -289,11 +305,16 @@ define <4 x i32> @combine_vec_lshr_shl_mask0(<4 x i32> %x) { ; SSE-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; SSE-NEXT: retq ; -; AVX-LABEL: combine_vec_lshr_shl_mask0: -; AVX: # %bb.0: -; AVX-NEXT: vbroadcastss {{.*#+}} xmm1 = [1073741823,1073741823,1073741823,1073741823] -; AVX-NEXT: vandps %xmm1, %xmm0, %xmm0 -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_lshr_shl_mask0: +; AVX2: # %bb.0: +; AVX2-NEXT: vbroadcastss {{.*#+}} xmm1 = [1073741823,1073741823,1073741823,1073741823] +; AVX2-NEXT: vandps %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_lshr_shl_mask0: +; AVX512: # %bb.0: +; AVX512-NEXT: vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm0 +; AVX512-NEXT: retq %1 = shl <4 x i32> %x, %2 = lshr <4 x i32> %1, ret <4 x i32> %2 @@ -338,12 +359,18 @@ define <4 x i32> @combine_vec_lshr_lzcnt_bit0(<4 x i32> %x) { ; SSE-NEXT: pandn {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; SSE-NEXT: retq ; -; AVX-LABEL: combine_vec_lshr_lzcnt_bit0: -; AVX: # %bb.0: -; AVX-NEXT: vpsrld $4, %xmm0, %xmm0 -; AVX-NEXT: vpbroadcastd {{.*#+}} xmm1 = [1,1,1,1] -; AVX-NEXT: vpandn %xmm1, %xmm0, %xmm0 -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_lshr_lzcnt_bit0: +; AVX2: # %bb.0: +; AVX2-NEXT: vpsrld $4, %xmm0, %xmm0 +; AVX2-NEXT: vpbroadcastd {{.*#+}} xmm1 = [1,1,1,1] +; AVX2-NEXT: vpandn %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_lshr_lzcnt_bit0: +; AVX512: # %bb.0: +; AVX512-NEXT: vpsrld $4, %xmm0, %xmm0 +; AVX512-NEXT: vpandnd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm0 +; AVX512-NEXT: retq %1 = and <4 x i32> %x, %2 = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %1, i1 0) %3 = lshr <4 x i32> %2, @@ -373,25 +400,32 @@ define <4 x i32> @combine_vec_lshr_lzcnt_bit1(<4 x i32> %x) { ; SSE-NEXT: psrld $5, %xmm0 ; SSE-NEXT: retq ; -; AVX-LABEL: combine_vec_lshr_lzcnt_bit1: -; AVX: # %bb.0: -; AVX-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 -; AVX-NEXT: vmovq {{.*#+}} xmm1 = [4,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0] -; AVX-NEXT: vpshufb %xmm0, %xmm1, %xmm2 -; AVX-NEXT: vpsrlw $4, %xmm0, %xmm0 -; AVX-NEXT: vpxor %xmm3, %xmm3, %xmm3 -; AVX-NEXT: vpcmpeqb %xmm3, %xmm0, %xmm4 -; AVX-NEXT: vpand %xmm4, %xmm2, %xmm2 -; AVX-NEXT: vpshufb %xmm0, %xmm1, %xmm0 -; AVX-NEXT: vpaddb %xmm0, %xmm2, %xmm0 -; AVX-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1 -; AVX-NEXT: vpsrlw $8, %xmm0, %xmm0 -; AVX-NEXT: vpaddw %xmm1, %xmm0, %xmm0 -; AVX-NEXT: vpblendw {{.*#+}} xmm1 = xmm0[0],xmm3[1],xmm0[2],xmm3[3],xmm0[4],xmm3[5],xmm0[6],xmm3[7] -; AVX-NEXT: vpsrld $16, %xmm0, %xmm0 -; AVX-NEXT: vpaddd %xmm1, %xmm0, %xmm0 -; AVX-NEXT: vpsrld $5, %xmm0, %xmm0 -; AVX-NEXT: retq +; AVX2-LABEL: combine_vec_lshr_lzcnt_bit1: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX2-NEXT: vmovq {{.*#+}} xmm1 = [4,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0] +; AVX2-NEXT: vpshufb %xmm0, %xmm1, %xmm2 +; AVX2-NEXT: vpsrlw $4, %xmm0, %xmm0 +; AVX2-NEXT: vpxor %xmm3, %xmm3, %xmm3 +; AVX2-NEXT: vpcmpeqb %xmm3, %xmm0, %xmm4 +; AVX2-NEXT: vpand %xmm4, %xmm2, %xmm2 +; AVX2-NEXT: vpshufb %xmm0, %xmm1, %xmm0 +; AVX2-NEXT: vpaddb %xmm0, %xmm2, %xmm0 +; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1 +; AVX2-NEXT: vpsrlw $8, %xmm0, %xmm0 +; AVX2-NEXT: vpaddw %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpblendw {{.*#+}} xmm1 = xmm0[0],xmm3[1],xmm0[2],xmm3[3],xmm0[4],xmm3[5],xmm0[6],xmm3[7] +; AVX2-NEXT: vpsrld $16, %xmm0, %xmm0 +; AVX2-NEXT: vpaddd %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpsrld $5, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec_lshr_lzcnt_bit1: +; AVX512: # %bb.0: +; AVX512-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX512-NEXT: vplzcntd %xmm0, %xmm0 +; AVX512-NEXT: vpsrld $5, %xmm0, %xmm0 +; AVX512-NEXT: retq %1 = and <4 x i32> %x, %2 = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %1, i1 0) %3 = lshr <4 x i32> %2, @@ -448,6 +482,14 @@ define <4 x i32> @combine_vec_lshr_trunc_and(<4 x i32> %x, <4 x i64> %y) { ; AVX2-FAST-PERLANE-NEXT: vpsrlvd %xmm1, %xmm0, %xmm0 ; AVX2-FAST-PERLANE-NEXT: vzeroupper ; AVX2-FAST-PERLANE-NEXT: retq +; +; AVX512-LABEL: combine_vec_lshr_trunc_and: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovqd %ymm1, %xmm1 +; AVX512-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 +; AVX512-NEXT: vpsrlvd %xmm1, %xmm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq %1 = and <4 x i64> %y, %2 = trunc <4 x i64> %1 to <4 x i32> %3 = lshr <4 x i32> %x, %2 -- GitLab From 6cd68c2f87832ef39eb502a20d358b4c7fa37b9e Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 11 Mar 2024 16:25:05 +0000 Subject: [PATCH 137/953] [X86] Add base SSE2 coverage to SRL/SRA combines tests --- llvm/test/CodeGen/X86/combine-sra.ll | 270 +++++++++++++++++--------- llvm/test/CodeGen/X86/combine-srl.ll | 275 +++++++++++++++++++-------- 2 files changed, 378 insertions(+), 167 deletions(-) diff --git a/llvm/test/CodeGen/X86/combine-sra.ll b/llvm/test/CodeGen/X86/combine-sra.ll index 0aac99457d7d..0675ced68d7a 100644 --- a/llvm/test/CodeGen/X86/combine-sra.ll +++ b/llvm/test/CodeGen/X86/combine-sra.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.1 | FileCheck %s --check-prefixes=CHECK,SSE +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefixes=CHECK,SSE,SSE2 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.1 | FileCheck %s --check-prefixes=CHECK,SSE,SSE41 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-SLOW ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-crosslane-shuffle,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-FAST-ALL ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-FAST-PERLANE @@ -86,19 +87,33 @@ define <4 x i32> @combine_vec_ashr_ashr0(<4 x i32> %x) { } define <4 x i32> @combine_vec_ashr_ashr1(<4 x i32> %x) { -; SSE-LABEL: combine_vec_ashr_ashr1: -; SSE: # %bb.0: -; SSE-NEXT: movdqa %xmm0, %xmm1 -; SSE-NEXT: psrad $10, %xmm1 -; SSE-NEXT: movdqa %xmm0, %xmm2 -; SSE-NEXT: psrad $6, %xmm2 -; SSE-NEXT: pblendw {{.*#+}} xmm2 = xmm2[0,1,2,3],xmm1[4,5,6,7] -; SSE-NEXT: movdqa %xmm0, %xmm1 -; SSE-NEXT: psrad $8, %xmm1 -; SSE-NEXT: psrad $4, %xmm0 -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm1[4,5,6,7] -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm2[2,3],xmm0[4,5],xmm2[6,7] -; SSE-NEXT: retq +; SSE2-LABEL: combine_vec_ashr_ashr1: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psrad $10, %xmm1 +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: psrad $8, %xmm2 +; SSE2-NEXT: punpckhqdq {{.*#+}} xmm2 = xmm2[1],xmm1[1] +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psrad $6, %xmm1 +; SSE2-NEXT: psrad $4, %xmm0 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,3],xmm2[0,3] +; SSE2-NEXT: retq +; +; SSE41-LABEL: combine_vec_ashr_ashr1: +; SSE41: # %bb.0: +; SSE41-NEXT: movdqa %xmm0, %xmm1 +; SSE41-NEXT: psrad $10, %xmm1 +; SSE41-NEXT: movdqa %xmm0, %xmm2 +; SSE41-NEXT: psrad $6, %xmm2 +; SSE41-NEXT: pblendw {{.*#+}} xmm2 = xmm2[0,1,2,3],xmm1[4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm1 +; SSE41-NEXT: psrad $8, %xmm1 +; SSE41-NEXT: psrad $4, %xmm0 +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm1[4,5,6,7] +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm2[2,3],xmm0[4,5],xmm2[6,7] +; SSE41-NEXT: retq ; ; AVX-LABEL: combine_vec_ashr_ashr1: ; AVX: # %bb.0: @@ -125,16 +140,30 @@ define <4 x i32> @combine_vec_ashr_ashr2(<4 x i32> %x) { } define <4 x i32> @combine_vec_ashr_ashr3(<4 x i32> %x) { -; SSE-LABEL: combine_vec_ashr_ashr3: -; SSE: # %bb.0: -; SSE-NEXT: movdqa %xmm0, %xmm1 -; SSE-NEXT: psrad $27, %xmm1 -; SSE-NEXT: movdqa %xmm0, %xmm2 -; SSE-NEXT: psrad $15, %xmm2 -; SSE-NEXT: pblendw {{.*#+}} xmm2 = xmm2[0,1,2,3],xmm1[4,5,6,7] -; SSE-NEXT: psrad $31, %xmm0 -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm2[2,3],xmm0[4,5],xmm2[6,7] -; SSE-NEXT: retq +; SSE2-LABEL: combine_vec_ashr_ashr3: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: psrad $27, %xmm2 +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psrad $31, %xmm1 +; SSE2-NEXT: movdqa %xmm1, %xmm3 +; SSE2-NEXT: punpckhqdq {{.*#+}} xmm3 = xmm3[1],xmm2[1] +; SSE2-NEXT: psrad $15, %xmm0 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0] +; SSE2-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,3],xmm3[0,3] +; SSE2-NEXT: movaps %xmm1, %xmm0 +; SSE2-NEXT: retq +; +; SSE41-LABEL: combine_vec_ashr_ashr3: +; SSE41: # %bb.0: +; SSE41-NEXT: movdqa %xmm0, %xmm1 +; SSE41-NEXT: psrad $27, %xmm1 +; SSE41-NEXT: movdqa %xmm0, %xmm2 +; SSE41-NEXT: psrad $15, %xmm2 +; SSE41-NEXT: pblendw {{.*#+}} xmm2 = xmm2[0,1,2,3],xmm1[4,5,6,7] +; SSE41-NEXT: psrad $31, %xmm0 +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm2[2,3],xmm0[4,5],xmm2[6,7] +; SSE41-NEXT: retq ; ; AVX-LABEL: combine_vec_ashr_ashr3: ; AVX: # %bb.0: @@ -147,26 +176,48 @@ define <4 x i32> @combine_vec_ashr_ashr3(<4 x i32> %x) { ; fold (sra x, (trunc (and y, c))) -> (sra x, (and (trunc y), (trunc c))). define <4 x i32> @combine_vec_ashr_trunc_and(<4 x i32> %x, <4 x i64> %y) { -; SSE-LABEL: combine_vec_ashr_trunc_and: -; SSE: # %bb.0: -; SSE-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] -; SSE-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 -; SSE-NEXT: pshuflw {{.*#+}} xmm2 = xmm1[2,3,3,3,4,5,6,7] -; SSE-NEXT: movdqa %xmm0, %xmm3 -; SSE-NEXT: psrad %xmm2, %xmm3 -; SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] -; SSE-NEXT: pshuflw {{.*#+}} xmm4 = xmm2[2,3,3,3,4,5,6,7] -; SSE-NEXT: movdqa %xmm0, %xmm5 -; SSE-NEXT: psrad %xmm4, %xmm5 -; SSE-NEXT: pblendw {{.*#+}} xmm5 = xmm3[0,1,2,3],xmm5[4,5,6,7] -; SSE-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[0,1,1,1,4,5,6,7] -; SSE-NEXT: movdqa %xmm0, %xmm3 -; SSE-NEXT: psrad %xmm1, %xmm3 -; SSE-NEXT: pshuflw {{.*#+}} xmm1 = xmm2[0,1,1,1,4,5,6,7] -; SSE-NEXT: psrad %xmm1, %xmm0 -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm3[0,1,2,3],xmm0[4,5,6,7] -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm5[2,3],xmm0[4,5],xmm5[6,7] -; SSE-NEXT: retq +; SSE2-LABEL: combine_vec_ashr_trunc_and: +; SSE2: # %bb.0: +; SSE2-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; SSE2-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 +; SSE2-NEXT: pshuflw {{.*#+}} xmm2 = xmm1[2,3,3,3,4,5,6,7] +; SSE2-NEXT: movdqa %xmm0, %xmm3 +; SSE2-NEXT: psrad %xmm2, %xmm3 +; SSE2-NEXT: pshuflw {{.*#+}} xmm4 = xmm1[0,1,1,1,4,5,6,7] +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: psrad %xmm4, %xmm2 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm3[0] +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; SSE2-NEXT: pshuflw {{.*#+}} xmm3 = xmm1[2,3,3,3,4,5,6,7] +; SSE2-NEXT: movdqa %xmm0, %xmm4 +; SSE2-NEXT: psrad %xmm3, %xmm4 +; SSE2-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[0,1,1,1,4,5,6,7] +; SSE2-NEXT: psrad %xmm1, %xmm0 +; SSE2-NEXT: punpckhqdq {{.*#+}} xmm0 = xmm0[1],xmm4[1] +; SSE2-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,3],xmm0[0,3] +; SSE2-NEXT: movaps %xmm2, %xmm0 +; SSE2-NEXT: retq +; +; SSE41-LABEL: combine_vec_ashr_trunc_and: +; SSE41: # %bb.0: +; SSE41-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; SSE41-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 +; SSE41-NEXT: pshuflw {{.*#+}} xmm2 = xmm1[2,3,3,3,4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm3 +; SSE41-NEXT: psrad %xmm2, %xmm3 +; SSE41-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] +; SSE41-NEXT: pshuflw {{.*#+}} xmm4 = xmm2[2,3,3,3,4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm5 +; SSE41-NEXT: psrad %xmm4, %xmm5 +; SSE41-NEXT: pblendw {{.*#+}} xmm5 = xmm3[0,1,2,3],xmm5[4,5,6,7] +; SSE41-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[0,1,1,1,4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm3 +; SSE41-NEXT: psrad %xmm1, %xmm3 +; SSE41-NEXT: pshuflw {{.*#+}} xmm1 = xmm2[0,1,1,1,4,5,6,7] +; SSE41-NEXT: psrad %xmm1, %xmm0 +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm3[0,1,2,3],xmm0[4,5,6,7] +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm5[2,3],xmm0[4,5],xmm5[6,7] +; SSE41-NEXT: retq ; ; AVX2-SLOW-LABEL: combine_vec_ashr_trunc_and: ; AVX2-SLOW: # %bb.0: @@ -211,17 +262,31 @@ define <4 x i32> @combine_vec_ashr_trunc_and(<4 x i32> %x, <4 x i64> %y) { ; fold (sra (trunc (srl x, c1)), c2) -> (trunc (sra x, c1 + c2)) ; if c1 is equal to the number of bits the trunc removes define <4 x i32> @combine_vec_ashr_trunc_lshr(<4 x i64> %x) { -; SSE-LABEL: combine_vec_ashr_trunc_lshr: -; SSE: # %bb.0: -; SSE-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,3],xmm1[1,3] -; SSE-NEXT: movaps %xmm0, %xmm2 -; SSE-NEXT: psrad $2, %xmm2 -; SSE-NEXT: pblendw {{.*#+}} xmm2 = xmm0[0,1,2,3],xmm2[4,5,6,7] -; SSE-NEXT: psrad $1, %xmm0 -; SSE-NEXT: psrad $3, %xmm1 -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm1[4,5,6,7] -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm2[0,1],xmm0[2,3],xmm2[4,5],xmm0[6,7] -; SSE-NEXT: retq +; SSE2-LABEL: combine_vec_ashr_trunc_lshr: +; SSE2: # %bb.0: +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,3],xmm1[1,3] +; SSE2-NEXT: movaps %xmm0, %xmm1 +; SSE2-NEXT: psrad $3, %xmm1 +; SSE2-NEXT: movaps %xmm0, %xmm2 +; SSE2-NEXT: psrad $2, %xmm2 +; SSE2-NEXT: punpckhqdq {{.*#+}} xmm2 = xmm2[1],xmm1[1] +; SSE2-NEXT: movaps %xmm0, %xmm1 +; SSE2-NEXT: psrad $1, %xmm1 +; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,3],xmm2[0,3] +; SSE2-NEXT: retq +; +; SSE41-LABEL: combine_vec_ashr_trunc_lshr: +; SSE41: # %bb.0: +; SSE41-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,3],xmm1[1,3] +; SSE41-NEXT: movaps %xmm0, %xmm2 +; SSE41-NEXT: psrad $2, %xmm2 +; SSE41-NEXT: pblendw {{.*#+}} xmm2 = xmm0[0,1,2,3],xmm2[4,5,6,7] +; SSE41-NEXT: psrad $1, %xmm0 +; SSE41-NEXT: psrad $3, %xmm1 +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm1[4,5,6,7] +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm2[0,1],xmm0[2,3],xmm2[4,5],xmm0[6,7] +; SSE41-NEXT: retq ; ; AVX2-SLOW-LABEL: combine_vec_ashr_trunc_lshr: ; AVX2-SLOW: # %bb.0: @@ -298,17 +363,31 @@ define <16 x i8> @combine_vec_ashr_trunc_lshr_splat(<16 x i32> %x) { ; fold (sra (trunc (sra x, c1)), c2) -> (trunc (sra x, c1 + c2)) ; if c1 is equal to the number of bits the trunc removes define <4 x i32> @combine_vec_ashr_trunc_ashr(<4 x i64> %x) { -; SSE-LABEL: combine_vec_ashr_trunc_ashr: -; SSE: # %bb.0: -; SSE-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,3],xmm1[1,3] -; SSE-NEXT: movaps %xmm0, %xmm2 -; SSE-NEXT: psrad $2, %xmm2 -; SSE-NEXT: pblendw {{.*#+}} xmm2 = xmm0[0,1,2,3],xmm2[4,5,6,7] -; SSE-NEXT: psrad $1, %xmm0 -; SSE-NEXT: psrad $3, %xmm1 -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm1[4,5,6,7] -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm2[0,1],xmm0[2,3],xmm2[4,5],xmm0[6,7] -; SSE-NEXT: retq +; SSE2-LABEL: combine_vec_ashr_trunc_ashr: +; SSE2: # %bb.0: +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,3],xmm1[1,3] +; SSE2-NEXT: movaps %xmm0, %xmm1 +; SSE2-NEXT: psrad $3, %xmm1 +; SSE2-NEXT: movaps %xmm0, %xmm2 +; SSE2-NEXT: psrad $2, %xmm2 +; SSE2-NEXT: punpckhqdq {{.*#+}} xmm2 = xmm2[1],xmm1[1] +; SSE2-NEXT: movaps %xmm0, %xmm1 +; SSE2-NEXT: psrad $1, %xmm1 +; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,3],xmm2[0,3] +; SSE2-NEXT: retq +; +; SSE41-LABEL: combine_vec_ashr_trunc_ashr: +; SSE41: # %bb.0: +; SSE41-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,3],xmm1[1,3] +; SSE41-NEXT: movaps %xmm0, %xmm2 +; SSE41-NEXT: psrad $2, %xmm2 +; SSE41-NEXT: pblendw {{.*#+}} xmm2 = xmm0[0,1,2,3],xmm2[4,5,6,7] +; SSE41-NEXT: psrad $1, %xmm0 +; SSE41-NEXT: psrad $3, %xmm1 +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm1[4,5,6,7] +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm2[0,1],xmm0[2,3],xmm2[4,5],xmm0[6,7] +; SSE41-NEXT: retq ; ; AVX2-SLOW-LABEL: combine_vec_ashr_trunc_ashr: ; AVX2-SLOW: # %bb.0: @@ -377,25 +456,46 @@ define <8 x i16> @combine_vec_ashr_trunc_ashr_splat(<8 x i32> %x) { ; If the sign bit is known to be zero, switch this to a SRL. define <4 x i32> @combine_vec_ashr_positive(<4 x i32> %x, <4 x i32> %y) { -; SSE-LABEL: combine_vec_ashr_positive: -; SSE: # %bb.0: -; SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 -; SSE-NEXT: pshuflw {{.*#+}} xmm2 = xmm1[2,3,3,3,4,5,6,7] -; SSE-NEXT: movdqa %xmm0, %xmm3 -; SSE-NEXT: psrld %xmm2, %xmm3 -; SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] -; SSE-NEXT: pshuflw {{.*#+}} xmm4 = xmm2[2,3,3,3,4,5,6,7] -; SSE-NEXT: movdqa %xmm0, %xmm5 -; SSE-NEXT: psrld %xmm4, %xmm5 -; SSE-NEXT: pblendw {{.*#+}} xmm5 = xmm3[0,1,2,3],xmm5[4,5,6,7] -; SSE-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[0,1,1,1,4,5,6,7] -; SSE-NEXT: movdqa %xmm0, %xmm3 -; SSE-NEXT: psrld %xmm1, %xmm3 -; SSE-NEXT: pshuflw {{.*#+}} xmm1 = xmm2[0,1,1,1,4,5,6,7] -; SSE-NEXT: psrld %xmm1, %xmm0 -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm3[0,1,2,3],xmm0[4,5,6,7] -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm5[2,3],xmm0[4,5],xmm5[6,7] -; SSE-NEXT: retq +; SSE2-LABEL: combine_vec_ashr_positive: +; SSE2: # %bb.0: +; SSE2-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; SSE2-NEXT: pshuflw {{.*#+}} xmm2 = xmm1[2,3,3,3,4,5,6,7] +; SSE2-NEXT: movdqa %xmm0, %xmm3 +; SSE2-NEXT: psrld %xmm2, %xmm3 +; SSE2-NEXT: pshuflw {{.*#+}} xmm4 = xmm1[0,1,1,1,4,5,6,7] +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: psrld %xmm4, %xmm2 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm3[0] +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; SSE2-NEXT: pshuflw {{.*#+}} xmm3 = xmm1[2,3,3,3,4,5,6,7] +; SSE2-NEXT: movdqa %xmm0, %xmm4 +; SSE2-NEXT: psrld %xmm3, %xmm4 +; SSE2-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[0,1,1,1,4,5,6,7] +; SSE2-NEXT: psrld %xmm1, %xmm0 +; SSE2-NEXT: punpckhqdq {{.*#+}} xmm0 = xmm0[1],xmm4[1] +; SSE2-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,3],xmm0[0,3] +; SSE2-NEXT: movaps %xmm2, %xmm0 +; SSE2-NEXT: retq +; +; SSE41-LABEL: combine_vec_ashr_positive: +; SSE41: # %bb.0: +; SSE41-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; SSE41-NEXT: pshuflw {{.*#+}} xmm2 = xmm1[2,3,3,3,4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm3 +; SSE41-NEXT: psrld %xmm2, %xmm3 +; SSE41-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] +; SSE41-NEXT: pshuflw {{.*#+}} xmm4 = xmm2[2,3,3,3,4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm5 +; SSE41-NEXT: psrld %xmm4, %xmm5 +; SSE41-NEXT: pblendw {{.*#+}} xmm5 = xmm3[0,1,2,3],xmm5[4,5,6,7] +; SSE41-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[0,1,1,1,4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm3 +; SSE41-NEXT: psrld %xmm1, %xmm3 +; SSE41-NEXT: pshuflw {{.*#+}} xmm1 = xmm2[0,1,1,1,4,5,6,7] +; SSE41-NEXT: psrld %xmm1, %xmm0 +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm3[0,1,2,3],xmm0[4,5,6,7] +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm5[2,3],xmm0[4,5],xmm5[6,7] +; SSE41-NEXT: retq ; ; AVX-LABEL: combine_vec_ashr_positive: ; AVX: # %bb.0: diff --git a/llvm/test/CodeGen/X86/combine-srl.ll b/llvm/test/CodeGen/X86/combine-srl.ll index 79c86a6b012e..33649e6d87b9 100644 --- a/llvm/test/CodeGen/X86/combine-srl.ll +++ b/llvm/test/CodeGen/X86/combine-srl.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.1 | FileCheck %s --check-prefixes=CHECK,SSE +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefixes=CHECK,SSE,SSE2 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.1 | FileCheck %s --check-prefixes=CHECK,SSE,SSE41 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-SLOW ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-crosslane-shuffle,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-FAST-ALL ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2,+fast-variable-perlane-shuffle | FileCheck %s --check-prefixes=CHECK,AVX,AVX2,AVX2-FAST-PERLANE @@ -102,19 +103,33 @@ define <4 x i32> @combine_vec_lshr_lshr0(<4 x i32> %x) { } define <4 x i32> @combine_vec_lshr_lshr1(<4 x i32> %x) { -; SSE-LABEL: combine_vec_lshr_lshr1: -; SSE: # %bb.0: -; SSE-NEXT: movdqa %xmm0, %xmm1 -; SSE-NEXT: psrld $10, %xmm1 -; SSE-NEXT: movdqa %xmm0, %xmm2 -; SSE-NEXT: psrld $6, %xmm2 -; SSE-NEXT: pblendw {{.*#+}} xmm2 = xmm2[0,1,2,3],xmm1[4,5,6,7] -; SSE-NEXT: movdqa %xmm0, %xmm1 -; SSE-NEXT: psrld $8, %xmm1 -; SSE-NEXT: psrld $4, %xmm0 -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm1[4,5,6,7] -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm2[2,3],xmm0[4,5],xmm2[6,7] -; SSE-NEXT: retq +; SSE2-LABEL: combine_vec_lshr_lshr1: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psrld $10, %xmm1 +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: psrld $8, %xmm2 +; SSE2-NEXT: punpckhqdq {{.*#+}} xmm2 = xmm2[1],xmm1[1] +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psrld $6, %xmm1 +; SSE2-NEXT: psrld $4, %xmm0 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,3],xmm2[0,3] +; SSE2-NEXT: retq +; +; SSE41-LABEL: combine_vec_lshr_lshr1: +; SSE41: # %bb.0: +; SSE41-NEXT: movdqa %xmm0, %xmm1 +; SSE41-NEXT: psrld $10, %xmm1 +; SSE41-NEXT: movdqa %xmm0, %xmm2 +; SSE41-NEXT: psrld $6, %xmm2 +; SSE41-NEXT: pblendw {{.*#+}} xmm2 = xmm2[0,1,2,3],xmm1[4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm1 +; SSE41-NEXT: psrld $8, %xmm1 +; SSE41-NEXT: psrld $4, %xmm0 +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm1[4,5,6,7] +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm2[2,3],xmm0[4,5],xmm2[6,7] +; SSE41-NEXT: retq ; ; AVX-LABEL: combine_vec_lshr_lshr1: ; AVX: # %bb.0: @@ -158,12 +173,19 @@ define <4 x i32> @combine_vec_lshr_lshr_zero1(<4 x i32> %x) { ; fold (srl (trunc (srl x, c1)), c2) -> (trunc (srl x, (add c1, c2))) define <4 x i32> @combine_vec_lshr_trunc_lshr0(<4 x i64> %x) { -; SSE-LABEL: combine_vec_lshr_trunc_lshr0: -; SSE: # %bb.0: -; SSE-NEXT: psrlq $48, %xmm1 -; SSE-NEXT: psrlq $48, %xmm0 -; SSE-NEXT: packusdw %xmm1, %xmm0 -; SSE-NEXT: retq +; SSE2-LABEL: combine_vec_lshr_trunc_lshr0: +; SSE2: # %bb.0: +; SSE2-NEXT: psrlq $48, %xmm1 +; SSE2-NEXT: psrlq $48, %xmm0 +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2] +; SSE2-NEXT: retq +; +; SSE41-LABEL: combine_vec_lshr_trunc_lshr0: +; SSE41: # %bb.0: +; SSE41-NEXT: psrlq $48, %xmm1 +; SSE41-NEXT: psrlq $48, %xmm0 +; SSE41-NEXT: packusdw %xmm1, %xmm0 +; SSE41-NEXT: retq ; ; AVX2-SLOW-LABEL: combine_vec_lshr_trunc_lshr0: ; AVX2-SLOW: # %bb.0: @@ -203,27 +225,50 @@ define <4 x i32> @combine_vec_lshr_trunc_lshr0(<4 x i64> %x) { } define <4 x i32> @combine_vec_lshr_trunc_lshr1(<4 x i64> %x) { -; SSE-LABEL: combine_vec_lshr_trunc_lshr1: -; SSE: # %bb.0: -; SSE-NEXT: movdqa %xmm1, %xmm2 -; SSE-NEXT: psrlq $35, %xmm2 -; SSE-NEXT: psrlq $34, %xmm1 -; SSE-NEXT: pblendw {{.*#+}} xmm1 = xmm1[0,1,2,3],xmm2[4,5,6,7] -; SSE-NEXT: movdqa %xmm0, %xmm2 -; SSE-NEXT: psrlq $33, %xmm2 -; SSE-NEXT: psrlq $32, %xmm0 -; SSE-NEXT: pblendw {{.*#+}} xmm2 = xmm0[0,1,2,3],xmm2[4,5,6,7] -; SSE-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,2],xmm1[0,2] -; SSE-NEXT: movaps %xmm2, %xmm1 -; SSE-NEXT: psrld $19, %xmm1 -; SSE-NEXT: movaps %xmm2, %xmm3 -; SSE-NEXT: psrld $17, %xmm3 -; SSE-NEXT: pblendw {{.*#+}} xmm3 = xmm3[0,1,2,3],xmm1[4,5,6,7] -; SSE-NEXT: psrld $18, %xmm2 -; SSE-NEXT: psrld $16, %xmm0 -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm2[4,5,6,7] -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm3[2,3],xmm0[4,5],xmm3[6,7] -; SSE-NEXT: retq +; SSE2-LABEL: combine_vec_lshr_trunc_lshr1: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm1, %xmm2 +; SSE2-NEXT: psrlq $34, %xmm2 +; SSE2-NEXT: psrlq $35, %xmm1 +; SSE2-NEXT: movsd {{.*#+}} xmm1 = xmm2[0],xmm1[1] +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: psrlq $32, %xmm2 +; SSE2-NEXT: psrlq $33, %xmm0 +; SSE2-NEXT: movsd {{.*#+}} xmm0 = xmm2[0],xmm0[1] +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2] +; SSE2-NEXT: movaps %xmm0, %xmm1 +; SSE2-NEXT: psrld $19, %xmm1 +; SSE2-NEXT: movaps %xmm0, %xmm3 +; SSE2-NEXT: psrld $18, %xmm3 +; SSE2-NEXT: punpckhqdq {{.*#+}} xmm3 = xmm3[1],xmm1[1] +; SSE2-NEXT: psrld $17, %xmm0 +; SSE2-NEXT: psrld $16, %xmm2 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm0[0] +; SSE2-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,3],xmm3[0,3] +; SSE2-NEXT: movaps %xmm2, %xmm0 +; SSE2-NEXT: retq +; +; SSE41-LABEL: combine_vec_lshr_trunc_lshr1: +; SSE41: # %bb.0: +; SSE41-NEXT: movdqa %xmm1, %xmm2 +; SSE41-NEXT: psrlq $35, %xmm2 +; SSE41-NEXT: psrlq $34, %xmm1 +; SSE41-NEXT: pblendw {{.*#+}} xmm1 = xmm1[0,1,2,3],xmm2[4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm2 +; SSE41-NEXT: psrlq $33, %xmm2 +; SSE41-NEXT: psrlq $32, %xmm0 +; SSE41-NEXT: pblendw {{.*#+}} xmm2 = xmm0[0,1,2,3],xmm2[4,5,6,7] +; SSE41-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,2],xmm1[0,2] +; SSE41-NEXT: movaps %xmm2, %xmm1 +; SSE41-NEXT: psrld $19, %xmm1 +; SSE41-NEXT: movaps %xmm2, %xmm3 +; SSE41-NEXT: psrld $17, %xmm3 +; SSE41-NEXT: pblendw {{.*#+}} xmm3 = xmm3[0,1,2,3],xmm1[4,5,6,7] +; SSE41-NEXT: psrld $18, %xmm2 +; SSE41-NEXT: psrld $16, %xmm0 +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm2[4,5,6,7] +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm3[2,3],xmm0[4,5],xmm3[6,7] +; SSE41-NEXT: retq ; ; AVX2-SLOW-LABEL: combine_vec_lshr_trunc_lshr1: ; AVX2-SLOW: # %bb.0: @@ -378,27 +423,71 @@ define <4 x i32> @combine_vec_lshr_lzcnt_bit0(<4 x i32> %x) { } define <4 x i32> @combine_vec_lshr_lzcnt_bit1(<4 x i32> %x) { -; SSE-LABEL: combine_vec_lshr_lzcnt_bit1: -; SSE: # %bb.0: -; SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 -; SSE-NEXT: movq {{.*#+}} xmm1 = [4,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0] -; SSE-NEXT: movdqa %xmm1, %xmm2 -; SSE-NEXT: pshufb %xmm0, %xmm2 -; SSE-NEXT: psrlw $4, %xmm0 -; SSE-NEXT: pxor %xmm3, %xmm3 -; SSE-NEXT: pshufb %xmm0, %xmm1 -; SSE-NEXT: pcmpeqb %xmm3, %xmm0 -; SSE-NEXT: pand %xmm2, %xmm0 -; SSE-NEXT: paddb %xmm1, %xmm0 -; SSE-NEXT: pmovzxbw {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] -; SSE-NEXT: pand %xmm0, %xmm1 -; SSE-NEXT: psrlw $8, %xmm0 -; SSE-NEXT: paddw %xmm1, %xmm0 -; SSE-NEXT: pblendw {{.*#+}} xmm3 = xmm0[0],xmm3[1],xmm0[2],xmm3[3],xmm0[4],xmm3[5],xmm0[6],xmm3[7] -; SSE-NEXT: psrld $16, %xmm0 -; SSE-NEXT: paddd %xmm3, %xmm0 -; SSE-NEXT: psrld $5, %xmm0 -; SSE-NEXT: retq +; SSE2-LABEL: combine_vec_lshr_lzcnt_bit1: +; SSE2: # %bb.0: +; SSE2-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psrld $1, %xmm1 +; SSE2-NEXT: por %xmm1, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psrld $2, %xmm1 +; SSE2-NEXT: por %xmm1, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psrld $4, %xmm1 +; SSE2-NEXT: por %xmm1, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psrld $8, %xmm1 +; SSE2-NEXT: por %xmm1, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psrld $16, %xmm1 +; SSE2-NEXT: por %xmm1, %xmm0 +; SSE2-NEXT: pcmpeqd %xmm1, %xmm1 +; SSE2-NEXT: pxor %xmm1, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm1 +; SSE2-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 +; SSE2-NEXT: psubb %xmm1, %xmm0 +; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51] +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: psrlw $2, %xmm0 +; SSE2-NEXT: pand %xmm1, %xmm0 +; SSE2-NEXT: paddb %xmm2, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psrlw $4, %xmm1 +; SSE2-NEXT: paddb %xmm1, %xmm0 +; SSE2-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; SSE2-NEXT: pxor %xmm1, %xmm1 +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm2 = xmm2[2],xmm1[2],xmm2[3],xmm1[3] +; SSE2-NEXT: psadbw %xmm1, %xmm2 +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] +; SSE2-NEXT: psadbw %xmm1, %xmm0 +; SSE2-NEXT: packuswb %xmm2, %xmm0 +; SSE2-NEXT: psrld $5, %xmm0 +; SSE2-NEXT: retq +; +; SSE41-LABEL: combine_vec_lshr_lzcnt_bit1: +; SSE41: # %bb.0: +; SSE41-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; SSE41-NEXT: movq {{.*#+}} xmm1 = [4,3,2,2,1,1,1,1,0,0,0,0,0,0,0,0] +; SSE41-NEXT: movdqa %xmm1, %xmm2 +; SSE41-NEXT: pshufb %xmm0, %xmm2 +; SSE41-NEXT: psrlw $4, %xmm0 +; SSE41-NEXT: pxor %xmm3, %xmm3 +; SSE41-NEXT: pshufb %xmm0, %xmm1 +; SSE41-NEXT: pcmpeqb %xmm3, %xmm0 +; SSE41-NEXT: pand %xmm2, %xmm0 +; SSE41-NEXT: paddb %xmm1, %xmm0 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; SSE41-NEXT: pand %xmm0, %xmm1 +; SSE41-NEXT: psrlw $8, %xmm0 +; SSE41-NEXT: paddw %xmm1, %xmm0 +; SSE41-NEXT: pblendw {{.*#+}} xmm3 = xmm0[0],xmm3[1],xmm0[2],xmm3[3],xmm0[4],xmm3[5],xmm0[6],xmm3[7] +; SSE41-NEXT: psrld $16, %xmm0 +; SSE41-NEXT: paddd %xmm3, %xmm0 +; SSE41-NEXT: psrld $5, %xmm0 +; SSE41-NEXT: retq ; ; AVX2-LABEL: combine_vec_lshr_lzcnt_bit1: ; AVX2: # %bb.0: @@ -435,26 +524,48 @@ declare <4 x i32> @llvm.ctlz.v4i32(<4 x i32>, i1) ; fold (srl x, (trunc (and y, c))) -> (srl x, (and (trunc y), (trunc c))). define <4 x i32> @combine_vec_lshr_trunc_and(<4 x i32> %x, <4 x i64> %y) { -; SSE-LABEL: combine_vec_lshr_trunc_and: -; SSE: # %bb.0: -; SSE-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] -; SSE-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 -; SSE-NEXT: pshuflw {{.*#+}} xmm2 = xmm1[2,3,3,3,4,5,6,7] -; SSE-NEXT: movdqa %xmm0, %xmm3 -; SSE-NEXT: psrld %xmm2, %xmm3 -; SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] -; SSE-NEXT: pshuflw {{.*#+}} xmm4 = xmm2[2,3,3,3,4,5,6,7] -; SSE-NEXT: movdqa %xmm0, %xmm5 -; SSE-NEXT: psrld %xmm4, %xmm5 -; SSE-NEXT: pblendw {{.*#+}} xmm5 = xmm3[0,1,2,3],xmm5[4,5,6,7] -; SSE-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[0,1,1,1,4,5,6,7] -; SSE-NEXT: movdqa %xmm0, %xmm3 -; SSE-NEXT: psrld %xmm1, %xmm3 -; SSE-NEXT: pshuflw {{.*#+}} xmm1 = xmm2[0,1,1,1,4,5,6,7] -; SSE-NEXT: psrld %xmm1, %xmm0 -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm3[0,1,2,3],xmm0[4,5,6,7] -; SSE-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm5[2,3],xmm0[4,5],xmm5[6,7] -; SSE-NEXT: retq +; SSE2-LABEL: combine_vec_lshr_trunc_and: +; SSE2: # %bb.0: +; SSE2-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; SSE2-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 +; SSE2-NEXT: pshuflw {{.*#+}} xmm2 = xmm1[2,3,3,3,4,5,6,7] +; SSE2-NEXT: movdqa %xmm0, %xmm3 +; SSE2-NEXT: psrld %xmm2, %xmm3 +; SSE2-NEXT: pshuflw {{.*#+}} xmm4 = xmm1[0,1,1,1,4,5,6,7] +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: psrld %xmm4, %xmm2 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm3[0] +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; SSE2-NEXT: pshuflw {{.*#+}} xmm3 = xmm1[2,3,3,3,4,5,6,7] +; SSE2-NEXT: movdqa %xmm0, %xmm4 +; SSE2-NEXT: psrld %xmm3, %xmm4 +; SSE2-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[0,1,1,1,4,5,6,7] +; SSE2-NEXT: psrld %xmm1, %xmm0 +; SSE2-NEXT: punpckhqdq {{.*#+}} xmm0 = xmm0[1],xmm4[1] +; SSE2-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,3],xmm0[0,3] +; SSE2-NEXT: movaps %xmm2, %xmm0 +; SSE2-NEXT: retq +; +; SSE41-LABEL: combine_vec_lshr_trunc_and: +; SSE41: # %bb.0: +; SSE41-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; SSE41-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 +; SSE41-NEXT: pshuflw {{.*#+}} xmm2 = xmm1[2,3,3,3,4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm3 +; SSE41-NEXT: psrld %xmm2, %xmm3 +; SSE41-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] +; SSE41-NEXT: pshuflw {{.*#+}} xmm4 = xmm2[2,3,3,3,4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm5 +; SSE41-NEXT: psrld %xmm4, %xmm5 +; SSE41-NEXT: pblendw {{.*#+}} xmm5 = xmm3[0,1,2,3],xmm5[4,5,6,7] +; SSE41-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[0,1,1,1,4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm3 +; SSE41-NEXT: psrld %xmm1, %xmm3 +; SSE41-NEXT: pshuflw {{.*#+}} xmm1 = xmm2[0,1,1,1,4,5,6,7] +; SSE41-NEXT: psrld %xmm1, %xmm0 +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm3[0,1,2,3],xmm0[4,5,6,7] +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm5[2,3],xmm0[4,5],xmm5[6,7] +; SSE41-NEXT: retq ; ; AVX2-SLOW-LABEL: combine_vec_lshr_trunc_and: ; AVX2-SLOW: # %bb.0: -- GitLab From 81e20472a0c5a4a8edc5ec38dc345d580681af81 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Mon, 11 Mar 2024 17:43:14 +0100 Subject: [PATCH 138/953] [cmake] Exposes LLVM version number in the runtimes. (#84641) This allows sharing the LLVM version number in libc++. --- cmake/Modules/LLVMVersion.cmake | 15 +++++++++++++++ llvm/CMakeLists.txt | 13 +------------ runtimes/CMakeLists.txt | 2 ++ 3 files changed, 18 insertions(+), 12 deletions(-) create mode 100644 cmake/Modules/LLVMVersion.cmake diff --git a/cmake/Modules/LLVMVersion.cmake b/cmake/Modules/LLVMVersion.cmake new file mode 100644 index 000000000000..5e28283fbc1c --- /dev/null +++ b/cmake/Modules/LLVMVersion.cmake @@ -0,0 +1,15 @@ +# The LLVM Version number information + +if(NOT DEFINED LLVM_VERSION_MAJOR) + set(LLVM_VERSION_MAJOR 19) +endif() +if(NOT DEFINED LLVM_VERSION_MINOR) + set(LLVM_VERSION_MINOR 0) +endif() +if(NOT DEFINED LLVM_VERSION_PATCH) + set(LLVM_VERSION_PATCH 0) +endif() +if(NOT DEFINED LLVM_VERSION_SUFFIX) + set(LLVM_VERSION_SUFFIX git) +endif() + diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 494d8abeb64d..d9a17a869acf 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -15,18 +15,7 @@ if(NOT LLVM_NO_INSTALL_NAME_DIR_FOR_BUILD_TREE) set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON) endif() -if(NOT DEFINED LLVM_VERSION_MAJOR) - set(LLVM_VERSION_MAJOR 19) -endif() -if(NOT DEFINED LLVM_VERSION_MINOR) - set(LLVM_VERSION_MINOR 0) -endif() -if(NOT DEFINED LLVM_VERSION_PATCH) - set(LLVM_VERSION_PATCH 0) -endif() -if(NOT DEFINED LLVM_VERSION_SUFFIX) - set(LLVM_VERSION_SUFFIX git) -endif() +include(${LLVM_COMMON_CMAKE_UTILS}/Modules/LLVMVersion.cmake) set_directory_properties(PROPERTIES LLVM_VERSION_MAJOR "${LLVM_VERSION_MAJOR}") diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt index 29b47b862c21..6f24fbcccec9 100644 --- a/runtimes/CMakeLists.txt +++ b/runtimes/CMakeLists.txt @@ -6,6 +6,8 @@ set(LLVM_COMMON_CMAKE_UTILS "${CMAKE_CURRENT_SOURCE_DIR}/../cmake") include(${LLVM_COMMON_CMAKE_UTILS}/Modules/CMakePolicy.cmake NO_POLICY_SCOPE) +include(${LLVM_COMMON_CMAKE_UTILS}/Modules/LLVMVersion.cmake) + project(Runtimes C CXX ASM) list(INSERT CMAKE_MODULE_PATH 0 -- GitLab From 9a9aa41dea83039154601082b1aa2c56e35a5a17 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Mon, 11 Mar 2024 17:45:48 +0100 Subject: [PATCH 139/953] [LLDB][doc] Updates build instructions. (#84630) Recently building libc++ requires building libunwind too. This updates the LLDB instructions. I noticed this recently and it was separately filed as https://github.com/llvm/llvm-project/issues/84053 --- lldb/docs/resources/build.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lldb/docs/resources/build.rst b/lldb/docs/resources/build.rst index 995273a97b65..09d3d15a9408 100644 --- a/lldb/docs/resources/build.rst +++ b/lldb/docs/resources/build.rst @@ -331,7 +331,7 @@ macOS ^^^^^ On macOS the LLDB test suite requires libc++. Either add -``LLVM_ENABLE_RUNTIMES="libcxx;libcxxabi"`` or disable the test suite with +``LLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind"`` or disable the test suite with ``LLDB_INCLUDE_TESTS=OFF``. Further useful options: * ``LLDB_BUILD_FRAMEWORK:BOOL``: Builds the LLDB.framework. @@ -370,7 +370,7 @@ LLVM `_): $ cmake -B /path/to/lldb-build -G Ninja \ -C /path/to/llvm-project/lldb/cmake/caches/Apple-lldb-macOS.cmake \ -DLLVM_ENABLE_PROJECTS="clang;lldb" \ - -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ + -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" \ llvm-project/llvm $ DESTDIR=/path/to/lldb-install ninja -C /path/to/lldb-build check-lldb install-distribution @@ -386,7 +386,7 @@ Build LLDB standalone for development with Xcode: $ cmake -B /path/to/llvm-build -G Ninja \ -C /path/to/llvm-project/lldb/cmake/caches/Apple-lldb-base.cmake \ -DLLVM_ENABLE_PROJECTS="clang" \ - -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ + -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" \ llvm-project/llvm $ ninja -C /path/to/llvm-build -- GitLab From 501bc101c04675969ab673b247f2a58fa72bd09e Mon Sep 17 00:00:00 2001 From: karzan <61278770+karzanWang@users.noreply.github.com> Date: Tue, 12 Mar 2024 01:07:12 +0800 Subject: [PATCH 140/953] [lldb] Save the edited line before clearing it in Editline::PrintAsync (#84154) If the `m_editor_status` is `EditorStatus::Editing`, PrintAsync clears the currently edited line. In some situations, the edited line is not saved. After the stream flushes, PrintAsync tries to display the unsaved line, causing the loss of the edited line. The issue arose while I was debugging REPRLRun in [Fuzzilli](https://github.com/googleprojectzero/fuzzilli). I started LLDB and attempted to set a breakpoint in libreprl-posix.c. I entered `breakpoint set -f lib` and used the "tab" key for command completion. After completion, the edited line was flushed, leaving a blank line. --- lldb/source/Host/common/Editline.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp index e66271e8a6ee..ed61aecc23b9 100644 --- a/lldb/source/Host/common/Editline.cpp +++ b/lldb/source/Host/common/Editline.cpp @@ -1597,6 +1597,7 @@ bool Editline::GetLines(int first_line_number, StringList &lines, void Editline::PrintAsync(Stream *stream, const char *s, size_t len) { std::lock_guard guard(m_output_mutex); if (m_editor_status == EditorStatus::Editing) { + SaveEditedLine(); MoveCursor(CursorLocation::EditingCursor, CursorLocation::BlockStart); fprintf(m_output_file, ANSI_CLEAR_BELOW); } -- GitLab From 07d7b9c255078edc6f04bd4e68416bdf3e8735ab Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Mon, 11 Mar 2024 18:17:18 +0100 Subject: [PATCH 141/953] [libc] Fix forward arm32 builtbot (#84794) Introduced by https://github.com/llvm/llvm-project/pull/83441. --- libc/test/src/string/memory_utils/CMakeLists.txt | 1 + libc/test/src/string/memory_utils/op_tests.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/libc/test/src/string/memory_utils/CMakeLists.txt b/libc/test/src/string/memory_utils/CMakeLists.txt index 567f85e37bfa..a0dddd2f97b5 100644 --- a/libc/test/src/string/memory_utils/CMakeLists.txt +++ b/libc/test/src/string/memory_utils/CMakeLists.txt @@ -12,6 +12,7 @@ add_libc_test( libc.src.__support.CPP.array libc.src.__support.CPP.cstddef libc.src.__support.CPP.span + libc.src.__support.macros.properties.types libc.src.__support.macros.sanitizer libc.src.string.memory_utils.memory_utils UNIT_TEST_ONLY diff --git a/libc/test/src/string/memory_utils/op_tests.cpp b/libc/test/src/string/memory_utils/op_tests.cpp index 95a04755eb4d..703a26b16b03 100644 --- a/libc/test/src/string/memory_utils/op_tests.cpp +++ b/libc/test/src/string/memory_utils/op_tests.cpp @@ -10,6 +10,7 @@ #include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT64 #include "src/string/memory_utils/op_aarch64.h" #include "src/string/memory_utils/op_builtin.h" +#include "src/string/memory_utils/op_generic.h" #include "src/string/memory_utils/op_riscv.h" #include "src/string/memory_utils/op_x86.h" #include "test/UnitTest/Test.h" -- GitLab From bdbad0d07bb600301cb324e87a6be37ca4af591a Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Mon, 11 Mar 2024 10:21:07 -0700 Subject: [PATCH 142/953] Turn off instruction flow control annotations by default (#84607) Walter Erquinigo added optional instruction annotations for x86 instructions in 2022 for the `thread trace dump instruction` command, and code to DisassemblerLLVMC to add annotations for instructions that change flow control, v. https://reviews.llvm.org/D128477 This was added as an option to `disassemble`, and the trace dump command enables it by default, but several other instruction dumpers were changed to display them by default as well. These are only implemented for Intel instructions, so our disassembly on other targets ends up looking like ``` (lldb) x/5i 0x1000086e4 0x1000086e4: 0xa9be6ffc unknown stp x28, x27, [sp, #-0x20]! 0x1000086e8: 0xa9017bfd unknown stp x29, x30, [sp, #0x10] 0x1000086ec: 0x910043fd unknown add x29, sp, #0x10 0x1000086f0: 0xd11843ff unknown sub sp, sp, #0x610 0x1000086f4: 0x910c63e8 unknown add x8, sp, #0x318 ``` instead of `disassemble`'s output style of ``` lldb`main: lldb[0x1000086e4] <+0>: stp x28, x27, [sp, #-0x20]! lldb[0x1000086e8] <+4>: stp x29, x30, [sp, #0x10] lldb[0x1000086ec] <+8>: add x29, sp, #0x10 lldb[0x1000086f0] <+12>: sub sp, sp, #0x610 lldb[0x1000086f4] <+16>: add x8, sp, #0x318 ``` Adding symbolic annotations for assembly instructions is something I'm interested in too, because we may have users investigating a crash or apparent-incorrect behavior who must debug optimized assembly and they may not be familiar with the ISA they're using, so short of flipping through a many-thousand-page PDF to understand each instruction, they're lost. They don't write assembly or work at that level, but to understand a bug, they have to understand what the instructions are actually doing. But the annotations that exist today don't move us forward much on that front - I'd argue that the flow control instructions on Intel are not hard to understand from their names, but that might just be my personal bias. Much trickier instructions exist in any event. Displaying this information by default for all targets when we only have one class of instructions on one target is not a good default. Also, in 2011 when Greg implemented the `memory read -f i` (aka `x/i`) command ``` commit 5009f9d5010a7e34ae15f962dac8505ea11a8716 Author: Greg Clayton Date: Thu Oct 27 17:55:14 2011 +0000 [...] eFormatInstruction will print out disassembly with bytes and it will use the current target's architecture. The format character for this is "i" (which used to be being used for the integer format, but the integer format also has "d", so we gave the "i" format to disassembly), the long format is "instruction". ``` he had DumpDataExtractor's DumpInstructions print the bytes of the instruction -- that's the first field we see above for the `x/5i` after the address -- and this is only useful for people who are debugging the disassembler itself, I would argue. I don't want this displayed by default either. tl;dr this patch removes both fields from `memory read -f -i` and I think this is the right call today. While I'm really interested in instruction annotation, I don't think `x/i` is the right place to have it enabled by default unless it's really compelling on at least some of our major targets. --- lldb/source/Core/DumpDataExtractor.cpp | 4 ++-- lldb/source/Expression/IRExecutionUnit.cpp | 2 +- .../InstEmulation/UnwindAssemblyInstEmulation.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lldb/source/Core/DumpDataExtractor.cpp b/lldb/source/Core/DumpDataExtractor.cpp index 986c9a181919..826edd7bab04 100644 --- a/lldb/source/Core/DumpDataExtractor.cpp +++ b/lldb/source/Core/DumpDataExtractor.cpp @@ -150,8 +150,8 @@ static lldb::offset_t DumpInstructions(const DataExtractor &DE, Stream *s, if (bytes_consumed) { offset += bytes_consumed; const bool show_address = base_addr != LLDB_INVALID_ADDRESS; - const bool show_bytes = true; - const bool show_control_flow_kind = true; + const bool show_bytes = false; + const bool show_control_flow_kind = false; ExecutionContext exe_ctx; exe_scope->CalculateExecutionContext(exe_ctx); disassembler_sp->GetInstructionList().Dump( diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 0682746e448e..e4e131d70d43 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -201,7 +201,7 @@ Status IRExecutionUnit::DisassembleFunction(Stream &stream, UINT32_MAX, false, false); InstructionList &instruction_list = disassembler_sp->GetInstructionList(); - instruction_list.Dump(&stream, true, true, /*show_control_flow_kind=*/true, + instruction_list.Dump(&stream, true, true, /*show_control_flow_kind=*/false, &exe_ctx); return ret; diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index 7ff5cd2c23b0..c4a171ec7d01 100644 --- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -83,7 +83,7 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly( const uint32_t addr_byte_size = m_arch.GetAddressByteSize(); const bool show_address = true; const bool show_bytes = true; - const bool show_control_flow_kind = true; + const bool show_control_flow_kind = false; m_cfa_reg_info = *m_inst_emulator_up->GetRegisterInfo( unwind_plan.GetRegisterKind(), unwind_plan.GetInitialCFARegister()); m_fp_is_cfa = false; -- GitLab From 36a2752923a76f0b747bc35b7cd1bd1d1bf5bf05 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Mon, 11 Mar 2024 18:21:19 +0100 Subject: [PATCH 143/953] [bazel] Grab correct version info after 81e20472a0c5a4a8edc5ec38dc345d580681af81 This is a bit awkward. --- utils/bazel/configure.bzl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/utils/bazel/configure.bzl b/utils/bazel/configure.bzl index 88a576548e16..d6cd6aa0813e 100644 --- a/utils/bazel/configure.bzl +++ b/utils/bazel/configure.bzl @@ -149,6 +149,14 @@ def _llvm_configure_impl(repository_ctx): llvm_cmake, ) + # Grab version info and merge it with the other vars + version = _extract_cmake_settings( + repository_ctx, + "cmake/Modules/LLVMVersion.cmake", + ) + version = {k: v for k, v in version.items() if v != None} + vars.update(version) + _write_dict_to_file( repository_ctx, filepath = "vars.bzl", -- GitLab From 866ac9a165d65606910987c119ebee6a85480192 Mon Sep 17 00:00:00 2001 From: annamthomas Date: Mon, 11 Mar 2024 13:23:00 -0400 Subject: [PATCH 144/953] [LV] Address postcommit review for PR84782 (#84797) This testcase was added to show miscompile in https://github.com/llvm/llvm-project/issues/81872 --- .../Transforms/LoopVectorize/X86/pr81872.ll | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll b/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll index c6b1944b2009..14acb6f57aa0 100644 --- a/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll +++ b/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll @@ -3,15 +3,13 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" -@global = external global ptr addrspace(1), align 8 - ; PR 81872 explains the issue. ; If we vectorize, we have a miscompile where array IV and thereby value stored in (arr[99], ; arr[98]) is calculated incorrectly since disjoint or was only disjoint because ; of dominating conditions. Dropping the disjoint to avoid poison still changes ; the behaviour since now the or is no longer equivalent to the add. -; Function Attrs: uwtable +; define void @test(ptr noundef align 8 dereferenceable_or_null(16) %arr) #0 { ; CHECK-LABEL: define void @test( ; CHECK-SAME: ptr noundef align 8 dereferenceable_or_null(16) [[ARR:%.*]]) #[[ATTR0:[0-9]+]] { @@ -45,43 +43,43 @@ define void @test(ptr noundef align 8 dereferenceable_or_null(16) %arr) #0 { ; CHECK-NEXT: br i1 true, label [[BB6:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 87, [[MIDDLE_BLOCK]] ], [ 99, [[BB5:%.*]] ] -; CHECK-NEXT: br label [[BB15:%.*]] -; CHECK: bb15: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[BB20:%.*]] ] +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] ; CHECK-NEXT: [[AND:%.*]] = and i64 [[IV]], 1 ; CHECK-NEXT: [[ICMP17:%.*]] = icmp eq i64 [[AND]], 0 -; CHECK-NEXT: br i1 [[ICMP17]], label [[BB18:%.*]], label [[BB20]], !prof [[PROF5:![0-9]+]] +; CHECK-NEXT: br i1 [[ICMP17]], label [[BB18:%.*]], label [[LOOP_LATCH]], !prof [[PROF5:![0-9]+]] ; CHECK: bb18: ; CHECK-NEXT: [[OR:%.*]] = or disjoint i64 [[IV]], 1 ; CHECK-NEXT: [[GETELEMENTPTR19:%.*]] = getelementptr inbounds i64, ptr [[ARR]], i64 [[OR]] ; CHECK-NEXT: store i64 1, ptr [[GETELEMENTPTR19]], align 8 -; CHECK-NEXT: br label [[BB20]] -; CHECK: bb20: +; CHECK-NEXT: br label [[LOOP_LATCH]] +; CHECK: loop.latch: ; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], -1 ; CHECK-NEXT: [[ICMP22:%.*]] = icmp eq i64 [[IV_NEXT]], 90 -; CHECK-NEXT: br i1 [[ICMP22]], label [[BB6]], label [[BB15]], !prof [[PROF6:![0-9]+]], !llvm.loop [[LOOP7:![0-9]+]] +; CHECK-NEXT: br i1 [[ICMP22]], label [[BB6]], label [[LOOP_HEADER]], !prof [[PROF6:![0-9]+]], !llvm.loop [[LOOP7:![0-9]+]] ; CHECK: bb6: ; CHECK-NEXT: ret void ; bb5: - br label %bb15 + br label %loop.header -bb15: ; preds = %bb20, %bb8 - %iv = phi i64 [ 99, %bb5 ], [ %iv.next, %bb20 ] +loop.header: ; preds = %loop.latch, %bb8 + %iv = phi i64 [ 99, %bb5 ], [ %iv.next, %loop.latch ] %and = and i64 %iv, 1 %icmp17 = icmp eq i64 %and, 0 - br i1 %icmp17, label %bb18, label %bb20, !prof !21 + br i1 %icmp17, label %bb18, label %loop.latch, !prof !21 -bb18: ; preds = %bb15 +bb18: ; preds = %loop.header %or = or disjoint i64 %iv, 1 %getelementptr19 = getelementptr inbounds i64, ptr %arr, i64 %or store i64 1, ptr %getelementptr19, align 8 - br label %bb20 + br label %loop.latch -bb20: ; preds = %bb18, %bb15 +loop.latch: ; preds = %bb18, %loop.header %iv.next = add nsw i64 %iv, -1 %icmp22 = icmp eq i64 %iv.next, 90 - br i1 %icmp22, label %bb6, label %bb15, !prof !22 + br i1 %icmp22, label %bb6, label %loop.header, !prof !22 bb6: ret void -- GitLab From 8467457afc61d70e881c9817ace26356ef757733 Mon Sep 17 00:00:00 2001 From: Bhuminjay Soni Date: Mon, 11 Mar 2024 22:55:32 +0530 Subject: [PATCH 145/953] Add new flag -Wreturn-mismatch (#82872) This pull request fixes #72116 where a new flag is introduced for compatibility with GCC 14, the functionality of -Wreturn-type is modified to split some of its behaviors into -Wreturn-mismatch Fixes #72116 --- clang/docs/ReleaseNotes.rst | 3 ++ clang/include/clang/Basic/DiagnosticGroups.td | 4 ++- .../clang/Basic/DiagnosticSemaKinds.td | 6 ++-- clang/test/Misc/warning-wall.c | 1 + clang/test/Sema/return-type-mismatch.c | 36 +++++++++++++++++++ 5 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 clang/test/Sema/return-type-mismatch.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index bce27dc8c4a9..88e552d5c461 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -183,6 +183,9 @@ Deprecated Compiler Flags Modified Compiler Flags ----------------------- +- Added a new diagnostic flag ``-Wreturn-mismatch`` which is grouped under + ``-Wreturn-type``, and moved some of the diagnostics previously controlled by + ``-Wreturn-type`` under this new flag. Fixes #GH72116. Removed Compiler Flags ------------------------- diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index ba1d4b2352e3..3f14167d6b84 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -617,7 +617,9 @@ def GNURedeclaredEnum : DiagGroup<"gnu-redeclared-enum">; def RedundantMove : DiagGroup<"redundant-move">; def Register : DiagGroup<"register", [DeprecatedRegister]>; def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">; -def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>; +def ReturnMismatch : DiagGroup<"return-mismatch">; +def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage, ReturnMismatch]>; + def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy", [CXX98CompatBindToTemporaryCopy]>; def SelfAssignmentField : DiagGroup<"self-assign-field">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9b5245695153..c54105507753 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10248,14 +10248,14 @@ def warn_second_parameter_to_va_arg_never_compatible : Warning< def warn_return_missing_expr : Warning< "non-void %select{function|method}1 %0 should return a value">, DefaultError, - InGroup; + InGroup; def ext_return_missing_expr : ExtWarn< "non-void %select{function|method}1 %0 should return a value">, DefaultError, - InGroup; + InGroup; def ext_return_has_expr : ExtWarn< "%select{void function|void method|constructor|destructor}1 %0 " "should not return a value">, - DefaultError, InGroup; + DefaultError, InGroup; def ext_return_has_void_expr : Extension< "void %select{function|method|block}1 %0 should not return void expression">; def err_return_init_list : Error< diff --git a/clang/test/Misc/warning-wall.c b/clang/test/Misc/warning-wall.c index 05a82770e26d..4909ab034ef3 100644 --- a/clang/test/Misc/warning-wall.c +++ b/clang/test/Misc/warning-wall.c @@ -44,6 +44,7 @@ CHECK-NEXT: -Wreorder-ctor CHECK-NEXT: -Wreorder-init-list CHECK-NEXT: -Wreturn-type CHECK-NEXT: -Wreturn-type-c-linkage +CHECK-NEXT: -Wreturn-mismatch CHECK-NEXT: -Wself-assign CHECK-NEXT: -Wself-assign-overloaded CHECK-NEXT: -Wself-assign-field diff --git a/clang/test/Sema/return-type-mismatch.c b/clang/test/Sema/return-type-mismatch.c new file mode 100644 index 000000000000..79a625d7df1f --- /dev/null +++ b/clang/test/Sema/return-type-mismatch.c @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -Wreturn-type -Wno-return-mismatch -fsyntax-only -verify=return-type %s +// RUN: %clang_cc1 -Wno-return-type -Wreturn-mismatch -fsyntax-only -verify=return-mismatch %s + +int foo(void) __attribute__((noreturn)); +int bar(void); + +void test1(void) { + return 1; // return-mismatch-warning{{void function 'test1' should not return a value}} +} + +int test2(void) { + return; // return-mismatch-warning{{non-void function 'test2' should return a value}} +} + +int test3(void) { + // return-type-warning@+1 {{non-void function does not return a value}} +} + +int test4(void) { + (void)(bar() || foo()); // return-type-warning@+1 {{non-void function does not return a value in all control paths}} +} + +void test5(void) { +} // no-warning + +int test6(void) { + return 0; // no-warning +} + +int test7(void) { + foo(); // no warning +} + +int test8(void) { + bar(); // return-type-warning@+1 {{non-void function does not return a value}} +} -- GitLab From 034cc2f5d0abcf7a465665246f16a1b75fbde93a Mon Sep 17 00:00:00 2001 From: Michael Maitland Date: Mon, 11 Mar 2024 13:47:30 -0400 Subject: [PATCH 146/953] [GISEL] Add G_INSERT_SUBVECTOR and G_EXTRACT_SUBVECTOR (#84538) G_INSERT and G_EXTRACT are not sufficient to use to represent both INSERT/EXTRACT on a subregister and INSERT/EXTRACT on a vector. We would like to be able to INSERT/EXTRACT on vectors in cases that INSERT/EXTRACT on vector subregisters are not sufficient, so we add these opcodes. I tried to do a patch where we treated G_EXTRACT as both G_EXTRACT_SUBVECTOR and G_EXTRACT_SUBREG, but ran into an infinite loop at this [point](https://github.com/llvm/llvm-project/blob/8b5b294ec2cf876bc5eb5bd5fcb56ef487e36d60/llvm/lib/Target/RISCV/RISCVISelLowering.cpp#L9932) in the SDAG equivalent code. --- llvm/docs/GlobalISel/GenericOpcode.rst | 35 +++++++ .../CodeGen/GlobalISel/MachineIRBuilder.h | 19 ++++ llvm/include/llvm/Support/TargetOpcodes.def | 6 ++ llvm/include/llvm/Target/GenericOpcodes.td | 14 +++ .../CodeGen/GlobalISel/MachineIRBuilder.cpp | 15 +++ llvm/lib/CodeGen/MachineVerifier.cpp | 98 +++++++++++++++++++ .../GlobalISel/legalizer-info-validation.mir | 6 ++ .../test_g_extract_subvector.mir | 31 ++++++ .../test_g_insert_subvector.mir | 43 ++++++++ 9 files changed, 267 insertions(+) create mode 100644 llvm/test/MachineVerifier/test_g_extract_subvector.mir create mode 100644 llvm/test/MachineVerifier/test_g_insert_subvector.mir diff --git a/llvm/docs/GlobalISel/GenericOpcode.rst b/llvm/docs/GlobalISel/GenericOpcode.rst index dda367607d04..f9f9e1186460 100644 --- a/llvm/docs/GlobalISel/GenericOpcode.rst +++ b/llvm/docs/GlobalISel/GenericOpcode.rst @@ -607,6 +607,41 @@ See the LLVM LangRef entry on '``llvm.lround.*'`` for details on behaviour. Vector Specific Operations -------------------------- +G_INSERT_SUBVECTOR +^^^^^^^^^^^^^^^^^^ + +Insert the second source vector into the first source vector. The index operand +represents the starting index in the first source vector at which the second +source vector should be inserted into. + +The index must be a constant multiple of the second source vector's minimum +vector length. If the vectors are scalable, then the index is first scaled by +the runtime scaling factor. The indices inserted in the source vector must be +valid indicies of that vector. If this condition cannot be determined statically +but is false at runtime, then the result vector is undefined. + +.. code-block:: none + + %2:_() = G_INSERT_SUBVECTOR %0:_(), %1:_(), 0 + +G_EXTRACT_SUBVECTOR +^^^^^^^^^^^^^^^^^^^ + +Extract a vector of destination type from the source vector. The index operand +represents the starting index from which a subvector is extracted from +the source vector. + +The index must be a constant multiple of the source vector's minimum vector +length. If the source vector is a scalable vector, then the index is first +scaled by the runtime scaling factor. The indices extracted from the source +vector must be valid indicies of that vector. If this condition cannot be +determined statically but is false at runtime, then the result vector is +undefined. + +.. code-block:: none + + %3:_() = G_EXTRACT_SUBVECTOR %2:_(), 2 + G_CONCAT_VECTORS ^^^^^^^^^^^^^^^^ diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index 6762b1b360d5..4732eaf4ee27 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -1121,6 +1121,25 @@ public: MachineInstrBuilder buildConcatVectors(const DstOp &Res, ArrayRef Ops); + /// Build and insert `Res = G_INSERT_SUBVECTOR Src0, Src1, Idx`. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res, \p Src0, and \p Src1 must be generic virtual registers with + /// vector type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildInsertSubvector(const DstOp &Res, const SrcOp &Src0, + const SrcOp &Src1, unsigned Index); + + /// Build and insert `Res = G_EXTRACT_SUBVECTOR Src, Idx0`. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res and \p Src must be generic virtual registers with vector type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildExtractSubvector(const DstOp &Res, const SrcOp &Src, + unsigned Index); + MachineInstrBuilder buildInsert(const DstOp &Res, const SrcOp &Src, const SrcOp &Op, unsigned Index); diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def index 94fba491148b..3dade14f043b 100644 --- a/llvm/include/llvm/Support/TargetOpcodes.def +++ b/llvm/include/llvm/Support/TargetOpcodes.def @@ -727,6 +727,12 @@ HANDLE_TARGET_OPCODE(G_BR) /// Generic branch to jump table entry. HANDLE_TARGET_OPCODE(G_BRJT) +/// Generic insert subvector. +HANDLE_TARGET_OPCODE(G_INSERT_SUBVECTOR) + +/// Generic extract subvector. +HANDLE_TARGET_OPCODE(G_EXTRACT_SUBVECTOR) + /// Generic insertelement. HANDLE_TARGET_OPCODE(G_INSERT_VECTOR_ELT) diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td index d967885aa2d7..8dc84fb0ba05 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -1426,6 +1426,20 @@ def G_WRITE_REGISTER : GenericInstruction { // Vector ops //------------------------------------------------------------------------------ +// Generic insert subvector. +def G_INSERT_SUBVECTOR : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src0, type1:$src1, untyped_imm_0:$idx); + let hasSideEffects = false; +} + +// Generic extract subvector. +def G_EXTRACT_SUBVECTOR : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src, untyped_imm_0:$idx); + let hasSideEffects = false; +} + // Generic insertelement. def G_INSERT_VECTOR_ELT : GenericInstruction { let OutOperandList = (outs type0:$dst); diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index 28e5bf85ca9c..9b12d443c96e 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -877,6 +877,21 @@ MachineIRBuilder::buildSelect(const DstOp &Res, const SrcOp &Tst, return buildInstr(TargetOpcode::G_SELECT, {Res}, {Tst, Op0, Op1}, Flags); } +MachineInstrBuilder MachineIRBuilder::buildInsertSubvector(const DstOp &Res, + const SrcOp &Src0, + const SrcOp &Src1, + unsigned Idx) { + return buildInstr(TargetOpcode::G_INSERT_SUBVECTOR, Res, + {Src0, Src1, uint64_t(Idx)}); +} + +MachineInstrBuilder MachineIRBuilder::buildExtractSubvector(const DstOp &Res, + const SrcOp &Src, + unsigned Idx) { + return buildInstr(TargetOpcode::G_INSERT_SUBVECTOR, Res, + {Src, uint64_t(Idx)}); +} + MachineInstrBuilder MachineIRBuilder::buildInsertVectorElement(const DstOp &Res, const SrcOp &Val, const SrcOp &Elt, const SrcOp &Idx) { diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp index 9003f1dded87..90cbf097370d 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -1613,6 +1613,104 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { report("G_BSWAP size must be a multiple of 16 bits", MI); break; } + case TargetOpcode::G_INSERT_SUBVECTOR: { + const MachineOperand &Src0Op = MI->getOperand(1); + if (!Src0Op.isReg()) { + report("G_INSERT_SUBVECTOR first source must be a register", MI); + break; + } + + const MachineOperand &Src1Op = MI->getOperand(2); + if (!Src1Op.isReg()) { + report("G_INSERT_SUBVECTOR second source must be a register", MI); + break; + } + + const MachineOperand &IndexOp = MI->getOperand(3); + if (!IndexOp.isImm()) { + report("G_INSERT_SUBVECTOR index must be an immediate", MI); + break; + } + + LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); + LLT Src0Ty = MRI->getType(Src0Op.getReg()); + LLT Src1Ty = MRI->getType(Src1Op.getReg()); + + if (!DstTy.isVector()) { + report("Destination type must be a vector", MI); + break; + } + + if (!Src0Ty.isVector()) { + report("First source must be a vector", MI); + break; + } + + if (!Src1Ty.isVector()) { + report("Second source must be a vector", MI); + break; + } + + if (DstTy != Src0Ty) { + report("Destination type must match the first source vector type", MI); + break; + } + + if (Src0Ty.getElementType() != Src1Ty.getElementType()) { + report("Element type of source vectors must be the same", MI); + break; + } + + if (IndexOp.getImm() != 0 && + Src1Ty.getElementCount().getKnownMinValue() % IndexOp.getImm() != 0) { + report("Index must be a multiple of the second source vector's " + "minimum vector length", + MI); + break; + } + break; + } + case TargetOpcode::G_EXTRACT_SUBVECTOR: { + const MachineOperand &SrcOp = MI->getOperand(1); + if (!SrcOp.isReg()) { + report("G_EXTRACT_SUBVECTOR first source must be a register", MI); + break; + } + + const MachineOperand &IndexOp = MI->getOperand(2); + if (!IndexOp.isImm()) { + report("G_EXTRACT_SUBVECTOR index must be an immediate", MI); + break; + } + + LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); + LLT SrcTy = MRI->getType(SrcOp.getReg()); + + if (!DstTy.isVector()) { + report("Destination type must be a vector", MI); + break; + } + + if (!SrcTy.isVector()) { + report("First source must be a vector", MI); + break; + } + + if (DstTy.getElementType() != SrcTy.getElementType()) { + report("Element type of vectors must be the same", MI); + break; + } + + if (IndexOp.getImm() != 0 && + SrcTy.getElementCount().getKnownMinValue() % IndexOp.getImm() != 0) { + report("Index must be a multiple of the source vector's minimum vector " + "length", + MI); + break; + } + + break; + } case TargetOpcode::G_SHUFFLE_VECTOR: { const MachineOperand &MaskOp = MI->getOperand(3); if (!MaskOp.isShuffleMask()) { diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir index ecad3f115134..ac330918b430 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -616,6 +616,12 @@ # DEBUG-NEXT: G_BRJT (opcode {{[0-9]+}}): 2 type indices # DEBUG-NEXT: .. the first uncovered type index: 2, OK # DEBUG-NEXT: .. the first uncovered imm index: 0, OK +# DEBUG-NEXT: G_INSERT_SUBVECTOR (opcode {{[0-9]+}}): 2 type indices, 1 imm index +# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined +# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined +# DEBUG-NEXT: G_EXTRACT_SUBVECTOR (opcode {{[0-9]+}}): 1 type index, 1 imm index +# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined +# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined # DEBUG-NEXT: G_INSERT_VECTOR_ELT (opcode {{[0-9]+}}): 3 type indices, 0 imm indices # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected diff --git a/llvm/test/MachineVerifier/test_g_extract_subvector.mir b/llvm/test/MachineVerifier/test_g_extract_subvector.mir new file mode 100644 index 000000000000..bc167d2eb7bc --- /dev/null +++ b/llvm/test/MachineVerifier/test_g_extract_subvector.mir @@ -0,0 +1,31 @@ +# RUN: not --crash llc -o - -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s +--- +name: g_extract_subvector +tracksRegLiveness: true +liveins: +body: | + bb.0: + %0:_(s32) = G_CONSTANT i32 0 + %1:_() = G_IMPLICIT_DEF + %2:_() = G_IMPLICIT_DEF + + ; CHECK: G_EXTRACT_SUBVECTOR first source must be a register + %3:_() = G_EXTRACT_SUBVECTOR 1, 0 + + ; CHECK: G_EXTRACT_SUBVECTOR index must be an immediate + %4:_() = G_EXTRACT_SUBVECTOR %2, %0 + + ; CHECK: Destination type must be a vector + %5:_(s32) = G_EXTRACT_SUBVECTOR %2, 0 + + ; CHECK: First source must be a vector + %6:_() = G_EXTRACT_SUBVECTOR %0, 0 + + %7:_() = G_IMPLICIT_DEF + + ; CHECK: Element type of vectors must be the same + %8:_() = G_EXTRACT_SUBVECTOR %7, 0 + + ; CHECK: Index must be a multiple of the source vector's minimum vector length + %9:_() = G_EXTRACT_SUBVECTOR %1, 3 +... diff --git a/llvm/test/MachineVerifier/test_g_insert_subvector.mir b/llvm/test/MachineVerifier/test_g_insert_subvector.mir new file mode 100644 index 000000000000..dce30cdb6b1e --- /dev/null +++ b/llvm/test/MachineVerifier/test_g_insert_subvector.mir @@ -0,0 +1,43 @@ +# RUN: not --crash llc -o - -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s + +--- +name: g_splat_vector +tracksRegLiveness: true +liveins: +body: | + bb.0: + %0:_(s32) = G_CONSTANT i32 0 + %1:_() = G_IMPLICIT_DEF + %2:_() = G_IMPLICIT_DEF + + ; CHECK: G_INSERT_SUBVECTOR first source must be a register + %3:_() = G_INSERT_SUBVECTOR 1, %2, 0 + + ; CHECK: G_INSERT_SUBVECTOR second source must be a register + %4:_() = G_INSERT_SUBVECTOR %1, 1, 0 + + ; CHECK: G_INSERT_SUBVECTOR index must be an immediate + %5:_() = G_INSERT_SUBVECTOR %1, %2, %0 + + ; CHECK: Destination type must be a vector + %6:_(s32) = G_INSERT_SUBVECTOR %1, %2, 0 + + ; CHECK: First source must be a vector + %7:_() = G_INSERT_SUBVECTOR %0, %2, 0 + + ; CHECK: Second source must be a vector + %8:_() = G_INSERT_SUBVECTOR %1, %0, 0 + + ; CHECK: Destination type must match the first source vector type + %9:_() = G_INSERT_SUBVECTOR %2, %1, 0 + + %10:_() = G_IMPLICIT_DEF + + ; CHECK: Element type of source vectors must be the same + %11:_() = G_INSERT_SUBVECTOR %1, %10, 0 + + %12:_() = G_IMPLICIT_DEF + + ; CHECK: Index must be a multiple of the second source vector's minimum vector length + %13:_() = G_INSERT_SUBVECTOR %12, %1, 3 +... -- GitLab From 2a3f27cce8983e5d6871b9ebb8f5e9dd91884f0c Mon Sep 17 00:00:00 2001 From: Joe Nash Date: Mon, 11 Mar 2024 13:58:45 -0400 Subject: [PATCH 147/953] [AMDGPU][True16] Make NotHasTrue16BitInsts a True16Predicate (#84771) NFC. Test coverage on VOPC shows NotHasTrue16BitInsts on the pre-gfx11 instructions is necessary (we cannot use the default NoTrue16Predicate). Update the VOP2 instructions in the same manner. --- llvm/lib/Target/AMDGPU/AMDGPU.td | 2 +- llvm/lib/Target/AMDGPU/VOP2Instructions.td | 12 ++++++------ llvm/lib/Target/AMDGPU/VOPCInstructions.td | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td index 7183148e1310..c877658cd38e 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPU.td +++ b/llvm/lib/Target/AMDGPU/AMDGPU.td @@ -1903,7 +1903,7 @@ def Has16BitInsts : Predicate<"Subtarget->has16BitInsts()">, def HasTrue16BitInsts : Predicate<"Subtarget->hasTrue16BitInsts()">, AssemblerPredicate<(all_of FeatureTrue16BitInsts)>; -def NotHasTrue16BitInsts : Predicate<"!Subtarget->hasTrue16BitInsts()">; +def NotHasTrue16BitInsts : True16PredicateClass<"!Subtarget->hasTrue16BitInsts()">; // Control use of True16 instructions. The real True16 instructions are // True16 instructions as they are defined in the ISA. Fake True16 diff --git a/llvm/lib/Target/AMDGPU/VOP2Instructions.td b/llvm/lib/Target/AMDGPU/VOP2Instructions.td index 8a92aa8228f1..f136a434971c 100644 --- a/llvm/lib/Target/AMDGPU/VOP2Instructions.td +++ b/llvm/lib/Target/AMDGPU/VOP2Instructions.td @@ -199,7 +199,7 @@ multiclass VOP2Inst_t16 { - let SubtargetPredicate = NotHasTrue16BitInsts, OtherPredicates = [Has16BitInsts] in { + let OtherPredicates = [Has16BitInsts], True16Predicate = NotHasTrue16BitInsts in { defm NAME : VOP2Inst; } let SubtargetPredicate = UseRealTrue16Insts in { @@ -219,7 +219,7 @@ multiclass VOP2Inst_e64_t16 { - let SubtargetPredicate = NotHasTrue16BitInsts, OtherPredicates = [Has16BitInsts] in { + let OtherPredicates = [Has16BitInsts], True16Predicate = NotHasTrue16BitInsts in { defm NAME : VOP2Inst; } let SubtargetPredicate = HasTrue16BitInsts in { @@ -900,7 +900,7 @@ def LDEXP_F16_VOPProfile_True16 : VOPProfile_Fake16 { let isReMaterializable = 1 in { let FPDPRounding = 1 in { - let SubtargetPredicate = NotHasTrue16BitInsts, OtherPredicates = [Has16BitInsts] in + let OtherPredicates = [Has16BitInsts], True16Predicate = NotHasTrue16BitInsts in defm V_LDEXP_F16 : VOP2Inst <"v_ldexp_f16", LDEXP_F16_VOPProfile>; let SubtargetPredicate = HasTrue16BitInsts in defm V_LDEXP_F16_t16 : VOP2Inst <"v_ldexp_f16_t16", LDEXP_F16_VOPProfile_True16>; @@ -950,7 +950,7 @@ let SubtargetPredicate = isGFX11Plus in { } // End SubtargetPredicate = isGFX11Plus let FPDPRounding = 1, isReMaterializable = 1, FixedSize = 1 in { -let SubtargetPredicate = isGFX10Plus, OtherPredicates = [NotHasTrue16BitInsts] in { +let SubtargetPredicate = isGFX10Plus, True16Predicate = NotHasTrue16BitInsts in { def V_FMAMK_F16 : VOP2_Pseudo <"v_fmamk_f16", VOP_MADMK_F16, [], "">; } let SubtargetPredicate = HasTrue16BitInsts in { @@ -958,7 +958,7 @@ def V_FMAMK_F16_t16 : VOP2_Pseudo <"v_fmamk_f16_t16", VOP_MADMK_F16_t16, [], ""> } let isCommutable = 1 in { -let SubtargetPredicate = isGFX10Plus, OtherPredicates = [NotHasTrue16BitInsts] in { +let SubtargetPredicate = isGFX10Plus, True16Predicate = NotHasTrue16BitInsts in { def V_FMAAK_F16 : VOP2_Pseudo <"v_fmaak_f16", VOP_MADAK_F16, [], "">; } let SubtargetPredicate = HasTrue16BitInsts in { @@ -971,7 +971,7 @@ let Constraints = "$vdst = $src2", DisableEncoding="$src2", isConvertibleToThreeAddress = 1, isCommutable = 1 in { -let SubtargetPredicate = isGFX10Plus, OtherPredicates = [NotHasTrue16BitInsts] in { +let SubtargetPredicate = isGFX10Plus, True16Predicate = NotHasTrue16BitInsts in { defm V_FMAC_F16 : VOP2Inst <"v_fmac_f16", VOP_MAC_F16>; } let SubtargetPredicate = HasTrue16BitInsts in { diff --git a/llvm/lib/Target/AMDGPU/VOPCInstructions.td b/llvm/lib/Target/AMDGPU/VOPCInstructions.td index e5e82447d55f..022fb7cb6775 100644 --- a/llvm/lib/Target/AMDGPU/VOPCInstructions.td +++ b/llvm/lib/Target/AMDGPU/VOPCInstructions.td @@ -408,7 +408,7 @@ def VOPC_I64_I64 : VOPC_NoSdst_Profile<[Write64Bit], i64>; multiclass VOPC_F16 { - let OtherPredicates = [NotHasTrue16BitInsts, Has16BitInsts] in { + let OtherPredicates = [Has16BitInsts], True16Predicate = NotHasTrue16BitInsts in { defm NAME : VOPC_Pseudos ; } let OtherPredicates = [HasTrue16BitInsts] in { @@ -424,7 +424,7 @@ multiclass VOPC_F64 { - let OtherPredicates = [NotHasTrue16BitInsts, Has16BitInsts] in { + let OtherPredicates = [Has16BitInsts], True16Predicate = NotHasTrue16BitInsts in { defm NAME : VOPC_Pseudos ; } let OtherPredicates = [HasTrue16BitInsts] in { @@ -439,7 +439,7 @@ multiclass VOPC_I64 ; multiclass VOPCX_F16 { - let OtherPredicates = [NotHasTrue16BitInsts, Has16BitInsts] in { + let OtherPredicates = [Has16BitInsts], True16Predicate = NotHasTrue16BitInsts in { defm NAME : VOPCX_Pseudos ; } let OtherPredicates = [HasTrue16BitInsts] in { @@ -454,7 +454,7 @@ multiclass VOPCX_F64 : VOPCX_Pseudos ; multiclass VOPCX_I16 { - let OtherPredicates = [NotHasTrue16BitInsts, Has16BitInsts] in { + let OtherPredicates = [Has16BitInsts], True16Predicate = NotHasTrue16BitInsts in { defm NAME : VOPCX_Pseudos ; } let OtherPredicates = [HasTrue16BitInsts] in { @@ -940,7 +940,7 @@ def VOPC_F32_I32 : VOPC_Class_NoSdst_Profile<[Write32Bit], f32>; def VOPC_F64_I32 : VOPC_Class_NoSdst_Profile<[Write64Bit], f64>; multiclass VOPC_CLASS_F16 { - let OtherPredicates = [NotHasTrue16BitInsts, Has16BitInsts] in { + let OtherPredicates = [Has16BitInsts], True16Predicate = NotHasTrue16BitInsts in { defm NAME : VOPC_Class_Pseudos ; } let OtherPredicates = [HasTrue16BitInsts] in { @@ -949,7 +949,7 @@ multiclass VOPC_CLASS_F16 { } multiclass VOPCX_CLASS_F16 { - let OtherPredicates = [NotHasTrue16BitInsts, Has16BitInsts] in { + let OtherPredicates = [Has16BitInsts], True16Predicate = NotHasTrue16BitInsts in { defm NAME : VOPCX_Class_Pseudos ; } let OtherPredicates = [HasTrue16BitInsts] in { -- GitLab From 725a0523a18ef1a75a6d4a010dc3debe1b08c9d1 Mon Sep 17 00:00:00 2001 From: Paul T Robinson Date: Mon, 11 Mar 2024 11:14:17 -0700 Subject: [PATCH 148/953] [Headers][X86] Add specific results to comparisons (#83316) Some comparison intrinsics were described as returning the "result" without specifying how. The "cmp" intrinsics return zero or all 1's in the corresponding elements of a returned vector; the "com" intrinsics return an integer 0 or 1. Also removed some redundant information. --- clang/lib/Headers/emmintrin.h | 114 +++++++++---------- clang/lib/Headers/smmintrin.h | 4 + clang/lib/Headers/xmmintrin.h | 202 ++++++++++++++++++++-------------- 3 files changed, 177 insertions(+), 143 deletions(-) diff --git a/clang/lib/Headers/emmintrin.h b/clang/lib/Headers/emmintrin.h index ebe295f160b2..984f0cf917e9 100644 --- a/clang/lib/Headers/emmintrin.h +++ b/clang/lib/Headers/emmintrin.h @@ -410,8 +410,9 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_xor_pd(__m128d __a, } /// Compares each of the corresponding double-precision values of the -/// 128-bit vectors of [2 x double] for equality. Each comparison yields 0x0 -/// for false, 0xFFFFFFFFFFFFFFFF for true. +/// 128-bit vectors of [2 x double] for equality. +/// +/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. /// /// \headerfile /// @@ -429,8 +430,9 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpeq_pd(__m128d __a, /// Compares each of the corresponding double-precision values of the /// 128-bit vectors of [2 x double] to determine if the values in the first -/// operand are less than those in the second operand. Each comparison -/// yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// operand are less than those in the second operand. +/// +/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. /// /// \headerfile /// @@ -949,8 +951,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpnge_sd(__m128d __a, /// Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] for equality. /// -/// The comparison yields 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower double-precision values is NaN, returns 0. /// /// \headerfile /// @@ -962,8 +964,7 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpnge_sd(__m128d __a, /// \param __b /// A 128-bit vector of [2 x double]. The lower double-precision value is /// compared to the lower double-precision value of \a __a. -/// \returns An integer containing the comparison results. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_comieq_sd(__m128d __a, __m128d __b) { return __builtin_ia32_comisdeq((__v2df)__a, (__v2df)__b); @@ -974,8 +975,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comieq_sd(__m128d __a, /// the value in the first parameter is less than the corresponding value in /// the second parameter. /// -/// The comparison yields 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower double-precision values is NaN, returns 0. /// /// \headerfile /// @@ -987,8 +988,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comieq_sd(__m128d __a, /// \param __b /// A 128-bit vector of [2 x double]. The lower double-precision value is /// compared to the lower double-precision value of \a __a. -/// \returns An integer containing the comparison results. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_comilt_sd(__m128d __a, __m128d __b) { return __builtin_ia32_comisdlt((__v2df)__a, (__v2df)__b); @@ -999,8 +999,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comilt_sd(__m128d __a, /// the value in the first parameter is less than or equal to the /// corresponding value in the second parameter. /// -/// The comparison yields 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower double-precision values is NaN, returns 0. /// /// \headerfile /// @@ -1012,8 +1012,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comilt_sd(__m128d __a, /// \param __b /// A 128-bit vector of [2 x double]. The lower double-precision value is /// compared to the lower double-precision value of \a __a. -/// \returns An integer containing the comparison results. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_comile_sd(__m128d __a, __m128d __b) { return __builtin_ia32_comisdle((__v2df)__a, (__v2df)__b); @@ -1024,8 +1023,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comile_sd(__m128d __a, /// the value in the first parameter is greater than the corresponding value /// in the second parameter. /// -/// The comparison yields 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower double-precision values is NaN, returns 0. /// /// \headerfile /// @@ -1037,8 +1036,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comile_sd(__m128d __a, /// \param __b /// A 128-bit vector of [2 x double]. The lower double-precision value is /// compared to the lower double-precision value of \a __a. -/// \returns An integer containing the comparison results. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_comigt_sd(__m128d __a, __m128d __b) { return __builtin_ia32_comisdgt((__v2df)__a, (__v2df)__b); @@ -1049,8 +1047,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comigt_sd(__m128d __a, /// the value in the first parameter is greater than or equal to the /// corresponding value in the second parameter. /// -/// The comparison yields 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower double-precision values is NaN, returns 0. /// /// \headerfile /// @@ -1062,8 +1060,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comigt_sd(__m128d __a, /// \param __b /// A 128-bit vector of [2 x double]. The lower double-precision value is /// compared to the lower double-precision value of \a __a. -/// \returns An integer containing the comparison results. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_comige_sd(__m128d __a, __m128d __b) { return __builtin_ia32_comisdge((__v2df)__a, (__v2df)__b); @@ -1074,7 +1071,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comige_sd(__m128d __a, /// the value in the first parameter is unequal to the corresponding value in /// the second parameter. /// -/// The comparison yields 0 for false, 1 for true. If either of the two +/// The comparison returns 0 for false, 1 for true. If either of the two /// lower double-precision values is NaN, 1 is returned. /// /// \headerfile @@ -1087,18 +1084,17 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comige_sd(__m128d __a, /// \param __b /// A 128-bit vector of [2 x double]. The lower double-precision value is /// compared to the lower double-precision value of \a __a. -/// \returns An integer containing the comparison results. If either of the two -/// lower double-precision values is NaN, 1 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_comineq_sd(__m128d __a, __m128d __b) { return __builtin_ia32_comisdneq((__v2df)__a, (__v2df)__b); } /// Compares the lower double-precision floating-point values in each of -/// the two 128-bit floating-point vectors of [2 x double] for equality. The -/// comparison yields 0 for false, 1 for true. +/// the two 128-bit floating-point vectors of [2 x double] for equality. /// -/// If either of the two lower double-precision values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower double-precision values is NaN, returns 0. /// /// \headerfile /// @@ -1110,8 +1106,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comineq_sd(__m128d __a, /// \param __b /// A 128-bit vector of [2 x double]. The lower double-precision value is /// compared to the lower double-precision value of \a __a. -/// \returns An integer containing the comparison results. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomieq_sd(__m128d __a, __m128d __b) { return __builtin_ia32_ucomisdeq((__v2df)__a, (__v2df)__b); @@ -1122,8 +1117,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomieq_sd(__m128d __a, /// the value in the first parameter is less than the corresponding value in /// the second parameter. /// -/// The comparison yields 0 for false, 1 for true. If either of the two lower -/// double-precision values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower double-precision values is NaN, returns 0. /// /// \headerfile /// @@ -1135,8 +1130,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomieq_sd(__m128d __a, /// \param __b /// A 128-bit vector of [2 x double]. The lower double-precision value is /// compared to the lower double-precision value of \a __a. -/// \returns An integer containing the comparison results. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomilt_sd(__m128d __a, __m128d __b) { return __builtin_ia32_ucomisdlt((__v2df)__a, (__v2df)__b); @@ -1147,8 +1141,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomilt_sd(__m128d __a, /// the value in the first parameter is less than or equal to the /// corresponding value in the second parameter. /// -/// The comparison yields 0 for false, 1 for true. If either of the two lower -/// double-precision values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower double-precision values is NaN, returns 0. /// /// \headerfile /// @@ -1160,8 +1154,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomilt_sd(__m128d __a, /// \param __b /// A 128-bit vector of [2 x double]. The lower double-precision value is /// compared to the lower double-precision value of \a __a. -/// \returns An integer containing the comparison results. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomile_sd(__m128d __a, __m128d __b) { return __builtin_ia32_ucomisdle((__v2df)__a, (__v2df)__b); @@ -1172,8 +1165,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomile_sd(__m128d __a, /// the value in the first parameter is greater than the corresponding value /// in the second parameter. /// -/// The comparison yields 0 for false, 1 for true. If either of the two lower -/// double-precision values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower double-precision values is NaN, returns 0. /// /// \headerfile /// @@ -1185,8 +1178,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomile_sd(__m128d __a, /// \param __b /// A 128-bit vector of [2 x double]. The lower double-precision value is /// compared to the lower double-precision value of \a __a. -/// \returns An integer containing the comparison results. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomigt_sd(__m128d __a, __m128d __b) { return __builtin_ia32_ucomisdgt((__v2df)__a, (__v2df)__b); @@ -1197,8 +1189,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomigt_sd(__m128d __a, /// the value in the first parameter is greater than or equal to the /// corresponding value in the second parameter. /// -/// The comparison yields 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower double-precision values is NaN, returns 0. /// /// \headerfile /// @@ -1210,8 +1202,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomigt_sd(__m128d __a, /// \param __b /// A 128-bit vector of [2 x double]. The lower double-precision value is /// compared to the lower double-precision value of \a __a. -/// \returns An integer containing the comparison results. If either of the two -/// lower double-precision values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomige_sd(__m128d __a, __m128d __b) { return __builtin_ia32_ucomisdge((__v2df)__a, (__v2df)__b); @@ -1222,8 +1213,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomige_sd(__m128d __a, /// the value in the first parameter is unequal to the corresponding value in /// the second parameter. /// -/// The comparison yields 0 for false, 1 for true. If either of the two lower -/// double-precision values is NaN, 1 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower double-precision values is NaN, 1 is returned. /// /// \headerfile /// @@ -1235,8 +1226,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomige_sd(__m128d __a, /// \param __b /// A 128-bit vector of [2 x double]. The lower double-precision value is /// compared to the lower double-precision value of \a __a. -/// \returns An integer containing the comparison result. If either of the two -/// lower double-precision values is NaN, 1 is returned. +/// \returns An integer containing the comparison result. static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomineq_sd(__m128d __a, __m128d __b) { return __builtin_ia32_ucomisdneq((__v2df)__a, (__v2df)__b); @@ -3023,8 +3013,9 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_srl_epi64(__m128i __a, } /// Compares each of the corresponding 8-bit values of the 128-bit -/// integer vectors for equality. Each comparison yields 0x0 for false, 0xFF -/// for true. +/// integer vectors for equality. +/// +/// Each comparison yields 0x0 for false, 0xFF for true. /// /// \headerfile /// @@ -3041,8 +3032,9 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cmpeq_epi8(__m128i __a, } /// Compares each of the corresponding 16-bit values of the 128-bit -/// integer vectors for equality. Each comparison yields 0x0 for false, -/// 0xFFFF for true. +/// integer vectors for equality. +/// +/// Each comparison yields 0x0 for false, 0xFFFF for true. /// /// \headerfile /// @@ -3059,8 +3051,9 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cmpeq_epi16(__m128i __a, } /// Compares each of the corresponding 32-bit values of the 128-bit -/// integer vectors for equality. Each comparison yields 0x0 for false, -/// 0xFFFFFFFF for true. +/// integer vectors for equality. +/// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. /// /// \headerfile /// @@ -3078,8 +3071,9 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cmpeq_epi32(__m128i __a, /// Compares each of the corresponding signed 8-bit values of the 128-bit /// integer vectors to determine if the values in the first operand are -/// greater than those in the second operand. Each comparison yields 0x0 for -/// false, 0xFF for true. +/// greater than those in the second operand. +/// +/// Each comparison yields 0x0 for false, 0xFF for true. /// /// \headerfile /// diff --git a/clang/lib/Headers/smmintrin.h b/clang/lib/Headers/smmintrin.h index c52ffb77e33d..9fb9cc9b0134 100644 --- a/clang/lib/Headers/smmintrin.h +++ b/clang/lib/Headers/smmintrin.h @@ -1188,6 +1188,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_testnzc_si128(__m128i __M, /// Compares each of the corresponding 64-bit values of the 128-bit /// integer vectors for equality. /// +/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// /// \headerfile /// /// This intrinsic corresponds to the VPCMPEQQ / PCMPEQQ instruction. @@ -2301,6 +2303,8 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_minpos_epu16(__m128i __V) { /// integer vectors to determine if the values in the first operand are /// greater than those in the second operand. /// +/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// /// \headerfile /// /// This intrinsic corresponds to the VPCMPGTQ / PCMPGTQ instruction. diff --git a/clang/lib/Headers/xmmintrin.h b/clang/lib/Headers/xmmintrin.h index 1f5993e0c368..8e386a72cde7 100644 --- a/clang/lib/Headers/xmmintrin.h +++ b/clang/lib/Headers/xmmintrin.h @@ -474,7 +474,9 @@ _mm_xor_ps(__m128 __a, __m128 __b) } /// Compares two 32-bit float values in the low-order bits of both -/// operands for equality and returns the result of the comparison in the +/// operands for equality. +/// +/// The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector [4 x float]. /// /// \headerfile @@ -498,6 +500,8 @@ _mm_cmpeq_ss(__m128 __a, __m128 __b) /// Compares each of the corresponding 32-bit float values of the /// 128-bit vectors of [4 x float] for equality. /// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// /// \headerfile /// /// This intrinsic corresponds to the VCMPEQPS / CMPEQPS instructions. @@ -515,8 +519,10 @@ _mm_cmpeq_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the value in the first operand is less than the -/// corresponding value in the second operand and returns the result of the -/// comparison in the low-order bits of a vector of [4 x float]. +/// corresponding value in the second operand. +/// +/// The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// low-order bits of a vector of [4 x float]. /// /// \headerfile /// @@ -540,6 +546,8 @@ _mm_cmplt_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are less than those in the second operand. /// +/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// /// \headerfile /// /// This intrinsic corresponds to the VCMPLTPS / CMPLTPS instructions. @@ -557,9 +565,10 @@ _mm_cmplt_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the value in the first operand is less than or -/// equal to the corresponding value in the second operand and returns the -/// result of the comparison in the low-order bits of a vector of -/// [4 x float]. +/// equal to the corresponding value in the second operand. +/// +/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true, in +/// the low-order bits of a vector of [4 x float]. /// /// \headerfile /// @@ -583,6 +592,8 @@ _mm_cmple_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are less than or equal to those in the second operand. /// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// /// \headerfile /// /// This intrinsic corresponds to the VCMPLEPS / CMPLEPS instructions. @@ -600,8 +611,10 @@ _mm_cmple_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the value in the first operand is greater than -/// the corresponding value in the second operand and returns the result of -/// the comparison in the low-order bits of a vector of [4 x float]. +/// the corresponding value in the second operand. +/// +/// The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// low-order bits of a vector of [4 x float]. /// /// \headerfile /// @@ -627,6 +640,8 @@ _mm_cmpgt_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are greater than those in the second operand. /// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// /// \headerfile /// /// This intrinsic corresponds to the VCMPLTPS / CMPLTPS instructions. @@ -644,9 +659,10 @@ _mm_cmpgt_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the value in the first operand is greater than -/// or equal to the corresponding value in the second operand and returns -/// the result of the comparison in the low-order bits of a vector of -/// [4 x float]. +/// or equal to the corresponding value in the second operand. +/// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// low-order bits of a vector of [4 x float]. /// /// \headerfile /// @@ -672,6 +688,8 @@ _mm_cmpge_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are greater than or equal to those in the second operand. /// +/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// /// \headerfile /// /// This intrinsic corresponds to the VCMPLEPS / CMPLEPS instructions. @@ -687,8 +705,10 @@ _mm_cmpge_ps(__m128 __a, __m128 __b) return (__m128)__builtin_ia32_cmpleps((__v4sf)__b, (__v4sf)__a); } -/// Compares two 32-bit float values in the low-order bits of both -/// operands for inequality and returns the result of the comparison in the +/// Compares two 32-bit float values in the low-order bits of both operands +/// for inequality. +/// +/// The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. /// /// \headerfile @@ -713,6 +733,8 @@ _mm_cmpneq_ss(__m128 __a, __m128 __b) /// Compares each of the corresponding 32-bit float values of the /// 128-bit vectors of [4 x float] for inequality. /// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// /// \headerfile /// /// This intrinsic corresponds to the VCMPNEQPS / CMPNEQPS @@ -731,8 +753,10 @@ _mm_cmpneq_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the value in the first operand is not less than -/// the corresponding value in the second operand and returns the result of -/// the comparison in the low-order bits of a vector of [4 x float]. +/// the corresponding value in the second operand. +/// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// low-order bits of a vector of [4 x float]. /// /// \headerfile /// @@ -757,6 +781,8 @@ _mm_cmpnlt_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are not less than those in the second operand. /// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// /// \headerfile /// /// This intrinsic corresponds to the VCMPNLTPS / CMPNLTPS @@ -775,9 +801,10 @@ _mm_cmpnlt_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the value in the first operand is not less than -/// or equal to the corresponding value in the second operand and returns -/// the result of the comparison in the low-order bits of a vector of -/// [4 x float]. +/// or equal to the corresponding value in the second operand. +/// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// low-order bits of a vector of [4 x float]. /// /// \headerfile /// @@ -802,6 +829,8 @@ _mm_cmpnle_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are not less than or equal to those in the second operand. /// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// /// \headerfile /// /// This intrinsic corresponds to the VCMPNLEPS / CMPNLEPS @@ -820,9 +849,10 @@ _mm_cmpnle_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the value in the first operand is not greater -/// than the corresponding value in the second operand and returns the -/// result of the comparison in the low-order bits of a vector of -/// [4 x float]. +/// than the corresponding value in the second operand. +/// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// low-order bits of a vector of [4 x float]. /// /// \headerfile /// @@ -849,6 +879,8 @@ _mm_cmpngt_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are not greater than those in the second operand. /// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// /// \headerfile /// /// This intrinsic corresponds to the VCMPNLTPS / CMPNLTPS @@ -867,9 +899,10 @@ _mm_cmpngt_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the value in the first operand is not greater -/// than or equal to the corresponding value in the second operand and -/// returns the result of the comparison in the low-order bits of a vector -/// of [4 x float]. +/// than or equal to the corresponding value in the second operand. +/// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// low-order bits of a vector of [4 x float]. /// /// \headerfile /// @@ -896,6 +929,8 @@ _mm_cmpnge_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are not greater than or equal to those in the second operand. /// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// /// \headerfile /// /// This intrinsic corresponds to the VCMPNLEPS / CMPNLEPS @@ -914,9 +949,10 @@ _mm_cmpnge_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the value in the first operand is ordered with -/// respect to the corresponding value in the second operand and returns the -/// result of the comparison in the low-order bits of a vector of -/// [4 x float]. +/// respect to the corresponding value in the second operand. +/// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// low-order bits of a vector of [4 x float]. /// /// \headerfile /// @@ -941,6 +977,8 @@ _mm_cmpord_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are ordered with respect to those in the second operand. /// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// /// \headerfile /// /// This intrinsic corresponds to the VCMPORDPS / CMPORDPS @@ -959,9 +997,10 @@ _mm_cmpord_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the value in the first operand is unordered -/// with respect to the corresponding value in the second operand and -/// returns the result of the comparison in the low-order bits of a vector -/// of [4 x float]. +/// with respect to the corresponding value in the second operand. +/// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// low-order bits of a vector of [4 x float]. /// /// \headerfile /// @@ -986,6 +1025,8 @@ _mm_cmpunord_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are unordered with respect to those in the second operand. /// +/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// /// \headerfile /// /// This intrinsic corresponds to the VCMPUNORDPS / CMPUNORDPS @@ -1003,9 +1044,10 @@ _mm_cmpunord_ps(__m128 __a, __m128 __b) } /// Compares two 32-bit float values in the low-order bits of both -/// operands for equality and returns the result of the comparison. +/// operands for equality. /// -/// If either of the two lower 32-bit values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower floating-point values is NaN, returns 0. /// /// \headerfile /// @@ -1018,8 +1060,7 @@ _mm_cmpunord_ps(__m128 __a, __m128 __b) /// \param __b /// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are /// used in the comparison. -/// \returns An integer containing the comparison results. If either of the -/// two lower 32-bit values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_comieq_ss(__m128 __a, __m128 __b) { @@ -1028,9 +1069,10 @@ _mm_comieq_ss(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the first operand is less than the second -/// operand and returns the result of the comparison. +/// operand. /// -/// If either of the two lower 32-bit values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower floating-point values is NaN, returns 0. /// /// \headerfile /// @@ -1043,8 +1085,7 @@ _mm_comieq_ss(__m128 __a, __m128 __b) /// \param __b /// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are /// used in the comparison. -/// \returns An integer containing the comparison results. If either of the two -/// lower 32-bit values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_comilt_ss(__m128 __a, __m128 __b) { @@ -1053,9 +1094,10 @@ _mm_comilt_ss(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the first operand is less than or equal to the -/// second operand and returns the result of the comparison. +/// second operand. /// -/// If either of the two lower 32-bit values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower floating-point values is NaN, returns 0. /// /// \headerfile /// @@ -1067,8 +1109,7 @@ _mm_comilt_ss(__m128 __a, __m128 __b) /// \param __b /// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are /// used in the comparison. -/// \returns An integer containing the comparison results. If either of the two -/// lower 32-bit values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_comile_ss(__m128 __a, __m128 __b) { @@ -1077,9 +1118,10 @@ _mm_comile_ss(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the first operand is greater than the second -/// operand and returns the result of the comparison. +/// operand. /// -/// If either of the two lower 32-bit values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower floating-point values is NaN, returns 0. /// /// \headerfile /// @@ -1091,8 +1133,7 @@ _mm_comile_ss(__m128 __a, __m128 __b) /// \param __b /// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are /// used in the comparison. -/// \returns An integer containing the comparison results. If either of the -/// two lower 32-bit values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_comigt_ss(__m128 __a, __m128 __b) { @@ -1101,9 +1142,10 @@ _mm_comigt_ss(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the first operand is greater than or equal to -/// the second operand and returns the result of the comparison. +/// the second operand. /// -/// If either of the two lower 32-bit values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower floating-point values is NaN, returns 0. /// /// \headerfile /// @@ -1115,8 +1157,7 @@ _mm_comigt_ss(__m128 __a, __m128 __b) /// \param __b /// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are /// used in the comparison. -/// \returns An integer containing the comparison results. If either of the two -/// lower 32-bit values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_comige_ss(__m128 __a, __m128 __b) { @@ -1125,9 +1166,10 @@ _mm_comige_ss(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands to determine if the first operand is not equal to the second -/// operand and returns the result of the comparison. +/// operand. /// -/// If either of the two lower 32-bit values is NaN, 1 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower floating-point values is NaN, returns 0. /// /// \headerfile /// @@ -1139,8 +1181,7 @@ _mm_comige_ss(__m128 __a, __m128 __b) /// \param __b /// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are /// used in the comparison. -/// \returns An integer containing the comparison results. If either of the -/// two lower 32-bit values is NaN, 1 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_comineq_ss(__m128 __a, __m128 __b) { @@ -1148,10 +1189,10 @@ _mm_comineq_ss(__m128 __a, __m128 __b) } /// Performs an unordered comparison of two 32-bit float values using -/// the low-order bits of both operands to determine equality and returns -/// the result of the comparison. +/// the low-order bits of both operands to determine equality. /// -/// If either of the two lower 32-bit values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower floating-point values is NaN, returns 0. /// /// \headerfile /// @@ -1163,8 +1204,7 @@ _mm_comineq_ss(__m128 __a, __m128 __b) /// \param __b /// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are /// used in the comparison. -/// \returns An integer containing the comparison results. If either of the two -/// lower 32-bit values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomieq_ss(__m128 __a, __m128 __b) { @@ -1173,9 +1213,10 @@ _mm_ucomieq_ss(__m128 __a, __m128 __b) /// Performs an unordered comparison of two 32-bit float values using /// the low-order bits of both operands to determine if the first operand is -/// less than the second operand and returns the result of the comparison. +/// less than the second operand. /// -/// If either of the two lower 32-bit values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower floating-point values is NaN, returns 0. /// /// \headerfile /// @@ -1187,8 +1228,7 @@ _mm_ucomieq_ss(__m128 __a, __m128 __b) /// \param __b /// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are /// used in the comparison. -/// \returns An integer containing the comparison results. If either of the two -/// lower 32-bit values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomilt_ss(__m128 __a, __m128 __b) { @@ -1197,10 +1237,10 @@ _mm_ucomilt_ss(__m128 __a, __m128 __b) /// Performs an unordered comparison of two 32-bit float values using /// the low-order bits of both operands to determine if the first operand is -/// less than or equal to the second operand and returns the result of the -/// comparison. +/// less than or equal to the second operand. /// -/// If either of the two lower 32-bit values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower floating-point values is NaN, returns 0. /// /// \headerfile /// @@ -1212,8 +1252,7 @@ _mm_ucomilt_ss(__m128 __a, __m128 __b) /// \param __b /// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are /// used in the comparison. -/// \returns An integer containing the comparison results. If either of the two -/// lower 32-bit values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomile_ss(__m128 __a, __m128 __b) { @@ -1222,10 +1261,10 @@ _mm_ucomile_ss(__m128 __a, __m128 __b) /// Performs an unordered comparison of two 32-bit float values using /// the low-order bits of both operands to determine if the first operand is -/// greater than the second operand and returns the result of the -/// comparison. +/// greater than the second operand. /// -/// If either of the two lower 32-bit values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower floating-point values is NaN, returns 0. /// /// \headerfile /// @@ -1237,8 +1276,7 @@ _mm_ucomile_ss(__m128 __a, __m128 __b) /// \param __b /// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are /// used in the comparison. -/// \returns An integer containing the comparison results. If either of the two -/// lower 32-bit values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomigt_ss(__m128 __a, __m128 __b) { @@ -1247,10 +1285,10 @@ _mm_ucomigt_ss(__m128 __a, __m128 __b) /// Performs an unordered comparison of two 32-bit float values using /// the low-order bits of both operands to determine if the first operand is -/// greater than or equal to the second operand and returns the result of -/// the comparison. +/// greater than or equal to the second operand. /// -/// If either of the two lower 32-bit values is NaN, 0 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower floating-point values is NaN, returns 0. /// /// \headerfile /// @@ -1262,8 +1300,7 @@ _mm_ucomigt_ss(__m128 __a, __m128 __b) /// \param __b /// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are /// used in the comparison. -/// \returns An integer containing the comparison results. If either of the two -/// lower 32-bit values is NaN, 0 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomige_ss(__m128 __a, __m128 __b) { @@ -1271,10 +1308,10 @@ _mm_ucomige_ss(__m128 __a, __m128 __b) } /// Performs an unordered comparison of two 32-bit float values using -/// the low-order bits of both operands to determine inequality and returns -/// the result of the comparison. +/// the low-order bits of both operands to determine inequality. /// -/// If either of the two lower 32-bit values is NaN, 1 is returned. +/// The comparison returns 0 for false, 1 for true. If either of the two +/// lower floating-point values is NaN, returns 0. /// /// \headerfile /// @@ -1286,8 +1323,7 @@ _mm_ucomige_ss(__m128 __a, __m128 __b) /// \param __b /// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are /// used in the comparison. -/// \returns An integer containing the comparison results. If either of the two -/// lower 32-bit values is NaN, 1 is returned. +/// \returns An integer containing the comparison results. static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomineq_ss(__m128 __a, __m128 __b) { -- GitLab From 212604698c0f265702ec9c9486fe5b74a6fc2ff7 Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Mon, 11 Mar 2024 18:25:49 +0000 Subject: [PATCH 149/953] [AMDGPU] Add missing tests for GFX10 (t)buffer format d16 instructions (#84789) --- llvm/test/MC/AMDGPU/gfx10_asm_mubuf.s | 24 +++++++++++++++++++ llvm/test/MC/AMDGPU/mtbuf-gfx10.s | 6 +++++ .../MC/Disassembler/AMDGPU/gfx10_mtbuf.txt | 6 +++++ .../MC/Disassembler/AMDGPU/gfx10_mubuf.txt | 24 +++++++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/llvm/test/MC/AMDGPU/gfx10_asm_mubuf.s b/llvm/test/MC/AMDGPU/gfx10_asm_mubuf.s index 99c9c4aee4a7..aacdfcb4e871 100644 --- a/llvm/test/MC/AMDGPU/gfx10_asm_mubuf.s +++ b/llvm/test/MC/AMDGPU/gfx10_asm_mubuf.s @@ -5,6 +5,18 @@ // ENC_MUBUF. //===----------------------------------------------------------------------===// +buffer_load_format_d16_x v1, off, s[4:7], s1 +// GFX10: encoding: [0x00,0x00,0x00,0xe2,0x00,0x01,0x01,0x01] + +buffer_load_format_d16_xy v1, off, s[4:7], s1 +// GFX10: encoding: [0x00,0x00,0x04,0xe2,0x00,0x01,0x01,0x01] + +buffer_load_format_d16_xyz v[1:2], off, s[4:7], s1 +// GFX10: encoding: [0x00,0x00,0x08,0xe2,0x00,0x01,0x01,0x01] + +buffer_load_format_d16_xyzw v[1:2], off, s[4:7], s1 +// GFX10: encoding: [0x00,0x00,0x0c,0xe2,0x00,0x01,0x01,0x01] + buffer_load_format_x v5, off, s[8:11], s3 offset:4095 // GFX10: encoding: [0xff,0x0f,0x00,0xe0,0x00,0x05,0x02,0x03] @@ -221,6 +233,18 @@ buffer_load_format_xyzw v[5:8], off, s[8:11], s3 offset:4095 dlc buffer_load_format_xyzw v[5:8], off, s[8:11], s3 offset:4095 glc slc dlc // GFX10: encoding: [0xff,0xcf,0x0c,0xe0,0x00,0x05,0x42,0x03] +buffer_store_format_d16_x v1, off, s[4:7], s1 +// GFX10: encoding: [0x00,0x00,0x10,0xe2,0x00,0x01,0x01,0x01] + +buffer_store_format_d16_xy v1, off, s[4:7], s1 +// GFX10: encoding: [0x00,0x00,0x14,0xe2,0x00,0x01,0x01,0x01] + +buffer_store_format_d16_xyz v[1:2], off, s[4:7], s1 +// GFX10: encoding: [0x00,0x00,0x18,0xe2,0x00,0x01,0x01,0x01] + +buffer_store_format_d16_xyzw v[1:2], off, s[4:7], s1 +// GFX10: encoding: [0x00,0x00,0x1c,0xe2,0x00,0x01,0x01,0x01] + buffer_store_format_x v1, off, s[12:15], s4 offset:4095 // GFX10: encoding: [0xff,0x0f,0x10,0xe0,0x00,0x01,0x03,0x04] diff --git a/llvm/test/MC/AMDGPU/mtbuf-gfx10.s b/llvm/test/MC/AMDGPU/mtbuf-gfx10.s index f235280874c4..56add346bd21 100644 --- a/llvm/test/MC/AMDGPU/mtbuf-gfx10.s +++ b/llvm/test/MC/AMDGPU/mtbuf-gfx10.s @@ -11,6 +11,9 @@ tbuffer_load_format_d16_x v0, off, s[0:3], format:22, 0 // GFX10: tbuffer_load_format_d16_xy v0, off, s[0:3], 0 format:[BUF_FMT_32_FLOAT] ; encoding: [0x00,0x00,0xb1,0xe8,0x00,0x00,0x20,0x80] tbuffer_load_format_d16_xy v0, off, s[0:3], format:22, 0 +// GFX10: tbuffer_load_format_d16_xyz v[0:1], off, s[0:3], 0 format:[BUF_FMT_32_FLOAT] ; encoding: [0x00,0x00,0xb2,0xe8,0x00,0x00,0x20,0x80] +tbuffer_load_format_d16_xyz v[0:1], off, s[0:3], format:22, 0 + // GFX10: tbuffer_load_format_d16_xyzw v[0:1], off, s[0:3], 0 format:[BUF_FMT_32_FLOAT] ; encoding: [0x00,0x00,0xb3,0xe8,0x00,0x00,0x20,0x80] tbuffer_load_format_d16_xyzw v[0:1], off, s[0:3], format:22, 0 @@ -62,6 +65,9 @@ tbuffer_store_format_d16_x v0, v1, s[4:7], format:33, 0 idxen // GFX10: tbuffer_store_format_d16_xy v0, v1, s[4:7], 0 format:[BUF_FMT_10_11_11_SSCALED] idxen ; encoding: [0x00,0x20,0x0d,0xe9,0x01,0x00,0x21,0x80] tbuffer_store_format_d16_xy v0, v1, s[4:7], format:33, 0 idxen +// GFX10: tbuffer_store_format_d16_xyz v[0:1], v2, s[4:7], 0 format:[BUF_FMT_10_11_11_SSCALED] idxen ; encoding: [0x00,0x20,0x0e,0xe9,0x02,0x00,0x21,0x80] +tbuffer_store_format_d16_xyz v[0:1], v2, s[4:7], format:33, 0 idxen + // GFX10: tbuffer_store_format_d16_xyzw v[0:1], v2, s[4:7], 0 format:[BUF_FMT_10_11_11_SSCALED] idxen ; encoding: [0x00,0x20,0x0f,0xe9,0x02,0x00,0x21,0x80] tbuffer_store_format_d16_xyzw v[0:1], v2, s[4:7], format:33, 0 idxen diff --git a/llvm/test/MC/Disassembler/AMDGPU/gfx10_mtbuf.txt b/llvm/test/MC/Disassembler/AMDGPU/gfx10_mtbuf.txt index 950ce783baba..b6232e84549b 100644 --- a/llvm/test/MC/Disassembler/AMDGPU/gfx10_mtbuf.txt +++ b/llvm/test/MC/Disassembler/AMDGPU/gfx10_mtbuf.txt @@ -6,6 +6,9 @@ # GFX10: tbuffer_load_format_d16_xy v0, off, s[0:3], 0 format:[BUF_FMT_32_FLOAT] 0x00,0x00,0xb1,0xe8,0x00,0x00,0x20,0x80 +# GFX10: tbuffer_load_format_d16_xyz v[0:1], off, s[0:3], 0 format:[BUF_FMT_32_FLOAT] +0x00,0x00,0xb2,0xe8,0x00,0x00,0x20,0x80 + # GFX10: tbuffer_load_format_d16_xyzw v[0:1], off, s[0:3], 0 format:[BUF_FMT_32_FLOAT] 0x00,0x00,0xb3,0xe8,0x00,0x00,0x20,0x80 @@ -57,6 +60,9 @@ # GFX10: tbuffer_store_format_d16_xy v0, v1, s[4:7], 0 format:[BUF_FMT_10_11_11_SSCALED] idxen 0x00,0x20,0x0d,0xe9,0x01,0x00,0x21,0x80 +# GFX10: tbuffer_store_format_d16_xyz v[0:1], v2, s[4:7], 0 format:[BUF_FMT_10_11_11_SSCALED] idxen +0x00,0x20,0x0e,0xe9,0x02,0x00,0x21,0x80 + # GFX10: tbuffer_store_format_d16_xyzw v[0:1], v2, s[4:7], 0 format:[BUF_FMT_10_11_11_SSCALED] idxen 0x00,0x20,0x0f,0xe9,0x02,0x00,0x21,0x80 diff --git a/llvm/test/MC/Disassembler/AMDGPU/gfx10_mubuf.txt b/llvm/test/MC/Disassembler/AMDGPU/gfx10_mubuf.txt index 6fbe77e43ad4..b0731be4484c 100644 --- a/llvm/test/MC/Disassembler/AMDGPU/gfx10_mubuf.txt +++ b/llvm/test/MC/Disassembler/AMDGPU/gfx10_mubuf.txt @@ -1316,6 +1316,18 @@ # GFX10: buffer_load_dwordx4 v[5:8], v0, s[8:11], s3 offen offset:4095 ; encoding: [0xff,0x1f,0x38,0xe0,0x00,0x05,0x02,0x03] 0xff,0x1f,0x38,0xe0,0x00,0x05,0x02,0x03 +# GFX10: buffer_load_format_d16_x v1, off, s[4:7], s1 ; encoding: [0x00,0x00,0x00,0xe2,0x00,0x01,0x01,0x01] +0x00,0x00,0x00,0xe2,0x00,0x01,0x01,0x01 + +# GFX10: buffer_load_format_d16_xy v1, off, s[4:7], s1 ; encoding: [0x00,0x00,0x04,0xe2,0x00,0x01,0x01,0x01] +0x00,0x00,0x04,0xe2,0x00,0x01,0x01,0x01 + +# GFX10: buffer_load_format_d16_xyz v[1:2], off, s[4:7], s1 ; encoding: [0x00,0x00,0x08,0xe2,0x00,0x01,0x01,0x01] +0x00,0x00,0x08,0xe2,0x00,0x01,0x01,0x01 + +# GFX10: buffer_load_format_d16_xyzw v[1:2], off, s[4:7], s1 ; encoding: [0x00,0x00,0x0c,0xe2,0x00,0x01,0x01,0x01] +0x00,0x00,0x0c,0xe2,0x00,0x01,0x01,0x01 + # GFX10: buffer_load_format_x v255, off, s[8:11], s3 offset:4095 ; encoding: [0xff,0x0f,0x00,0xe0,0x00,0xff,0x02,0x03] 0xff,0x0f,0x00,0xe0,0x00,0xff,0x02,0x03 @@ -2015,6 +2027,18 @@ # GFX10: buffer_store_dwordx4 v[252:255], off, s[12:15], s4 offset:4095 ; encoding: [0xff,0x0f,0x78,0xe0,0x00,0xfc,0x03,0x04] 0xff,0x0f,0x78,0xe0,0x00,0xfc,0x03,0x04 +# GFX10: buffer_store_format_d16_x v1, off, s[4:7], s1 ; encoding: [0x00,0x00,0x10,0xe2,0x00,0x01,0x01,0x01] +0x00,0x00,0x10,0xe2,0x00,0x01,0x01,0x01 + +# GFX10: buffer_store_format_d16_xy v1, off, s[4:7], s1 ; encoding: [0x00,0x00,0x14,0xe2,0x00,0x01,0x01,0x01] +0x00,0x00,0x14,0xe2,0x00,0x01,0x01,0x01 + +# GFX10: buffer_store_format_d16_xyz v[1:2], off, s[4:7], s1 ; encoding: [0x00,0x00,0x18,0xe2,0x00,0x01,0x01,0x01] +0x00,0x00,0x18,0xe2,0x00,0x01,0x01,0x01 + +# GFX10: buffer_store_format_d16_xyzw v[1:2], off, s[4:7], s1 ; encoding: [0x00,0x00,0x1c,0xe2,0x00,0x01,0x01,0x01] +0x00,0x00,0x1c,0xe2,0x00,0x01,0x01,0x01 + # GFX10: buffer_store_format_x v1, off, s[12:15], -1 offset:4095 ; encoding: [0xff,0x0f,0x10,0xe0,0x00,0x01,0x03,0xc1] 0xff,0x0f,0x10,0xe0,0x00,0x01,0x03,0xc1 -- GitLab From 23be73208d63898611b81d4b93a0c254a40c879c Mon Sep 17 00:00:00 2001 From: Changpeng Fang Date: Mon, 11 Mar 2024 11:34:58 -0700 Subject: [PATCH 150/953] AMDGPU: Add an argument to DS_Real_gfx12 to disable alias, NFC (#84717) This is for cased that we simply want to rename from ps.Mnemonic, but ps.Mnemonic itself is not supported as an alias. --- llvm/lib/Target/AMDGPU/DSInstructions.td | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/DSInstructions.td b/llvm/lib/Target/AMDGPU/DSInstructions.td index a84227ebf506..cc763df5a476 100644 --- a/llvm/lib/Target/AMDGPU/DSInstructions.td +++ b/llvm/lib/Target/AMDGPU/DSInstructions.td @@ -1210,13 +1210,13 @@ class Base_DS_Real_gfx6_gfx7_gfx10_gfx11_gfx12 op, DS_Pseudo ps, int ef, // GFX12. //===----------------------------------------------------------------------===// -multiclass DS_Real_gfx12 op, string name = !tolower(NAME)> { +multiclass DS_Real_gfx12 op, string name = !tolower(NAME), bit needAlias = true> { defvar ps = !cast(NAME); let AssemblerPredicate = isGFX12Plus, DecoderNamespace = "GFX12" in def _gfx12 : Base_DS_Real_gfx6_gfx7_gfx10_gfx11_gfx12; - if !ne(ps.Mnemonic, name) then + if !and(needAlias, !ne(ps.Mnemonic, name)) then def : MnemonicAlias, Requires<[isGFX12Plus]>; } -- GitLab From 5b4c35064760816e4c29921df8f7ff4f2621d4f9 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 11 Mar 2024 13:39:47 -0500 Subject: [PATCH 151/953] [flang][unittests] Fix buffer underrun in LengthWithoutTrailingSpaces (#84382) Account for the descriptor containing a zero-length string. Also, avoid iterating backwards too far. This was detected by address sanitizer. --- flang/runtime/command.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flang/runtime/command.cpp b/flang/runtime/command.cpp index 7c44890545bd..fabfe601688b 100644 --- a/flang/runtime/command.cpp +++ b/flang/runtime/command.cpp @@ -196,11 +196,11 @@ std::int32_t RTNAME(GetCommand)(const Descriptor *value, } static std::size_t LengthWithoutTrailingSpaces(const Descriptor &d) { - std::size_t s{d.ElementBytes() - 1}; - while (*d.OffsetElement(s) == ' ') { + std::size_t s{d.ElementBytes()}; // This can be 0. + while (s != 0 && *d.OffsetElement(s - 1) == ' ') { --s; } - return s + 1; + return s; } std::int32_t RTNAME(GetEnvVariable)(const Descriptor &name, -- GitLab From 8846b91e15d4c8d280ee727c0f69b958f9b1440b Mon Sep 17 00:00:00 2001 From: Jeff Niu Date: Mon, 11 Mar 2024 11:44:11 -0700 Subject: [PATCH 152/953] Revert "[CMake][LIT] Add option to run lit testsuites in parallel" (#84813) Reverts llvm/llvm-project#82899 Per the discussion on the PR, this needs more design and justification. --- llvm/CMakeLists.txt | 2 -- llvm/cmake/modules/AddLLVM.cmake | 17 +++++------------ llvm/docs/CMake.rst | 6 ------ 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index d9a17a869acf..bd141619d03f 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -712,8 +712,6 @@ if(LLVM_INDIVIDUAL_TEST_COVERAGE) endif() set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") -option(LLVM_PARALLEL_LIT "Enable multiple lit suites to run in parallel" OFF) - # On Win32 hosts, provide an option to specify the path to the GnuWin32 tools. if( WIN32 AND NOT CYGWIN ) set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools") diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake index 828de4bd9940..374f5e085d91 100644 --- a/llvm/cmake/modules/AddLLVM.cmake +++ b/llvm/cmake/modules/AddLLVM.cmake @@ -1947,18 +1947,11 @@ function(add_lit_target target comment) list(APPEND LIT_COMMAND --param ${param}) endforeach() if (ARG_UNPARSED_ARGUMENTS) - if (LLVM_PARALLEL_LIT) - add_custom_target(${target} - COMMAND ${LIT_COMMAND} ${ARG_UNPARSED_ARGUMENTS} - COMMENT "${comment}" - ) - else() - add_custom_target(${target} - COMMAND ${LIT_COMMAND} ${ARG_UNPARSED_ARGUMENTS} - COMMENT "${comment}" - USES_TERMINAL - ) - endif() + add_custom_target(${target} + COMMAND ${LIT_COMMAND} ${ARG_UNPARSED_ARGUMENTS} + COMMENT "${comment}" + USES_TERMINAL + ) else() add_custom_target(${target} COMMAND ${CMAKE_COMMAND} -E echo "${target} does nothing, no tools built.") diff --git a/llvm/docs/CMake.rst b/llvm/docs/CMake.rst index be5da5652e31..1490b38feb1e 100644 --- a/llvm/docs/CMake.rst +++ b/llvm/docs/CMake.rst @@ -762,12 +762,6 @@ enabled sub-projects. Nearly all of these variable names begin with **LLVM_PARALLEL_LINK_JOBS**:STRING Define the maximum number of concurrent link jobs. -**LLVM_PARALLEL_LIT**:BOOL - Defaults to ``OFF``. If set to ``OFF``, lit testsuites will be configured - with CMake's ``USES_TERMINAL`` flag to give direct access to the terminal. If - set to ``ON``, that flag will be removed allowing Ninja to schedule multiple - lit testsuites in parallel. - **LLVM_RAM_PER_COMPILE_JOB**:STRING Calculates the amount of Ninja compile jobs according to available resources. Value has to be in MB, overwrites LLVM_PARALLEL_COMPILE_JOBS. Compile jobs -- GitLab From b4e0890458043ef486fdecba9aad65799ec0ab35 Mon Sep 17 00:00:00 2001 From: Florian Mayer Date: Mon, 11 Mar 2024 11:46:45 -0700 Subject: [PATCH 153/953] [NFC] [scudo] move static_assert closer to class it relates to (#84257) delete other static_assert --- compiler-rt/lib/scudo/standalone/combined.h | 10 ---------- compiler-rt/lib/scudo/standalone/stack_depot.h | 4 ++++ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h index 069b5f64475d..4dacfac70792 100644 --- a/compiler-rt/lib/scudo/standalone/combined.h +++ b/compiler-rt/lib/scudo/standalone/combined.h @@ -1553,16 +1553,6 @@ private: constexpr u32 kFramesPerStack = 16; static_assert(isPowerOfTwo(kFramesPerStack)); - // We need StackDepot to be aligned to 8-bytes so the ring we store after - // is correctly assigned. - static_assert(sizeof(StackDepot) % alignof(atomic_u64) == 0); - - // Make sure the maximum sized StackDepot fits withint a uintptr_t to - // simplify the overflow checking. - static_assert(sizeof(StackDepot) + UINT32_MAX * sizeof(atomic_u64) * - UINT32_MAX * sizeof(atomic_u32) < - UINTPTR_MAX); - if (AllocationRingBufferSize > kMaxU32Pow2 / kStacksPerRingBufferEntry) return; u32 TabSize = static_cast(roundUpPowerOfTwo(kStacksPerRingBufferEntry * diff --git a/compiler-rt/lib/scudo/standalone/stack_depot.h b/compiler-rt/lib/scudo/standalone/stack_depot.h index 620137e44f37..cf3cabf7085b 100644 --- a/compiler-rt/lib/scudo/standalone/stack_depot.h +++ b/compiler-rt/lib/scudo/standalone/stack_depot.h @@ -199,6 +199,10 @@ public: void enable() NO_THREAD_SAFETY_ANALYSIS { RingEndMu.unlock(); } }; +// We need StackDepot to be aligned to 8-bytes so the ring we store after +// is correctly assigned. +static_assert(sizeof(StackDepot) % alignof(atomic_u64) == 0); + } // namespace scudo #endif // SCUDO_STACK_DEPOT_H_ -- GitLab From a8eb2f0dabacb334cbfc78eaffde9a75b1ba64a4 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Mon, 11 Mar 2024 18:47:30 +0000 Subject: [PATCH 154/953] [Clang][AST] Print attributes of Obj-C interfaces When pretty printing an Objective-C interface declaration, Clang previously didn't print any attributes that are applied to the declaration. --- clang/lib/AST/DeclPrinter.cpp | 5 +++++ clang/test/AST/ast-print-objectivec.m | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 43d221968ea3..b701581b2474 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -1517,6 +1517,11 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) { return; } bool eolnOut = false; + if (OID->hasAttrs()) { + prettyPrintAttributes(OID); + Out << "\n"; + } + Out << "@interface " << I; if (auto TypeParams = OID->getTypeParamListAsWritten()) { diff --git a/clang/test/AST/ast-print-objectivec.m b/clang/test/AST/ast-print-objectivec.m index 05a0a5d4aa74..a0652f38e713 100644 --- a/clang/test/AST/ast-print-objectivec.m +++ b/clang/test/AST/ast-print-objectivec.m @@ -21,6 +21,10 @@ - (void)methodWithArg:(int)x andAnotherOne:(int)y { } @end +__attribute__((availability(macosx,introduced=10.1.0,deprecated=10.2))) +@interface InterfaceWithAttribute +@end + // CHECK: @protocol P // CHECK: - (void)MethP __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2))); // CHECK: @end @@ -45,6 +49,10 @@ // CHECK: @end +// CHECK: __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2))) +// CHECK: @interface InterfaceWithAttribute +// CHECK: @end + @class C1; struct __attribute__((objc_bridge_related(C1,,))) S1; -- GitLab From 337a20071518d647a0d453f93055817131aa15e9 Mon Sep 17 00:00:00 2001 From: Florian Mayer Date: Mon, 11 Mar 2024 11:47:59 -0700 Subject: [PATCH 155/953] [NFC] [scudo] Move static_assert to class it concerns (#84245) --- compiler-rt/lib/scudo/standalone/combined.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h index 4dacfac70792..9e1fd6d6dca3 100644 --- a/compiler-rt/lib/scudo/standalone/combined.h +++ b/compiler-rt/lib/scudo/standalone/combined.h @@ -1081,6 +1081,11 @@ private: // An array of Size (at least one) elements of type Entry is immediately // following to this struct. }; + static_assert(sizeof(AllocationRingBuffer) % + alignof(typename AllocationRingBuffer::Entry) == + 0, + "invalid alignment"); + // Pointer to memory mapped area starting with AllocationRingBuffer struct, // and immediately followed by Size elements of type Entry. atomic_uptr RingBufferAddress = {}; @@ -1585,10 +1590,6 @@ private: atomic_store(&RingBufferAddress, reinterpret_cast(RB), memory_order_release); - static_assert(sizeof(AllocationRingBuffer) % - alignof(typename AllocationRingBuffer::Entry) == - 0, - "invalid alignment"); } void unmapRingBuffer() { -- GitLab From 08a9207f947b8b022d70f8ee7eeeda7acc6aac76 Mon Sep 17 00:00:00 2001 From: Usama Hameed Date: Mon, 11 Mar 2024 11:57:53 -0700 Subject: [PATCH 156/953] [LLDB] ASanLibsanitizers Use `sanitizers_address_on_report` breakpoint (#84583) symbol This patch puts the default breakpoint on the sanitizers_address_on_report symbol, and uses the old symbol as a backup if the default case is not found rdar://123911522 --- .../InstrumentationRuntimeASanLibsanitizers.cpp | 11 +++++++++-- .../Utility/ReportRetriever.cpp | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASanLibsanitizers.cpp b/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASanLibsanitizers.cpp index d84cd36d7ce1..cd91f4a6ff1b 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASanLibsanitizers.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/ASanLibsanitizers/InstrumentationRuntimeASanLibsanitizers.cpp @@ -90,9 +90,16 @@ void InstrumentationRuntimeASanLibsanitizers::Activate() { if (!process_sp) return; + lldb::ModuleSP module_sp = GetRuntimeModuleSP(); + Breakpoint *breakpoint = ReportRetriever::SetupBreakpoint( - GetRuntimeModuleSP(), process_sp, - ConstString("_Z22raise_sanitizers_error23sanitizer_error_context")); + module_sp, process_sp, ConstString("sanitizers_address_on_report")); + + if (!breakpoint) { + breakpoint = ReportRetriever::SetupBreakpoint( + module_sp, process_sp, + ConstString("_Z22raise_sanitizers_error23sanitizer_error_context")); + } if (!breakpoint) return; diff --git a/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp b/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp index ff58c4cababa..298b63bc716f 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp @@ -219,6 +219,7 @@ bool ReportRetriever::NotifyBreakpointHit(ProcessSP process_sp, return true; // Return true to stop the target } +// FIXME: Setup the breakpoint using a less fragile SPI. rdar://124399066 Breakpoint *ReportRetriever::SetupBreakpoint(ModuleSP module_sp, ProcessSP process_sp, ConstString symbol_name) { -- GitLab From eaa71a97f9155ea9df33141ef2fb369dc8fc464f Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Mon, 11 Mar 2024 12:07:28 -0700 Subject: [PATCH 157/953] [clang] Add optional pass to remove UBSAN traps using PGO (#84214) With #83471 it reduces UBSAN overhead from 44% to 6%. Measured as "Geomean difference" on "test-suite/MultiSource/Benchmarks" with PGO build. On real large server binary we see 95% of code is still instrumented, with 10% -> 1.5% UBSAN overhead improvements. We can pass this test only with subset of UBSAN, so base overhead is smaller. We have followup patches to improve it even further. --- clang/lib/CodeGen/BackendUtil.cpp | 21 +++++++++++++++++++++ clang/test/CodeGen/remote-traps.c | 15 +++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 clang/test/CodeGen/remote-traps.c diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 7310e3817c79..82b30b8d8156 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -76,6 +76,7 @@ #include "llvm/Transforms/Instrumentation/MemProfiler.h" #include "llvm/Transforms/Instrumentation/MemorySanitizer.h" #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h" +#include "llvm/Transforms/Instrumentation/RemoveTrapsPass.h" #include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h" #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" @@ -83,6 +84,7 @@ #include "llvm/Transforms/Scalar/EarlyCSE.h" #include "llvm/Transforms/Scalar/GVN.h" #include "llvm/Transforms/Scalar/JumpThreading.h" +#include "llvm/Transforms/Scalar/SimplifyCFG.h" #include "llvm/Transforms/Utils/Debugify.h" #include "llvm/Transforms/Utils/EntryExitInstrumenter.h" #include "llvm/Transforms/Utils/ModuleUtils.h" @@ -98,6 +100,10 @@ using namespace llvm; namespace llvm { extern cl::opt PrintPipelinePasses; +cl::opt ClRemoveTraps("clang-remove-traps", cl::Optional, + cl::desc("Insert remove-traps pass."), + cl::init(false)); + // Experiment to move sanitizers earlier. static cl::opt ClSanitizeOnOptimizerEarlyEP( "sanitizer-early-opt-ep", cl::Optional, @@ -744,6 +750,21 @@ static void addSanitizers(const Triple &TargetTriple, // LastEP does not need GlobalsAA. PB.registerOptimizerLastEPCallback(SanitizersCallback); } + + if (ClRemoveTraps) { + // We can optimize after inliner, and PGO profile matching. The hook below + // is called at the end `buildFunctionSimplificationPipeline`, which called + // from `buildInlinerPipeline`, which called after profile matching. + PB.registerScalarOptimizerLateEPCallback( + [](FunctionPassManager &FPM, OptimizationLevel Level) { + // RemoveTrapsPass expects trap blocks preceded by conditional + // branches, which usually is not the case without SimplifyCFG. + // TODO: Remove `SimplifyCFGPass` after switching to dedicated + // intrinsic. + FPM.addPass(SimplifyCFGPass()); + FPM.addPass(RemoveTrapsPass()); + }); + } } void EmitAssemblyHelper::RunOptimizationPipeline( diff --git a/clang/test/CodeGen/remote-traps.c b/clang/test/CodeGen/remote-traps.c new file mode 100644 index 000000000000..f053d1bd157f --- /dev/null +++ b/clang/test/CodeGen/remote-traps.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -O1 -emit-llvm -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow %s -o - | FileCheck %s +// RUN: %clang_cc1 -O1 -emit-llvm -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -mllvm -clang-remove-traps -mllvm -remove-traps-random-rate=1 %s -o - | FileCheck %s --implicit-check-not="call void @llvm.ubsantrap" --check-prefixes=REMOVE + +int f(int x) { + return x + 123; +} + +// CHECK-LABEL: define dso_local noundef i32 @f( +// CHECK: call { i32, i1 } @llvm.sadd.with.overflow.i32( +// CHECK: trap: +// CHECK-NEXT: call void @llvm.ubsantrap(i8 0) +// CHECK-NEXT: unreachable + +// REMOVE-LABEL: define dso_local noundef i32 @f( +// REMOVE: call { i32, i1 } @llvm.sadd.with.overflow.i32( -- GitLab From d1d80cc3197faa4194cddcc79ff704b7d4c5b9e4 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Mon, 11 Mar 2024 14:09:59 -0500 Subject: [PATCH 158/953] [HIP] Make the new driver bundle outputs for device-only (#84534) Summary: The current behavior of HIP is that when --offload-device-only is set it still bundles the outputs into a fat binary. Even though this is different from how all the other targets handle this, it seems to be dependned on by some tooling so just make it backwards compatible for the `-fno-gpu-rdc` case. --- clang/lib/Driver/Driver.cpp | 11 ++++++++++- clang/test/Driver/hip-binding.hip | 13 +++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index fce43430a913..190782a79a24 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -4638,7 +4638,12 @@ Action *Driver::BuildOffloadingActions(Compilation &C, } } - if (offloadDeviceOnly()) + // All kinds exit now in device-only mode except for non-RDC mode HIP. + if (offloadDeviceOnly() && + (!C.isOffloadingHostKind(Action::OFK_HIP) || + !Args.hasFlag(options::OPT_gpu_bundle_output, + options::OPT_no_gpu_bundle_output, true) || + Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))) return C.MakeAction(DDeps, types::TY_Nothing); if (OffloadActions.empty()) @@ -4671,6 +4676,10 @@ Action *Driver::BuildOffloadingActions(Compilation &C, nullptr, C.getActiveOffloadKinds()); } + // HIP wants '--offload-device-only' to create a fatbinary by default. + if (offloadDeviceOnly()) + return C.MakeAction(DDep, types::TY_Nothing); + // If we are unable to embed a single device output into the host, we need to // add each device output as a host dependency to ensure they are still built. bool SingleDeviceOutput = !llvm::any_of(OffloadActions, [](Action *A) { diff --git a/clang/test/Driver/hip-binding.hip b/clang/test/Driver/hip-binding.hip index 79ec2039edb7..c116ad80a8ad 100644 --- a/clang/test/Driver/hip-binding.hip +++ b/clang/test/Driver/hip-binding.hip @@ -65,9 +65,18 @@ // MULTI-D-ONLY-NEXT: # "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[GFX90a]]"], output: "[[GFX90a_OUT:.+]]" // // RUN: not %clang -### --target=x86_64-linux-gnu --offload-new-driver -ccc-print-bindings -nogpulib -nogpuinc \ -// RUN: --offload-arch=gfx90a --offload-arch=gfx908 --offload-device-only -c -o %t %s 2>&1 \ +// RUN: --no-gpu-bundle-output --offload-arch=gfx90a --offload-arch=gfx908 --offload-device-only -c -o %t %s 2>&1 \ +// RUN: | FileCheck -check-prefix=MULTI-D-ONLY-NO-BUNDLE-O %s +// MULTI-D-ONLY-NO-BUNDLE-O: error: cannot specify -o when generating multiple output files + +// RUN: %clang -### --target=x86_64-linux-gnu --offload-new-driver -ccc-print-bindings -nogpulib -nogpuinc \ +// RUN: --gpu-bundle-output --offload-arch=gfx90a --offload-arch=gfx908 --offload-device-only -c -o a.out %s 2>&1 \ // RUN: | FileCheck -check-prefix=MULTI-D-ONLY-O %s -// MULTI-D-ONLY-O: error: cannot specify -o when generating multiple output files +// MULTI-D-ONLY-O: "amdgcn-amd-amdhsa" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[GFX908_OBJ:.+]]" +// MULTI-D-ONLY-O-NEXT: "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[GFX908_OBJ]]"], output: "[[GFX908:.+]]" +// MULTI-D-ONLY-O-NEXT: "amdgcn-amd-amdhsa" - "clang", inputs: ["[[INPUT]]"], output: "[[GFX90A_OBJ:.+]]" +// MULTI-D-ONLY-O-NEXT: "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[GFX90A_OBJ]]"], output: "[[GFX90A:.+]]" +// MULTI-D-ONLY-O-NEXT: "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[GFX908]]", "[[GFX90A]]"], output: "a.out" // // Check to ensure that we can use '-fsyntax-only' for HIP output with the new -- GitLab From 6d4aa9d70e4808498584cc61a295c0b93310196d Mon Sep 17 00:00:00 2001 From: Alexander Yermolovich <43973793+ayermolo@users.noreply.github.com> Date: Mon, 11 Mar 2024 12:20:25 -0700 Subject: [PATCH 159/953] [BOLT][DWWARF] Fix foreign TU index with local TUs (#84594) The foreign TU list immediately follows the local TU list and they both use the same index, so that if there are N local TU entries, the index for the first foreign TU is N. Changed so that the size of local TU is accounted for when setting foreign TU index. --- bolt/lib/Core/DebugNames.cpp | 7 +- .../dwarf5-debug-names-ftu-ltu-mix-helper.s | 314 +++++++++++ .../dwarf5-debug-names-ftu-ltu-mix-helper1.s | 315 +++++++++++ .../dwarf5-df-debug-names-ftu-ltu-mix-main.s | 505 ++++++++++++++++++ ...warf5-df-main-debug-names-ftu-ltu-mix.test | 56 ++ 5 files changed, 1196 insertions(+), 1 deletion(-) create mode 100644 bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper.s create mode 100644 bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper1.s create mode 100644 bolt/test/X86/Inputs/dwarf5-df-debug-names-ftu-ltu-mix-main.s create mode 100644 bolt/test/X86/dwarf5-df-main-debug-names-ftu-ltu-mix.test diff --git a/bolt/lib/Core/DebugNames.cpp b/bolt/lib/Core/DebugNames.cpp index 1a7792afbbd9..384e63695dfd 100644 --- a/bolt/lib/Core/DebugNames.cpp +++ b/bolt/lib/Core/DebugNames.cpp @@ -345,8 +345,13 @@ void DWARF5AcceleratorTable::finalize() { std::optional DWARF5AcceleratorTable::getIndexForEntry( const BOLTDWARF5AccelTableData &Value) const { + // The foreign TU list immediately follows the local TU list and they both + // use the same index, so that if there are N local TU entries, the index for + // the first foreign TU is N. if (Value.isTU()) - return {{Value.getUnitID(), {dwarf::DW_IDX_type_unit, TUIndexForm}}}; + return {{(Value.getSecondUnitID() ? (unsigned)LocalTUList.size() : 0) + + Value.getUnitID(), + {dwarf::DW_IDX_type_unit, TUIndexForm}}}; if (CUList.size() > 1) return {{Value.getUnitID(), {dwarf::DW_IDX_compile_unit, CUIndexForm}}}; return std::nullopt; diff --git a/bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper.s b/bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper.s new file mode 100644 index 000000000000..68eee45ec983 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper.s @@ -0,0 +1,314 @@ +# struct AMono { +# int x; +# }; +# +# AMono globalMono; +# # clang++ -g2 -gdwarf-5 -gpubnames -S -fdebug-types-section -o + + .text + .file "helper.cpp" + .file 0 "/home" "helper.cpp" md5 0x3c0ac73d7b074961c6e8202230a76228 + .section .debug_info,"G",@progbits,6412503741467814911,comdat +.Ltu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 6412503741467814911 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x20 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0x10 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 6 # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member + .byte 4 # DW_AT_name + .long 51 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x33:0x4 DW_TAG_base_type + .byte 5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .type globalMono,@object # @globalMono + .bss + .globl globalMono + .p2align 2, 0x0 +globalMono: + .zero 4 + .size globalMono, 4 + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 5 # Abbrev [5] 0xc:0x27 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 6 # Abbrev [6] 0x1e:0xb DW_TAG_variable + .byte 3 # DW_AT_name + .long 41 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 7 # Abbrev [7] 0x29:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 6412503741467814911 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_str_offsets,"",@progbits + .long 32 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" # string offset=0 +.Linfo_string1: + .asciz "helper.cpp" # string offset=104 +.Linfo_string2: + .asciz "/home" # string offset=115 +.Linfo_string3: + .asciz "globalMono" # string offset=153 +.Linfo_string4: + .asciz "AMono" # string offset=164 +.Linfo_string5: + .asciz "x" # string offset=170 +.Linfo_string6: + .asciz "int" # string offset=172 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string4 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad globalMono +.Ldebug_addr_end0: + .section .debug_names,"",@progbits + .long .Lnames_end0-.Lnames_start0 # Header: unit length +.Lnames_start0: + .short 5 # Header: version + .short 0 # Header: padding + .long 1 # Header: compilation unit count + .long 1 # Header: local type unit count + .long 0 # Header: foreign type unit count + .long 3 # Header: bucket count + .long 3 # Header: name count + .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size + .long 8 # Header: augmentation string size + .ascii "LLVM0700" # Header: augmentation string + .long .Lcu_begin0 # Compilation unit 0 + .long .Ltu_begin0 # Type unit 0 + .long 0 # Bucket 0 + .long 0 # Bucket 1 + .long 1 # Bucket 2 + .long 193495088 # Hash in Bucket 2 + .long 253228319 # Hash in Bucket 2 + .long -857151761 # Hash in Bucket 2 + .long .Linfo_string6 # String in Bucket 2: int + .long .Linfo_string4 # String in Bucket 2: AMono + .long .Linfo_string3 # String in Bucket 2: globalMono + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2 +.Lnames_abbrev_start0: + .byte 1 # Abbrev code + .byte 36 # DW_TAG_base_type + .byte 2 # DW_IDX_type_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 2 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 2 # DW_IDX_type_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 3 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 4 # Abbrev code + .byte 52 # DW_TAG_variable + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames1: +.L1: + .byte 1 # Abbreviation code + .byte 0 # DW_IDX_type_unit + .long 51 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: int +.Lnames0: +.L2: + .byte 2 # Abbreviation code + .byte 0 # DW_IDX_type_unit + .long 35 # DW_IDX_die_offset +.L3: # DW_IDX_parent + .byte 3 # Abbreviation code + .long 41 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: AMono +.Lnames2: +.L0: + .byte 4 # Abbreviation code + .long 30 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: globalMono + .p2align 2, 0x0 +.Lnames_end0: + .ident "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper1.s b/bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper1.s new file mode 100644 index 000000000000..8b28c19dc87d --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper1.s @@ -0,0 +1,315 @@ +# struct BMono { +# int x; +# }; +# +# BMono globalMono1; +# clang++ -g2 -gdwarf-5 -gpubnames -S -fdebug-types-section -o + + + .text + .file "helper1.cpp" + .file 0 "/home" "helper1.cpp" md5 0x1fdaf911330b73495aed962bc02cfb3a + .section .debug_info,"G",@progbits,5884764266900841573,comdat +.Ltu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 5884764266900841573 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x20 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0x10 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 6 # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member + .byte 4 # DW_AT_name + .long 51 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x33:0x4 DW_TAG_base_type + .byte 5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .type globalMono1,@object # @globalMono1 + .bss + .globl globalMono1 + .p2align 2, 0x0 +globalMono1: + .zero 4 + .size globalMono1, 4 + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 5 # Abbrev [5] 0xc:0x27 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 6 # Abbrev [6] 0x1e:0xb DW_TAG_variable + .byte 3 # DW_AT_name + .long 41 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 7 # Abbrev [7] 0x29:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 5884764266900841573 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_str_offsets,"",@progbits + .long 32 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" # string offset=0 +.Linfo_string1: + .asciz "helper1.cpp" # string offset=104 +.Linfo_string2: + .asciz "/home" # string offset=116 +.Linfo_string3: + .asciz "globalMono1" # string offset=154 +.Linfo_string4: + .asciz "BMono" # string offset=166 +.Linfo_string5: + .asciz "x" # string offset=172 +.Linfo_string6: + .asciz "int" # string offset=174 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string4 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad globalMono1 +.Ldebug_addr_end0: + .section .debug_names,"",@progbits + .long .Lnames_end0-.Lnames_start0 # Header: unit length +.Lnames_start0: + .short 5 # Header: version + .short 0 # Header: padding + .long 1 # Header: compilation unit count + .long 1 # Header: local type unit count + .long 0 # Header: foreign type unit count + .long 3 # Header: bucket count + .long 3 # Header: name count + .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size + .long 8 # Header: augmentation string size + .ascii "LLVM0700" # Header: augmentation string + .long .Lcu_begin0 # Compilation unit 0 + .long .Ltu_begin0 # Type unit 0 + .long 0 # Bucket 0 + .long 0 # Bucket 1 + .long 1 # Bucket 2 + .long 193495088 # Hash in Bucket 2 + .long 254414240 # Hash in Bucket 2 + .long 1778763008 # Hash in Bucket 2 + .long .Linfo_string6 # String in Bucket 2: int + .long .Linfo_string4 # String in Bucket 2: BMono + .long .Linfo_string3 # String in Bucket 2: globalMono1 + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2 +.Lnames_abbrev_start0: + .byte 1 # Abbrev code + .byte 36 # DW_TAG_base_type + .byte 2 # DW_IDX_type_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 2 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 2 # DW_IDX_type_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 3 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 4 # Abbrev code + .byte 52 # DW_TAG_variable + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames1: +.L1: + .byte 1 # Abbreviation code + .byte 0 # DW_IDX_type_unit + .long 51 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: int +.Lnames0: +.L2: + .byte 2 # Abbreviation code + .byte 0 # DW_IDX_type_unit + .long 35 # DW_IDX_die_offset +.L3: # DW_IDX_parent + .byte 3 # Abbreviation code + .long 41 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: BMono +.Lnames2: +.L0: + .byte 4 # Abbreviation code + .long 30 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: globalMono1 + .p2align 2, 0x0 +.Lnames_end0: + .ident "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf5-df-debug-names-ftu-ltu-mix-main.s b/bolt/test/X86/Inputs/dwarf5-df-debug-names-ftu-ltu-mix-main.s new file mode 100644 index 000000000000..69f6c5a5376a --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-df-debug-names-ftu-ltu-mix-main.s @@ -0,0 +1,505 @@ +# struct ASplit { +# int x; +# }; +# +# ASplit globalSplit; +# int main() { +# return 0; +# } +# clang++ -g2 -gdwarf-5 -gpubnames -S -fdebug-types-section -gsplit-dwarf -fdebug-compilation-dir='.' + + .text + .file "main.cpp" + .file 0 "." "main.cpp" md5 0xbb74a3c2960dafa324547ebbd87d13ea + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 5 # DWARF version number + .byte 6 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad -8602855756067469281 # Type Signature + .long 33 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x1e DW_TAG_type_unit + .short 33 # DW_AT_language + .byte 1 # DW_AT_comp_dir + .byte 2 # DW_AT_dwo_name + .long 0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x21:0x10 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 5 # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x27:0x9 DW_TAG_member + .byte 3 # DW_AT_name + .long 49 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x31:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end0: + .text + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .loc 0 6 0 # main.cpp:6:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movl $0, -4(%rbp) +.Ltmp0: + .loc 0 7 3 prologue_end # main.cpp:7:3 + xorl %eax, %eax + .loc 0 7 3 epilogue_begin is_stmt 0 # main.cpp:7:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .type globalSplit,@object # @globalSplit + .bss + .globl globalSplit + .p2align 2, 0x0 +globalSplit: + .zero 4 + .size globalSplit, 4 + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 74 # DW_TAG_skeleton_unit + .byte 0 # DW_CHILDREN_no + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 4 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 5806847994123082226 + .byte 1 # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 0 # DW_AT_comp_dir + .byte 1 # DW_AT_dwo_name + .byte 1 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 12 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Lskel_string0: + .asciz "." # string offset=0 +.Lskel_string1: + .asciz "ASplit" # string offset=2 +.Lskel_string2: + .asciz "int" # string offset=9 +.Lskel_string3: + .asciz "globalSplit" # string offset=13 +.Lskel_string4: + .asciz "main" # string offset=25 +.Lskel_string5: + .asciz "main.dwo" # string offset=30 + .section .debug_str_offsets,"",@progbits + .long .Lskel_string0 + .long .Lskel_string5 + .section .debug_str_offsets.dwo,"e",@progbits + .long 40 # Length of String Offsets Set + .short 5 + .short 0 + .section .debug_str.dwo,"eMS",@progbits,1 +.Linfo_string0: + .asciz "globalSplit" # string offset=0 +.Linfo_string1: + .asciz "." # string offset=12 +.Linfo_string2: + .asciz "main.dwo" # string offset=14 +.Linfo_string3: + .asciz "x" # string offset=23 +.Linfo_string4: + .asciz "int" # string offset=25 +.Linfo_string5: + .asciz "ASplit" # string offset=29 +.Linfo_string6: + .asciz "main" # string offset=36 +.Linfo_string7: + .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" # string offset=41 +.Linfo_string8: + .asciz "main.cpp" # string offset=145 + .section .debug_str_offsets.dwo,"e",@progbits + .long 0 + .long 12 + .long 14 + .long 23 + .long 25 + .long 29 + .long 36 + .long 41 + .long 145 + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit +.Ldebug_info_dwo_start1: + .short 5 # DWARF version number + .byte 5 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad 5806847994123082226 + .byte 5 # Abbrev [5] 0x14:0x2e DW_TAG_compile_unit + .byte 7 # DW_AT_producer + .short 33 # DW_AT_language + .byte 8 # DW_AT_name + .byte 2 # DW_AT_dwo_name + .byte 6 # Abbrev [6] 0x1a:0xb DW_TAG_variable + .byte 0 # DW_AT_name + .long 37 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 7 # Abbrev [7] 0x25:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad -8602855756067469281 # DW_AT_signature + .byte 8 # Abbrev [8] 0x2e:0xf DW_TAG_subprogram + .byte 1 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 6 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 61 # DW_AT_type + # DW_AT_external + .byte 4 # Abbrev [4] 0x3d:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end1: + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_line.dwo,"e",@progbits +.Ltmp2: + .long .Ldebug_line_end0-.Ldebug_line_start0 # unit length +.Ldebug_line_start0: + .short 5 + .byte 8 + .byte 0 + .long .Lprologue_end0-.Lprologue_start0 +.Lprologue_start0: + .byte 1 + .byte 1 + .byte 1 + .byte -5 + .byte 14 + .byte 1 + .byte 1 + .byte 1 + .byte 8 + .byte 1 + .byte 46 + .byte 0 + .byte 3 + .byte 1 + .byte 8 + .byte 2 + .byte 15 + .byte 5 + .byte 30 + .byte 1 + .ascii "main.cpp" + .byte 0 + .byte 0 + .byte 0xbb, 0x74, 0xa3, 0xc2 + .byte 0x96, 0x0d, 0xaf, 0xa3 + .byte 0x24, 0x54, 0x7e, 0xbb + .byte 0xd8, 0x7d, 0x13, 0xea +.Lprologue_end0: +.Ldebug_line_end0: + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad globalSplit + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + .section .debug_names,"",@progbits + .long .Lnames_end0-.Lnames_start0 # Header: unit length +.Lnames_start0: + .short 5 # Header: version + .short 0 # Header: padding + .long 1 # Header: compilation unit count + .long 0 # Header: local type unit count + .long 1 # Header: foreign type unit count + .long 4 # Header: bucket count + .long 4 # Header: name count + .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size + .long 8 # Header: augmentation string size + .ascii "LLVM0700" # Header: augmentation string + .long .Lcu_begin0 # Compilation unit 0 + .quad -8602855756067469281 # Type unit 0 + .long 1 # Bucket 0 + .long 0 # Bucket 1 + .long 2 # Bucket 2 + .long 0 # Bucket 3 + .long 193495088 # Hash in Bucket 0 + .long 1785912162 # Hash in Bucket 2 + .long 2090499946 # Hash in Bucket 2 + .long -226250862 # Hash in Bucket 2 + .long .Lskel_string2 # String in Bucket 0: int + .long .Lskel_string3 # String in Bucket 2: globalSplit + .long .Lskel_string4 # String in Bucket 2: main + .long .Lskel_string1 # String in Bucket 2: ASplit + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 0 + .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames3-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2 +.Lnames_abbrev_start0: + .byte 1 # Abbrev code + .byte 36 # DW_TAG_base_type + .byte 2 # DW_IDX_type_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 2 # Abbrev code + .byte 36 # DW_TAG_base_type + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 3 # Abbrev code + .byte 52 # DW_TAG_variable + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 4 # Abbrev code + .byte 46 # DW_TAG_subprogram + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 5 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 2 # DW_IDX_type_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 6 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames1: +.L5: + .byte 1 # Abbreviation code + .byte 0 # DW_IDX_type_unit + .long 49 # DW_IDX_die_offset +.L1: # DW_IDX_parent + .byte 2 # Abbreviation code + .long 61 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: int +.Lnames2: +.L0: + .byte 3 # Abbreviation code + .long 26 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: globalSplit +.Lnames3: +.L2: + .byte 4 # Abbreviation code + .long 46 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: main +.Lnames0: +.L4: + .byte 5 # Abbreviation code + .byte 0 # DW_IDX_type_unit + .long 33 # DW_IDX_die_offset +.L3: # DW_IDX_parent + .byte 6 # Abbreviation code + .long 37 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: ASplit + .p2align 2, 0x0 +.Lnames_end0: + .ident "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/dwarf5-df-main-debug-names-ftu-ltu-mix.test b/bolt/test/X86/dwarf5-df-main-debug-names-ftu-ltu-mix.test new file mode 100644 index 000000000000..8a8a4b118b8c --- /dev/null +++ b/bolt/test/X86/dwarf5-df-main-debug-names-ftu-ltu-mix.test @@ -0,0 +1,56 @@ +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-debug-names-ftu-ltu-mix-main.s \ +; RUN: -split-dwarf-file=main.dwo -o main.o +; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper.s -o helper.o +; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper1.s -o helper1.o +; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o helper.o helper1.o -o main.exe -fno-pic -no-pie +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections --create-debug-names-section=true +; RUN: llvm-dwarfdump --debug-names main.exe.bolt | FileCheck -check-prefix=BOLT %s + +;; Tests BOLT correctly sets foreign TU Index when there are local TUs. + +; BOLT: Compilation Unit offsets [ +; BOLT-NEXT: CU[0]: {{.+}} +; BOLT-NEXT: CU[1]: {{.+}} +; BOLT-NEXT: CU[2]: {{.+}} +; BOLT-NEXT: ] +; BOLT-NEXT: Local Type Unit offsets [ +; BOLT-NEXT: LocalTU[0]: {{.+}} +; BOLT-NEXT: LocalTU[1]: {{.+}} +; BOLT-NEXT: ] +; BOLT-NEXT: Foreign Type Unit signatures [ +; BOLT-NEXT: ForeignTU[0]: 0x889c84450dac881f +; BOLT-NEXT: ] +; BOLT: Name 3 { +; BOLT-NEXT: Hash: 0x6A05C500 +; BOLT-NEXT: String: {{.+}} "globalMono1" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: 0x5 +; BOLT-NEXT: Tag: DW_TAG_variable +; BOLT-NEXT: DW_IDX_compile_unit: 0x02 +; BOLT-NEXT: DW_IDX_die_offset: 0x0000001e +; BOLT-NEXT: } +; BOLT-NEXT: } +; BOLT: Name 6 { +; BOLT-NEXT: Hash: 0xF283AF92 +; BOLT-NEXT: String: {{.+}} "ASplit" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: 0x7 +; BOLT-NEXT: Tag: DW_TAG_structure_type +; BOLT-NEXT: DW_IDX_type_unit: 0x02 +; BOLT-NEXT: DW_IDX_compile_unit: 0x00 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000021 +; BOLT-NEXT: } +; BOLT-NEXT: } +; BOLT: Name 7 { +; BOLT-NEXT: Hash: 0xF17F51F +; BOLT-NEXT: String: {{.+}} "AMono" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: 0x4 +; BOLT-NEXT: Tag: DW_TAG_structure_type +; BOLT-NEXT: DW_IDX_type_unit: 0x00 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000023 +; BOLT-NEXT: } +; BOLT-NEXT: } -- GitLab From 6aef8dfe440c8234ce491dabb111a55b89754b4e Mon Sep 17 00:00:00 2001 From: amilendra Date: Mon, 11 Mar 2024 19:20:47 +0000 Subject: [PATCH 160/953] [libcxx] Update 128-bit-atomics feature test (#83841) The `128-bit-atomics` libcxx feature is incorrectly named because tests that are Xfailed with it is really using `int[128]`. Additionally, because toolchain support for that feature is determined based on a much smaller size (`char[16]`), tests would execute incorrectly without required toolchain support. So, rename `128-bit-atomics` as `1024-bit-atomics`, and use an appropriate type to check for the presence of the feature. --- libcxx/test/libcxx/atomics/atomics.align/align.pass.cpp | 2 +- .../atomic_compare_exchange_strong.pass.cpp | 2 +- .../atomic_compare_exchange_strong_explicit.pass.cpp | 2 +- .../atomic_compare_exchange_weak.pass.cpp | 2 +- .../atomic_compare_exchange_weak_explicit.pass.cpp | 2 +- .../atomics.types.operations.req/atomic_exchange.pass.cpp | 2 +- .../atomic_exchange_explicit.pass.cpp | 2 +- .../atomics.types.operations.req/atomic_init.pass.cpp | 2 +- .../atomics.types.operations.req/atomic_is_lock_free.pass.cpp | 2 +- .../atomics.types.operations.req/atomic_load.pass.cpp | 2 +- .../atomic_load_explicit.pass.cpp | 2 +- .../atomics.types.operations.req/atomic_store.pass.cpp | 2 +- .../atomic_store_explicit.pass.cpp | 2 +- .../atomics.types.operations.wait/atomic_notify_all.pass.cpp | 2 +- .../atomics.types.operations.wait/atomic_notify_one.pass.cpp | 2 +- .../atomics.types.operations.wait/atomic_wait.pass.cpp | 2 +- .../atomic_wait_explicit.pass.cpp | 2 +- libcxx/utils/libcxx/test/features.py | 4 ++-- 18 files changed, 19 insertions(+), 19 deletions(-) diff --git a/libcxx/test/libcxx/atomics/atomics.align/align.pass.cpp b/libcxx/test/libcxx/atomics/atomics.align/align.pass.cpp index e5cafde46760..5990fc411e50 100644 --- a/libcxx/test/libcxx/atomics/atomics.align/align.pass.cpp +++ b/libcxx/test/libcxx/atomics/atomics.align/align.pass.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// // // UNSUPPORTED: c++03 -// REQUIRES: has-128-bit-atomics +// REQUIRES: has-1024-bit-atomics // ADDITIONAL_COMPILE_FLAGS: -Wno-psabi // ... since C++20 std::__atomic_base initializes, so we get a warning about an // ABI change for vector variants since the constructor code for that is diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp index 1f0f61ed3e6e..73c74fc6589f 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong_explicit.pass.cpp index 0b6fcacb3d66..8d7803a15cd5 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong_explicit.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp index 5de2f519ea43..6c1aa06bd261 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp index fc0ad8a10acd..b00940684907 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange.pass.cpp index 31cd316e023a..6ebe64087fa0 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange_explicit.pass.cpp index 834a811c6434..3a505c8aa156 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange_explicit.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_init.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_init.pass.cpp index 4eced1d2b7f3..88775cf32d56 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_init.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_init.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS // diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp index 1a3b8393d8f9..11a6b002a786 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load.pass.cpp index 5bb2bb2b614f..36f1ee3ba370 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load_explicit.pass.cpp index ecb27a261eb6..476e268c971c 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load_explicit.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store.pass.cpp index 25a845e9e1f8..94c570fb5d96 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store_explicit.pass.cpp index d22657237327..6d1acebe615f 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store_explicit.pass.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_notify_all.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_notify_all.pass.cpp index 93ed607d413b..2b9f34b731f8 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_notify_all.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_notify_all.pass.cpp @@ -8,7 +8,7 @@ // // UNSUPPORTED: no-threads // XFAIL: c++03 -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // XFAIL: availability-synchronization_library-missing diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_notify_one.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_notify_one.pass.cpp index ad48ef1441f4..dfa781c56600 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_notify_one.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_notify_one.pass.cpp @@ -8,7 +8,7 @@ // // UNSUPPORTED: no-threads // XFAIL: c++03 -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // XFAIL: availability-synchronization_library-missing diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp index 449e50fa12b5..38142b336e72 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp @@ -8,7 +8,7 @@ // // UNSUPPORTED: no-threads // XFAIL: c++03 -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // XFAIL: availability-synchronization_library-missing diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait_explicit.pass.cpp index a6ee4fc63279..2db95a0b67a7 100644 --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait_explicit.pass.cpp @@ -8,7 +8,7 @@ // // UNSUPPORTED: no-threads // XFAIL: c++03 -// XFAIL: !has-128-bit-atomics +// XFAIL: !has-1024-bit-atomics // XFAIL: availability-synchronization_library-missing diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py index 3f0dc0c50a0d..4fd8798b794a 100644 --- a/libcxx/utils/libcxx/test/features.py +++ b/libcxx/utils/libcxx/test/features.py @@ -171,12 +171,12 @@ DEFAULT_FEATURES = [ ), ), Feature( - name="has-128-bit-atomics", + name="has-1024-bit-atomics", when=lambda cfg: sourceBuilds( cfg, """ #include - struct Large { char storage[128/8]; }; + struct Large { int storage[1024/8]; }; std::atomic x; int main(int, char**) { (void)x.load(); (void)x.is_lock_free(); return 0; } """, -- GitLab From 18f49cf2e69676497cccc81ad5f5296fedcde338 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 11 Mar 2024 15:21:38 -0400 Subject: [PATCH 161/953] [libc++] Remove XFAIL for SIMD in optimized build (#84767) It seems that updating the compiler in the CI resolved the issue, which causes the test to be XPASSing now. Fixes #74327 --- .../simd/simd.class/simd_ctor_conversion.pass.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libcxx/test/std/experimental/simd/simd.class/simd_ctor_conversion.pass.cpp b/libcxx/test/std/experimental/simd/simd.class/simd_ctor_conversion.pass.cpp index 5920d62e0e5a..7ce4bed9c7db 100644 --- a/libcxx/test/std/experimental/simd/simd.class/simd_ctor_conversion.pass.cpp +++ b/libcxx/test/std/experimental/simd/simd.class/simd_ctor_conversion.pass.cpp @@ -9,10 +9,6 @@ // UNSUPPORTED: c++03, c++11, c++14 // XFAIL: target=powerpc{{.*}}le-unknown-linux-gnu -// TODO: This test makes incorrect assumptions about floating point conversions. -// See https://github.com/llvm/llvm-project/issues/74327. -// XFAIL: optimization=speed - // // // [simd.class] -- GitLab From d2e57c5c36d9b084f804cfd96a47472e23d05cac Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 11 Mar 2024 15:22:51 -0400 Subject: [PATCH 162/953] [libc++] Re-enable the clang_modules_include test for Objective-C++ (#66801) This reverts commit aa60b2687, which was a temporary workaround. The underlying issue was fixed in Clang via c2c840bd92cf. This was originally https://reviews.llvm.org/D158694. --- libcxx/test/libcxx/clang_modules_include.gen.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/libcxx/test/libcxx/clang_modules_include.gen.py b/libcxx/test/libcxx/clang_modules_include.gen.py index e3593eefad2f..61a925823764 100644 --- a/libcxx/test/libcxx/clang_modules_include.gen.py +++ b/libcxx/test/libcxx/clang_modules_include.gen.py @@ -47,11 +47,8 @@ for header in public_headers: #include <{header}> """) -# TODO: Remove the UNSUPPORTED{BLOCKLIT}: clang-modules-build once issues with this test have been figured out. print(f"""\ //--- __std_clang_module.compile.pass.mm -// UNSUPPORTED{BLOCKLIT}: clang-modules-build - // RUN{BLOCKLIT}: %{{cxx}} %s %{{flags}} %{{compile_flags}} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only // REQUIRES{BLOCKLIT}: clang-modules-build -- GitLab From 42ee286e51260286c59fa1186d0e56ad0f446054 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Mon, 11 Mar 2024 15:25:28 -0400 Subject: [PATCH 163/953] Fixing test from 8467457afc61d70e881c9817ace26356ef757733 The clangd test was testing the previous diagnostic logic and now it's testing with the new warning flag. --- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp index 2f6dd0611b66..25d2f03e0b36 100644 --- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp +++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp @@ -544,7 +544,7 @@ TEST(DiagnosticTest, RespectsDiagnosticConfig) { Diag(Main.range("ret"), "void function 'x' should not return a value"))); Config Cfg; - Cfg.Diagnostics.Suppress.insert("return-type"); + Cfg.Diagnostics.Suppress.insert("return-mismatch"); WithContextValue WithCfg(Config::Key, std::move(Cfg)); EXPECT_THAT(TU.build().getDiagnostics(), ElementsAre(Diag(Main.range(), -- GitLab From a70d7298818aae94ee62cd50c3ba195aaa10acb1 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 11 Mar 2024 14:30:30 -0500 Subject: [PATCH 164/953] [flang] Avoid left shifts of negative signed values (#84786) Shifting left a signed, negative value is an undefined behavior in C++. This was detected by the undefined behavior sanitizer. --- flang/include/flang/Evaluate/integer.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/flang/include/flang/Evaluate/integer.h b/flang/include/flang/Evaluate/integer.h index 977d35c7eecf..31768c21daae 100644 --- a/flang/include/flang/Evaluate/integer.h +++ b/flang/include/flang/Evaluate/integer.h @@ -150,7 +150,10 @@ public: } } } else { - INT signExtension{-(n < 0)}; + // Avoid left shifts of negative signed values (that's an undefined + // behavior in C++). + auto signExtension{std::make_unsigned_t(n < 0)}; + signExtension = ~signExtension + 1; static_assert(nBits >= partBits); if constexpr (nBits > partBits) { signExtension <<= nBits - partBits; @@ -474,7 +477,12 @@ public: SINT n = ToUInt(); constexpr std::size_t maxBits{CHAR_BIT * sizeof n}; if constexpr (bits < maxBits) { - n |= -(n >> (bits - 1)) << bits; + // Avoid left shifts of negative signed values (that's an undefined + // behavior in C++). + auto u{std::make_unsigned_t(ToUInt())}; + u = (u >> (bits - 1)) << (bits - 1); // Get the sign bit only. + u = ~u + 1; // Negate top bits if not 0. + n |= static_cast(u); } return n; } -- GitLab From 1def98d9f2eb2ae39e774369693e6f2f74551b7f Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 11 Mar 2024 14:35:31 -0500 Subject: [PATCH 165/953] [flang] Avoid forming a reference from null pointer (#84787) Doing so is an undefined behavior. This was detected by the undefined behavior sanitizer. --- flang/lib/Parser/token-sequence.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/flang/lib/Parser/token-sequence.cpp b/flang/lib/Parser/token-sequence.cpp index c5a630c471d1..799d13a42366 100644 --- a/flang/lib/Parser/token-sequence.cpp +++ b/flang/lib/Parser/token-sequence.cpp @@ -136,7 +136,10 @@ void TokenSequence::Put( } void TokenSequence::Put(const CharBlock &t, Provenance provenance) { - Put(&t[0], t.size(), provenance); + // Avoid t[0] if t is empty: it would create a reference to nullptr, + // which is UB. + const char *addr{t.size() ? &t[0] : nullptr}; + Put(addr, t.size(), provenance); } void TokenSequence::Put(const std::string &s, Provenance provenance) { -- GitLab From a25fa92d870a5cbb3eeccdc7458d1bc6834b695a Mon Sep 17 00:00:00 2001 From: lntue <35648136+lntue@users.noreply.github.com> Date: Mon, 11 Mar 2024 15:39:05 -0400 Subject: [PATCH 166/953] [libc][stdbit] Add C tests for stdbit generic macros. (#84670) Currently there is no tests for generic macros of generated `stdbit.h` header in C, and it is easy to make typo mistakes as in https://github.com/llvm/llvm-project/issues/84658. In this patch, we add a simple test for them in C. --- libc/test/include/CMakeLists.txt | 25 +++++++++ libc/test/include/stdbit_stub.h | 73 ++++++++++++++++++++++++++ libc/test/include/stdbit_test.c | 61 ++++++++++++++++++++++ libc/test/include/stdbit_test.cpp | 85 +------------------------------ 4 files changed, 160 insertions(+), 84 deletions(-) create mode 100644 libc/test/include/stdbit_stub.h create mode 100644 libc/test/include/stdbit_test.c diff --git a/libc/test/include/CMakeLists.txt b/libc/test/include/CMakeLists.txt index bf845c94170f..d76ad442d36c 100644 --- a/libc/test/include/CMakeLists.txt +++ b/libc/test/include/CMakeLists.txt @@ -22,16 +22,41 @@ if(LLVM_LIBC_FULL_BUILD AND libc.include.stdbit IN_LIST TARGET_PUBLIC_HEADERS) stdbit_test SUITE libc_include_tests + HDRS + stdbit_stub.h SRCS stdbit_test.cpp DEPENDS libc.include.llvm-libc-macros.stdbit_macros + libc.include.llvm_libc_common_h libc.include.stdbit # Intentionally do not depend on libc.src.stdbit.*. The include test is # simply testing the macros provided by stdbit.h, not the implementation # of the underlying functions which the type generic macros may dispatch # to. ) + add_libc_test( + stdbit_c_test + UNIT_TEST_ONLY + SUITE + libc_include_tests + HDRS + stdbit_stub.h + SRCS + stdbit_test.c + COMPILE_OPTIONS + -Wall + -Werror + DEPENDS + libc.include.llvm-libc-macros.stdbit_macros + libc.include.llvm_libc_common_h + libc.include.stdbit + libc.src.assert.__assert_fail + # Intentionally do not depend on libc.src.stdbit.*. The include test is + # simply testing the macros provided by stdbit.h, not the implementation + # of the underlying functions which the type generic macros may dispatch + # to. + ) endif() add_libc_test( diff --git a/libc/test/include/stdbit_stub.h b/libc/test/include/stdbit_stub.h new file mode 100644 index 000000000000..65b1ca3b2c29 --- /dev/null +++ b/libc/test/include/stdbit_stub.h @@ -0,0 +1,73 @@ +//===-- Utilities for testing stdbit --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +/* + * Declare these BEFORE including stdbit-macros.h so that this test may still be + * run even if a given target doesn't yet have these individual entrypoints + * enabled. + */ + +#include "include/__llvm-libc-common.h" + +#include // bool in C + +#define STDBIT_STUB_FUNCTION(FUNC_NAME, LEADING_VAL) \ + unsigned FUNC_NAME##_uc(unsigned char x) __NOEXCEPT { \ + return LEADING_VAL##AU; \ + } \ + unsigned FUNC_NAME##_us(unsigned short x) __NOEXCEPT { \ + return LEADING_VAL##BU; \ + } \ + unsigned FUNC_NAME##_ui(unsigned int x) __NOEXCEPT { \ + return LEADING_VAL##CU; \ + } \ + unsigned FUNC_NAME##_ul(unsigned long x) __NOEXCEPT { \ + return LEADING_VAL##DU; \ + } \ + unsigned FUNC_NAME##_ull(unsigned long long x) __NOEXCEPT { \ + return LEADING_VAL##EU; \ + } + +__BEGIN_C_DECLS + +STDBIT_STUB_FUNCTION(stdc_leading_zeros, 0xA) +STDBIT_STUB_FUNCTION(stdc_leading_ones, 0xB) +STDBIT_STUB_FUNCTION(stdc_trailing_zeros, 0xC) +STDBIT_STUB_FUNCTION(stdc_trailing_ones, 0xD) +STDBIT_STUB_FUNCTION(stdc_first_leading_zero, 0xE) +STDBIT_STUB_FUNCTION(stdc_first_leading_one, 0xF) +STDBIT_STUB_FUNCTION(stdc_first_trailing_zero, 0x0) +STDBIT_STUB_FUNCTION(stdc_first_trailing_one, 0x1) +STDBIT_STUB_FUNCTION(stdc_count_zeros, 0x2) +STDBIT_STUB_FUNCTION(stdc_count_ones, 0x3) + +bool stdc_has_single_bit_uc(unsigned char x) __NOEXCEPT { return false; } +bool stdc_has_single_bit_us(unsigned short x) __NOEXCEPT { return false; } +bool stdc_has_single_bit_ui(unsigned x) __NOEXCEPT { return false; } +bool stdc_has_single_bit_ul(unsigned long x) __NOEXCEPT { return false; } +bool stdc_has_single_bit_ull(unsigned long long x) __NOEXCEPT { return false; } + +STDBIT_STUB_FUNCTION(stdc_bit_width, 0x4) + +unsigned char stdc_bit_floor_uc(unsigned char x) __NOEXCEPT { return 0x5AU; } +unsigned short stdc_bit_floor_us(unsigned short x) __NOEXCEPT { return 0x5BU; } +unsigned stdc_bit_floor_ui(unsigned x) __NOEXCEPT { return 0x5CU; } +unsigned long stdc_bit_floor_ul(unsigned long x) __NOEXCEPT { return 0x5DUL; } +unsigned long long stdc_bit_floor_ull(unsigned long long x) __NOEXCEPT { + return 0x5EULL; +} + +unsigned char stdc_bit_ceil_uc(unsigned char x) __NOEXCEPT { return 0x6AU; } +unsigned short stdc_bit_ceil_us(unsigned short x) __NOEXCEPT { return 0x6BU; } +unsigned stdc_bit_ceil_ui(unsigned x) __NOEXCEPT { return 0x6CU; } +unsigned long stdc_bit_ceil_ul(unsigned long x) __NOEXCEPT { return 0x6DUL; } +unsigned long long stdc_bit_ceil_ull(unsigned long long x) __NOEXCEPT { + return 0x6EULL; +} + +__END_C_DECLS diff --git a/libc/test/include/stdbit_test.c b/libc/test/include/stdbit_test.c new file mode 100644 index 000000000000..e278e9a7374e --- /dev/null +++ b/libc/test/include/stdbit_test.c @@ -0,0 +1,61 @@ +//===-- Unittests for stdbit ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +/* + * The intent of this test is validate that: + * 1. We provide the definition of the various type generic macros of stdbit.h + * (the macros are transitively included from stdbit-macros.h by stdbit.h). + * 2. It dispatches to the correct underlying function. + * Because unit tests build without public packaging, the object files produced + * do not contain non-namespaced symbols. + */ + +/* + * Declare these BEFORE including stdbit-macros.h so that this test may still be + * run even if a given target doesn't yet have these individual entrypoints + * enabled. + */ +#include "stdbit_stub.h" + +#include "include/llvm-libc-macros/stdbit-macros.h" + +#include + +#define CHECK_FUNCTION(FUNC_NAME, VAL) \ + do { \ + assert(FUNC_NAME((unsigned char)0U) == VAL##AU); \ + assert(FUNC_NAME((unsigned short)0U) == VAL##BU); \ + assert(FUNC_NAME(0U) == VAL##CU); \ + assert(FUNC_NAME(0UL) == VAL##DU); \ + assert(FUNC_NAME(0ULL) == VAL##EU); \ + } while (0) + +int main(void) { + CHECK_FUNCTION(stdc_leading_zeros, 0xA); + CHECK_FUNCTION(stdc_leading_ones, 0xB); + CHECK_FUNCTION(stdc_trailing_zeros, 0xC); + CHECK_FUNCTION(stdc_trailing_ones, 0xD); + CHECK_FUNCTION(stdc_first_leading_zero, 0xE); + CHECK_FUNCTION(stdc_first_leading_one, 0xF); + CHECK_FUNCTION(stdc_first_trailing_zero, 0x0); + CHECK_FUNCTION(stdc_first_trailing_one, 0x1); + CHECK_FUNCTION(stdc_count_zeros, 0x2); + CHECK_FUNCTION(stdc_count_ones, 0x3); + + assert(!stdc_has_single_bit((unsigned char)1U)); + assert(!stdc_has_single_bit((unsigned short)1U)); + assert(!stdc_has_single_bit(1U)); + assert(!stdc_has_single_bit(1UL)); + assert(!stdc_has_single_bit(1ULL)); + + CHECK_FUNCTION(stdc_bit_width, 0x4); + CHECK_FUNCTION(stdc_bit_floor, 0x5); + CHECK_FUNCTION(stdc_bit_ceil, 0x6); + + return 0; +} diff --git a/libc/test/include/stdbit_test.cpp b/libc/test/include/stdbit_test.cpp index 6c12665c4454..f3227eb86959 100644 --- a/libc/test/include/stdbit_test.cpp +++ b/libc/test/include/stdbit_test.cpp @@ -22,90 +22,7 @@ * run even if a given target doesn't yet have these individual entrypoints * enabled. */ -extern "C" { -unsigned stdc_leading_zeros_uc(unsigned char) noexcept { return 0xAAU; } -unsigned stdc_leading_zeros_us(unsigned short) noexcept { return 0xABU; } -unsigned stdc_leading_zeros_ui(unsigned) noexcept { return 0xACU; } -unsigned stdc_leading_zeros_ul(unsigned long) noexcept { return 0xADU; } -unsigned stdc_leading_zeros_ull(unsigned long long) noexcept { return 0xAEU; } -unsigned stdc_leading_ones_uc(unsigned char) noexcept { return 0xBAU; } -unsigned stdc_leading_ones_us(unsigned short) noexcept { return 0xBBU; } -unsigned stdc_leading_ones_ui(unsigned) noexcept { return 0xBCU; } -unsigned stdc_leading_ones_ul(unsigned long) noexcept { return 0xBDU; } -unsigned stdc_leading_ones_ull(unsigned long long) noexcept { return 0xBEU; } -unsigned stdc_trailing_zeros_uc(unsigned char) noexcept { return 0xCAU; } -unsigned stdc_trailing_zeros_us(unsigned short) noexcept { return 0xCBU; } -unsigned stdc_trailing_zeros_ui(unsigned) noexcept { return 0xCCU; } -unsigned stdc_trailing_zeros_ul(unsigned long) noexcept { return 0xCDU; } -unsigned stdc_trailing_zeros_ull(unsigned long long) noexcept { return 0xCEU; } -unsigned stdc_trailing_ones_uc(unsigned char) noexcept { return 0xDAU; } -unsigned stdc_trailing_ones_us(unsigned short) noexcept { return 0xDBU; } -unsigned stdc_trailing_ones_ui(unsigned) noexcept { return 0xDCU; } -unsigned stdc_trailing_ones_ul(unsigned long) noexcept { return 0xDDU; } -unsigned stdc_trailing_ones_ull(unsigned long long) noexcept { return 0xDEU; } -unsigned stdc_first_leading_zero_uc(unsigned char) noexcept { return 0xEAU; } -unsigned stdc_first_leading_zero_us(unsigned short) noexcept { return 0xEBU; } -unsigned stdc_first_leading_zero_ui(unsigned) noexcept { return 0xECU; } -unsigned stdc_first_leading_zero_ul(unsigned long) noexcept { return 0xEDU; } -unsigned stdc_first_leading_zero_ull(unsigned long long) noexcept { - return 0xEEU; -} -unsigned stdc_first_leading_one_uc(unsigned char) noexcept { return 0xFAU; } -unsigned stdc_first_leading_one_us(unsigned short) noexcept { return 0xFBU; } -unsigned stdc_first_leading_one_ui(unsigned) noexcept { return 0xFCU; } -unsigned stdc_first_leading_one_ul(unsigned long) noexcept { return 0xFDU; } -unsigned stdc_first_leading_one_ull(unsigned long long) noexcept { - return 0xFEU; -} -unsigned stdc_first_trailing_zero_uc(unsigned char) noexcept { return 0x0AU; } -unsigned stdc_first_trailing_zero_us(unsigned short) noexcept { return 0x0BU; } -unsigned stdc_first_trailing_zero_ui(unsigned) noexcept { return 0x0CU; } -unsigned stdc_first_trailing_zero_ul(unsigned long) noexcept { return 0x0DU; } -unsigned stdc_first_trailing_zero_ull(unsigned long long) noexcept { - return 0x0EU; -} -unsigned stdc_first_trailing_one_uc(unsigned char) noexcept { return 0x1AU; } -unsigned stdc_first_trailing_one_us(unsigned short) noexcept { return 0x1BU; } -unsigned stdc_first_trailing_one_ui(unsigned) noexcept { return 0x1CU; } -unsigned stdc_first_trailing_one_ul(unsigned long) noexcept { return 0x1DU; } -unsigned stdc_first_trailing_one_ull(unsigned long long) noexcept { - return 0x1EU; -} -unsigned stdc_count_zeros_uc(unsigned char) noexcept { return 0x2AU; } -unsigned stdc_count_zeros_us(unsigned short) noexcept { return 0x2BU; } -unsigned stdc_count_zeros_ui(unsigned) noexcept { return 0x2CU; } -unsigned stdc_count_zeros_ul(unsigned long) noexcept { return 0x2DU; } -unsigned stdc_count_zeros_ull(unsigned long long) noexcept { return 0x2EU; } -unsigned stdc_count_ones_uc(unsigned char) noexcept { return 0x3AU; } -unsigned stdc_count_ones_us(unsigned short) noexcept { return 0x3BU; } -unsigned stdc_count_ones_ui(unsigned) noexcept { return 0x3CU; } -unsigned stdc_count_ones_ul(unsigned long) noexcept { return 0x3DU; } -unsigned stdc_count_ones_ull(unsigned long long) noexcept { return 0x3EU; } -bool stdc_has_single_bit_uc(unsigned char) noexcept { return false; } -bool stdc_has_single_bit_us(unsigned short) noexcept { return false; } -bool stdc_has_single_bit_ui(unsigned) noexcept { return false; } -bool stdc_has_single_bit_ul(unsigned long) noexcept { return false; } -bool stdc_has_single_bit_ull(unsigned long long) noexcept { return false; } -unsigned stdc_bit_width_uc(unsigned char) noexcept { return 0x4AU; } -unsigned stdc_bit_width_us(unsigned short) noexcept { return 0x4BU; } -unsigned stdc_bit_width_ui(unsigned) noexcept { return 0x4CU; } -unsigned stdc_bit_width_ul(unsigned long) noexcept { return 0x4DU; } -unsigned stdc_bit_width_ull(unsigned long long) noexcept { return 0x4EU; } -unsigned char stdc_bit_floor_uc(unsigned char) noexcept { return 0x5AU; } -unsigned short stdc_bit_floor_us(unsigned short) noexcept { return 0x5BU; } -unsigned stdc_bit_floor_ui(unsigned) noexcept { return 0x5CU; } -unsigned long stdc_bit_floor_ul(unsigned long) noexcept { return 0x5DU; } -unsigned long long stdc_bit_floor_ull(unsigned long long) noexcept { - return 0x5EU; -} -unsigned char stdc_bit_ceil_uc(unsigned char) noexcept { return 0x6AU; } -unsigned short stdc_bit_ceil_us(unsigned short) noexcept { return 0x6BU; } -unsigned stdc_bit_ceil_ui(unsigned) noexcept { return 0x6CU; } -unsigned long stdc_bit_ceil_ul(unsigned long) noexcept { return 0x6DU; } -unsigned long long stdc_bit_ceil_ull(unsigned long long) noexcept { - return 0x6EU; -} -} +#include "stdbit_stub.h" #include "include/llvm-libc-macros/stdbit-macros.h" -- GitLab From 884b051a42896e94dc6032013e10483d84910f27 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 11 Mar 2024 09:55:44 -0700 Subject: [PATCH 167/953] Recommit "[TypePromotion] Support positive addition amounts in isSafeWrap. (#81690)" With special case with Add constant is 0. Original message: We can support these by changing the sext promotion to -zext(-C) and replacing a sgt check with ugt. Reframing the logic in terms of how the unsigned range are affected. More comments in the patch. The new cases check isLegalAddImmediate to avoid some regressions in lit tests. --- llvm/lib/CodeGen/TypePromotion.cpp | 129 ++++++++++-------- llvm/test/CodeGen/AArch64/and-mask-removal.ll | 18 +-- .../AArch64/signed-truncation-check.ll | 2 +- .../CodeGen/AArch64/typepromotion-overflow.ll | 5 +- .../CodeGen/RISCV/typepromotion-overflow.ll | 5 +- .../Transforms/TypePromotion/ARM/icmps.ll | 5 +- .../Transforms/TypePromotion/ARM/wrapping.ll | 10 +- 7 files changed, 92 insertions(+), 82 deletions(-) diff --git a/llvm/lib/CodeGen/TypePromotion.cpp b/llvm/lib/CodeGen/TypePromotion.cpp index 48ad8de77801..b0830308908d 100644 --- a/llvm/lib/CodeGen/TypePromotion.cpp +++ b/llvm/lib/CodeGen/TypePromotion.cpp @@ -136,6 +136,7 @@ public: class TypePromotionImpl { unsigned TypeSize = 0; + const TargetLowering *TLI = nullptr; LLVMContext *Ctx = nullptr; unsigned RegisterBitWidth = 0; SmallPtrSet AllVisited; @@ -272,64 +273,58 @@ bool TypePromotionImpl::isSink(Value *V) { /// Return whether this instruction can safely wrap. bool TypePromotionImpl::isSafeWrap(Instruction *I) { - // We can support a potentially wrapping instruction (I) if: + // We can support a potentially wrapping Add/Sub instruction (I) if: // - It is only used by an unsigned icmp. // - The icmp uses a constant. - // - The wrapping value (I) is decreasing, i.e would underflow - wrapping - // around zero to become a larger number than before. // - The wrapping instruction (I) also uses a constant. // - // We can then use the two constants to calculate whether the result would - // wrap in respect to itself in the original bitwidth. If it doesn't wrap, - // just underflows the range, the icmp would give the same result whether the - // result has been truncated or not. We calculate this by: - // - Zero extending both constants, if needed, to RegisterBitWidth. - // - Take the absolute value of I's constant, adding this to the icmp const. - // - Check that this value is not out of range for small type. If it is, it - // means that it has underflowed enough to wrap around the icmp constant. + // This a common pattern emitted to check if a value is within a range. // // For example: // - // %sub = sub i8 %a, 2 - // %cmp = icmp ule i8 %sub, 254 + // %sub = sub i8 %a, C1 + // %cmp = icmp ule i8 %sub, C2 + // + // or + // + // %add = add i8 %a, C1 + // %cmp = icmp ule i8 %add, C2. // - // If %a = 0, %sub = -2 == FE == 254 - // But if this is evalulated as a i32 - // %sub = -2 == FF FF FF FE == 4294967294 - // So the unsigned compares (i8 and i32) would not yield the same result. + // We will treat an add as though it were a subtract by -C1. To promote + // the Add/Sub we will zero extend the LHS and the subtracted amount. For Add, + // this means we need to negate the constant, zero extend to RegisterBitWidth, + // and negate in the larger type. // - // Another way to look at it is: - // %a - 2 <= 254 - // %a + 2 <= 254 + 2 - // %a <= 256 - // And we can't represent 256 in the i8 format, so we don't support it. + // This will produce a value in the range [-zext(C1), zext(X)-zext(C1)] where + // C1 is the subtracted amount. This is either a small unsigned number or a + // large unsigned number in the promoted type. // - // Whereas: + // Now we need to correct the compare constant C2. Values >= C1 in the + // original add result range have been remapped to large values in the + // promoted range. If the compare constant fell into this range we need to + // remap it as well. We can do this as -(zext(-C2)). // - // %sub i8 %a, 1 + // For example: + // + // %sub = sub i8 %a, 2 // %cmp = icmp ule i8 %sub, 254 // - // If %a = 0, %sub = -1 == FF == 255 - // As i32: - // %sub = -1 == FF FF FF FF == 4294967295 + // becomes // - // In this case, the unsigned compare results would be the same and this - // would also be true for ult, uge and ugt: - // - (255 < 254) == (0xFFFFFFFF < 254) == false - // - (255 <= 254) == (0xFFFFFFFF <= 254) == false - // - (255 > 254) == (0xFFFFFFFF > 254) == true - // - (255 >= 254) == (0xFFFFFFFF >= 254) == true + // %zext = zext %a to i32 + // %sub = sub i32 %zext, 2 + // %cmp = icmp ule i32 %sub, 4294967294 // - // To demonstrate why we can't handle increasing values: + // Another example: // - // %add = add i8 %a, 2 - // %cmp = icmp ult i8 %add, 127 + // %sub = sub i8 %a, 1 + // %cmp = icmp ule i8 %sub, 254 // - // If %a = 254, %add = 256 == (i8 1) - // As i32: - // %add = 256 + // becomes // - // (1 < 127) != (256 < 127) + // %zext = zext %a to i32 + // %sub = sub i32 %zext, 1 + // %cmp = icmp ule i32 %sub, 254 unsigned Opc = I->getOpcode(); if (Opc != Instruction::Add && Opc != Instruction::Sub) @@ -356,21 +351,29 @@ bool TypePromotionImpl::isSafeWrap(Instruction *I) { APInt OverflowConst = cast(I->getOperand(1))->getValue(); if (Opc == Instruction::Sub) OverflowConst = -OverflowConst; - if (!OverflowConst.isNonPositive()) - return false; + + // If the constant is positive, we will end up filling the promoted bits with + // all 1s. Make sure that results in a cheap add constant. + if (!OverflowConst.isNonPositive()) { + // We don't have the true promoted width, just use 64 so we can create an + // int64_t for the isLegalAddImmediate call. + if (OverflowConst.getBitWidth() >= 64) + return false; + + APInt NewConst = -((-OverflowConst).zext(64)); + if (!TLI->isLegalAddImmediate(NewConst.getSExtValue())) + return false; + } SafeWrap.insert(I); - // Using C1 = OverflowConst and C2 = ICmpConst, we can either prove that: - // zext(x) + sext(C1) s C2 - // zext(x) + sext(C1) (Op)) { - // For subtract, we don't need to sext the constant. We only put it in + // For subtract, we only need to zext the constant. We only put it in // SafeWrap because SafeWrap.size() is used elsewhere. - // For cmp, we need to sign extend a constant appearing in either - // operand. For add, we should only sign extend the RHS. - Constant *NewConst = - ConstantInt::get(Const->getContext(), - (SafeWrap.contains(I) && - (I->getOpcode() == Instruction::ICmp || i == 1) && - I->getOpcode() != Instruction::Sub) - ? Const->getValue().sext(PromotedWidth) - : Const->getValue().zext(PromotedWidth)); - I->setOperand(i, NewConst); + // For Add and ICmp we need to find how far the constant is from the + // top of its original unsigned range and place it the same distance + // from the top of its new unsigned range. We can do this by negating + // the constant, zero extending it, then negating in the new type. + APInt NewConst; + if (SafeWrap.contains(I)) { + if (I->getOpcode() == Instruction::ICmp) + NewConst = -((-Const->getValue()).zext(PromotedWidth)); + else if (I->getOpcode() == Instruction::Add && i == 1) + NewConst = -((-Const->getValue()).zext(PromotedWidth)); + else + NewConst = Const->getValue().zext(PromotedWidth); + } else + NewConst = Const->getValue().zext(PromotedWidth); + + I->setOperand(i, ConstantInt::get(Const->getContext(), NewConst)); } else if (isa(Op)) I->setOperand(i, ConstantInt::get(ExtTy, 0)); } @@ -917,7 +926,7 @@ bool TypePromotionImpl::run(Function &F, const TargetMachine *TM, bool MadeChange = false; const DataLayout &DL = F.getParent()->getDataLayout(); const TargetSubtargetInfo *SubtargetInfo = TM->getSubtargetImpl(F); - const TargetLowering *TLI = SubtargetInfo->getTargetLowering(); + TLI = SubtargetInfo->getTargetLowering(); RegisterBitWidth = TTI.getRegisterBitWidth(TargetTransformInfo::RGK_Scalar).getFixedValue(); Ctx = &F.getParent()->getContext(); diff --git a/llvm/test/CodeGen/AArch64/and-mask-removal.ll b/llvm/test/CodeGen/AArch64/and-mask-removal.ll index 17ff01597016..a8a59f159126 100644 --- a/llvm/test/CodeGen/AArch64/and-mask-removal.ll +++ b/llvm/test/CodeGen/AArch64/and-mask-removal.ll @@ -65,9 +65,8 @@ if.end: ; preds = %if.then, %entry define zeroext i1 @test8_0(i8 zeroext %x) align 2 { ; CHECK-LABEL: test8_0: ; CHECK: ; %bb.0: ; %entry -; CHECK-NEXT: add w8, w0, #74 -; CHECK-NEXT: and w8, w8, #0xff -; CHECK-NEXT: cmp w8, #236 +; CHECK-NEXT: sub w8, w0, #182 +; CHECK-NEXT: cmn w8, #20 ; CHECK-NEXT: cset w0, lo ; CHECK-NEXT: ret entry: @@ -508,16 +507,17 @@ define i64 @pr58109(i8 signext %0) { define i64 @pr58109b(i8 signext %0, i64 %a, i64 %b) { ; CHECK-SD-LABEL: pr58109b: ; CHECK-SD: ; %bb.0: -; CHECK-SD-NEXT: add w8, w0, #1 -; CHECK-SD-NEXT: tst w8, #0xfe -; CHECK-SD-NEXT: csel x0, x1, x2, eq +; CHECK-SD-NEXT: and w8, w0, #0xff +; CHECK-SD-NEXT: sub w8, w8, #255 +; CHECK-SD-NEXT: cmn w8, #254 +; CHECK-SD-NEXT: csel x0, x1, x2, lo ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: pr58109b: ; CHECK-GI: ; %bb.0: -; CHECK-GI-NEXT: add w8, w0, #1 -; CHECK-GI-NEXT: and w8, w8, #0xff -; CHECK-GI-NEXT: cmp w8, #2 +; CHECK-GI-NEXT: mov w8, #-255 ; =0xffffff01 +; CHECK-GI-NEXT: add w8, w8, w0, uxtb +; CHECK-GI-NEXT: cmn w8, #254 ; CHECK-GI-NEXT: csel x0, x1, x2, lo ; CHECK-GI-NEXT: ret %2 = add i8 %0, 1 diff --git a/llvm/test/CodeGen/AArch64/signed-truncation-check.ll b/llvm/test/CodeGen/AArch64/signed-truncation-check.ll index ab42e6463fee..bb4df6d8935b 100644 --- a/llvm/test/CodeGen/AArch64/signed-truncation-check.ll +++ b/llvm/test/CodeGen/AArch64/signed-truncation-check.ll @@ -396,7 +396,7 @@ define i1 @add_ultcmp_bad_i24_i8(i24 %x) nounwind { define i1 @add_ulecmp_bad_i16_i8(i16 %x) nounwind { ; CHECK-LABEL: add_ulecmp_bad_i16_i8: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w0, #1 +; CHECK-NEXT: mov w0, #1 // =0x1 ; CHECK-NEXT: ret %tmp0 = add i16 %x, 128 ; 1U << (8-1) %tmp1 = icmp ule i16 %tmp0, -1 ; when we +1 it, it will wrap to 0 diff --git a/llvm/test/CodeGen/AArch64/typepromotion-overflow.ll b/llvm/test/CodeGen/AArch64/typepromotion-overflow.ll index ccfbf456693d..39edc03ced44 100644 --- a/llvm/test/CodeGen/AArch64/typepromotion-overflow.ll +++ b/llvm/test/CodeGen/AArch64/typepromotion-overflow.ll @@ -246,9 +246,8 @@ define i32 @safe_sub_var_imm(ptr nocapture readonly %b) local_unnamed_addr #1 { ; CHECK-LABEL: safe_sub_var_imm: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: ldrb w8, [x0] -; CHECK-NEXT: add w8, w8, #8 -; CHECK-NEXT: and w8, w8, #0xff -; CHECK-NEXT: cmp w8, #252 +; CHECK-NEXT: sub w8, w8, #248 +; CHECK-NEXT: cmn w8, #4 ; CHECK-NEXT: cset w0, hi ; CHECK-NEXT: ret entry: diff --git a/llvm/test/CodeGen/RISCV/typepromotion-overflow.ll b/llvm/test/CodeGen/RISCV/typepromotion-overflow.ll index 3740dc675949..ec7e0ecce80c 100644 --- a/llvm/test/CodeGen/RISCV/typepromotion-overflow.ll +++ b/llvm/test/CodeGen/RISCV/typepromotion-overflow.ll @@ -283,9 +283,8 @@ define i32 @safe_sub_var_imm(ptr nocapture readonly %b) local_unnamed_addr #1 { ; CHECK-LABEL: safe_sub_var_imm: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: lbu a0, 0(a0) -; CHECK-NEXT: addi a0, a0, 8 -; CHECK-NEXT: andi a0, a0, 255 -; CHECK-NEXT: sltiu a0, a0, 253 +; CHECK-NEXT: addi a0, a0, -248 +; CHECK-NEXT: sltiu a0, a0, -3 ; CHECK-NEXT: xori a0, a0, 1 ; CHECK-NEXT: ret entry: diff --git a/llvm/test/Transforms/TypePromotion/ARM/icmps.ll b/llvm/test/Transforms/TypePromotion/ARM/icmps.ll index 842aab121b96..7e03d689fdc9 100644 --- a/llvm/test/Transforms/TypePromotion/ARM/icmps.ll +++ b/llvm/test/Transforms/TypePromotion/ARM/icmps.ll @@ -4,8 +4,9 @@ define i32 @test_ult_254_inc_imm(i8 zeroext %x) { ; CHECK-LABEL: @test_ult_254_inc_imm( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X:%.*]], 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[ADD]], -2 +; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[X:%.*]] to i32 +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP0]], -255 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], -2 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 35, i32 47 ; CHECK-NEXT: ret i32 [[RES]] ; diff --git a/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll b/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll index 377708cf7113..78c5e7323cea 100644 --- a/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll +++ b/llvm/test/Transforms/TypePromotion/ARM/wrapping.ll @@ -89,8 +89,9 @@ define i32 @overflow_add_const_limit(i8 zeroext %a, i8 zeroext %b) { define i32 @overflow_add_positive_const_limit(i8 zeroext %a) { ; CHECK-LABEL: @overflow_add_positive_const_limit( -; CHECK-NEXT: [[ADD:%.*]] = add i8 [[A:%.*]], 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[ADD]], -128 +; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP1]], -255 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[ADD]], -128 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16 ; CHECK-NEXT: ret i32 [[RES]] ; @@ -144,8 +145,9 @@ define i32 @safe_add_underflow_neg(i8 zeroext %a) { define i32 @overflow_sub_negative_const_limit(i8 zeroext %a) { ; CHECK-LABEL: @overflow_sub_negative_const_limit( -; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[A:%.*]], -1 -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[SUB]], -128 +; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[TMP1]], 255 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[SUB]], -128 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 8, i32 16 ; CHECK-NEXT: ret i32 [[RES]] ; -- GitLab From 5feaef63c08b6fefb6b0eaff2270ccb14740cca2 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Mon, 11 Mar 2024 19:40:43 +0000 Subject: [PATCH 168/953] [TBAA] Generate tbaa.struct single field with char tag for unions. (#84370) At the moment,distinct fields for each union member are generated. When copying a union, we don't know which union member is active, so there's no benefit from recording the different fields. It can result in converting tbaa.struct fields to incorrect tbaa nodes when extracting fields. PR: https://github.com/llvm/llvm-project/pull/84370 --- clang/lib/CodeGen/CodeGenTBAA.cpp | 8 ++++++++ clang/test/CodeGen/tbaa-struct.cpp | 8 +++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp index 1f07205a5af2..a1e14c5f0a8c 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -286,6 +286,14 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset, /* Things not handled yet include: C++ base classes, bitfields, */ if (const RecordType *TTy = QTy->getAs()) { + if (TTy->isUnionType()) { + uint64_t Size = Context.getTypeSizeInChars(QTy).getQuantity(); + llvm::MDNode *TBAAType = getChar(); + llvm::MDNode *TBAATag = getAccessTagInfo(TBAAAccessInfo(TBAAType, Size)); + Fields.push_back( + llvm::MDBuilder::TBAAStructField(BaseOffset, Size, TBAATag)); + return true; + } const RecordDecl *RD = TTy->getDecl()->getDefinition(); if (RD->hasFlexibleArrayMember()) return false; diff --git a/clang/test/CodeGen/tbaa-struct.cpp b/clang/test/CodeGen/tbaa-struct.cpp index 63e409794644..9b4b7415142d 100644 --- a/clang/test/CodeGen/tbaa-struct.cpp +++ b/clang/test/CodeGen/tbaa-struct.cpp @@ -191,7 +191,7 @@ void copy12(UnionMember2 *a1, UnionMember2 *a2) { // (offset, size) = (0,1) char; (4,2) short; (8,4) int; (12,1) char; (16,4) int; (20,4) int // CHECK-OLD: [[TS2]] = !{i64 0, i64 1, !{{.*}}, i64 4, i64 2, !{{.*}}, i64 8, i64 4, !{{.*}}, i64 12, i64 1, !{{.*}}, i64 16, i64 4, {{.*}}, i64 20, i64 4, {{.*}}} // (offset, size) = (0,8) char; (0,2) char; (4,8) char -// CHECK-OLD: [[TS3]] = !{i64 0, i64 8, !{{.*}}, i64 0, i64 2, !{{.*}}, i64 4, i64 8, !{{.*}}} +// CHECK-OLD: [[TS3]] = !{i64 0, i64 12, [[TAG_CHAR]]} // CHECK-OLD: [[TS4]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]]} // CHECK-OLD: [[TS5]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 4, i64 1, [[TAG_CHAR]], i64 5, i64 1, [[TAG_CHAR]]} // CHECK-OLD: [[TS6]] = !{i64 0, i64 2, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE:!.+]]} @@ -199,10 +199,8 @@ void copy12(UnionMember2 *a1, UnionMember2 *a2) { // CHECK-OLD [[DOUBLE]] = !{!"double", [[CHAR]], i64 0} // CHECK-OLD: [[TS7]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 3, i64 1, [[TAG_CHAR]], i64 4, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]], i64 16, i64 1, [[TAG_CHAR]]} // CHECK-OLD: [[TS8]] = !{i64 0, i64 4, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]]} -// CHECK-OLD: [[TS9]] = !{i64 0, i64 8, [[TAG_DOUBLE]], i64 0, i64 4, [[TAG_FLOAT:!.+]], i64 8, i64 4, [[TAG_INT]]} -// CHECK-OLD: [[TAG_FLOAT]] = !{[[FLOAT:!.+]], [[FLOAT]], i64 0} -// CHECK-OLD: [[FLOAT]] = !{!"float", [[CHAR]], i64 0} -// CHECK-OLD: [[TS10]] = !{i64 0, i64 4, [[TAG_INT]], i64 8, i64 8, [[TAG_DOUBLE]], i64 8, i64 4, [[TAG_FLOAT:!.+]]} +// CHECK-OLD: [[TS9]] = !{i64 0, i64 8, [[TAG_CHAR]], i64 8, i64 4, [[TAG_INT]]} +// CHECK-OLD: [[TS10]] = !{i64 0, i64 4, [[TAG_INT]], i64 8, i64 8, [[TAG_CHAR]]} // CHECK-NEW-DAG: [[TYPE_char:!.*]] = !{{{.*}}, i64 1, !"omnipotent char"} // CHECK-NEW-DAG: [[TAG_char]] = !{[[TYPE_char]], [[TYPE_char]], i64 0, i64 0} -- GitLab From 94c988bcfdea596e5c9078be8ec28688eb0d96a3 Mon Sep 17 00:00:00 2001 From: Arthur Eubanks Date: Mon, 11 Mar 2024 19:47:48 +0000 Subject: [PATCH 169/953] [NFC] Remove unused parameter from shouldAssumeDSOLocal() --- llvm/include/llvm/Target/TargetMachine.h | 2 +- llvm/lib/CodeGen/GlobalMerge.cpp | 2 +- llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 2 +- llvm/lib/Target/AArch64/AArch64Subtarget.cpp | 5 ++--- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 3 +-- llvm/lib/Target/ARM/ARMISelLowering.cpp | 8 +++----- llvm/lib/Target/ARM/ARMSubtarget.cpp | 2 +- llvm/lib/Target/CSKY/CSKYISelLowering.cpp | 8 +++----- llvm/lib/Target/Hexagon/HexagonISelLowering.cpp | 2 +- llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp | 10 ++++------ llvm/lib/Target/M68k/M68kSubtarget.cpp | 6 +++--- llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 7 +++---- llvm/lib/Target/PowerPC/PPCSubtarget.cpp | 2 +- llvm/lib/Target/SystemZ/SystemZSubtarget.cpp | 2 +- llvm/lib/Target/TargetMachine.cpp | 5 ++--- llvm/lib/Target/VE/VEISelLowering.cpp | 2 +- .../lib/Target/WebAssembly/WebAssemblyISelLowering.cpp | 4 ++-- llvm/lib/Target/X86/X86Subtarget.cpp | 4 ++-- 18 files changed, 33 insertions(+), 43 deletions(-) diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h index d7ce088cad49..37df9589e30d 100644 --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -241,7 +241,7 @@ public: bool isPositionIndependent() const; - bool shouldAssumeDSOLocal(const Module &M, const GlobalValue *GV) const; + bool shouldAssumeDSOLocal(const GlobalValue *GV) const; /// Returns true if this target uses emulated TLS. bool useEmulatedTLS() const; diff --git a/llvm/lib/CodeGen/GlobalMerge.cpp b/llvm/lib/CodeGen/GlobalMerge.cpp index a2b5cbf7bad9..4941d5b01ae0 100644 --- a/llvm/lib/CodeGen/GlobalMerge.cpp +++ b/llvm/lib/CodeGen/GlobalMerge.cpp @@ -641,7 +641,7 @@ bool GlobalMergeImpl::run(Module &M) { continue; // It's not safe to merge globals that may be preempted - if (TM && !TM->shouldAssumeDSOLocal(M, &GV)) + if (TM && !TM->shouldAssumeDSOLocal(&GV)) continue; if (!(Opt.MergeExternal && GV.hasExternalLinkage()) && diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index a639cba5e35a..b3dc9de71373 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -491,7 +491,7 @@ TargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { // If the address is not even local to this DSO we will have to load it from // a got and then add the offset. - if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) + if (!TM.shouldAssumeDSOLocal(GV)) return false; // If the code is position independent we will have to add a base register. diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp index 23b1deb3697f..bb268b2ba926 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp @@ -398,7 +398,7 @@ AArch64Subtarget::ClassifyGlobalReference(const GlobalValue *GV, if (GV->isTagged()) return AArch64II::MO_GOT; - if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) { + if (!TM.shouldAssumeDSOLocal(GV)) { if (GV->hasDLLImportStorageClass()) { return AArch64II::MO_GOT | AArch64II::MO_DLLIMPORT; } @@ -435,8 +435,7 @@ unsigned AArch64Subtarget::classifyGlobalFunctionReference( // NonLazyBind goes via GOT unless we know it's available locally. auto *F = dyn_cast(GV); if ((!isTargetMachO() || MachOUseNonLazyBind) && F && - F->hasFnAttribute(Attribute::NonLazyBind) && - !TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) + F->hasFnAttribute(Attribute::NonLazyBind) && !TM.shouldAssumeDSOLocal(GV)) return AArch64II::MO_GOT; if (getTargetTriple().isOSWindows()) { diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index 1889ab007288..9bc1b8eb598f 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -6219,8 +6219,7 @@ bool SITargetLowering::shouldEmitGOTReloc(const GlobalValue *GV) const { // address space for functions to avoid the explicit check. return (GV->getValueType()->isFunctionTy() || !isNonGlobalAddrSpace(GV->getAddressSpace())) && - !shouldEmitFixup(GV) && - !getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV); + !shouldEmitFixup(GV) && !getTargetMachine().shouldAssumeDSOLocal(GV); } bool SITargetLowering::shouldEmitPCReloc(const GlobalValue *GV) const { diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index dc81178311b6..7ac49782ea84 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -2655,12 +2655,10 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, bool isDirect = false; const TargetMachine &TM = getTargetMachine(); - const Module *Mod = MF.getFunction().getParent(); const GlobalValue *GVal = nullptr; if (GlobalAddressSDNode *G = dyn_cast(Callee)) GVal = G->getGlobal(); - bool isStub = - !TM.shouldAssumeDSOLocal(*Mod, GVal) && Subtarget->isTargetMachO(); + bool isStub = !TM.shouldAssumeDSOLocal(GVal) && Subtarget->isTargetMachO(); bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass()); bool isLocalARMFunc = false; @@ -2737,7 +2735,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, unsigned TargetFlags = ARMII::MO_NO_FLAG; if (GVal->hasDLLImportStorageClass()) TargetFlags = ARMII::MO_DLLIMPORT; - else if (!TM.shouldAssumeDSOLocal(*GVal->getParent(), GVal)) + else if (!TM.shouldAssumeDSOLocal(GVal)) TargetFlags = ARMII::MO_COFFSTUB; Callee = DAG.getTargetGlobalAddress(GVal, dl, PtrVt, /*offset=*/0, TargetFlags); @@ -4021,7 +4019,7 @@ SDValue ARMTargetLowering::LowerGlobalAddressWindows(SDValue Op, ARMII::TOF TargetFlags = ARMII::MO_NO_FLAG; if (GV->hasDLLImportStorageClass()) TargetFlags = ARMII::MO_DLLIMPORT; - else if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) + else if (!TM.shouldAssumeDSOLocal(GV)) TargetFlags = ARMII::MO_COFFSTUB; EVT PtrVT = getPointerTy(DAG.getDataLayout()); SDValue Result; diff --git a/llvm/lib/Target/ARM/ARMSubtarget.cpp b/llvm/lib/Target/ARM/ARMSubtarget.cpp index 717e61518c6e..04ba20a17187 100644 --- a/llvm/lib/Target/ARM/ARMSubtarget.cpp +++ b/llvm/lib/Target/ARM/ARMSubtarget.cpp @@ -353,7 +353,7 @@ bool ARMSubtarget::isRWPI() const { } bool ARMSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const { - if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) + if (!TM.shouldAssumeDSOLocal(GV)) return true; // 32 bit macho has no relocation for a-b if a is undefined, even if b is in diff --git a/llvm/lib/Target/CSKY/CSKYISelLowering.cpp b/llvm/lib/Target/CSKY/CSKYISelLowering.cpp index 90f70b83a02d..869277a391a5 100644 --- a/llvm/lib/Target/CSKY/CSKYISelLowering.cpp +++ b/llvm/lib/Target/CSKY/CSKYISelLowering.cpp @@ -649,8 +649,7 @@ SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI, if (GlobalAddressSDNode *S = dyn_cast(Callee)) { const GlobalValue *GV = S->getGlobal(); - bool IsLocal = - getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV); + bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(GV); if (isPositionIndependent() || !Subtarget.has2E3()) { IsRegCall = true; @@ -662,8 +661,7 @@ SDValue CSKYTargetLowering::LowerCall(CallLoweringInfo &CLI, cast(Callee), Ty, DAG, CSKYII::MO_None)); } } else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { - bool IsLocal = getTargetMachine().shouldAssumeDSOLocal( - *MF.getFunction().getParent(), nullptr); + bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(nullptr); if (isPositionIndependent() || !Subtarget.has2E3()) { IsRegCall = true; @@ -1153,7 +1151,7 @@ SDValue CSKYTargetLowering::LowerGlobalAddress(SDValue Op, int64_t Offset = N->getOffset(); const GlobalValue *GV = N->getGlobal(); - bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV); + bool IsLocal = getTargetMachine().shouldAssumeDSOLocal(GV); SDValue Addr = getAddr(N, DAG, IsLocal); // In order to maximise the opportunity for common subexpression elimination, diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp index eda1150835a1..41462cceef51 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -1238,7 +1238,7 @@ HexagonTargetLowering::LowerGLOBALADDRESS(SDValue Op, SelectionDAG &DAG) const { return DAG.getNode(HexagonISD::CONST32, dl, PtrVT, GA); } - bool UsePCRel = getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV); + bool UsePCRel = getTargetMachine().shouldAssumeDSOLocal(GV); if (UsePCRel) { SDValue GA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, Offset, HexagonII::MO_PCREL); diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 2d71423d6dd5..c87f5341d7fe 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -4251,14 +4251,12 @@ LoongArchTargetLowering::LowerCall(CallLoweringInfo &CLI, // split it and then direct call can be matched by PseudoCALL. if (GlobalAddressSDNode *S = dyn_cast(Callee)) { const GlobalValue *GV = S->getGlobal(); - unsigned OpFlags = - getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV) - ? LoongArchII::MO_CALL - : LoongArchII::MO_CALL_PLT; + unsigned OpFlags = getTargetMachine().shouldAssumeDSOLocal(GV) + ? LoongArchII::MO_CALL + : LoongArchII::MO_CALL_PLT; Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT, 0, OpFlags); } else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { - unsigned OpFlags = getTargetMachine().shouldAssumeDSOLocal( - *MF.getFunction().getParent(), nullptr) + unsigned OpFlags = getTargetMachine().shouldAssumeDSOLocal(nullptr) ? LoongArchII::MO_CALL : LoongArchII::MO_CALL_PLT; Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, OpFlags); diff --git a/llvm/lib/Target/M68k/M68kSubtarget.cpp b/llvm/lib/Target/M68k/M68kSubtarget.cpp index 86e81cd08ea2..3af1e994c01c 100644 --- a/llvm/lib/Target/M68k/M68kSubtarget.cpp +++ b/llvm/lib/Target/M68k/M68kSubtarget.cpp @@ -175,7 +175,7 @@ M68kSubtarget::classifyLocalReference(const GlobalValue *GV) const { } unsigned char M68kSubtarget::classifyExternalReference(const Module &M) const { - if (TM.shouldAssumeDSOLocal(M, nullptr)) + if (TM.shouldAssumeDSOLocal(nullptr)) return classifyLocalReference(nullptr); if (isPositionIndependent()) @@ -191,7 +191,7 @@ M68kSubtarget::classifyGlobalReference(const GlobalValue *GV) const { unsigned char M68kSubtarget::classifyGlobalReference(const GlobalValue *GV, const Module &M) const { - if (TM.shouldAssumeDSOLocal(M, GV)) + if (TM.shouldAssumeDSOLocal(GV)) return classifyLocalReference(GV); switch (TM.getCodeModel()) { @@ -240,7 +240,7 @@ unsigned char M68kSubtarget::classifyGlobalFunctionReference(const GlobalValue *GV, const Module &M) const { // local always use pc-rel referencing - if (TM.shouldAssumeDSOLocal(M, GV)) + if (TM.shouldAssumeDSOLocal(GV)) return M68kII::MO_NO_FLAG; // If the function is marked as non-lazy, generate an indirect call diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 68c80dd9aa5c..aef2d483c6df 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -4818,7 +4818,7 @@ static bool callsShareTOCBase(const Function *Caller, // If the callee is preemptable, then the static linker will use a plt-stub // which saves the toc to the stack, and needs a nop after the call // instruction to convert to a toc-restore. - if (!TM.shouldAssumeDSOLocal(*Caller->getParent(), CalleeGV)) + if (!TM.shouldAssumeDSOLocal(CalleeGV)) return false; // Functions with PC Relative enabled may clobber the TOC in the same DSO. @@ -5420,10 +5420,9 @@ static SDValue transformCallee(const SDValue &Callee, SelectionDAG &DAG, // Returns true if the callee is local, and false otherwise. auto isLocalCallee = [&]() { const GlobalAddressSDNode *G = dyn_cast(Callee); - const Module *Mod = DAG.getMachineFunction().getFunction().getParent(); const GlobalValue *GV = G ? G->getGlobal() : nullptr; - return DAG.getTarget().shouldAssumeDSOLocal(*Mod, GV) && + return DAG.getTarget().shouldAssumeDSOLocal(GV) && !isa_and_nonnull(GV); }; @@ -18045,7 +18044,7 @@ bool PPCTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const { return false; // If the function is local then we have a good chance at tail-calling it - return getTargetMachine().shouldAssumeDSOLocal(*Caller->getParent(), Callee); + return getTargetMachine().shouldAssumeDSOLocal(Callee); } bool PPCTargetLowering:: diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp index 2735bdee3bcf..5380ec1c4c0d 100644 --- a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp @@ -189,7 +189,7 @@ bool PPCSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const { // Large code model always uses the TOC even for local symbols. if (TM.getCodeModel() == CodeModel::Large) return true; - if (TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) + if (TM.shouldAssumeDSOLocal(GV)) return false; return true; } diff --git a/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp b/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp index 491bff7f3c30..d0badd3692e4 100644 --- a/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp +++ b/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp @@ -122,7 +122,7 @@ bool SystemZSubtarget::isPC32DBLSymbol(const GlobalValue *GV, // For the small model, all locally-binding symbols are in range. if (CM == CodeModel::Small) - return TLInfo.getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV); + return TLInfo.getTargetMachine().shouldAssumeDSOLocal(GV); // For Medium and above, assume that the symbol is not within the 4GB range. // Taking the address of locally-defined text would be OK, but that diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp index 4258a76b54b9..8b177a89c919 100644 --- a/llvm/lib/Target/TargetMachine.cpp +++ b/llvm/lib/Target/TargetMachine.cpp @@ -160,8 +160,7 @@ static TLSModel::Model getSelectedTLSModel(const GlobalValue *GV) { llvm_unreachable("invalid TLS model"); } -bool TargetMachine::shouldAssumeDSOLocal(const Module &M, - const GlobalValue *GV) const { +bool TargetMachine::shouldAssumeDSOLocal(const GlobalValue *GV) const { const Triple &TT = getTargetTriple(); Reloc::Model RM = getRelocationModel(); @@ -225,7 +224,7 @@ TLSModel::Model TargetMachine::getTLSModel(const GlobalValue *GV) const { bool IsPIE = GV->getParent()->getPIELevel() != PIELevel::Default; Reloc::Model RM = getRelocationModel(); bool IsSharedLibrary = RM == Reloc::PIC_ && !IsPIE; - bool IsLocal = shouldAssumeDSOLocal(*GV->getParent(), GV); + bool IsLocal = shouldAssumeDSOLocal(GV); TLSModel::Model Model; if (IsSharedLibrary) { diff --git a/llvm/lib/Target/VE/VEISelLowering.cpp b/llvm/lib/Target/VE/VEISelLowering.cpp index 0e41a2d7aa03..6e31c8b7c9a0 100644 --- a/llvm/lib/Target/VE/VEISelLowering.cpp +++ b/llvm/lib/Target/VE/VEISelLowering.cpp @@ -653,7 +653,7 @@ SDValue VETargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, auto *CalleeG = dyn_cast(Callee); if (CalleeG) GV = CalleeG->getGlobal(); - bool Local = TM.shouldAssumeDSOLocal(*Mod, GV); + bool Local = TM.shouldAssumeDSOLocal(GV); bool UsePlt = !Local; MachineFunction &MF = DAG.getMachineFunction(); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 7c47790d1e35..905ff3b90184 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -1683,7 +1683,7 @@ WebAssemblyTargetLowering::LowerGlobalTLSAddress(SDValue Op, if (model == GlobalValue::LocalExecTLSModel || model == GlobalValue::LocalDynamicTLSModel || (model == GlobalValue::GeneralDynamicTLSModel && - getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV))) { + getTargetMachine().shouldAssumeDSOLocal(GV))) { // For DSO-local TLS variables we use offset from __tls_base MVT PtrVT = getPointerTy(DAG.getDataLayout()); @@ -1729,7 +1729,7 @@ SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op, // need special treatment for tables in PIC mode. if (isPositionIndependent() && !WebAssembly::isWebAssemblyTableType(GV->getValueType())) { - if (getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV)) { + if (getTargetMachine().shouldAssumeDSOLocal(GV)) { MachineFunction &MF = DAG.getMachineFunction(); MVT PtrVT = getPointerTy(MF.getDataLayout()); const char *BaseName; diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp index 07f535685e8f..c2e6ddd7e7fa 100644 --- a/llvm/lib/Target/X86/X86Subtarget.cpp +++ b/llvm/lib/Target/X86/X86Subtarget.cpp @@ -140,7 +140,7 @@ unsigned char X86Subtarget::classifyGlobalReference(const GlobalValue *GV, } } - if (TM.shouldAssumeDSOLocal(M, GV)) + if (TM.shouldAssumeDSOLocal(GV)) return classifyLocalReference(GV); if (isTargetCOFF()) { @@ -190,7 +190,7 @@ X86Subtarget::classifyGlobalFunctionReference(const GlobalValue *GV) const { unsigned char X86Subtarget::classifyGlobalFunctionReference(const GlobalValue *GV, const Module &M) const { - if (TM.shouldAssumeDSOLocal(M, GV)) + if (TM.shouldAssumeDSOLocal(GV)) return X86II::MO_NO_FLAG; // Functions on COFF can be non-DSO local for three reasons: -- GitLab From 6462eadbd316aed1b1074ed73bcaf1698886bba1 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Mon, 11 Mar 2024 13:04:56 -0700 Subject: [PATCH 170/953] Report back errors in GetNumChildren() (#84265) This is a proof-of-concept patch that illustrates how to use the Expected return values to surface rich error messages all the way up to the ValueObjectPrinter. This is the final patch in the series that includes https://github.com/llvm/llvm-project/pull/83501 and https://github.com/llvm/llvm-project/pull/84219 --- .../lldb/DataFormatters/ValueObjectPrinter.h | 2 +- lldb/source/Core/ValueObjectVariable.cpp | 3 ++- .../DataFormatters/ValueObjectPrinter.cpp | 22 +++++++++++++++---- .../TypeSystem/Clang/TypeSystemClang.cpp | 9 +++++--- lldb/source/Symbol/CompilerType.cpp | 3 ++- .../functionalities/valobj_errors/Makefile | 9 ++++++++ .../valobj_errors/TestValueObjectErrors.py | 14 ++++++++++++ .../functionalities/valobj_errors/hidden.c | 4 ++++ .../API/functionalities/valobj_errors/main.c | 9 ++++++++ .../x86/DW_AT_declaration-with-children.s | 2 +- .../x86/debug-types-missing-signature.test | 2 +- 11 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 lldb/test/API/functionalities/valobj_errors/Makefile create mode 100644 lldb/test/API/functionalities/valobj_errors/TestValueObjectErrors.py create mode 100644 lldb/test/API/functionalities/valobj_errors/hidden.c create mode 100644 lldb/test/API/functionalities/valobj_errors/main.c diff --git a/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h b/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h index fe46321c3186..32b101a2f984 100644 --- a/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h +++ b/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h @@ -127,7 +127,7 @@ protected: void PrintChild(lldb::ValueObjectSP child_sp, const DumpValueObjectOptions::PointerDepth &curr_ptr_depth); - uint32_t GetMaxNumChildrenToPrint(bool &print_dotdotdot); + llvm::Expected GetMaxNumChildrenToPrint(bool &print_dotdotdot); void PrintChildren(bool value_printed, bool summary_printed, diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp index fb29c22c0ab5..67d71c90a959 100644 --- a/lldb/source/Core/ValueObjectVariable.cpp +++ b/lldb/source/Core/ValueObjectVariable.cpp @@ -99,7 +99,8 @@ ValueObjectVariable::CalculateNumChildren(uint32_t max) { CompilerType type(GetCompilerType()); if (!type.IsValid()) - return 0; + return llvm::make_error("invalid type", + llvm::inconvertibleErrorCode()); ExecutionContext exe_ctx(GetExecutionContextRef()); const bool omit_empty_base_classes = true; diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp index b853199e878c..bbdc2a998157 100644 --- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp +++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp @@ -621,13 +621,17 @@ void ValueObjectPrinter::PrintChild( } } -uint32_t ValueObjectPrinter::GetMaxNumChildrenToPrint(bool &print_dotdotdot) { +llvm::Expected +ValueObjectPrinter::GetMaxNumChildrenToPrint(bool &print_dotdotdot) { ValueObject &synth_valobj = GetValueObjectForChildrenGeneration(); if (m_options.m_pointer_as_array) return m_options.m_pointer_as_array.m_element_count; - uint32_t num_children = synth_valobj.GetNumChildrenIgnoringErrors(); + auto num_children_or_err = synth_valobj.GetNumChildren(); + if (!num_children_or_err) + return num_children_or_err; + uint32_t num_children = *num_children_or_err; print_dotdotdot = false; if (num_children) { const size_t max_num_children = GetMostSpecializedValue() @@ -704,7 +708,12 @@ void ValueObjectPrinter::PrintChildren( ValueObject &synth_valobj = GetValueObjectForChildrenGeneration(); bool print_dotdotdot = false; - size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); + auto num_children_or_err = GetMaxNumChildrenToPrint(print_dotdotdot); + if (!num_children_or_err) { + *m_stream << " <" << llvm::toString(num_children_or_err.takeError()) << '>'; + return; + } + uint32_t num_children = *num_children_or_err; if (num_children) { bool any_children_printed = false; @@ -753,7 +762,12 @@ bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) { ValueObject &synth_valobj = GetValueObjectForChildrenGeneration(); bool print_dotdotdot = false; - size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); + auto num_children_or_err = GetMaxNumChildrenToPrint(print_dotdotdot); + if (!num_children_or_err) { + *m_stream << '<' << llvm::toString(num_children_or_err.takeError()) << '>'; + return true; + } + uint32_t num_children = *num_children_or_err; if (num_children) { m_stream->PutChar('('); diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index c02b08cb4782..68d9165b90a4 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -5268,7 +5268,8 @@ TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type, bool omit_empty_base_classes, const ExecutionContext *exe_ctx) { if (!type) - return 0; + return llvm::make_error("invalid clang type", + llvm::inconvertibleErrorCode()); uint32_t num_children = 0; clang::QualType qual_type(RemoveWrappingTypes(GetQualType(type))); @@ -5325,9 +5326,11 @@ TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type, } num_children += std::distance(record_decl->field_begin(), record_decl->field_end()); - } + } else + return llvm::make_error( + "incomplete type \"" + GetDisplayTypeName(type).GetString() + "\"", + llvm::inconvertibleErrorCode()); break; - case clang::Type::ObjCObject: case clang::Type::ObjCInterface: if (GetCompleteQualType(&getASTContext(), qual_type)) { diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp index 85dd2d841a5a..8e4c3c761f78 100644 --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -777,7 +777,8 @@ CompilerType::GetNumChildren(bool omit_empty_base_classes, if (auto type_system_sp = GetTypeSystem()) return type_system_sp->GetNumChildren(m_type, omit_empty_base_classes, exe_ctx); - return 0; + return llvm::make_error("invalid type", + llvm::inconvertibleErrorCode()); } lldb::BasicType CompilerType::GetBasicTypeEnumeration() const { diff --git a/lldb/test/API/functionalities/valobj_errors/Makefile b/lldb/test/API/functionalities/valobj_errors/Makefile new file mode 100644 index 000000000000..d2c966a71411 --- /dev/null +++ b/lldb/test/API/functionalities/valobj_errors/Makefile @@ -0,0 +1,9 @@ +C_SOURCES := main.c +LD_EXTRAS = hidden.o + +a.out: hidden.o + +hidden.o: hidden.c + $(CC) -g0 -c -o $@ $< + +include Makefile.rules diff --git a/lldb/test/API/functionalities/valobj_errors/TestValueObjectErrors.py b/lldb/test/API/functionalities/valobj_errors/TestValueObjectErrors.py new file mode 100644 index 000000000000..8a114005c493 --- /dev/null +++ b/lldb/test/API/functionalities/valobj_errors/TestValueObjectErrors.py @@ -0,0 +1,14 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ValueObjectErrorsTestCase(TestBase): + def test(self): + """Test that the error message for a missing type + is visible when printing an object""" + self.build() + lldbutil.run_to_source_breakpoint(self, "break here", + lldb.SBFileSpec('main.c')) + self.expect('v -ptr-depth 1 x', substrs=['']) diff --git a/lldb/test/API/functionalities/valobj_errors/hidden.c b/lldb/test/API/functionalities/valobj_errors/hidden.c new file mode 100644 index 000000000000..d3b93ce1ab9c --- /dev/null +++ b/lldb/test/API/functionalities/valobj_errors/hidden.c @@ -0,0 +1,4 @@ +struct Opaque { + int i, j, k; +} *global; +struct Opaque *getOpaque() { return &global; } diff --git a/lldb/test/API/functionalities/valobj_errors/main.c b/lldb/test/API/functionalities/valobj_errors/main.c new file mode 100644 index 000000000000..fabdca9d3a2e --- /dev/null +++ b/lldb/test/API/functionalities/valobj_errors/main.c @@ -0,0 +1,9 @@ +struct Opaque; +struct Opaque *getOpaque(); +void puts(const char *); + +int main() { + struct Opaque *x = getOpaque(); + puts("break here\n"); + return (int)x; +} diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-with-children.s b/lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-with-children.s index bc462ca32e9c..8633d02f492e 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-with-children.s +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-with-children.s @@ -12,7 +12,7 @@ target var a # CHECK-LABEL: target var a # FIXME: This should also produce some kind of an error. -# CHECK: (A) a = {} +# CHECK: (A) a = expr a # CHECK-LABEL: expr a # CHECK: incomplete type 'A' where a complete type is required diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/debug-types-missing-signature.test b/lldb/test/Shell/SymbolFile/DWARF/x86/debug-types-missing-signature.test index e94b10a68d4e..548dd6cdbc27 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/x86/debug-types-missing-signature.test +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/debug-types-missing-signature.test @@ -21,6 +21,6 @@ RUN: not %lldb %t -b -o "expression (EC) 1" 2>&1 | FileCheck --check-prefix=PRIN PRINTEC: use of undeclared identifier 'EC' RUN: %lldb %t -b -o "target variable a e ec" | FileCheck --check-prefix=VARS %s -VARS: (const (unnamed struct)) a = {} +VARS: (const (unnamed struct)) a = VARS: (const (unnamed enum)) e = 0x1 VARS: (const (unnamed enum)) ec = 0x1 -- GitLab From 4628e33a7762384180a72cc9074a7ec49fbbdb95 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Mon, 11 Mar 2024 13:21:00 -0700 Subject: [PATCH 171/953] [NFC][docs] Rename duplicate label to something unique --- llvm/docs/LangRef.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index b70220dec926..77ec72f176d6 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -143,7 +143,7 @@ It also shows a convention that we follow in this document. When demonstrating instructions, we will follow an instruction with a comment that defines the type and name of value produced. -.. _strings: +.. _string_constants: String constants ---------------- -- GitLab From 4d21e75210d936d4f05e8aa9ea33beb552cd19b1 Mon Sep 17 00:00:00 2001 From: lntue <35648136+lntue@users.noreply.github.com> Date: Mon, 11 Mar 2024 16:27:42 -0400 Subject: [PATCH 172/953] [libc][math][c23] Add fmodl and fmodf128 math functions. (#84600) - Allow `FMod` template to have different computational types and make it work for 80-bit long double. - Switch to use `uint64_t` as the intermediate computational types for `float`, significantly reduce the latency of `fmodf` when the exponent difference is large. --- libc/config/linux/aarch64/entrypoints.txt | 2 + libc/config/linux/riscv/entrypoints.txt | 2 + libc/config/linux/x86_64/entrypoints.txt | 2 + libc/config/windows/entrypoints.txt | 1 + libc/docs/math/index.rst | 4 +- libc/spec/stdc.td | 3 +- libc/src/__support/FPUtil/FPBits.h | 17 ++- libc/src/__support/FPUtil/generic/FMod.h | 143 +++++++----------- libc/src/math/CMakeLists.txt | 2 + libc/src/math/fmodf128.h | 20 +++ libc/src/math/fmodl.h | 18 +++ libc/src/math/generic/CMakeLists.txt | 27 +++- libc/src/math/generic/fmodf.cpp | 2 +- libc/src/math/generic/fmodf128.cpp | 19 +++ libc/src/math/generic/fmodl.cpp | 19 +++ .../exhaustive/fmod_generic_impl_test.cpp | 9 +- .../BinaryOpSingleOutputPerf.h | 2 +- .../math/performance_testing/CMakeLists.txt | 22 +++ .../performance_testing/fmodf128_perf.cpp | 16 ++ .../math/performance_testing/fmodl_perf.cpp | 16 ++ libc/test/src/math/smoke/CMakeLists.txt | 36 +++++ libc/test/src/math/smoke/fmodf128_test.cpp | 13 ++ libc/test/src/math/smoke/fmodl_test.cpp | 13 ++ 23 files changed, 303 insertions(+), 105 deletions(-) create mode 100644 libc/src/math/fmodf128.h create mode 100644 libc/src/math/fmodl.h create mode 100644 libc/src/math/generic/fmodf128.cpp create mode 100644 libc/src/math/generic/fmodl.cpp create mode 100644 libc/test/src/math/performance_testing/fmodf128_perf.cpp create mode 100644 libc/test/src/math/performance_testing/fmodl_perf.cpp create mode 100644 libc/test/src/math/smoke/fmodf128_test.cpp create mode 100644 libc/test/src/math/smoke/fmodl_test.cpp diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index b447b5dfe098..1656973cb27c 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -335,6 +335,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fminl libc.src.math.fmod libc.src.math.fmodf + libc.src.math.fmodl libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl @@ -426,6 +427,7 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.floorf128 libc.src.math.fmaxf128 libc.src.math.fminf128 + libc.src.math.fmodf128 libc.src.math.frexpf128 libc.src.math.ilogbf128 libc.src.math.ldexpf128 diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 5175b14adf2e..07d1acfcfe07 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -343,6 +343,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fmaxl libc.src.math.fmod libc.src.math.fmodf + libc.src.math.fmodl libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl @@ -434,6 +435,7 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.floorf128 libc.src.math.fmaxf128 libc.src.math.fminf128 + libc.src.math.fmodf128 libc.src.math.frexpf128 libc.src.math.ilogbf128 libc.src.math.ldexpf128 diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index b8bec14a3d2a..e0324061a9c7 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -376,6 +376,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fmaxl libc.src.math.fmod libc.src.math.fmodf + libc.src.math.fmodl libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl @@ -469,6 +470,7 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.floorf128 libc.src.math.fmaxf128 libc.src.math.fminf128 + libc.src.math.fmodf128 libc.src.math.frexpf128 libc.src.math.ilogbf128 libc.src.math.ldexpf128 diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt index 1c9ed7bbcfed..d6227a427afe 100644 --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -155,6 +155,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fmaxl libc.src.math.fmod libc.src.math.fmodf + libc.src.math.fmodl libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst index b22ed5127c17..6984b785125f 100644 --- a/libc/docs/math/index.rst +++ b/libc/docs/math/index.rst @@ -169,7 +169,9 @@ Basic Operations +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | fmodf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fmodl | | | | | | | | | | | | | +| fmodl | |check| | |check| | | |check| | |check| | | | |check| | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fmodf128 | |check| | |check| | | |check| | | | | | | | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | frexp | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index d91f5c1f7233..1f14fe758130 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -405,8 +405,9 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"fmaf", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, FunctionSpec<"fmod", RetValSpec, [ArgSpec, ArgSpec]>, - FunctionSpec<"fmodf", RetValSpec, [ArgSpec, ArgSpec]>, + FunctionSpec<"fmodl", RetValSpec, [ArgSpec, ArgSpec]>, + GuardedFunctionSpec<"fmodf128", RetValSpec, [ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"frexp", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"frexpf", RetValSpec, [ArgSpec, ArgSpec]>, diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h index 7b3882dde1b7..b06b3f7b7395 100644 --- a/libc/src/__support/FPUtil/FPBits.h +++ b/libc/src/__support/FPUtil/FPBits.h @@ -640,6 +640,7 @@ public: using UP::EXP_MASK; using UP::FRACTION_MASK; using UP::SIG_LEN; + using UP::SIG_MASK; using UP::SIGN_MASK; LIBC_INLINE_VAR static constexpr int MAX_BIASED_EXPONENT = (1 << UP::EXP_LEN) - 1; @@ -729,6 +730,9 @@ public: bits = UP::merge(bits, mantVal, FRACTION_MASK); } + LIBC_INLINE constexpr void set_significand(StorageType sigVal) { + bits = UP::merge(bits, sigVal, SIG_MASK); + } // Unsafe function to create a floating point representation. // It simply packs the sign, biased exponent and mantissa values without // checking bound nor normalization. @@ -755,20 +759,19 @@ public: // 4) "number" zero value is not processed correctly. // 5) Number is unsigned, so the result can be only positive. LIBC_INLINE static constexpr RetT make_value(StorageType number, int ep) { - static_assert(fp_type != FPType::X86_Binary80, - "This function is not tested for X86 Extended Precision"); - FPRepImpl result; - // offset: +1 for sign, but -1 for implicit first bit - int lz = cpp::countl_zero(number) - UP::EXP_LEN; + FPRepImpl result(0); + int lz = + UP::FRACTION_LEN + 1 - (UP::STORAGE_LEN - cpp::countl_zero(number)); + number <<= lz; ep -= lz; if (LIBC_LIKELY(ep >= 0)) { // Implicit number bit will be removed by mask - result.set_mantissa(number); + result.set_significand(number); result.set_biased_exponent(ep + 1); } else { - result.set_mantissa(number >> -ep); + result.set_significand(number >> -ep); } return RetT(result.uintval()); } diff --git a/libc/src/__support/FPUtil/generic/FMod.h b/libc/src/__support/FPUtil/generic/FMod.h index 2d31290bc4bc..24fb264b779b 100644 --- a/libc/src/__support/FPUtil/generic/FMod.h +++ b/libc/src/__support/FPUtil/generic/FMod.h @@ -117,63 +117,9 @@ namespace generic { // be implemented in another handler. // Signaling NaN converted to quiet NaN with FE_INVALID exception. // https://www.open-std.org/JTC1/SC22/WG14/www/docs/n1011.htm -template struct FModExceptionalInputHandler { - - static_assert(cpp::is_floating_point_v, - "FModCStandardWrapper instantiated with invalid type."); - - LIBC_INLINE static bool pre_check(T x, T y, T &out) { - using FPB = fputil::FPBits; - const T quiet_nan = FPB::quiet_nan().get_val(); - FPB sx(x), sy(y); - if (LIBC_LIKELY(!sy.is_zero() && !sy.is_inf_or_nan() && - !sx.is_inf_or_nan())) { - return false; - } - - if (sx.is_nan() || sy.is_nan()) { - if ((sx.is_nan() && !sx.is_quiet_nan()) || - (sy.is_nan() && !sy.is_quiet_nan())) - fputil::raise_except_if_required(FE_INVALID); - out = quiet_nan; - return true; - } - - if (sx.is_inf() || sy.is_zero()) { - fputil::raise_except_if_required(FE_INVALID); - fputil::set_errno_if_required(EDOM); - out = quiet_nan; - return true; - } - - if (sy.is_inf()) { - out = x; - return true; - } - - // case where x == 0 - out = x; - return true; - } -}; - -template struct FModFastMathWrapper { - - static_assert(cpp::is_floating_point_v, - "FModFastMathWrapper instantiated with invalid type."); - - static bool pre_check(T, T, T &) { return false; } -}; - -template class FModDivisionSimpleHelper { -private: - using StorageType = typename FPBits::StorageType; - -public: - LIBC_INLINE constexpr static StorageType execute(int exp_diff, - int sides_zeroes_count, - StorageType m_x, - StorageType m_y) { +template struct FModDivisionSimpleHelper { + LIBC_INLINE constexpr static T execute(int exp_diff, int sides_zeroes_count, + T m_x, T m_y) { while (exp_diff > sides_zeroes_count) { exp_diff -= sides_zeroes_count; m_x <<= sides_zeroes_count; @@ -185,28 +131,21 @@ public: } }; -template class FModDivisionInvMultHelper { -private: - using FPB = FPBits; - using StorageType = typename FPB::StorageType; - -public: - LIBC_INLINE constexpr static StorageType execute(int exp_diff, - int sides_zeroes_count, - StorageType m_x, - StorageType m_y) { +template struct FModDivisionInvMultHelper { + LIBC_INLINE constexpr static T execute(int exp_diff, int sides_zeroes_count, + T m_x, T m_y) { + constexpr int LENGTH = sizeof(T) * CHAR_BIT; if (exp_diff > sides_zeroes_count) { - StorageType inv_hy = (cpp::numeric_limits::max() / m_y); + T inv_hy = (cpp::numeric_limits::max() / m_y); while (exp_diff > sides_zeroes_count) { exp_diff -= sides_zeroes_count; - StorageType hd = - (m_x * inv_hy) >> (FPB::TOTAL_LEN - sides_zeroes_count); + T hd = (m_x * inv_hy) >> (LENGTH - sides_zeroes_count); m_x <<= sides_zeroes_count; m_x -= hd * m_y; while (LIBC_UNLIKELY(m_x > m_y)) m_x -= m_y; } - StorageType hd = (m_x * inv_hy) >> (FPB::TOTAL_LEN - exp_diff); + T hd = (m_x * inv_hy) >> (LENGTH - exp_diff); m_x <<= exp_diff; m_x -= hd * m_y; while (LIBC_UNLIKELY(m_x > m_y)) @@ -219,22 +158,49 @@ public: } }; -template , - class DivisionHelper = FModDivisionSimpleHelper> +template ::StorageType, + typename DivisionHelper = FModDivisionSimpleHelper> class FMod { - static_assert(cpp::is_floating_point_v, + static_assert(cpp::is_floating_point_v && cpp::is_unsigned_v && + (sizeof(U) * CHAR_BIT > FPBits::FRACTION_LEN), "FMod instantiated with invalid type."); private: using FPB = FPBits; using StorageType = typename FPB::StorageType; + LIBC_INLINE static bool pre_check(T x, T y, T &out) { + using FPB = fputil::FPBits; + const T quiet_nan = FPB::quiet_nan().get_val(); + FPB sx(x), sy(y); + if (LIBC_LIKELY(!sy.is_zero() && !sy.is_inf_or_nan() && + !sx.is_inf_or_nan())) + return false; + + if (sx.is_nan() || sy.is_nan()) { + if (sx.is_signaling_nan() || sy.is_signaling_nan()) + fputil::raise_except_if_required(FE_INVALID); + out = quiet_nan; + return true; + } + + if (sx.is_inf() || sy.is_zero()) { + fputil::raise_except_if_required(FE_INVALID); + fputil::set_errno_if_required(EDOM); + out = quiet_nan; + return true; + } + + out = x; + return true; + } + LIBC_INLINE static constexpr FPB eval_internal(FPB sx, FPB sy) { if (LIBC_LIKELY(sx.uintval() <= sy.uintval())) { if (sx.uintval() < sy.uintval()) return sx; // |x|<|y| return x - return FPB(FPB::zero()); // |x|=|y| return 0.0 + return FPB::zero(); // |x|=|y| return 0.0 } int e_x = sx.get_biased_exponent(); @@ -247,11 +213,11 @@ private: StorageType m_y = sy.get_explicit_mantissa(); StorageType d = (e_x == e_y) ? (m_x - m_y) : (m_x << (e_x - e_y)) % m_y; if (d == 0) - return FPB(FPB::zero()); + return FPB::zero(); // iy - 1 because of "zero power" for number with power 1 return FPB::make_value(d, e_y - 1); } - /* Both subnormal special case. */ + // Both subnormal special case. if (LIBC_UNLIKELY(e_x == 0 && e_y == 0)) { FPB d; d.set_mantissa(sx.uintval() % sy.uintval()); @@ -259,15 +225,17 @@ private: } // Note that hx is not subnormal by conditions above. - StorageType m_x = sx.get_explicit_mantissa(); + U m_x = static_cast(sx.get_explicit_mantissa()); e_x--; - StorageType m_y = sy.get_explicit_mantissa(); - int lead_zeros_m_y = FPB::EXP_LEN; + U m_y = static_cast(sy.get_explicit_mantissa()); + constexpr int DEFAULT_LEAD_ZEROS = + sizeof(U) * CHAR_BIT - FPB::FRACTION_LEN - 1; + int lead_zeros_m_y = DEFAULT_LEAD_ZEROS; if (LIBC_LIKELY(e_y > 0)) { e_y--; } else { - m_y = sy.get_mantissa(); + m_y = static_cast(sy.get_mantissa()); lead_zeros_m_y = cpp::countl_zero(m_y); } @@ -286,26 +254,27 @@ private: { // Shift hx left until the end or n = 0 - int left_shift = exp_diff < int(FPB::EXP_LEN) ? exp_diff : FPB::EXP_LEN; + int left_shift = + exp_diff < DEFAULT_LEAD_ZEROS ? exp_diff : DEFAULT_LEAD_ZEROS; m_x <<= left_shift; exp_diff -= left_shift; } m_x %= m_y; if (LIBC_UNLIKELY(m_x == 0)) - return FPB(FPB::zero()); + return FPB::zero(); if (exp_diff == 0) - return FPB::make_value(m_x, e_y); + return FPB::make_value(static_cast(m_x), e_y); - /* hx next can't be 0, because hx < hy, hy % 2 == 1 hx * 2^i % hy != 0 */ + // hx next can't be 0, because hx < hy, hy % 2 == 1 hx * 2^i % hy != 0 m_x = DivisionHelper::execute(exp_diff, sides_zeroes_count, m_x, m_y); - return FPB::make_value(m_x, e_y); + return FPB::make_value(static_cast(m_x), e_y); } public: LIBC_INLINE static T eval(T x, T y) { - if (T out; Wrapper::pre_check(x, y, out)) + if (T out; LIBC_UNLIKELY(pre_check(x, y, out))) return out; FPB sx(x), sy(y); Sign sign = sx.sign(); diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index 6c06d383ec2b..bba02aa78a23 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -119,6 +119,8 @@ add_math_entrypoint_object(fminf128) add_math_entrypoint_object(fmod) add_math_entrypoint_object(fmodf) +add_math_entrypoint_object(fmodl) +add_math_entrypoint_object(fmodf128) add_math_entrypoint_object(frexp) add_math_entrypoint_object(frexpf) diff --git a/libc/src/math/fmodf128.h b/libc/src/math/fmodf128.h new file mode 100644 index 000000000000..b3242705f025 --- /dev/null +++ b/libc/src/math/fmodf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for fmodf128 ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_MATH_FMODF128_H +#define LLVM_LIBC_SRC_MATH_FMODF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 fmodf128(float128 x, float128 y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMODF128_H diff --git a/libc/src/math/fmodl.h b/libc/src/math/fmodl.h new file mode 100644 index 000000000000..f259ddb238a8 --- /dev/null +++ b/libc/src/math/fmodl.h @@ -0,0 +1,18 @@ +//===-- Implementation header for fmodl -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_MATH_FMODL_H +#define LLVM_LIBC_SRC_MATH_FMODL_H + +namespace LIBC_NAMESPACE { + +long double fmodl(long double x, long double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMODL_H diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 933a05dad157..bc4e9b34cfc2 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -1859,7 +1859,6 @@ add_entrypoint_object( HDRS ../fmod.h DEPENDS - libc.include.math libc.src.__support.FPUtil.generic.fmod COMPILE_OPTIONS -O3 @@ -1872,7 +1871,31 @@ add_entrypoint_object( HDRS ../fmodf.h DEPENDS - libc.include.math + libc.src.__support.FPUtil.generic.fmod + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fmodl + SRCS + fmodl.cpp + HDRS + ../fmodl.h + DEPENDS + libc.src.__support.FPUtil.generic.fmod + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fmodf128 + SRCS + fmodf128.cpp + HDRS + ../fmodf128.h + DEPENDS + libc.src.__support.macros.properties.types libc.src.__support.FPUtil.generic.fmod COMPILE_OPTIONS -O3 diff --git a/libc/src/math/generic/fmodf.cpp b/libc/src/math/generic/fmodf.cpp index 7a29ff1f18d3..9a9e46e29b46 100644 --- a/libc/src/math/generic/fmodf.cpp +++ b/libc/src/math/generic/fmodf.cpp @@ -13,7 +13,7 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(float, fmodf, (float x, float y)) { - return fputil::generic::FMod::eval(x, y); + return fputil::generic::FMod::eval(x, y); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmodf128.cpp b/libc/src/math/generic/fmodf128.cpp new file mode 100644 index 000000000000..08a379702d88 --- /dev/null +++ b/libc/src/math/generic/fmodf128.cpp @@ -0,0 +1,19 @@ +//===-- Single-precision fmodf128 function --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/math/fmodf128.h" +#include "src/__support/FPUtil/generic/FMod.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, fmodf128, (float128 x, float128 y)) { + return fputil::generic::FMod::eval(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmodl.cpp b/libc/src/math/generic/fmodl.cpp new file mode 100644 index 000000000000..23a370289055 --- /dev/null +++ b/libc/src/math/generic/fmodl.cpp @@ -0,0 +1,19 @@ +//===-- Single-precision fmodl function -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/math/fmodl.h" +#include "src/__support/FPUtil/generic/FMod.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, fmodl, (long double x, long double y)) { + return fputil::generic::FMod::eval(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/test/src/math/exhaustive/fmod_generic_impl_test.cpp b/libc/test/src/math/exhaustive/fmod_generic_impl_test.cpp index b47d24c54869..25a5e3898599 100644 --- a/libc/test/src/math/exhaustive/fmod_generic_impl_test.cpp +++ b/libc/test/src/math/exhaustive/fmod_generic_impl_test.cpp @@ -19,10 +19,11 @@ namespace mpfr = LIBC_NAMESPACE::testing::mpfr; template class LlvmLibcFModTest : public LIBC_NAMESPACE::testing::Test { + using U = typename LIBC_NAMESPACE::fputil::FPBits::StorageType; using DivisionHelper = LIBC_NAMESPACE::cpp::conditional_t< InverseMultiplication, - LIBC_NAMESPACE::fputil::generic::FModDivisionInvMultHelper, - LIBC_NAMESPACE::fputil::generic::FModDivisionSimpleHelper>; + LIBC_NAMESPACE::fputil::generic::FModDivisionInvMultHelper, + LIBC_NAMESPACE::fputil::generic::FModDivisionSimpleHelper>; static constexpr std::array test_bases = { T(0.0), @@ -39,9 +40,7 @@ class LlvmLibcFModTest : public LIBC_NAMESPACE::testing::Test { public: void testExtensive() { - using FMod = LIBC_NAMESPACE::fputil::generic::FMod< - T, LIBC_NAMESPACE::fputil::generic::FModFastMathWrapper, - DivisionHelper>; + using FMod = LIBC_NAMESPACE::fputil::generic::FMod; using nl = std::numeric_limits; int min2 = nl::min_exponent - nl::digits - 5; int max2 = nl::max_exponent + 3; diff --git a/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h b/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h index 68d37b46b77c..504d1be94b89 100644 --- a/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h +++ b/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h @@ -86,7 +86,7 @@ public: "close to each other:\n"; run_perf_in_range( myFunc, otherFunc, /* startingBit= */ FPBits(T(0x1.0p-10)).uintval(), - /* endingBit= */ FPBits(T(0x1.0p+10)).uintval(), 10'000'001, log); + /* endingBit= */ FPBits(T(0x1.0p+10)).uintval(), 1'001'001, log); } static void run_diff(Func myFunc, Func otherFunc, const char *logFile) { diff --git a/libc/test/src/math/performance_testing/CMakeLists.txt b/libc/test/src/math/performance_testing/CMakeLists.txt index d20c2eb303a7..d1fb24e37f72 100644 --- a/libc/test/src/math/performance_testing/CMakeLists.txt +++ b/libc/test/src/math/performance_testing/CMakeLists.txt @@ -331,3 +331,25 @@ add_perf_binary( COMPILE_OPTIONS -fno-builtin ) + +add_perf_binary( + fmodl_perf + SRCS + fmodl_perf.cpp + DEPENDS + .single_input_single_output_diff + libc.src.math.fmodl + COMPILE_OPTIONS + -fno-builtin +) + +add_perf_binary( + fmodf128_perf + SRCS + fmodf128_perf.cpp + DEPENDS + .single_input_single_output_diff + libc.src.math.fmodf128 + COMPILE_OPTIONS + -fno-builtin +) diff --git a/libc/test/src/math/performance_testing/fmodf128_perf.cpp b/libc/test/src/math/performance_testing/fmodf128_perf.cpp new file mode 100644 index 000000000000..8165e9254dd5 --- /dev/null +++ b/libc/test/src/math/performance_testing/fmodf128_perf.cpp @@ -0,0 +1,16 @@ +//===-- Differential test for fmodf128 ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "BinaryOpSingleOutputDiff.h" + +#include "src/math/fmodf128.h" + +#include + +BINARY_OP_SINGLE_OUTPUT_PERF(float, LIBC_NAMESPACE::fmodf128, ::fmodf128, + "fmodf128_perf.log") diff --git a/libc/test/src/math/performance_testing/fmodl_perf.cpp b/libc/test/src/math/performance_testing/fmodl_perf.cpp new file mode 100644 index 000000000000..aefdf2d6b42f --- /dev/null +++ b/libc/test/src/math/performance_testing/fmodl_perf.cpp @@ -0,0 +1,16 @@ +//===-- Differential test for fmodl ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "BinaryOpSingleOutputDiff.h" + +#include "src/math/fmodl.h" + +#include + +BINARY_OP_SINGLE_OUTPUT_PERF(long double, LIBC_NAMESPACE::fmodl, ::fmodl, + "fmodl_perf.log") diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index 8d3871dd427a..d9be172056a8 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -1793,6 +1793,42 @@ add_fp_unittest( UNIT_TEST_ONLY ) +add_fp_unittest( + fmodl_test + SUITE + libc-math-smoke-tests + SRCS + fmodl_test.cpp + HDRS + FModTest.h + DEPENDS + libc.include.math + libc.src.errno.errno + libc.src.math.fmodl + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.nearest_integer_operations + # FIXME: Currently fails on the GPU build. + UNIT_TEST_ONLY +) + +add_fp_unittest( + fmodf128_test + SUITE + libc-math-smoke-tests + SRCS + fmodf128_test.cpp + HDRS + FModTest.h + DEPENDS + libc.include.math + libc.src.errno.errno + libc.src.math.fmodf128 + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.nearest_integer_operations + # FIXME: Currently fails on the GPU build. + UNIT_TEST_ONLY +) + add_fp_unittest( coshf_test SUITE diff --git a/libc/test/src/math/smoke/fmodf128_test.cpp b/libc/test/src/math/smoke/fmodf128_test.cpp new file mode 100644 index 000000000000..f75aadac8438 --- /dev/null +++ b/libc/test/src/math/smoke/fmodf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmodf128 --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "FModTest.h" + +#include "src/math/fmodf128.h" + +LIST_FMOD_TESTS(float128, LIBC_NAMESPACE::fmodf128) diff --git a/libc/test/src/math/smoke/fmodl_test.cpp b/libc/test/src/math/smoke/fmodl_test.cpp new file mode 100644 index 000000000000..b69ed8ec85c8 --- /dev/null +++ b/libc/test/src/math/smoke/fmodl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmodl -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "FModTest.h" + +#include "src/math/fmodl.h" + +LIST_FMOD_TESTS(long double, LIBC_NAMESPACE::fmodl) -- GitLab From f4c1e8747b33815969e60a53cab3dac4d0f55f6c Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Mon, 11 Mar 2024 16:28:05 -0400 Subject: [PATCH 173/953] [libc++][hardening] Reclassify string_view(ptr, len)'s size assertion (#79297) The comment makes this error condition sound less problematic than it is. If the length does not match the pointer's bounds, all bounds-checking in string_view goes wrong. A length over PTRDIFF_MAX cannot possibly be a correct bounds and was mostly an underflowed negative number cast to a size_t. The documentation for _LIBCPP_ASSERT_VALID_INPUT_RANGE discusses ranges being valid, including an iterator and a count, which seemed appropriate here. --- libcxx/include/string_view | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libcxx/include/string_view b/libcxx/include/string_view index e0dd5c5b19ac..e8584a69c1e1 100644 --- a/libcxx/include/string_view +++ b/libcxx/include/string_view @@ -310,9 +310,10 @@ public: : __data_(__s), __size_(__len) { #if _LIBCPP_STD_VER >= 14 - // This will result in creating an invalid `string_view` object -- some calculations involving `size` would - // overflow, making it effectively truncated. - _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + // Allocations must fit in `ptrdiff_t` for pointer arithmetic to work. If `__len` exceeds it, the input + // range could not have been valid. Most likely the caller underflowed some arithmetic and inadvertently + // passed in a negative length. + _LIBCPP_ASSERT_VALID_INPUT_RANGE( __len <= static_cast(numeric_limits::max()), "string_view::string_view(_CharT *, size_t): length does not fit in difference_type"); _LIBCPP_ASSERT_NON_NULL( -- GitLab From f832beebda6d31fef01a8cb680b82df33c666eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?= =?UTF-8?q?=E3=83=B3=29?= Date: Mon, 11 Mar 2024 13:41:27 -0700 Subject: [PATCH 174/953] [flang][NFC] Use the tablegen definition for FIR dialect (#84822) FIROpsDialect has been declared manually with a class inheriting from the MLIR Dialect class. Another declaration is done using tablegen here `flang/include/flang/Optimizer/Dialect/FIRDialect.td`. This patch merge the two declaration so we can use the tablegen generated class for all the FIROpsDialect needs. This is part of a series of patch to bring FIR up to date with the current MLIR infra. --- .../flang/Optimizer/Dialect/CMakeLists.txt | 4 +++ .../flang/Optimizer/Dialect/FIRAttr.td | 6 ++-- .../flang/Optimizer/Dialect/FIRDialect.h | 33 ++----------------- .../flang/Optimizer/Dialect/FIRDialect.td | 29 ++++++++++++++-- .../include/flang/Optimizer/Dialect/FIROps.td | 2 +- .../flang/Optimizer/Dialect/FIRTypes.td | 2 +- flang/lib/Optimizer/Dialect/FIRDialect.cpp | 11 ++----- 7 files changed, 40 insertions(+), 47 deletions(-) diff --git a/flang/include/flang/Optimizer/Dialect/CMakeLists.txt b/flang/include/flang/Optimizer/Dialect/CMakeLists.txt index fe9864a26295..f00993d4d377 100644 --- a/flang/include/flang/Optimizer/Dialect/CMakeLists.txt +++ b/flang/include/flang/Optimizer/Dialect/CMakeLists.txt @@ -1,6 +1,10 @@ # This replicates part of the add_mlir_dialect cmake function from MLIR that # cannot be used her because it expects to be run inside MLIR directory which # is not the case for FIR. +set(LLVM_TARGET_DEFINITIONS FIRDialect.td) +mlir_tablegen(FIRDialect.h.inc -gen-dialect-decls -dialect=fir) +mlir_tablegen(FIRDialect.cpp.inc -gen-dialect-defs -dialect=fir) + set(LLVM_TARGET_DEFINITIONS FIRAttr.td) mlir_tablegen(FIREnumAttr.h.inc -gen-enum-decls) mlir_tablegen(FIREnumAttr.cpp.inc -gen-enum-defs) diff --git a/flang/include/flang/Optimizer/Dialect/FIRAttr.td b/flang/include/flang/Optimizer/Dialect/FIRAttr.td index 66d6cd471116..2ac4af9e66aa 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRAttr.td +++ b/flang/include/flang/Optimizer/Dialect/FIRAttr.td @@ -16,7 +16,7 @@ include "flang/Optimizer/Dialect/FIRDialect.td" include "mlir/IR/EnumAttr.td" -class fir_Attr : AttrDef; +class fir_Attr : AttrDef; def FIRnoAttributes : I32BitEnumAttrCaseNone<"None">; def FIRallocatable : I32BitEnumAttrCaseBit<"allocatable", 0>; @@ -91,7 +91,7 @@ def fir_CUDADataAttribute : I32EnumAttr< } def fir_CUDADataAttributeAttr : - EnumAttr { + EnumAttr { let assemblyFormat = [{ ```<` $value `>` }]; } @@ -109,7 +109,7 @@ def fir_CUDAProcAttribute : I32EnumAttr< } def fir_CUDAProcAttributeAttr : - EnumAttr { + EnumAttr { let assemblyFormat = [{ ```<` $value `>` }]; } diff --git a/flang/include/flang/Optimizer/Dialect/FIRDialect.h b/flang/include/flang/Optimizer/Dialect/FIRDialect.h index 238385505dbf..ed7c98ec82e2 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRDialect.h +++ b/flang/include/flang/Optimizer/Dialect/FIRDialect.h @@ -15,43 +15,14 @@ #include "mlir/IR/Dialect.h" +#include "flang/Optimizer/Dialect/FIRDialect.h.inc" + namespace mlir { class IRMapping; } // namespace mlir namespace fir { -/// FIR dialect -class FIROpsDialect final : public mlir::Dialect { -public: - explicit FIROpsDialect(mlir::MLIRContext *ctx); - virtual ~FIROpsDialect(); - - static llvm::StringRef getDialectNamespace() { return "fir"; } - - mlir::Type parseType(mlir::DialectAsmParser &parser) const override; - void printType(mlir::Type ty, mlir::DialectAsmPrinter &p) const override; - - mlir::Attribute parseAttribute(mlir::DialectAsmParser &parser, - mlir::Type type) const override; - void printAttribute(mlir::Attribute attr, - mlir::DialectAsmPrinter &p) const override; - - /// Return string name of fir.runtime attribute. - static constexpr llvm::StringRef getFirRuntimeAttrName() { - return "fir.runtime"; - } - -private: - // Register the Attributes of this dialect. - void registerAttributes(); - // Register the Types of this dialect. - void registerTypes(); - // Register external interfaces on operations of - // this dialect. - void registerOpExternalInterfaces(); -}; - /// The FIR codegen dialect is a dialect containing a small set of transient /// operations used exclusively during code generation. class FIRCodeGenDialect final : public mlir::Dialect { diff --git a/flang/include/flang/Optimizer/Dialect/FIRDialect.td b/flang/include/flang/Optimizer/Dialect/FIRDialect.td index b366b6d40e4e..0dfb3eda585c 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRDialect.td +++ b/flang/include/flang/Optimizer/Dialect/FIRDialect.td @@ -21,7 +21,7 @@ include "mlir/Interfaces/InferTypeOpInterface.td" include "mlir/Interfaces/LoopLikeInterface.td" include "mlir/Interfaces/SideEffectInterfaces.td" -def fir_Dialect : Dialect { +def FIROpsDialect : Dialect { let name = "fir"; let cppNamespace = "::fir"; let useDefaultTypePrinterParser = 0; @@ -30,10 +30,33 @@ def fir_Dialect : Dialect { let dependentDialects = [ // Arith dialect provides FastMathFlagsAttr // supported by some FIR operations. - "arith::ArithDialect", + "mlir::arith::ArithDialect", // TBAA Tag types - "LLVM::LLVMDialect" + "mlir::LLVM::LLVMDialect" ]; + let extraClassDeclaration = [{ + private: + // Register the builtin Attributes. + void registerAttributes(); + // Register the builtin Types. + void registerTypes(); + // Register external interfaces on operations of + // this dialect. + void registerOpExternalInterfaces(); + public: + mlir::Type parseType(mlir::DialectAsmParser &parser) const override; + void printType(mlir::Type ty, mlir::DialectAsmPrinter &p) const override; + + mlir::Attribute parseAttribute(mlir::DialectAsmParser &parser, + mlir::Type type) const override; + void printAttribute(mlir::Attribute attr, + mlir::DialectAsmPrinter &p) const override; + + // Return string name of fir.runtime attribute. + static constexpr llvm::StringRef getFirRuntimeAttrName() { + return "fir.runtime"; + } + }]; } #endif // FORTRAN_DIALECT_FIR_DIALECT diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td index db5e5f4bc682..65a86d25333b 100644 --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -27,7 +27,7 @@ include "mlir/IR/BuiltinAttributes.td" // Base class for FIR operations. // All operations automatically get a prefix of "fir.". class fir_Op traits> - : Op; + : Op; // Base class for FIR operations that take a single argument class fir_SimpleOp traits> diff --git a/flang/include/flang/Optimizer/Dialect/FIRTypes.td b/flang/include/flang/Optimizer/Dialect/FIRTypes.td index 2a2f50720859..4c6a8064991a 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRTypes.td +++ b/flang/include/flang/Optimizer/Dialect/FIRTypes.td @@ -22,7 +22,7 @@ include "flang/Optimizer/Dialect/FIRDialect.td" class FIR_Type traits = [], string baseCppClass = "::mlir::Type"> - : TypeDef { + : TypeDef { let mnemonic = typeMnemonic; } diff --git a/flang/lib/Optimizer/Dialect/FIRDialect.cpp b/flang/lib/Optimizer/Dialect/FIRDialect.cpp index 850b6120b2a0..4d1e8cd1405a 100644 --- a/flang/lib/Optimizer/Dialect/FIRDialect.cpp +++ b/flang/lib/Optimizer/Dialect/FIRDialect.cpp @@ -18,6 +18,8 @@ #include "mlir/Target/LLVMIR/ModuleTranslation.h" #include "mlir/Transforms/InliningUtils.h" +#include "flang/Optimizer/Dialect/FIRDialect.cpp.inc" + using namespace fir; namespace { @@ -58,9 +60,7 @@ struct FIRInlinerInterface : public mlir::DialectInlinerInterface { }; } // namespace -fir::FIROpsDialect::FIROpsDialect(mlir::MLIRContext *ctx) - : mlir::Dialect("fir", ctx, mlir::TypeID::get()) { - getContext()->loadDialect(); +void fir::FIROpsDialect::initialize() { registerTypes(); registerAttributes(); addOperations< @@ -94,11 +94,6 @@ void fir::addFIRToLLVMIRExtension(mlir::DialectRegistry ®istry) { }); } -// anchor the class vtable to this compilation unit -fir::FIROpsDialect::~FIROpsDialect() { - // do nothing -} - mlir::Type fir::FIROpsDialect::parseType(mlir::DialectAsmParser &parser) const { return parseFirType(const_cast(this), parser); } -- GitLab From f19d9e1617292a95b665171574630b8674d3ae1e Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Thu, 7 Mar 2024 11:28:28 -0600 Subject: [PATCH 175/953] [KnownBits] Add test for computing more information for `lshr`/`ashr` with `exact` flag; NFC --- .../Analysis/ValueTracking/knownbits-shift.ll | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 llvm/test/Analysis/ValueTracking/knownbits-shift.ll diff --git a/llvm/test/Analysis/ValueTracking/knownbits-shift.ll b/llvm/test/Analysis/ValueTracking/knownbits-shift.ll new file mode 100644 index 000000000000..3235f69b5221 --- /dev/null +++ b/llvm/test/Analysis/ValueTracking/knownbits-shift.ll @@ -0,0 +1,24 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes=instcombine -S < %s | FileCheck %s + +define i8 @simplify_lshr_with_exact(i8 %x) { +; CHECK-LABEL: @simplify_lshr_with_exact( +; CHECK-NEXT: [[SHR:%.*]] = lshr exact i8 6, [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = and i8 [[SHR]], 2 +; CHECK-NEXT: ret i8 [[R]] +; + %shr = lshr exact i8 6, %x + %r = and i8 %shr, 2 + ret i8 %r +} + +define i8 @simplify_ashr_with_exact(i8 %x) { +; CHECK-LABEL: @simplify_ashr_with_exact( +; CHECK-NEXT: [[SHR:%.*]] = ashr exact i8 -122, [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = and i8 [[SHR]], 2 +; CHECK-NEXT: ret i8 [[R]] +; + %shr = ashr exact i8 -122, %x + %r = and i8 %shr, 2 + ret i8 %r +} -- GitLab From a9d913ebcd567ad14ffdc8c8684c4f0611e1e2da Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Tue, 5 Mar 2024 21:56:27 -0600 Subject: [PATCH 176/953] [KnownBits] Add API support for `exact` in `lshr`/`ashr`; NFC --- llvm/include/llvm/Support/KnownBits.h | 4 ++-- llvm/lib/Analysis/ValueTracking.cpp | 14 ++++++++------ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 6 ++++-- llvm/lib/Support/KnownBits.cpp | 4 ++-- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h index 46dbf0c2baa5..06d2c90f7b0f 100644 --- a/llvm/include/llvm/Support/KnownBits.h +++ b/llvm/include/llvm/Support/KnownBits.h @@ -402,12 +402,12 @@ public: /// Compute known bits for lshr(LHS, RHS). /// NOTE: RHS (shift amount) bitwidth doesn't need to be the same as LHS. static KnownBits lshr(const KnownBits &LHS, const KnownBits &RHS, - bool ShAmtNonZero = false); + bool ShAmtNonZero = false, bool Exact = false); /// Compute known bits for ashr(LHS, RHS). /// NOTE: RHS (shift amount) bitwidth doesn't need to be the same as LHS. static KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS, - bool ShAmtNonZero = false); + bool ShAmtNonZero = false, bool Exact = false); /// Determine if these known bits always give the same ICMP_EQ result. static std::optional eq(const KnownBits &LHS, const KnownBits &RHS); diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 6d0e79e11eed..d7f60d85b452 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1142,9 +1142,10 @@ static void computeKnownBitsFromOperator(const Operator *I, break; } case Instruction::LShr: { - auto KF = [](const KnownBits &KnownVal, const KnownBits &KnownAmt, - bool ShAmtNonZero) { - return KnownBits::lshr(KnownVal, KnownAmt, ShAmtNonZero); + bool Exact = Q.IIQ.isExact(cast(I)); + auto KF = [Exact](const KnownBits &KnownVal, const KnownBits &KnownAmt, + bool ShAmtNonZero) { + return KnownBits::lshr(KnownVal, KnownAmt, ShAmtNonZero, Exact); }; computeKnownBitsFromShiftOperator(I, DemandedElts, Known, Known2, Depth, Q, KF); @@ -1155,9 +1156,10 @@ static void computeKnownBitsFromOperator(const Operator *I, break; } case Instruction::AShr: { - auto KF = [](const KnownBits &KnownVal, const KnownBits &KnownAmt, - bool ShAmtNonZero) { - return KnownBits::ashr(KnownVal, KnownAmt, ShAmtNonZero); + bool Exact = Q.IIQ.isExact(cast(I)); + auto KF = [Exact](const KnownBits &KnownVal, const KnownBits &KnownAmt, + bool ShAmtNonZero) { + return KnownBits::ashr(KnownVal, KnownAmt, ShAmtNonZero, Exact); }; computeKnownBitsFromShiftOperator(I, DemandedElts, Known, Known2, Depth, Q, KF); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 06fe716a22db..7a0c1c328df1 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -3485,7 +3485,8 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts, case ISD::SRL: Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); - Known = KnownBits::lshr(Known, Known2); + Known = KnownBits::lshr(Known, Known2, /*ShAmtNonZero=*/false, + Op->getFlags().hasExact()); // Minimum shift high bits are known zero. if (const APInt *ShMinAmt = @@ -3495,7 +3496,8 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts, case ISD::SRA: Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); - Known = KnownBits::ashr(Known, Known2); + Known = KnownBits::ashr(Known, Known2, /*ShAmtNonZero=*/false, + Op->getFlags().hasExact()); break; case ISD::FSHL: case ISD::FSHR: diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp index 74d857457aec..ed25e52b9ace 100644 --- a/llvm/lib/Support/KnownBits.cpp +++ b/llvm/lib/Support/KnownBits.cpp @@ -343,7 +343,7 @@ KnownBits KnownBits::shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW, } KnownBits KnownBits::lshr(const KnownBits &LHS, const KnownBits &RHS, - bool ShAmtNonZero) { + bool ShAmtNonZero, bool /*Exact*/) { unsigned BitWidth = LHS.getBitWidth(); auto ShiftByConst = [&](const KnownBits &LHS, unsigned ShiftAmt) { KnownBits Known = LHS; @@ -389,7 +389,7 @@ KnownBits KnownBits::lshr(const KnownBits &LHS, const KnownBits &RHS, } KnownBits KnownBits::ashr(const KnownBits &LHS, const KnownBits &RHS, - bool ShAmtNonZero) { + bool ShAmtNonZero, bool /*Exact*/) { unsigned BitWidth = LHS.getBitWidth(); auto ShiftByConst = [&](const KnownBits &LHS, unsigned ShiftAmt) { KnownBits Known = LHS; -- GitLab From d81db0e5f5b1404ff4813af3050d671528ad45cc Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Tue, 5 Mar 2024 22:03:44 -0600 Subject: [PATCH 177/953] [KnownBits] Implement knownbits `lshr`/`ashr` with exact flag The exact flag basically allows us to set an upper bound on shift amount when we have a known 1 in `LHS`. Typically we deduce exact using knownbits (on non-exact incoming shifts), so this is particularly impactful, but may be useful in some circumstances. Closes #84254 --- llvm/lib/Support/KnownBits.cpp | 28 +++++++++++++++++-- .../Analysis/ValueTracking/knownbits-shift.ll | 8 ++---- llvm/unittests/Support/KnownBitsTest.cpp | 26 +++++++++++++++++ 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp index ed25e52b9ace..c33c3680825a 100644 --- a/llvm/lib/Support/KnownBits.cpp +++ b/llvm/lib/Support/KnownBits.cpp @@ -343,7 +343,7 @@ KnownBits KnownBits::shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW, } KnownBits KnownBits::lshr(const KnownBits &LHS, const KnownBits &RHS, - bool ShAmtNonZero, bool /*Exact*/) { + bool ShAmtNonZero, bool Exact) { unsigned BitWidth = LHS.getBitWidth(); auto ShiftByConst = [&](const KnownBits &LHS, unsigned ShiftAmt) { KnownBits Known = LHS; @@ -367,6 +367,18 @@ KnownBits KnownBits::lshr(const KnownBits &LHS, const KnownBits &RHS, // Find the common bits from all possible shifts. APInt MaxValue = RHS.getMaxValue(); unsigned MaxShiftAmount = getMaxShiftAmount(MaxValue, BitWidth); + + // If exact, bound MaxShiftAmount to first known 1 in LHS. + if (Exact) { + unsigned FirstOne = LHS.countMaxTrailingZeros(); + if (FirstOne < MinShiftAmount) { + // Always poison. Return zero because we don't like returning conflict. + Known.setAllZero(); + return Known; + } + MaxShiftAmount = std::min(MaxShiftAmount, FirstOne); + } + unsigned ShiftAmtZeroMask = RHS.Zero.zextOrTrunc(32).getZExtValue(); unsigned ShiftAmtOneMask = RHS.One.zextOrTrunc(32).getZExtValue(); Known.Zero.setAllBits(); @@ -389,7 +401,7 @@ KnownBits KnownBits::lshr(const KnownBits &LHS, const KnownBits &RHS, } KnownBits KnownBits::ashr(const KnownBits &LHS, const KnownBits &RHS, - bool ShAmtNonZero, bool /*Exact*/) { + bool ShAmtNonZero, bool Exact) { unsigned BitWidth = LHS.getBitWidth(); auto ShiftByConst = [&](const KnownBits &LHS, unsigned ShiftAmt) { KnownBits Known = LHS; @@ -415,6 +427,18 @@ KnownBits KnownBits::ashr(const KnownBits &LHS, const KnownBits &RHS, // Find the common bits from all possible shifts. APInt MaxValue = RHS.getMaxValue(); unsigned MaxShiftAmount = getMaxShiftAmount(MaxValue, BitWidth); + + // If exact, bound MaxShiftAmount to first known 1 in LHS. + if (Exact) { + unsigned FirstOne = LHS.countMaxTrailingZeros(); + if (FirstOne < MinShiftAmount) { + // Always poison. Return zero because we don't like returning conflict. + Known.setAllZero(); + return Known; + } + MaxShiftAmount = std::min(MaxShiftAmount, FirstOne); + } + unsigned ShiftAmtZeroMask = RHS.Zero.zextOrTrunc(32).getZExtValue(); unsigned ShiftAmtOneMask = RHS.One.zextOrTrunc(32).getZExtValue(); Known.Zero.setAllBits(); diff --git a/llvm/test/Analysis/ValueTracking/knownbits-shift.ll b/llvm/test/Analysis/ValueTracking/knownbits-shift.ll index 3235f69b5221..5cb355eff5a6 100644 --- a/llvm/test/Analysis/ValueTracking/knownbits-shift.ll +++ b/llvm/test/Analysis/ValueTracking/knownbits-shift.ll @@ -3,9 +3,7 @@ define i8 @simplify_lshr_with_exact(i8 %x) { ; CHECK-LABEL: @simplify_lshr_with_exact( -; CHECK-NEXT: [[SHR:%.*]] = lshr exact i8 6, [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = and i8 [[SHR]], 2 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 2 ; %shr = lshr exact i8 6, %x %r = and i8 %shr, 2 @@ -14,9 +12,7 @@ define i8 @simplify_lshr_with_exact(i8 %x) { define i8 @simplify_ashr_with_exact(i8 %x) { ; CHECK-LABEL: @simplify_ashr_with_exact( -; CHECK-NEXT: [[SHR:%.*]] = ashr exact i8 -122, [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = and i8 [[SHR]], 2 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 2 ; %shr = ashr exact i8 -122, %x %r = and i8 %shr, 2 diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index 658f3796721c..7c183e9626f9 100644 --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -516,6 +516,19 @@ TEST(KnownBitsTest, BinaryExhaustive) { return N1.lshr(N2); }, checkOptimalityBinary, /* RefinePoisonToZero */ true); + testBinaryOpExhaustive( + [](const KnownBits &Known1, const KnownBits &Known2) { + return KnownBits::lshr(Known1, Known2, /*ShAmtNonZero=*/false, + /*Exact=*/true); + }, + [](const APInt &N1, const APInt &N2) -> std::optional { + if (N2.uge(N2.getBitWidth())) + return std::nullopt; + if (!N1.extractBits(N2.getZExtValue(), 0).isZero()) + return std::nullopt; + return N1.lshr(N2); + }, + checkOptimalityBinary, /* RefinePoisonToZero */ true); testBinaryOpExhaustive( [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::ashr(Known1, Known2); @@ -526,6 +539,19 @@ TEST(KnownBitsTest, BinaryExhaustive) { return N1.ashr(N2); }, checkOptimalityBinary, /* RefinePoisonToZero */ true); + testBinaryOpExhaustive( + [](const KnownBits &Known1, const KnownBits &Known2) { + return KnownBits::ashr(Known1, Known2, /*ShAmtNonZero=*/false, + /*Exact=*/true); + }, + [](const APInt &N1, const APInt &N2) -> std::optional { + if (N2.uge(N2.getBitWidth())) + return std::nullopt; + if (!N1.extractBits(N2.getZExtValue(), 0).isZero()) + return std::nullopt; + return N1.ashr(N2); + }, + checkOptimalityBinary, /* RefinePoisonToZero */ true); testBinaryOpExhaustive( [](const KnownBits &Known1, const KnownBits &Known2) { -- GitLab From 65fd664daf4fb283d9a09e01f19709b38b99173a Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Mon, 11 Mar 2024 14:00:03 -0700 Subject: [PATCH 178/953] Run pre-merge build with -k 0 to ensure all tests runs (#84828) The -k option allows to continue the build after failures as much as possible. This is useful here because when we run > ninja check-llvm check-clang we would like the clang tests to run even if there is a failure in a llvm tests. The downside is that a build failure in one file that would prevent from running any test does not prevent from building more targets, wasting build resources potentially. Fixes #83371 --- .ci/monolithic-linux.sh | 2 +- .ci/monolithic-windows.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/monolithic-linux.sh b/.ci/monolithic-linux.sh index 1e7b2d2a36c2..fe1a9e57ff4a 100755 --- a/.ci/monolithic-linux.sh +++ b/.ci/monolithic-linux.sh @@ -54,4 +54,4 @@ cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ echo "--- ninja" # Targets are not escaped as they are passed as separate arguments. -ninja -C "${BUILD_DIR}" ${targets} +ninja -C -k 0 "${BUILD_DIR}" ${targets} diff --git a/.ci/monolithic-windows.sh b/.ci/monolithic-windows.sh index 9561bf668a90..c12e5544c1a1 100755 --- a/.ci/monolithic-windows.sh +++ b/.ci/monolithic-windows.sh @@ -62,4 +62,4 @@ cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ echo "--- ninja" # Targets are not escaped as they are passed as separate arguments. -ninja -C "${BUILD_DIR}" ${targets} +ninja -C -k 0 "${BUILD_DIR}" ${targets} -- GitLab From 31ffdb56b4df9b772d763dccabbfde542545d695 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Mon, 11 Mar 2024 21:06:03 +0000 Subject: [PATCH 179/953] [ArgPromotion] Add test case for #84807. Test case for https://github.com/llvm/llvm-project/issues/84807, showing a mis-compile in ArgPromotion. --- ...ing-and-non-aliasing-loads-with-clobber.ll | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 llvm/test/Transforms/ArgumentPromotion/aliasing-and-non-aliasing-loads-with-clobber.ll diff --git a/llvm/test/Transforms/ArgumentPromotion/aliasing-and-non-aliasing-loads-with-clobber.ll b/llvm/test/Transforms/ArgumentPromotion/aliasing-and-non-aliasing-loads-with-clobber.ll new file mode 100644 index 000000000000..69385a7ea51a --- /dev/null +++ b/llvm/test/Transforms/ArgumentPromotion/aliasing-and-non-aliasing-loads-with-clobber.ll @@ -0,0 +1,100 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -p argpromotion -S %s | FileCheck %s + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" + +@f = dso_local global { i16, i64 } { i16 1, i64 0 }, align 8 + +; Test case for https://github.com/llvm/llvm-project/issues/84807. + +; FIXME: Currently the loads from @callee are moved to @caller, even though +; the store in %then may aliases to load from %q. + +define i32 @caller1(i1 %c) { +; CHECK-LABEL: define i32 @caller1( +; CHECK-SAME: i1 [[C:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[F_VAL:%.*]] = load i16, ptr @f, align 8 +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr @f, i64 8 +; CHECK-NEXT: [[F_VAL1:%.*]] = load i64, ptr [[TMP0]], align 8 +; CHECK-NEXT: call void @callee1(i16 [[F_VAL]], i64 [[F_VAL1]], i1 [[C]]) +; CHECK-NEXT: ret i32 0 +; +entry: + call void @callee1(ptr noundef nonnull @f, i1 %c) + ret i32 0 +} + +define internal void @callee1(ptr nocapture noundef readonly %q, i1 %c) { +; CHECK-LABEL: define internal void @callee1( +; CHECK-SAME: i16 [[Q_0_VAL:%.*]], i64 [[Q_8_VAL:%.*]], i1 [[C:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[EXIT:%.*]] +; CHECK: then: +; CHECK-NEXT: store i16 123, ptr @f, align 8 +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: call void @use(i16 [[Q_0_VAL]], i64 [[Q_8_VAL]]) +; CHECK-NEXT: ret void +; +entry: + br i1 %c, label %then, label %exit + +then: + store i16 123, ptr @f, align 8 + br label %exit + +exit: + %l.0 = load i16, ptr %q, align 8 + %gep.8 = getelementptr inbounds i8, ptr %q, i64 8 + %l.1 = load i64, ptr %gep.8, align 8 + call void @use(i16 %l.0, i64 %l.1) + ret void + + uselistorder ptr %q, { 1, 0 } +} + +; Same as @caller1/callee2, but with default uselist order. +define i32 @caller2(i1 %c) { +; CHECK-LABEL: define i32 @caller2( +; CHECK-SAME: i1 [[C:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: call void @callee2(ptr noundef nonnull @f, i1 [[C]]) +; CHECK-NEXT: ret i32 0 +; +entry: + call void @callee2(ptr noundef nonnull @f, i1 %c) + ret i32 0 +} + +define internal void @callee2(ptr nocapture noundef readonly %q, i1 %c) { +; CHECK-LABEL: define internal void @callee2( +; CHECK-SAME: ptr nocapture noundef readonly [[Q:%.*]], i1 [[C:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[EXIT:%.*]] +; CHECK: then: +; CHECK-NEXT: store i16 123, ptr @f, align 8 +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[Q_0_VAL:%.*]] = load i16, ptr [[Q]], align 8 +; CHECK-NEXT: [[GEP_8:%.*]] = getelementptr inbounds i8, ptr [[Q]], i64 8 +; CHECK-NEXT: [[Q_8_VAL:%.*]] = load i64, ptr [[GEP_8]], align 8 +; CHECK-NEXT: call void @use(i16 [[Q_0_VAL]], i64 [[Q_8_VAL]]) +; CHECK-NEXT: ret void +; +entry: + br i1 %c, label %then, label %exit + +then: + store i16 123, ptr @f, align 8 + br label %exit + +exit: + %l.0 = load i16, ptr %q, align 8 + %gep.8 = getelementptr inbounds i8, ptr %q, i64 8 + %l.1 = load i64, ptr %gep.8, align 8 + call void @use(i16 %l.0, i64 %l.1) + ret void +} + +declare void @use(i16, i64) -- GitLab From 0f0f0ffc750b5d1364d20b8ecd3f070e9e816ecf Mon Sep 17 00:00:00 2001 From: Arthur Eubanks Date: Mon, 11 Mar 2024 21:08:26 +0000 Subject: [PATCH 180/953] [NFC] Remove unused variable after 94c988bc --- llvm/lib/Target/VE/VEISelLowering.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/lib/Target/VE/VEISelLowering.cpp b/llvm/lib/Target/VE/VEISelLowering.cpp index 6e31c8b7c9a0..96340f603a87 100644 --- a/llvm/lib/Target/VE/VEISelLowering.cpp +++ b/llvm/lib/Target/VE/VEISelLowering.cpp @@ -648,7 +648,6 @@ SDValue VETargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // PC-relative references to external symbols should go through $stub. // If so, we need to prepare GlobalBaseReg first. const TargetMachine &TM = DAG.getTarget(); - const Module *Mod = DAG.getMachineFunction().getFunction().getParent(); const GlobalValue *GV = nullptr; auto *CalleeG = dyn_cast(Callee); if (CalleeG) -- GitLab From 3707c540d23a5684a1c37b0f7e41c1d8ed7f1f8a Mon Sep 17 00:00:00 2001 From: jimingham Date: Mon, 11 Mar 2024 14:13:37 -0700 Subject: [PATCH 181/953] Make ValueObject::Cast work for casts from smaller to larger structs in the cases where this currently can work. (#84588) The ValueObjectConstResult classes that back expression result variables play a complicated game with where the data for their values is stored. They try to make it appear as though they are still tied to the memory in the target into which their value was written when the expression is run, but they also keep a copy in the Host which they use after the value is made (expression results are "history values" so that's how we make sure they have "the value at the time of the expression".) However, that means that if you ask them to cast themselves to a value bigger than their original size, they don't have a way to get more memory for that purpose. The same thing is true of ValueObjects backed by DataExtractors, the data extractors don't know how to get more data than they were made with in general. The only place where we actually ask ValueObjects to sample outside their captured bounds is when you do ValueObject::Cast from one structure type to a bigger structure type. In https://reviews.llvm.org/D153657 I handled this by just disallowing casts from one structure value to a larger one. My reasoning at the time was that the use case for this was to support discriminator based C inheritance schemes, and you can't directly cast values in C, only pointers, so this was not a natural way to handle those types. It seemed logical that since you would have had to start with pointers in the implementation, that's how you would write your lldb introspection code as well. Famous last words... Turns out there are some heavy users of the SB API's who were relying on this working, and this is a behavior change, so this patch makes this work in the cases where it used to work before, while still disallowing the cases we don't know how to support. Note that if you had done this Cast operation before with either expression results or value objects from data extractors, lldb would not have returned the correct results, so the cases this patch outlaws are ones that actually produce invalid results. So nobody should be using Cast in these cases, or if they were, this patch will point out the bug they hadn't yet noticed. --- lldb/source/Core/ValueObject.cpp | 20 ++++-- .../test/API/python_api/value/TestValueAPI.py | 68 ++++++++++++++++--- lldb/test/API/python_api/value/main.c | 15 +++- 3 files changed, 89 insertions(+), 14 deletions(-) diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index d813044d02ff..f39bd07a2553 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -2744,8 +2744,19 @@ ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) { ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) { // Only allow casts if the original type is equal or larger than the cast - // type. We don't know how to fetch more data for all the ConstResult types, - // so we can't guarantee this will work: + // type, unless we know this is a load address. Getting the size wrong for + // a host side storage could leak lldb memory, so we absolutely want to + // prevent that. We may not always get the right value, for instance if we + // have an expression result value that's copied into a storage location in + // the target may not have copied enough memory. I'm not trying to fix that + // here, I'm just making Cast from a smaller to a larger possible in all the + // cases where that doesn't risk making a Value out of random lldb memory. + // You have to check the ValueObject's Value for the address types, since + // ValueObjects that use live addresses will tell you they fetch data from the + // live address, but once they are made, they actually don't. + // FIXME: Can we make ValueObject's with a live address fetch "more data" from + // the live address if it is still valid? + Status error; CompilerType my_type = GetCompilerType(); @@ -2753,9 +2764,10 @@ ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) { = ExecutionContext(GetExecutionContextRef()) .GetBestExecutionContextScope(); if (compiler_type.GetByteSize(exe_scope) - <= GetCompilerType().GetByteSize(exe_scope)) { + <= GetCompilerType().GetByteSize(exe_scope) + || m_value.GetValueType() == Value::ValueType::LoadAddress) return DoCast(compiler_type); - } + error.SetErrorString("Can only cast to a type that is equal to or smaller " "than the orignal type."); diff --git a/lldb/test/API/python_api/value/TestValueAPI.py b/lldb/test/API/python_api/value/TestValueAPI.py index 18376f76e3c8..512100912d6f 100644 --- a/lldb/test/API/python_api/value/TestValueAPI.py +++ b/lldb/test/API/python_api/value/TestValueAPI.py @@ -148,14 +148,66 @@ class ValueAPITestCase(TestBase): # Test some other cases of the Cast API. We allow casts from one struct type # to another, which is a little weird, but we don't support casting from a - # smaller type to a larger as we often wouldn't know how to get the extra data: - val_f = target.EvaluateExpression("f") - bad_cast = val_s.Cast(val_f.GetType()) - self.assertFailure( - bad_cast.GetError(), - "Can only cast to a type that is equal to or smaller than the orignal type.", - ) - weird_cast = val_f.Cast(val_s.GetType()) + # smaller type to a larger when the underlying data is not in the inferior, + # since then we have no way to fetch the out-of-bounds values. + # For an expression that references a variable, or a FindVariable result, + # or an SBValue made from an address and a type, we can get back to the target, + # so those will work. Make sure they do and get the right extra values as well. + + # We're casting everything to the type of "f", so get that first: + f_var = frame0.FindVariable("f") + self.assertSuccess(f_var.error, "Got f") + bigger_type = f_var.GetType() + + # First try a value that we got from FindVariable + container = frame0.FindVariable("my_container") + self.assertSuccess(container.error, "Found my_container") + fv_small = container.GetValueForExpressionPath(".data.small") + self.assertSuccess(fv_small.error, "Found small in my_container") + fv_cast = fv_small.Cast(bigger_type) + self.assertSuccess(fv_cast.error, "Can cast up from FindVariable") + child_checks = [ + ValueCheck(name="a", value="33", type="int"), + ValueCheck(name="b", value="44", type="int"), + ValueCheck(name="c", value="55", type="int"), + ] + cast_check = ValueCheck(type=bigger_type.name, children=child_checks) + + # Now try one we made with expr. This one should fail, because expr + # stores the "canonical value" in host memory, and doesn't know how + # to augment that from the live address. + expr_cont = frame0.EvaluateExpression("my_container") + self.assertSuccess(expr_cont.error, "Got my_container by expr") + expr_small = expr_cont.GetValueForExpressionPath(".data.small") + self.assertSuccess(expr_small.error, "Got small by expr") + expr_cast = expr_small.Cast(bigger_type) + self.assertFailure(expr_cast.error, msg="Cannot cast expr result") + + # Now try one we made with CreateValueFromAddress. That will succeed + # because this directly tracks the inferior memory. + small_addr = fv_small.addr + self.assertTrue(small_addr.IsValid()) + small_type = fv_small.GetType() + vfa_small = target.CreateValueFromAddress( + "small_from_addr", small_addr, small_type + ) + self.assertSuccess(vfa_small.error, "Made small from address") + vfa_cast = vfa_small.Cast(bigger_type) + self.assertSuccess(vfa_cast.error, "Made a cast from vfa_small") + cast_check.check_value(self, vfa_cast, "Cast of ValueFromAddress succeeds") + + # Next try ValueObject created from data. They should fail as there's no + # way to grow the data: + data_small = target.CreateValueFromData( + "small_from_data", fv_small.data, fv_small.type + ) + self.assertSuccess(data_small.error, "Made a valid object from data") + data_cast = data_small.Cast(bigger_type) + self.assertFailure(data_cast.error, msg="Cannot cast data backed SBValue") + + # Now check casting from a larger type to a smaller, we can always do this, + # so just test one case: + weird_cast = f_var.Cast(val_s.GetType()) self.assertSuccess(weird_cast.GetError(), "Can cast from a larger to a smaller") self.assertEqual( weird_cast.GetChildMemberWithName("a").GetValueAsSigned(0), diff --git a/lldb/test/API/python_api/value/main.c b/lldb/test/API/python_api/value/main.c index 672b0df376dc..cdb2aa2f6147 100644 --- a/lldb/test/API/python_api/value/main.c +++ b/lldb/test/API/python_api/value/main.c @@ -22,7 +22,7 @@ const char *weekdays[5] = { "Monday", const char **g_table[2] = { days_of_week, weekdays }; typedef int MyInt; - + struct MyStruct { int a; @@ -36,6 +36,15 @@ struct MyBiggerStruct int c; }; +struct Container +{ + int discriminator; + union Data { + struct MyStruct small; + struct MyBiggerStruct big; + } data; +}; + int main (int argc, char const *argv[]) { uint32_t uinthex = 0xE0A35F10; @@ -43,8 +52,10 @@ int main (int argc, char const *argv[]) int i; MyInt a = 12345; - struct MyStruct s = { 11, 22 }; + struct MyStruct s = {11, 22}; struct MyBiggerStruct f = { 33, 44, 55 }; + struct Container my_container; + my_container.data.big = f; int *my_int_ptr = &g_my_int; printf("my_int_ptr points to location %p\n", my_int_ptr); int *fixed_int_ptr = (int*)(void*)0xAA; -- GitLab From 762cbd82da4debf8b026a4eb4ade66720acf3182 Mon Sep 17 00:00:00 2001 From: lntue <35648136+lntue@users.noreply.github.com> Date: Mon, 11 Mar 2024 17:43:50 -0400 Subject: [PATCH 182/953] [libc][NFC] Do not add libc test framework and -fno-rtti to C tests. (#84837) --- .../modules/LLVMLibCCompileOptionRules.cmake | 6 ++++-- libc/cmake/modules/LLVMLibCTestRules.cmake | 15 ++++++++++----- libc/test/include/CMakeLists.txt | 1 + 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake index 893a807b5b61..5bc0898298ce 100644 --- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake +++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake @@ -108,7 +108,7 @@ function(_get_common_compile_options output_var flags) set(${output_var} ${compile_options} PARENT_SCOPE) endfunction() -function(_get_common_test_compile_options output_var flags) +function(_get_common_test_compile_options output_var c_test flags) _get_compile_options_from_flags(compile_flags ${flags}) set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT} ${compile_flags}) @@ -122,7 +122,9 @@ function(_get_common_test_compile_options output_var flags) list(APPEND compile_options "-fno-exceptions") list(APPEND compile_options "-fno-unwind-tables") list(APPEND compile_options "-fno-asynchronous-unwind-tables") - list(APPEND compile_options "-fno-rtti") + if(NOT ${c_test}) + list(APPEND compile_options "-fno-rtti") + endif() endif() if(LIBC_COMPILER_HAS_FIXED_POINT) diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake index 0bdd72091fe8..eb6be91b55e2 100644 --- a/libc/cmake/modules/LLVMLibCTestRules.cmake +++ b/libc/cmake/modules/LLVMLibCTestRules.cmake @@ -111,7 +111,7 @@ function(create_libc_unittest fq_target_name) cmake_parse_arguments( "LIBC_UNITTEST" - "NO_RUN_POSTBUILD" # Optional arguments + "NO_RUN_POSTBUILD;C_TEST" # Optional arguments "SUITE;CXX_STANDARD" # Single value arguments "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS;LINK_LIBRARIES;FLAGS" # Multi-value arguments ${ARGN} @@ -126,11 +126,14 @@ function(create_libc_unittest fq_target_name) endif() get_fq_deps_list(fq_deps_list ${LIBC_UNITTEST_DEPENDS}) - list(APPEND fq_deps_list libc.src.__support.StringUtil.error_to_string - libc.test.UnitTest.ErrnoSetterMatcher) + if(NOT LIBC_UNITTEST_C_TEST) + list(APPEND fq_deps_list libc.src.__support.StringUtil.error_to_string + libc.test.UnitTest.ErrnoSetterMatcher) + endif() list(REMOVE_DUPLICATES fq_deps_list) - _get_common_test_compile_options(compile_options "${LIBC_UNITTEST_FLAGS}") + _get_common_test_compile_options(compile_options "${LIBC_UNITTEST_C_TEST}" + "${LIBC_UNITTEST_FLAGS}") list(APPEND compile_options ${LIBC_UNITTEST_COMPILE_OPTIONS}) if(SHOW_INTERMEDIATE_OBJECTS) @@ -214,7 +217,9 @@ function(create_libc_unittest fq_target_name) ) # LibcUnitTest should not depend on anything in LINK_LIBRARIES. - list(APPEND link_libraries LibcDeathTestExecutors.unit LibcTest.unit) + if(NOT LIBC_UNITTEST_C_TEST) + list(APPEND link_libraries LibcDeathTestExecutors.unit LibcTest.unit) + endif() target_link_libraries(${fq_build_target_name} PRIVATE ${link_libraries}) diff --git a/libc/test/include/CMakeLists.txt b/libc/test/include/CMakeLists.txt index d76ad442d36c..8d8dff53169f 100644 --- a/libc/test/include/CMakeLists.txt +++ b/libc/test/include/CMakeLists.txt @@ -37,6 +37,7 @@ if(LLVM_LIBC_FULL_BUILD AND libc.include.stdbit IN_LIST TARGET_PUBLIC_HEADERS) ) add_libc_test( stdbit_c_test + C_TEST UNIT_TEST_ONLY SUITE libc_include_tests -- GitLab From c93c76b562784926b22a69d3f82a5032dcb4a274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 12 Mar 2024 00:03:26 +0200 Subject: [PATCH 183/953] [LLD] [COFF] Set the right alignment for DelayDirectoryChunk (#84697) This makes a difference when linking executables with delay loaded libraries for arm32; the delay loader implementation can load data from the registry with instructions that assume alignment. This issue does not show up when linking in MinGW mode, because a PseudoRelocTableChunk gets injected, which also sets alignment, even if the chunk itself is empty. --- lld/COFF/DLL.cpp | 2 +- lld/test/COFF/delayimports-armnt.yaml | 25 +++++++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/lld/COFF/DLL.cpp b/lld/COFF/DLL.cpp index d0b74ac44549..5f00eaded76d 100644 --- a/lld/COFF/DLL.cpp +++ b/lld/COFF/DLL.cpp @@ -172,7 +172,7 @@ binImports(COFFLinkerContext &ctx, // A chunk for the delay import descriptor table etnry. class DelayDirectoryChunk : public NonSectionChunk { public: - explicit DelayDirectoryChunk(Chunk *n) : dllName(n) {} + explicit DelayDirectoryChunk(Chunk *n) : dllName(n) { setAlignment(4); } size_t getSize() const override { return sizeof(delay_import_directory_table_entry); diff --git a/lld/test/COFF/delayimports-armnt.yaml b/lld/test/COFF/delayimports-armnt.yaml index 7d9bc38c5c36..ea96d864ef53 100644 --- a/lld/test/COFF/delayimports-armnt.yaml +++ b/lld/test/COFF/delayimports-armnt.yaml @@ -6,6 +6,7 @@ # RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s # RUN: llvm-readobj --coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s # RUN: llvm-objdump --no-print-imm-hex -d %t.exe | FileCheck --check-prefix=DISASM %s +# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=DIR %s # IMPORT: Format: COFF-ARM # IMPORT-NEXT: Arch: thumb @@ -13,9 +14,9 @@ # IMPORT-NEXT: DelayImport { # IMPORT-NEXT: Name: library.dll # IMPORT-NEXT: Attributes: 0x1 -# IMPORT-NEXT: ModuleHandle: 0x3000 -# IMPORT-NEXT: ImportAddressTable: 0x3008 -# IMPORT-NEXT: ImportNameTable: 0x2040 +# IMPORT-NEXT: ModuleHandle: 0x3008 +# IMPORT-NEXT: ImportAddressTable: 0x3010 +# IMPORT-NEXT: ImportNameTable: 0x2044 # IMPORT-NEXT: BoundDelayImportTable: 0x0 # IMPORT-NEXT: UnloadDelayImportTable: 0x0 # IMPORT-NEXT: Import { @@ -43,7 +44,7 @@ # BASEREL-NEXT: } # BASEREL-NEXT: Entry { # BASEREL-NEXT: Type: HIGHLOW -# BASEREL-NEXT: Address: 0x3008 +# BASEREL-NEXT: Address: 0x3010 # BASEREL-NEXT: } # BASEREL-NEXT: Entry { # BASEREL-NEXT: Type: ABSOLUTE @@ -52,20 +53,24 @@ # BASEREL-NEXT: ] # # DISASM: 00401000 <.text>: -# DISASM: 40100c: f243 0c08 movw r12, #12296 +# DISASM: 40100c: f243 0c10 movw r12, #12304 # DISASM-NEXT: f2c0 0c40 movt r12, #64 # DISASM-NEXT: f000 b800 b.w {{.+}} @ imm = #0 # DISASM-NEXT: e92d 480f push.w {r0, r1, r2, r3, r11, lr} # DISASM-NEXT: f20d 0b10 addw r11, sp, #16 # DISASM-NEXT: ed2d 0b10 vpush {d0, d1, d2, d3, d4, d5, d6, d7} # DISASM-NEXT: 4661 mov r1, r12 -# DISASM-NEXT: f242 0000 movw r0, #8192 +# DISASM-NEXT: f242 0004 movw r0, #8196 # DISASM-NEXT: f2c0 0040 movt r0, #64 # DISASM-NEXT: f7ff ffe7 bl 0x401000 <.text> # DISASM-NEXT: 4684 mov r12, r0 # DISASM-NEXT: ecbd 0b10 vpop {d0, d1, d2, d3, d4, d5, d6, d7} # DISASM-NEXT: e8bd 480f pop.w {r0, r1, r2, r3, r11, lr} # DISASM-NEXT: 4760 bx r12 +# +# DIR: DelayImportDescriptorRVA: 0x2004 +# DIR-NEXT: DelayImportDescriptorSize: 0x40 + --- !COFF header: @@ -80,6 +85,14 @@ sections: - VirtualAddress: 0 SymbolName: __imp_function Type: IMAGE_REL_ARM_MOV32T + - Name: .rdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + Alignment: 1 + SectionData: 01 + - Name: .data + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] + Alignment: 1 + SectionData: 02 symbols: - Name: .text Value: 0 -- GitLab From 60e562d11aeca8020de8d50ded7f0ba9e10e8843 Mon Sep 17 00:00:00 2001 From: Quinn Dawkins Date: Mon, 11 Mar 2024 18:24:23 -0400 Subject: [PATCH 184/953] [mlir][linalg] Add unit dim folding pattern for tensor.pad (#84684) Unit extent dims that are not padded by a tensor.pad can be folded away. When folding unit extent dims of surrounding linalg ops, this increases the chance that the iteration space of the linalg op will align with nearby pad ops, improving fusion opportunities. --- .../Dialect/Linalg/Transforms/Transforms.h | 4 + .../Linalg/Transforms/DropUnitDims.cpp | 122 ++++++++++++++++++ .../Dialect/Linalg/drop-unit-extent-dims.mlir | 87 +++++++++++++ 3 files changed, 213 insertions(+) diff --git a/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h b/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h index 65cf19e7a4fc..c64ecb79c5ca 100644 --- a/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h +++ b/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h @@ -481,6 +481,10 @@ struct ControlDropUnitDims { if (auto genericOp = dyn_cast_or_null(op)) { return llvm::to_vector(llvm::seq(0, genericOp.getNumLoops())); } + if (auto padOp = dyn_cast_or_null(op)) { + return llvm::to_vector( + llvm::seq(0, padOp.getSourceType().getRank())); + } return SmallVector{}; }; }; diff --git a/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp b/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp index 45cab81be4f5..023ea277bcf4 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp @@ -561,6 +561,126 @@ private: }; } // namespace +//===---------------------------------------------------------------------===// +// Drop dimensions that are unit-extents within tensor operations. +//===---------------------------------------------------------------------===// + +namespace { +struct DropPadUnitDims : public OpRewritePattern { + DropPadUnitDims(MLIRContext *context, ControlDropUnitDims options = {}, + PatternBenefit benefit = 1) + : OpRewritePattern(context, benefit), options(std::move(options)) {} + + LogicalResult matchAndRewrite(tensor::PadOp padOp, + PatternRewriter &rewriter) const override { + // 1a. Get the allowed list of dimensions to drop from the `options`. + SmallVector allowedUnitDims = options.controlFn(padOp); + if (allowedUnitDims.empty()) { + return rewriter.notifyMatchFailure( + padOp, "control function returns no allowed unit dims to prune"); + } + + if (padOp.getSourceType().getEncoding()) { + return rewriter.notifyMatchFailure( + padOp, "cannot collapse dims of tensor with encoding"); + } + + // Fail for non-constant padding values. The body of the pad could + // depend on the padding indices and/or properties of the padded + // tensor so for now we fail. + // TODO: Support non-constant padding values. + Value paddingVal = padOp.getConstantPaddingValue(); + if (!paddingVal) { + return rewriter.notifyMatchFailure( + padOp, "unimplemented: non-constant padding value"); + } + + ArrayRef sourceShape = padOp.getSourceType().getShape(); + int64_t padRank = sourceShape.size(); + + auto isStaticZero = [](OpFoldResult f) { + std::optional maybeInt = getConstantIntValue(f); + return maybeInt && *maybeInt == 0; + }; + + llvm::SmallDenseSet unitDimsFilter(allowedUnitDims.begin(), + allowedUnitDims.end()); + llvm::SmallDenseSet unitDims; + SmallVector newShape; + SmallVector newLowPad; + SmallVector newHighPad; + for (const auto [dim, size, low, high] : + zip_equal(llvm::seq(static_cast(0), padRank), sourceShape, + padOp.getMixedLowPad(), padOp.getMixedHighPad())) { + if (unitDimsFilter.contains(dim) && size == 1 && isStaticZero(low) && + isStaticZero(high)) { + unitDims.insert(dim); + } else { + newShape.push_back(size); + newLowPad.push_back(low); + newHighPad.push_back(high); + } + } + + if (unitDims.empty()) { + return rewriter.notifyMatchFailure(padOp, "no unit dims to collapse"); + } + + ReassociationIndices reassociationGroup; + SmallVector reassociationMap; + int64_t dim = 0; + while (dim < padRank && unitDims.contains(dim)) + reassociationGroup.push_back(dim++); + while (dim < padRank) { + assert(!unitDims.contains(dim) && "expected non unit-extent"); + reassociationGroup.push_back(dim); + dim++; + // Fold all following dimensions that are unit-extent. + while (dim < padRank && unitDims.contains(dim)) + reassociationGroup.push_back(dim++); + reassociationMap.push_back(reassociationGroup); + reassociationGroup.clear(); + } + + Value collapsedSource = + collapseValue(rewriter, padOp.getLoc(), padOp.getSource(), newShape, + reassociationMap, options.rankReductionStrategy); + + auto newPadOp = rewriter.create( + padOp.getLoc(), /*result=*/Type(), collapsedSource, newLowPad, + newHighPad, paddingVal, padOp.getNofold()); + + Value dest = padOp.getResult(); + if (options.rankReductionStrategy == + ControlDropUnitDims::RankReductionStrategy::ExtractInsertSlice) { + SmallVector expandedSizes; + int64_t numUnitDims = 0; + for (auto dim : llvm::seq(static_cast(0), padRank)) { + if (unitDims.contains(dim)) { + expandedSizes.push_back(rewriter.getIndexAttr(1)); + numUnitDims++; + continue; + } + expandedSizes.push_back(tensor::getMixedSize( + rewriter, padOp.getLoc(), newPadOp, dim - numUnitDims)); + } + dest = rewriter.create( + padOp.getLoc(), expandedSizes, + padOp.getResultType().getElementType()); + } + + Value expandedValue = + expandValue(rewriter, padOp.getLoc(), newPadOp.getResult(), dest, + reassociationMap, options.rankReductionStrategy); + rewriter.replaceOp(padOp, expandedValue); + return success(); + } + +private: + ControlDropUnitDims options; +}; +} // namespace + namespace { /// Convert `extract_slice` operations to rank-reduced versions. struct RankReducedExtractSliceOp @@ -640,6 +760,7 @@ populateFoldUnitExtentDimsViaReshapesPatterns(RewritePatternSet &patterns, ControlDropUnitDims &options) { auto *context = patterns.getContext(); patterns.add(context, options); + patterns.add(context, options); // TODO: Patterns unrelated to unit dim folding should be factored out. patterns.add, @@ -661,6 +782,7 @@ populateFoldUnitExtentDimsViaSlicesPatterns(RewritePatternSet &patterns, options.rankReductionStrategy = ControlDropUnitDims::RankReductionStrategy::ExtractInsertSlice; patterns.add(context, options); + patterns.add(context, options); // TODO: Patterns unrelated to unit dim folding should be factored out. linalg::FillOp::getCanonicalizationPatterns(patterns, context); tensor::EmptyOp::getCanonicalizationPatterns(patterns, context); diff --git a/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir b/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir index 0c51a032df90..f2c490b83207 100644 --- a/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir +++ b/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir @@ -946,3 +946,90 @@ func.func @drop_all_loops(%arg0 : memref<1x1xf32, 3>) -> memref<1x1xf32, 3> // CHECK-SLICES-LABEL: func @drop_all_loops // CHECK-SLICES: memref.subview %{{.*}}[0, 0] [1, 1] [1, 1] : memref<1x1xf32, 3> to memref, 3> // CHECK-SLICES: linalg.generic{{.*}}memref, 3> + +// ----- + +func.func @drop_unit_pad_dims(%arg0: tensor<1x1x3x1x1xf32>) -> tensor<1x2x3x1x3xf32> +{ + %c0 = arith.constant 0 : index + %cst0 = arith.constant 0.0 : f32 + %0 = tensor.pad %arg0 low[0, 1, 0, %c0, 0] high[0, 0, 0, %c0, 2] { + ^bb0(%arg1: index, %arg2: index, %arg3: index, %arg4: index, %arg5: index): + tensor.yield %cst0 : f32 + } : tensor<1x1x3x1x1xf32> to tensor<1x2x3x1x3xf32> + return %0 : tensor<1x2x3x1x3xf32> +} + +// CHECK-LABEL: func @drop_unit_pad_dims +// CHECK: %[[COLLAPSE:.+]] = tensor.collapse_shape +// CHECK-SAME: {{\[}}[0, 1], [2, 3], [4]{{\]}} : tensor<1x1x3x1x1xf32> into tensor<1x3x1xf32> +// CHECK: %[[PADDED:.+]] = tensor.pad %[[COLLAPSE]] low[1, 0, 0] high[0, 0, 2] +// CHECK: } : tensor<1x3x1xf32> to tensor<2x3x3xf32> +// CHECK: tensor.expand_shape %[[PADDED]] +// CHECK-SAME: {{\[}}[0, 1], [2, 3], [4]{{\]}} : tensor<2x3x3xf32> into tensor<1x2x3x1x3xf32> + +// CHECK-SLICES-LABEL: func @drop_unit_pad_dims +// CHECK-SLICES: %[[EXTRACT:.+]] = tensor.extract_slice +// CHECK-SLICES-SAME: [0, 0, 0, 0, 0] [1, 1, 3, 1, 1] [1, 1, 1, 1, 1] : tensor<1x1x3x1x1xf32> to tensor<1x3x1xf32> +// CHECK-SLICES: %[[PADDED:.+]] = tensor.pad %[[EXTRACT]] low[1, 0, 0] high[0, 0, 2] +// CHECK-SLICES: } : tensor<1x3x1xf32> to tensor<2x3x3xf32> +// CHECK-SLICES: tensor.insert_slice %[[PADDED]] +// CHECK-SLICES-SAME: [0, 0, 0, 0, 0] [1, 2, 3, 1, 3] [1, 1, 1, 1, 1] : tensor<2x3x3xf32> into tensor<1x2x3x1x3xf32> + +// ----- + +func.func @drop_unit_pad_dynamic_dims(%arg0: tensor<1x?xf32>) -> tensor<1x?xf32> +{ + %c0 = arith.constant 0 : index + %cst0 = arith.constant 0.0 : f32 + %0 = tensor.pad %arg0 low[0, 5] high[0, 6] { + ^bb0(%arg1: index, %arg2: index): + tensor.yield %cst0 : f32 + } : tensor<1x?xf32> to tensor<1x?xf32> + return %0 : tensor<1x?xf32> +} + +// CHECK-LABEL: func @drop_unit_pad_dynamic_dims +// CHECK: %[[COLLAPSE:.+]] = tensor.collapse_shape +// CHECK-SAME: {{\[}}[0, 1]{{\]}} : tensor<1x?xf32> into tensor +// CHECK: %[[PADDED:.+]] = tensor.pad %[[COLLAPSE]] low[5] high[6] +// CHECK: } : tensor to tensor +// CHECK: tensor.expand_shape %[[PADDED]] +// CHECK-SAME: {{\[}}[0, 1]{{\]}} : tensor into tensor<1x?xf32> + +// CHECK-SLICES: #[[$MAP:.+]] = affine_map<()[s0] -> (s0 + 11)> + +// CHECK-SLICES-LABEL: func @drop_unit_pad_dynamic_dims +// CHECK-SLICES-SAME: %[[ARG0:[A-Za-z0-9]+]]: tensor<1x?xf32> +// CHECK-SLICES: %[[DIM:.+]] = tensor.dim %[[ARG0]], %c1 +// CHECK-SLICES: %[[EXTRACT:.+]] = tensor.extract_slice +// CHECK-SLICES-SAME: [0, 0] [1, %[[DIM]]] [1, 1] : tensor<1x?xf32> to tensor +// CHECK-SLICES: %[[PADDED:.+]] = tensor.pad %[[EXTRACT]] low[5] high[6] +// CHECK-SLICES: } : tensor to tensor +// CHECK-SLICES: %[[PADDED_DIM:.+]] = affine.apply #[[$MAP]]()[%[[DIM]]] +// CHECK-SLICES: %[[EMPTY:.+]] = tensor.empty(%[[PADDED_DIM]]) : tensor<1x?xf32> +// CHECK-SLICES: tensor.insert_slice %[[PADDED]] into %[[EMPTY]] +// CHECK-SLICES-SAME: [0, 0] [1, %[[PADDED_DIM]]] [1, 1] : tensor into tensor<1x?xf32> + +// ----- + +func.func @do_not_drop_non_constant_padding(%arg0: tensor<1x1x3x1x1xf32>, %pad: f32) -> tensor<1x2x3x1x3xf32> +{ + %c0 = arith.constant 0 : index + %0 = tensor.pad %arg0 low[0, 1, 0, %c0, 0] high[0, 0, 0, %c0, 2] { + ^bb0(%arg1: index, %arg2: index, %arg3: index, %arg4: index, %arg5: index): + %0 = arith.index_cast %arg3 : index to i64 + %1 = arith.sitofp %0 : i64 to f32 + %add = arith.addf %pad, %1 : f32 + tensor.yield %add : f32 + } : tensor<1x1x3x1x1xf32> to tensor<1x2x3x1x3xf32> + return %0 : tensor<1x2x3x1x3xf32> +} + +// CHECK-LABEL: func @do_not_drop_non_constant_padding +// CHECK: tensor.pad %{{.*}} low[0, 1, 0, %c0, 0] high[0, 0, 0, %c0, 2] +// CHECK: } : tensor<1x1x3x1x1xf32> to tensor<1x2x3x1x3xf32> + +// CHECK-SLICES-LABEL: func @do_not_drop_non_constant_padding +// CHECK-SLICES: tensor.pad %{{.*}} low[0, 1, 0, %c0, 0] high[0, 0, 0, %c0, 2] +// CHECK-SLICES: } : tensor<1x1x3x1x1xf32> to tensor<1x2x3x1x3xf32> -- GitLab From 6397f223c456ce5a0cc246cd81673794a4860fd1 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Mon, 11 Mar 2024 15:32:41 -0700 Subject: [PATCH 185/953] [clang] Fix test after #84214 --- clang/test/CodeGen/remote-traps.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/test/CodeGen/remote-traps.c b/clang/test/CodeGen/remote-traps.c index f053d1bd157f..6751afb96d25 100644 --- a/clang/test/CodeGen/remote-traps.c +++ b/clang/test/CodeGen/remote-traps.c @@ -1,15 +1,15 @@ // RUN: %clang_cc1 -O1 -emit-llvm -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow %s -o - | FileCheck %s // RUN: %clang_cc1 -O1 -emit-llvm -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -mllvm -clang-remove-traps -mllvm -remove-traps-random-rate=1 %s -o - | FileCheck %s --implicit-check-not="call void @llvm.ubsantrap" --check-prefixes=REMOVE -int f(int x) { +int test(int x) { return x + 123; } -// CHECK-LABEL: define dso_local noundef i32 @f( +// CHECK-LABEL: define {{.*}}i32 @test( // CHECK: call { i32, i1 } @llvm.sadd.with.overflow.i32( // CHECK: trap: // CHECK-NEXT: call void @llvm.ubsantrap(i8 0) // CHECK-NEXT: unreachable -// REMOVE-LABEL: define dso_local noundef i32 @f( +// REMOVE-LABEL: define {{.*}}i32 @test( // REMOVE: call { i32, i1 } @llvm.sadd.with.overflow.i32( -- GitLab From a950c06d9864ec34d401702f398dc09fbec87891 Mon Sep 17 00:00:00 2001 From: Connor Sughrue <55301806+cpsughrue@users.noreply.github.com> Date: Mon, 11 Mar 2024 15:41:50 -0700 Subject: [PATCH 186/953] [CI] Run pre-merge build with -k 0 placed after "${BUILD_DIR}" (#84846) #84828 added `-k 0` to pre-merge CI so that if one job fails the others would continue building. This pull request fixes the location of `-k 0` in the ninja command line. Resolves #84842 and #83371 --- .ci/monolithic-linux.sh | 2 +- .ci/monolithic-windows.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/monolithic-linux.sh b/.ci/monolithic-linux.sh index fe1a9e57ff4a..9e670c447fba 100755 --- a/.ci/monolithic-linux.sh +++ b/.ci/monolithic-linux.sh @@ -54,4 +54,4 @@ cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ echo "--- ninja" # Targets are not escaped as they are passed as separate arguments. -ninja -C -k 0 "${BUILD_DIR}" ${targets} +ninja -C "${BUILD_DIR}" -k 0 ${targets} diff --git a/.ci/monolithic-windows.sh b/.ci/monolithic-windows.sh index c12e5544c1a1..52ba13036f91 100755 --- a/.ci/monolithic-windows.sh +++ b/.ci/monolithic-windows.sh @@ -62,4 +62,4 @@ cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ echo "--- ninja" # Targets are not escaped as they are passed as separate arguments. -ninja -C -k 0 "${BUILD_DIR}" ${targets} +ninja -C "${BUILD_DIR}" -k 0 ${targets} -- GitLab From 83c9244ae4bee8a494a7abe313a6e9f22ac4be55 Mon Sep 17 00:00:00 2001 From: Yinying Li Date: Mon, 11 Mar 2024 18:44:32 -0400 Subject: [PATCH 187/953] [mlir][sparse] Migrate more tests to use sparse_tensor.print (#84833) Continuous efforts following #84249. --- .../CPU/concatenate_dim_0_permute.mlir | 78 ++-- .../SparseTensor/CPU/concatenate_dim_1.mlir | 58 ++- .../CPU/concatenate_dim_1_permute.mlir | 72 ++-- .../SparseTensor/CPU/dual_sparse_conv_2d.mlir | 99 +++-- .../Dialect/SparseTensor/CPU/reshape_dot.mlir | 4 +- .../SparseTensor/CPU/sparse_block3d.mlir | 38 +- .../Dialect/SparseTensor/CPU/sparse_cast.mlir | 4 +- .../Dialect/SparseTensor/CPU/sparse_cmp.mlir | 49 ++- .../SparseTensor/CPU/sparse_codegen_dim.mlir | 4 +- .../CPU/sparse_codegen_foreach.mlir | 11 +- .../CPU/sparse_collapse_shape.mlir | 128 ++++--- .../CPU/sparse_constant_to_sparse_tensor.mlir | 31 +- .../CPU/sparse_conv_1d_nwc_wcf.mlir | 53 +-- .../SparseTensor/CPU/sparse_conv_2d.mlir | 125 ++++--- .../SparseTensor/CPU/sparse_conv_2d_55.mlir | 4 +- .../CPU/sparse_conv_2d_nchw_fchw.mlir | 4 +- .../CPU/sparse_conv_2d_nhwc_hwcf.mlir | 166 +++++---- .../SparseTensor/CPU/sparse_conv_3d.mlir | 344 +++++++++--------- .../CPU/sparse_conv_3d_ndhwc_dhwcf.mlir | 212 ++++++----- 19 files changed, 777 insertions(+), 707 deletions(-) diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/concatenate_dim_0_permute.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/concatenate_dim_0_permute.mlir index 11edd854ec08..9c9b0e3330c9 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/concatenate_dim_0_permute.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/concatenate_dim_0_permute.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} @@ -99,20 +99,6 @@ module { return } - func.func @dump_mat_perm_9x4(%A: tensor<9x4xf64, #MAT_C_C_P>) { - %c = sparse_tensor.convert %A : tensor<9x4xf64, #MAT_C_C_P> to tensor<9x4xf64> - %cu = tensor.cast %c : tensor<9x4xf64> to tensor<*xf64> - call @printMemrefF64(%cu) : (tensor<*xf64>) -> () - - %n = sparse_tensor.number_of_entries %A : tensor<9x4xf64, #MAT_C_C_P> - vector.print %n : index - - %1 = sparse_tensor.values %A : tensor<9x4xf64, #MAT_C_C_P> to memref - call @printMemref1dF64(%1) : (memref) -> () - - return - } - func.func @dump_mat_dense_9x4(%A: tensor<9x4xf64>) { %u = tensor.cast %A : tensor<9x4xf64> to tensor<*xf64> call @printMemrefF64(%u) : (tensor<*xf64>) -> () @@ -120,18 +106,8 @@ module { return } - func.func @dump_mat_annotated_dense_9x4(%A: tensor<9x4xf64, #MAT_D_D>) { - %n = sparse_tensor.number_of_entries %A : tensor<9x4xf64, #MAT_D_D> - vector.print %n : index - - %1 = sparse_tensor.values %A : tensor<9x4xf64, #MAT_D_D> to memref - call @printMemref1dF64(%1) : (memref) -> () - - return - } - // Driver method to call and verify kernels. - func.func @entry() { + func.func @main() { %m42 = arith.constant dense< [ [ 1.0, 0.0 ], [ 3.1, 0.0 ], @@ -163,20 +139,21 @@ module { %sm34cdp = sparse_tensor.convert %m34 : tensor<3x4xf64> to tensor<3x4xf64, #MAT_C_D_P> %sm44dcp = sparse_tensor.convert %m44 : tensor<4x4xf64> to tensor<4x4xf64, #MAT_D_C_P> - // CHECK: {{\[}}[1, 0, 3, 0], - // CHECK-NEXT: [0, 2, 0, 0], - // CHECK-NEXT: [1, 0, 1, 1], - // CHECK-NEXT: [0, 0.5, 0, 0], - // CHECK-NEXT: [1, 5, 2, 0], - // CHECK-NEXT: [0, 0, 1.5, 1], - // CHECK-NEXT: [0, 3.5, 0, 0], - // CHECK-NEXT: [1, 5, 2, 0], - // CHECK-NEXT: [1, 0.5, 0, 0]] - // CHECK-NEXT: 18 - // CHECK: [1, 1, 1, 1, 1, 2, 0.5, 5, 3.5, 5, 0.5, 3, 1, 2, 1.5, 2, 1, 1 + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 18 + // CHECK-NEXT: dim = ( 9, 4 ) + // CHECK-NEXT: lvl = ( 4, 9 ) + // CHECK-NEXT: pos[0] : ( 0, 4 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3 + // CHECK-NEXT: pos[1] : ( 0, 5, 11, 16, 18 + // CHECK-NEXT: crd[1] : ( 0, 2, 4, 7, 8, 1, 3, 4, 6, 7, 8, 0, 2, 4, 5, 7, 2, 5 + // CHECK-NEXT: values : ( 1, 1, 1, 1, 1, 2, 0.5, 5, 3.5, 5, 0.5, 3, 1, 2, 1.5, 2, 1, 1 + // CHECK-NEXT: ---- + // %4 = call @concat_sparse_sparse_perm(%sm24ccp, %sm34cd, %sm44dc) : (tensor<2x4xf64, #MAT_C_C_P>, tensor<3x4xf64, #MAT_C_D>, tensor<4x4xf64, #MAT_D_C>) -> tensor<9x4xf64, #MAT_C_C_P> - call @dump_mat_perm_9x4(%4) : (tensor<9x4xf64, #MAT_C_C_P>) -> () + sparse_tensor.print %4 : tensor<9x4xf64, #MAT_C_C_P> // CHECK: {{\[}}[1, 0, 3, 0], // CHECK-NEXT: [0, 2, 0, 0], @@ -191,20 +168,21 @@ module { : (tensor<2x4xf64, #MAT_C_C_P>, tensor<3x4xf64, #MAT_C_D_P>, tensor<4x4xf64, #MAT_D_C>) -> tensor<9x4xf64> call @dump_mat_dense_9x4(%5) : (tensor<9x4xf64>) -> () - // CHECK: {{\[}}[1, 0, 3, 0], - // CHECK-NEXT: [0, 2, 0, 0], - // CHECK-NEXT: [1, 0, 1, 1], - // CHECK-NEXT: [0, 0.5, 0, 0], - // CHECK-NEXT: [1, 5, 2, 0], - // CHECK-NEXT: [0, 0, 1.5, 1], - // CHECK-NEXT: [0, 3.5, 0, 0], - // CHECK-NEXT: [1, 5, 2, 0], - // CHECK-NEXT: [1, 0.5, 0, 0]] - // CHECK-NEXT: 18 - // CHECK: [1, 3, 2, 1, 1, 1, 0.5, 1, 5, 2, 1.5, 1, 3.5, 1, 5, 2, 1, 0.5 + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 18 + // CHECK-NEXT: dim = ( 9, 4 ) + // CHECK-NEXT: lvl = ( 9, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 9 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5, 6, 7, 8 + // CHECK-NEXT: pos[1] : ( 0, 2, 3, 6, 7, 10, 12, 13, 16, 18 + // CHECK-NEXT: crd[1] : ( 0, 2, 1, 0, 2, 3, 1, 0, 1, 2, 2, 3, 1, 0, 1, 2, 0, 1 + // CHECK-NEXT: values : ( 1, 3, 2, 1, 1, 1, 0.5, 1, 5, 2, 1.5, 1, 3.5, 1, 5, 2, 1, 0.5 + // CHECK-NEXT: ---- + // %6 = call @concat_mix_sparse_perm(%m24, %sm34cdp, %sm44dc) : (tensor<2x4xf64>, tensor<3x4xf64, #MAT_C_D_P>, tensor<4x4xf64, #MAT_D_C>) -> tensor<9x4xf64, #MAT_C_C> - call @dump_mat_9x4(%6) : (tensor<9x4xf64, #MAT_C_C>) -> () + sparse_tensor.print %6 : tensor<9x4xf64, #MAT_C_C> // CHECK: {{\[}}[1, 0, 3, 0], // CHECK-NEXT: [0, 2, 0, 0], diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/concatenate_dim_1.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/concatenate_dim_1.mlir index 48d382570092..ae067bf18527 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/concatenate_dim_1.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/concatenate_dim_1.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} @@ -82,20 +82,6 @@ module { return %0 : tensor<4x9xf64> } - func.func @dump_mat_4x9(%A: tensor<4x9xf64, #MAT_C_C>) { - %c = sparse_tensor.convert %A : tensor<4x9xf64, #MAT_C_C> to tensor<4x9xf64> - %cu = tensor.cast %c : tensor<4x9xf64> to tensor<*xf64> - call @printMemrefF64(%cu) : (tensor<*xf64>) -> () - - %n = sparse_tensor.number_of_entries %A : tensor<4x9xf64, #MAT_C_C> - vector.print %n : index - - %1 = sparse_tensor.values %A : tensor<4x9xf64, #MAT_C_C> to memref - call @printMemref1dF64(%1) : (memref) -> () - - return - } - func.func @dump_mat_dense_4x9(%A: tensor<4x9xf64>) { %1 = tensor.cast %A : tensor<4x9xf64> to tensor<*xf64> call @printMemrefF64(%1) : (tensor<*xf64>) -> () @@ -104,7 +90,7 @@ module { } // Driver method to call and verify kernels. - func.func @entry() { + func.func @main() { %m42 = arith.constant dense< [ [ 1.0, 0.0 ], [ 3.1, 0.0 ], @@ -125,15 +111,21 @@ module { %sm43cd = sparse_tensor.convert %m43 : tensor<4x3xf64> to tensor<4x3xf64, #MAT_C_D> %sm44dc = sparse_tensor.convert %m44 : tensor<4x4xf64> to tensor<4x4xf64, #MAT_D_C> - // CHECK: {{\[}}[1, 0, 1, 0, 1, 0, 0, 1.5, 1], - // CHECK-NEXT: [3.1, 0, 1, 0, 0.5, 0, 3.5, 0, 0], - // CHECK-NEXT: [0, 2, 0, 0, 1, 1, 5, 2, 0], - // CHECK-NEXT: [0, 0, 5, 2, 0, 1, 0.5, 0, 0]] - // CHECK-NEXT: 18 - // CHECK: [1, 1, 1, 1.5, 1, 3.1, 1, 0.5, 3.5, 2, 1, 1, 5, 2, 5, 2, 1, 0.5 + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 18 + // CHECK-NEXT: dim = ( 4, 9 ) + // CHECK-NEXT: lvl = ( 4, 9 ) + // CHECK-NEXT: pos[0] : ( 0, 4 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3 + // CHECK-NEXT: pos[1] : ( 0, 5, 9, 14, 18 + // CHECK-NEXT: crd[1] : ( 0, 2, 4, 7, 8, 0, 2, 4, 6, 1, 4, 5, 6, 7, 2, 3, 5, 6 + // CHECK-NEXT: values : ( 1, 1, 1, 1.5, 1, 3.1, 1, 0.5, 3.5, 2, 1, 1, 5, 2, 5, 2, 1, 0.5 + // CHECK-NEXT: ---- + // %8 = call @concat_sparse_sparse_dim1(%sm42cc, %sm43cd, %sm44dc) : (tensor<4x2xf64, #MAT_C_C>, tensor<4x3xf64, #MAT_C_D>, tensor<4x4xf64, #MAT_D_C>) -> tensor<4x9xf64, #MAT_C_C> - call @dump_mat_4x9(%8) : (tensor<4x9xf64, #MAT_C_C>) -> () + sparse_tensor.print %8 : tensor<4x9xf64, #MAT_C_C> // CHECK: {{\[}}[1, 0, 1, 0, 1, 0, 0, 1.5, 1], // CHECK-NEXT: [3.1, 0, 1, 0, 0.5, 0, 3.5, 0, 0], @@ -143,15 +135,21 @@ module { : (tensor<4x2xf64, #MAT_C_C>, tensor<4x3xf64, #MAT_C_D>, tensor<4x4xf64, #MAT_D_C>) -> tensor<4x9xf64> call @dump_mat_dense_4x9(%9) : (tensor<4x9xf64>) -> () - // CHECK: {{\[}}[1, 0, 1, 0, 1, 0, 0, 1.5, 1], - // CHECK-NEXT: [3.1, 0, 1, 0, 0.5, 0, 3.5, 0, 0], - // CHECK-NEXT: [0, 2, 0, 0, 1, 1, 5, 2, 0], - // CHECK-NEXT: [0, 0, 5, 2, 0, 1, 0.5, 0, 0]] - // CHECK-NEXT: 18 - // CHECK: [1, 1, 1, 1.5, 1, 3.1, 1, 0.5, 3.5, 2, 1, 1, 5, 2, 5, 2, 1, 0.5 + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 18 + // CHECK-NEXT: dim = ( 4, 9 ) + // CHECK-NEXT: lvl = ( 4, 9 ) + // CHECK-NEXT: pos[0] : ( 0, 4 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3 + // CHECK-NEXT: pos[1] : ( 0, 5, 9, 14, 18 + // CHECK-NEXT: crd[1] : ( 0, 2, 4, 7, 8, 0, 2, 4, 6, 1, 4, 5, 6, 7, 2, 3, 5, 6 + // CHECK-NEXT: values : ( 1, 1, 1, 1.5, 1, 3.1, 1, 0.5, 3.5, 2, 1, 1, 5, 2, 5, 2, 1, 0.5 + // CHECK-NEXT: ---- + // %10 = call @concat_mix_sparse_dim1(%m42, %sm43cd, %sm44dc) : (tensor<4x2xf64>, tensor<4x3xf64, #MAT_C_D>, tensor<4x4xf64, #MAT_D_C>) -> tensor<4x9xf64, #MAT_C_C> - call @dump_mat_4x9(%10) : (tensor<4x9xf64, #MAT_C_C>) -> () + sparse_tensor.print %10 : tensor<4x9xf64, #MAT_C_C> // CHECK: {{\[}}[1, 0, 1, 0, 1, 0, 0, 1.5, 1], // CHECK-NEXT: [3.1, 0, 1, 0, 0.5, 0, 3.5, 0, 0], diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/concatenate_dim_1_permute.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/concatenate_dim_1_permute.mlir index dcdaa072c02f..ce746f27c4d8 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/concatenate_dim_1_permute.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/concatenate_dim_1_permute.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} @@ -85,34 +85,6 @@ module { return %0 : tensor<4x9xf64> } - func.func @dump_mat_4x9(%A: tensor<4x9xf64, #MAT_C_C>) { - %c = sparse_tensor.convert %A : tensor<4x9xf64, #MAT_C_C> to tensor<4x9xf64> - %cu = tensor.cast %c : tensor<4x9xf64> to tensor<*xf64> - call @printMemrefF64(%cu) : (tensor<*xf64>) -> () - - %n = sparse_tensor.number_of_entries %A : tensor<4x9xf64, #MAT_C_C> - vector.print %n : index - - %1 = sparse_tensor.values %A : tensor<4x9xf64, #MAT_C_C> to memref - call @printMemref1dF64(%1) : (memref) -> () - - return - } - - func.func @dump_mat_perm_4x9(%A: tensor<4x9xf64, #MAT_C_C_P>) { - %c = sparse_tensor.convert %A : tensor<4x9xf64, #MAT_C_C_P> to tensor<4x9xf64> - %cu = tensor.cast %c : tensor<4x9xf64> to tensor<*xf64> - call @printMemrefF64(%cu) : (tensor<*xf64>) -> () - - %n = sparse_tensor.number_of_entries %A : tensor<4x9xf64, #MAT_C_C_P> - vector.print %n : index - - %1 = sparse_tensor.values %A : tensor<4x9xf64, #MAT_C_C_P> to memref - call @printMemref1dF64(%1) : (memref) -> () - - return - } - func.func @dump_mat_dense_4x9(%A: tensor<4x9xf64>) { %1 = tensor.cast %A : tensor<4x9xf64> to tensor<*xf64> call @printMemrefF64(%1) : (tensor<*xf64>) -> () @@ -121,7 +93,7 @@ module { } // Driver method to call and verify kernels. - func.func @entry() { + func.func @main() { %m42 = arith.constant dense< [ [ 1.0, 0.0 ], [ 3.1, 0.0 ], @@ -153,15 +125,21 @@ module { %sm43cdp = sparse_tensor.convert %m43 : tensor<4x3xf64> to tensor<4x3xf64, #MAT_C_D_P> %sm44dcp = sparse_tensor.convert %m44 : tensor<4x4xf64> to tensor<4x4xf64, #MAT_D_C_P> - // CHECK: {{\[}}[1, 0, 1, 0, 1, 0, 0, 1.5, 1], - // CHECK-NEXT: [3.1, 0, 1, 0, 0.5, 0, 3.5, 0, 0], - // CHECK-NEXT: [0, 2, 0, 0, 1, 1, 5, 2, 0], - // CHECK-NEXT: [0, 0, 5, 2, 0, 1, 0.5, 0, 0]] - // CHECK-NEXT: 18 - // CHECK: [1, 3.1, 2, 1, 1, 5, 2, 1, 0.5, 1, 1, 1, 3.5, 5, 0.5, 1.5, 2, 1 + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 18 + // CHECK-NEXT: dim = ( 4, 9 ) + // CHECK-NEXT: lvl = ( 9, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 9 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5, 6, 7, 8 + // CHECK-NEXT: pos[1] : ( 0, 2, 3, 6, 7, 10, 12, 15, 17, 18 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 0, 1, 3, 3, 0, 1, 2, 2, 3, 1, 2, 3, 0, 2, 0 + // CHECK-NEXT: values : ( 1, 3.1, 2, 1, 1, 5, 2, 1, 0.5, 1, 1, 1, 3.5, 5, 0.5, 1.5, 2, 1 + // CHECK-NEXT: ---- + // %12 = call @concat_sparse_sparse_perm_dim1(%sm42ccp, %sm43cd, %sm44dc) : (tensor<4x2xf64, #MAT_C_C_P>, tensor<4x3xf64, #MAT_C_D>, tensor<4x4xf64, #MAT_D_C>) -> tensor<4x9xf64, #MAT_C_C_P> - call @dump_mat_perm_4x9(%12) : (tensor<4x9xf64, #MAT_C_C_P>) -> () + sparse_tensor.print %12 : tensor<4x9xf64, #MAT_C_C_P> // CHECK: {{\[}}[1, 0, 1, 0, 1, 0, 0, 1.5, 1], // CHECK-NEXT: [3.1, 0, 1, 0, 0.5, 0, 3.5, 0, 0], @@ -171,15 +149,21 @@ module { : (tensor<4x2xf64, #MAT_C_C_P>, tensor<4x3xf64, #MAT_C_D_P>, tensor<4x4xf64, #MAT_D_C>) -> tensor<4x9xf64> call @dump_mat_dense_4x9(%13) : (tensor<4x9xf64>) -> () - // CHECK: {{\[}}[1, 0, 1, 0, 1, 0, 0, 1.5, 1], - // CHECK-NEXT: [3.1, 0, 1, 0, 0.5, 0, 3.5, 0, 0], - // CHECK-NEXT: [0, 2, 0, 0, 1, 1, 5, 2, 0], - // CHECK-NEXT: [0, 0, 5, 2, 0, 1, 0.5, 0, 0]] - // CHECK-NEXT: 18 - // CHECK: [1, 1, 1, 1.5, 1, 3.1, 1, 0.5, 3.5, 2, 1, 1, 5, 2, 5, 2, 1, 0.5 + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 18 + // CHECK-NEXT: dim = ( 4, 9 ) + // CHECK-NEXT: lvl = ( 4, 9 ) + // CHECK-NEXT: pos[0] : ( 0, 4 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3 + // CHECK-NEXT: pos[1] : ( 0, 5, 9, 14, 18 + // CHECK-NEXT: crd[1] : ( 0, 2, 4, 7, 8, 0, 2, 4, 6, 1, 4, 5, 6, 7, 2, 3, 5, 6 + // CHECK-NEXT: values : ( 1, 1, 1, 1.5, 1, 3.1, 1, 0.5, 3.5, 2, 1, 1, 5, 2, 5, 2, 1, 0.5 + // CHECK-NEXT: ---- + // %14 = call @concat_mix_sparse_perm_dim1(%m42, %sm43cdp, %sm44dc) : (tensor<4x2xf64>, tensor<4x3xf64, #MAT_C_D_P>, tensor<4x4xf64, #MAT_D_C>) -> tensor<4x9xf64, #MAT_C_C> - call @dump_mat_4x9(%14) : (tensor<4x9xf64, #MAT_C_C>) -> () + sparse_tensor.print %14 : tensor<4x9xf64, #MAT_C_C> // CHECK: {{\[}}[1, 0, 1, 0, 1, 0, 0, 1.5, 1], // CHECK-NEXT: [3.1, 0, 1, 0, 0.5, 0, 3.5, 0, 0], diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/dual_sparse_conv_2d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/dual_sparse_conv_2d.mlir index 6c35e2b51ed8..350b5b41dafc 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/dual_sparse_conv_2d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/dual_sparse_conv_2d.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -85,7 +85,7 @@ module { return %0 : tensor<6x6xi32, #CSC> } - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %i0 = arith.constant 0 : i32 @@ -141,7 +141,6 @@ module { : (tensor<8x8xi32, #CSC>, tensor<3x3xi32, #CSC>) -> tensor<6x6xi32, #CSC> - // Verify the output. // // CHECK: ( ( 0, 0, -1, -6, -1, 6 ), @@ -156,64 +155,62 @@ module { vector.print %v : vector<6x6xi32> // - // Should be the same as dense output - // CHECK: ( ( 0, 0, -1, -6, -1, 6 ), - // CHECK-SAME: ( -1, 0, 1, 0, 1, 0 ), - // CHECK-SAME: ( 0, -1, 1, 0, 0, 0 ), - // CHECK-SAME: ( -1, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 0, 0, 3, 6, -3, -6 ), - // CHECK-SAME: ( 2, -1, 3, 0, -3, 0 ) ) + // Should be the same as dense output. // - %all_sparse_DCSR = sparse_tensor.convert %2 - : tensor<6x6xi32, #DCSR> to tensor<6x6xi32> - %v2 = vector.transfer_read %all_sparse_DCSR[%c0, %c0], %i0 - : tensor<6x6xi32>, vector<6x6xi32> - vector.print %v2 : vector<6x6xi32> + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 36 + // CHECK-NEXT: dim = ( 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6 ) + // CHECK-NEXT: pos[0] : ( 0, 6 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[1] : ( 0, 6, 12, 18, 24, 30, 36 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 0, 0, -1, -6, -1, 6, -1, 0, 1, 0, 1, 0, 0, -1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 3, 6, -3, -6, 2, -1, 3, 0, -3, 0 + // CHECK-NEXT: ---- + // + sparse_tensor.print %2 : tensor<6x6xi32, #DCSR> // - // Should be the same as dense output - // CHECK: ( ( 0, 0, -1, -6, -1, 6 ), - // CHECK-SAME: ( -1, 0, 1, 0, 1, 0 ), - // CHECK-SAME: ( 0, -1, 1, 0, 0, 0 ), - // CHECK-SAME: ( -1, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 0, 0, 3, 6, -3, -6 ), - // CHECK-SAME: ( 2, -1, 3, 0, -3, 0 ) ) + // Should be the same as dense output. // - %all_sparse_CD = sparse_tensor.convert %4 - : tensor<6x6xi32, #CDR> to tensor<6x6xi32> - %v4 = vector.transfer_read %all_sparse_CD[%c0, %c0], %i0 - : tensor<6x6xi32>, vector<6x6xi32> - vector.print %v4 : vector<6x6xi32> + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 36 + // CHECK-NEXT: dim = ( 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6 ) + // CHECK-NEXT: pos[1] : ( 0, 6, 12, 18, 24, 30, 36 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 0, 0, -1, -6, -1, 6, -1, 0, 1, 0, 1, 0, 0, -1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 3, 6, -3, -6, 2, -1, 3, 0, -3, 0 + // CHECK-NEXT: ---- + // + sparse_tensor.print %3 : tensor<6x6xi32, #CSR> // - // Should be the same as dense output - // CHECK: ( ( 0, 0, -1, -6, -1, 6 ), - // CHECK-SAME: ( -1, 0, 1, 0, 1, 0 ), - // CHECK-SAME: ( 0, -1, 1, 0, 0, 0 ), - // CHECK-SAME: ( -1, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 0, 0, 3, 6, -3, -6 ), - // CHECK-SAME: ( 2, -1, 3, 0, -3, 0 ) ) + // Should be the same as dense output. // - %all_sparse_CSR = sparse_tensor.convert %3 - : tensor<6x6xi32, #CSR> to tensor<6x6xi32> - %v3 = vector.transfer_read %all_sparse_CSR[%c0, %c0], %i0 - : tensor<6x6xi32>, vector<6x6xi32> - vector.print %v3 : vector<6x6xi32> + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 36 + // CHECK-NEXT: dim = ( 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6 ) + // CHECK-NEXT: pos[0] : ( 0, 6 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 0, 0, -1, -6, -1, 6, -1, 0, 1, 0, 1, 0, 0, -1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 3, 6, -3, -6, 2, -1, 3, 0, -3, 0 + // CHECK-NEXT: ---- + // + sparse_tensor.print %4 : tensor<6x6xi32, #CDR> // - // Should be the same as dense output - // CHECK: ( ( 0, 0, -1, -6, -1, 6 ), - // CHECK-SAME: ( -1, 0, 1, 0, 1, 0 ), - // CHECK-SAME: ( 0, -1, 1, 0, 0, 0 ), - // CHECK-SAME: ( -1, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 0, 0, 3, 6, -3, -6 ), - // CHECK-SAME: ( 2, -1, 3, 0, -3, 0 ) ) + // Should be the same as dense output. // - %all_sparse_CSC = sparse_tensor.convert %5 - : tensor<6x6xi32, #CSC> to tensor<6x6xi32> - %v5 = vector.transfer_read %all_sparse_CSC[%c0, %c0], %i0 - : tensor<6x6xi32>, vector<6x6xi32> - vector.print %v5 : vector<6x6xi32> + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 36 + // CHECK-NEXT: dim = ( 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6 ) + // CHECK-NEXT: pos[1] : ( 0, 6, 12, 18, 24, 30, 36 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 0, -1, 0, -1, 0, 2, 0, 0, -1, 0, 0, -1, -1, 1, 1, 0, 3, 3, -6, 0, 0, 0, 6, 0, -1, 1, 0, 0, -3, -3, 6, 0, 0, 0, -6, 0 + // CHECK-NEXT: ---- + // + sparse_tensor.print %5 : tensor<6x6xi32, #CSC> // Release the resources. bufferization.dealloc_tensor %sparse_input_DCSR : tensor<8x8xi32, #DCSR> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/reshape_dot.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/reshape_dot.mlir index 689428c23f7d..ebf9f4392d85 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/reshape_dot.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/reshape_dot.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -84,7 +84,7 @@ module { } - func.func @entry() { + func.func @main() { // Setup two sparse vectors. %d1 = arith.constant sparse< [ [0, 0], [1, 1], [2, 2], [2, 3], [4, 5] ], diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_block3d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_block3d.mlir index 024e86b4f165..2ff73923c832 100755 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_block3d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_block3d.mlir @@ -90,28 +90,38 @@ module { // ending at index (3,3,2)) with a “DCSR-flavored” along (j,k) with // dense “fibers” in the i-dim, we end up with 8 stored entries. // - // CHECK: 8 - // CHECK-NEXT: ( 1, 2, 3, 4, 5, 6, 7, 8 ) + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 4, 4, 4 ) + // CHECK-NEXT: lvl = ( 4, 4, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 0, 3 + // CHECK-NEXT: pos[1] : ( 0, 1, 2 + // CHECK-NEXT: crd[1] : ( 0, 2 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7, 8 + // CHECK-NEXT: ---- // - %na = sparse_tensor.number_of_entries %a : tensor<4x4x4xi32, #Sparse1> - vector.print %na : index - %ma = sparse_tensor.values %a: tensor<4x4x4xi32, #Sparse1> to memref - %va = vector.transfer_read %ma[%c0], %i0: memref, vector<8xi32> - vector.print %va : vector<8xi32> + sparse_tensor.print %a : tensor<4x4x4xi32, #Sparse1> // // If we store full 2x2x2 3-D blocks in the original index order // in a compressed fashion, we end up with 4 blocks to incorporate // all the nonzeros, and thus 32 stored entries. // - // CHECK: 32 - // CHECK-NEXT: ( 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 5, 0, 0, 0, 6, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 7, 0, 0, 0, 8, 0 ) + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 32 + // CHECK-NEXT: dim = ( 4, 4, 4 ) + // CHECK-NEXT: lvl = ( 2, 2, 2, 2, 2, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 0, 1 + // CHECK-NEXT: pos[1] : ( 0, 2, 4 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 1, 2, 3, 4 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 5, 0, 0, 0, 6, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 7, 0, 0, 0, 8, 0 + // CHECK-NEXT: ---- // - %nb = sparse_tensor.number_of_entries %b : tensor<4x4x4xi32, #Sparse2> - vector.print %nb : index - %mb = sparse_tensor.values %b: tensor<4x4x4xi32, #Sparse2> to memref - %vb = vector.transfer_read %mb[%c0], %i0: memref, vector<32xi32> - vector.print %vb : vector<32xi32> + sparse_tensor.print %b : tensor<4x4x4xi32, #Sparse2> // Release the resources. bufferization.dealloc_tensor %a : tensor<4x4x4xi32, #Sparse1> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_cast.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_cast.mlir index 6efe7b334b98..3b5168db23c5 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_cast.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_cast.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -178,7 +178,7 @@ module { // Main driver that converts a dense tensor into a sparse tensor // and then calls the sparse casting kernel. // - func.func @entry() { + func.func @main() { %z = arith.constant 0 : index %b = arith.constant 0 : i8 %i = arith.constant 0 : i32 diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_cmp.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_cmp.mlir index 035db33fb4b3..732bde55be91 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_cmp.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_cmp.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -96,7 +96,7 @@ module { // Main driver that constructs matrix and calls the sparse kernel to perform // element-wise comparison. // - func.func @entry() { + func.func @main() { %d0 = arith.constant 0 : i8 %c0 = arith.constant 0 : index @@ -124,33 +124,44 @@ module { : (tensor<4x4xf64, #DCSR>, tensor<4x4xf64, #DCSR>) -> tensor<4x4xi8, #DCSR> // - // All should have the same result. + // All should have the same boolean values. + // + // CHECK: ( ( 0, 1, 0, 1 ), ( 1, 0, 0, 0 ), ( 1, 0, 0, 1 ), ( 0, 0, 0, 0 ) ) + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 16 + // CHECK-NEXT: dim = ( 4, 4 ) + // CHECK-NEXT: lvl = ( 4, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 4 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12, 16 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 11 + // CHECK-NEXT: dim = ( 4, 4 ) + // CHECK-NEXT: lvl = ( 4, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 4 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 9, 11 + // CHECK-NEXT: crd[1] : ( 1, 2, 3, 0, 1, 0, 1, 2, 3, 0, 1 + // CHECK-NEXT: values : ( 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0 + // CHECK-NEXT: ---- // - // CHECK-COUNT-3: ( ( 0, 1, 0, 1 ), ( 1, 0, 0, 0 ), ( 1, 0, 0, 1 ), ( 0, 0, 0, 0 ) ) %v = vector.transfer_read %all_dn_out[%c0, %c0], %d0 : tensor<4x4xi8>, vector<4x4xi8> vector.print %v : vector<4x4xi8> - - %lhs_sp_ret = sparse_tensor.convert %lhs_sp_out - : tensor<4x4xi8, #DCSR> to tensor<4x4xi8> - %v1 = vector.transfer_read %lhs_sp_ret[%c0, %c0], %d0 - : tensor<4x4xi8>, vector<4x4xi8> - vector.print %v1 : vector<4x4xi8> - - %rhs_sp_ret = sparse_tensor.convert %all_sp_out - : tensor<4x4xi8, #DCSR> to tensor<4x4xi8> - %v2 = vector.transfer_read %rhs_sp_ret[%c0, %c0], %d0 - : tensor<4x4xi8>, vector<4x4xi8> - vector.print %v2 : vector<4x4xi8> - + sparse_tensor.print %lhs_sp_out : tensor<4x4xi8, #DCSR> + sparse_tensor.print %all_sp_out : tensor<4x4xi8, #DCSR> bufferization.dealloc_tensor %lhs_sp : tensor<4x4xf64, #DCSR> bufferization.dealloc_tensor %rhs_sp : tensor<4x4xf64, #DCSR> bufferization.dealloc_tensor %all_dn_out : tensor<4x4xi8> bufferization.dealloc_tensor %lhs_sp_out : tensor<4x4xi8, #DCSR> bufferization.dealloc_tensor %all_sp_out : tensor<4x4xi8, #DCSR> - bufferization.dealloc_tensor %lhs_sp_ret : tensor<4x4xi8> - bufferization.dealloc_tensor %rhs_sp_ret : tensor<4x4xi8> + return } } diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_codegen_dim.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_codegen_dim.mlir index 7925759714ed..c5d002aa1639 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_codegen_dim.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_codegen_dim.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -38,7 +38,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c2 = arith.constant 2 : index diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_codegen_foreach.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_codegen_foreach.mlir index 002a79055ce5..9deb5cd05fa3 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_codegen_foreach.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_codegen_foreach.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -144,7 +144,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { // // Initialize a 3-dim dense tensor. // @@ -166,6 +166,7 @@ module { %s4 = sparse_tensor.convert %src : tensor<2x2xf64> to tensor<2x2xf64, #SortedCOO> %s5 = sparse_tensor.convert %src : tensor<2x2xf64> to tensor<2x2xf64, #SortedCOOPerm> %s6 = sparse_tensor.convert %src3d : tensor<7x8x9xf64> to tensor<7x8x9xf64, #CCCPerm> + // CHECK: 0 // CHECK-NEXT: 0 // CHECK-NEXT: 1 @@ -173,6 +174,7 @@ module { // CHECK-NEXT: 6 // CHECK-NEXT: 5 call @foreach_print_const() : () -> () + // CHECK-NEXT: 0 // CHECK-NEXT: 0 // CHECK-NEXT: 1 @@ -186,6 +188,7 @@ module { // CHECK-NEXT: 1 // CHECK-NEXT: 6 call @foreach_print_dense(%src) : (tensor<2x2xf64>) -> () + // CHECK-NEXT: 0 // CHECK-NEXT: 0 // CHECK-NEXT: 1 @@ -199,6 +202,7 @@ module { // CHECK-NEXT: 1 // CHECK-NEXT: 6 call @foreach_print_1(%s1) : (tensor<2x2xf64, #Row>) -> () + // CHECK-NEXT: 0 // CHECK-NEXT: 0 // CHECK-NEXT: 1 @@ -212,6 +216,7 @@ module { // CHECK-NEXT: 1 // CHECK-NEXT: 6 call @foreach_print_2(%s2) : (tensor<2x2xf64, #CSR>) -> () + // CHECK-NEXT: 0 // CHECK-NEXT: 0 // CHECK-NEXT: 1 @@ -225,6 +230,7 @@ module { // CHECK-NEXT: 1 // CHECK-NEXT: 6 call @foreach_print_3(%s3) : (tensor<2x2xf64, #DCSC>) -> () + // CHECK-NEXT: 0 // CHECK-NEXT: 0 // CHECK-NEXT: 1 @@ -238,6 +244,7 @@ module { // CHECK-NEXT: 1 // CHECK-NEXT: 6 call @foreach_print_4(%s4) : (tensor<2x2xf64, #SortedCOO>) -> () + // CHECK-NEXT: 0 // CHECK-NEXT: 0 // CHECK-NEXT: 1 diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_collapse_shape.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_collapse_shape.mlir index 2b5155464f0e..cae599fa30ae 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_collapse_shape.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_collapse_shape.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -115,7 +115,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %df = arith.constant -1.0 : f64 @@ -157,69 +157,95 @@ module { // // CHECK: ( 1.1, 0, 1.3, 0, 2.1, 0, 2.3, 0, 3.1, 0, 3.3, 0 ) // CHECK-NEXT: ( 1.1, 0, 1.3, 0, 2.1, 0, 2.3, 0, 3.1, 0, 3.3, 0 ) - // CHECK-NEXT: ( 1.1, 1.3, 2.1, 2.3, 3.1, 3.3 - // CHECK-NEXT: ( 1.1, 1.3, 2.1, 2.3, 3.1, 3.3 - // CHECK-NEXT: ( ( 1, 0, 3, 0, 5, 0, 7, 0, 9, 0 ), - // CHECK-SAME: ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 21, 0, 23, 0, 25, 0, 27, 0, 29, 0 ), - // CHECK-SAME: ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 41, 0, 43, 0, 45, 0, 47, 0, 49, 0 ), - // CHECK-SAME: ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) ) - // CHECK-NEXT: ( ( 1, 0, 3, 0, 5, 0, 7, 0, 9, 0 ), - // CHECK-SAME: ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 21, 0, 23, 0, 25, 0, 27, 0, 29, 0 ), - // CHECK-SAME: ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 41, 0, 43, 0, 45, 0, 47, 0, 49, 0 ), - // CHECK-SAME: ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) ) - // CHECK-NEXT: ( 1, 3, 5, 7, 9, 21, 23, 25, 27, 29, 41, 43, 45, 47 - // CHECK-NEXT: ( 1, 3, 5, 7, 9, 21, 23, 25, 27, 29, 41, 43, 45, 47 - // CHECK-NEXT: ( ( 1, 0, 3, 0, 5, 0, 7, 0, 9, 0 ), - // CHECK-SAME: ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 21, 0, 23, 0, 25, 0, 27, 0, 29, 0 ), - // CHECK-SAME: ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 41, 0, 43, 0, 45, 0, 47, 0, 49, 0 ), - // CHECK-SAME: ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) ) - // CHECK-NEXT: ( ( 1, 0, 3, 0, 5, 0, 7, 0, 9, 0 ), - // CHECK-SAME: ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 21, 0, 23, 0, 25, 0, 27, 0, 29, 0 ), - // CHECK-SAME: ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 41, 0, 43, 0, 45, 0, 47, 0, 49, 0 ), - // CHECK-SAME: ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) ) - // CHECK-NEXT: ( 1, 3, 5, 7, 9, 21, 23, 25, 27, 29, 41, 43, 45, 47, 49 - // CHECK-NEXT: ( 1, 3, 5, 7, 9, 21, 23, 25, 27, 29, 41, 43, 45, 47, 49 - + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 6 + // CHECK-NEXT: dim = ( 12 ) + // CHECK-NEXT: lvl = ( 12 ) + // CHECK-NEXT: pos[0] : ( 0, 6 + // CHECK-NEXT: crd[0] : ( 0, 2, 4, 6, 8, 10 + // CHECK-NEXT: values : ( 1.1, 1.3, 2.1, 2.3, 3.1, 3.3 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 6 + // CHECK-NEXT: dim = ( 12 ) + // CHECK-NEXT: lvl = ( 12 ) + // CHECK-NEXT: pos[0] : ( 0, 6 + // CHECK-NEXT: crd[0] : ( 0, 2, 4, 6, 8, 10 + // CHECK-NEXT: values : ( 1.1, 1.3, 2.1, 2.3, 3.1, 3.3 + // CHECK-NEXT: ---- + // + // CHECK: ( ( 1, 0, 3, 0, 5, 0, 7, 0, 9, 0 ), ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), ( 21, 0, 23, 0, 25, 0, 27, 0, 29, 0 ), ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), ( 41, 0, 43, 0, 45, 0, 47, 0, 49, 0 ), ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) ) + // CHECK-NEXT: ( ( 1, 0, 3, 0, 5, 0, 7, 0, 9, 0 ), ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), ( 21, 0, 23, 0, 25, 0, 27, 0, 29, 0 ), ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), ( 41, 0, 43, 0, 45, 0, 47, 0, 49, 0 ), ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) ) + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 15 + // CHECK-NEXT: dim = ( 6, 10 ) + // CHECK-NEXT: lvl = ( 6, 10 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 2, 4 + // CHECK-NEXT: pos[1] : ( 0, 5, 10, 15 + // CHECK-NEXT: crd[1] : ( 0, 2, 4, 6, 8, 0, 2, 4, 6, 8, 0, 2, 4, 6, 8 + // CHECK-NEXT: values : ( 1, 3, 5, 7, 9, 21, 23, 25, 27, 29, 41, 43, 45, 47, 49 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 15 + // CHECK-NEXT: dim = ( 6, 10 ) + // CHECK-NEXT: lvl = ( 6, 10 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 2, 4 + // CHECK-NEXT: pos[1] : ( 0, 5, 10, 15 + // CHECK-NEXT: crd[1] : ( 0, 2, 4, 6, 8, 0, 2, 4, 6, 8, 0, 2, 4, 6, 8 + // CHECK-NEXT: values : ( 1, 3, 5, 7, 9, 21, 23, 25, 27, 29, 41, 43, 45, 47, 49 + // CHECK-NEXT: ---- + // + // CHECK: ( ( 1, 0, 3, 0, 5, 0, 7, 0, 9, 0 ), ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), ( 21, 0, 23, 0, 25, 0, 27, 0, 29, 0 ), ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), ( 41, 0, 43, 0, 45, 0, 47, 0, 49, 0 ), ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) ) + // CHECK-NEXT: ( ( 1, 0, 3, 0, 5, 0, 7, 0, 9, 0 ), ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), ( 21, 0, 23, 0, 25, 0, 27, 0, 29, 0 ), ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), ( 41, 0, 43, 0, 45, 0, 47, 0, 49, 0 ), ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) ) + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 15 + // CHECK-NEXT: dim = ( 6, 10 ) + // CHECK-NEXT: lvl = ( 6, 10 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 2, 4 + // CHECK-NEXT: pos[1] : ( 0, 5, 10, 15 + // CHECK-NEXT: crd[1] : ( 0, 2, 4, 6, 8, 0, 2, 4, 6, 8, 0, 2, 4, 6, 8 + // CHECK-NEXT: values : ( 1, 3, 5, 7, 9, 21, 23, 25, 27, 29, 41, 43, 45, 47, 49 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 15 + // CHECK-NEXT: dim = ( 6, 10 ) + // CHECK-NEXT: lvl = ( 6, 10 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 2, 4 + // CHECK-NEXT: pos[1] : ( 0, 5, 10, 15 + // CHECK-NEXT: crd[1] : ( 0, 2, 4, 6, 8, 0, 2, 4, 6, 8, 0, 2, 4, 6, 8 + // CHECK-NEXT: values : ( 1, 3, 5, 7, 9, 21, 23, 25, 27, 29, 41, 43, 45, 47, 49 + // CHECK-NEXT: ---- + // %v0 = vector.transfer_read %collapse0[%c0], %df: tensor<12xf64>, vector<12xf64> vector.print %v0 : vector<12xf64> %v1 = vector.transfer_read %collapse1[%c0], %df: tensor<12xf64>, vector<12xf64> vector.print %v1 : vector<12xf64> - %b2 = sparse_tensor.values %collapse2 : tensor<12xf64, #SparseVector> to memref - %v2 = vector.transfer_read %b2[%c0], %df: memref, vector<12xf64> - vector.print %v2 : vector<12xf64> - %b3 = sparse_tensor.values %collapse3 : tensor<12xf64, #SparseVector> to memref - %v3 = vector.transfer_read %b3[%c0], %df: memref, vector<12xf64> - vector.print %v3 : vector<12xf64> + sparse_tensor.print %collapse2 : tensor<12xf64, #SparseVector> + sparse_tensor.print %collapse3 : tensor<12xf64, #SparseVector> %v4 = vector.transfer_read %collapse4[%c0, %c0], %df: tensor<6x10xf64>, vector<6x10xf64> vector.print %v4 : vector<6x10xf64> %v5 = vector.transfer_read %collapse5[%c0, %c0], %df: tensor<6x10xf64>, vector<6x10xf64> vector.print %v5 : vector<6x10xf64> - %b6 = sparse_tensor.values %collapse6 : tensor<6x10xf64, #SparseMatrix> to memref - %v6 = vector.transfer_read %b6[%c0], %df: memref, vector<60xf64> - vector.print %v6 : vector<60xf64> - %b7 = sparse_tensor.values %collapse7 : tensor<6x10xf64, #SparseMatrix> to memref - %v7 = vector.transfer_read %b7[%c0], %df: memref, vector<60xf64> - vector.print %v7 : vector<60xf64> + sparse_tensor.print %collapse6 : tensor<6x10xf64, #SparseMatrix> + sparse_tensor.print %collapse7 : tensor<6x10xf64, #SparseMatrix> %v8 = vector.transfer_read %collapse8[%c0, %c0], %df: tensor, vector<6x10xf64> vector.print %v8 : vector<6x10xf64> %v9 = vector.transfer_read %collapse9[%c0, %c0], %df: tensor, vector<6x10xf64> vector.print %v9 : vector<6x10xf64> - %b10 = sparse_tensor.values %collapse10 : tensor to memref - %v10 = vector.transfer_read %b10[%c0], %df: memref, vector<60xf64> - vector.print %v10 : vector<60xf64> - %b11 = sparse_tensor.values %collapse11 : tensor to memref - %v11 = vector.transfer_read %b11[%c0], %df: memref, vector<60xf64> - vector.print %v11 : vector<60xf64> + sparse_tensor.print %collapse10 : tensor + sparse_tensor.print %collapse11 : tensor // Release sparse resources. bufferization.dealloc_tensor %sm : tensor<3x4xf64, #SparseMatrix> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_constant_to_sparse_tensor.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_constant_to_sparse_tensor.mlir index b5efdcc09a39..abdbf80d0bc4 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_constant_to_sparse_tensor.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_constant_to_sparse_tensor.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -38,7 +38,7 @@ // Integration tests for conversions from sparse constants to sparse tensors. // module { - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c2 = arith.constant 2 : index @@ -51,20 +51,19 @@ module { // Convert the tensor in COO format to a sparse tensor with annotation #Tensor1. %ts = sparse_tensor.convert %ti : tensor<10x8xf64> to tensor<10x8xf64, #Tensor1> - // CHECK: ( 0, 1, 4, 5, 6, 9 ) - %i0 = sparse_tensor.coordinates %ts { level = 0 : index } : tensor<10x8xf64, #Tensor1> to memref - %i0r = vector.transfer_read %i0[%c0], %c0: memref, vector<6xindex> - vector.print %i0r : vector<6xindex> - - // CHECK: ( 0, 7, 2, 2, 3, 4, 6, 7 ) - %i1 = sparse_tensor.coordinates %ts { level = 1 : index } : tensor<10x8xf64, #Tensor1> to memref - %i1r = vector.transfer_read %i1[%c0], %c0: memref, vector<8xindex> - vector.print %i1r : vector<8xindex> - - // CHECK: ( 1, 2, 3, 4, 5, 6, 7, 8 ) - %v = sparse_tensor.values %ts : tensor<10x8xf64, #Tensor1> to memref - %vr = vector.transfer_read %v[%c0], %d0: memref, vector<8xf64> - vector.print %vr : vector<8xf64> + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 10, 8 ) + // CHECK-NEXT: lvl = ( 10, 8 ) + // CHECK-NEXT: pos[0] : ( 0, 6 + // CHECK-NEXT: crd[0] : ( 0, 1, 4, 5, 6, 9 + // CHECK-NEXT: pos[1] : ( 0, 2, 3, 4, 5, 7, 8 + // CHECK-NEXT: crd[1] : ( 0, 7, 2, 2, 3, 4, 6, 7 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7, 8 + // CHECK-NEXT: ---- + // + sparse_tensor.print %ts : tensor<10x8xf64, #Tensor1> // Release the resources. bufferization.dealloc_tensor %ts : tensor<10x8xf64, #Tensor1> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_1d_nwc_wcf.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_1d_nwc_wcf.mlir index 16a67a145836..612e62bd34d2 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_1d_nwc_wcf.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_1d_nwc_wcf.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -79,7 +79,7 @@ func.func @conv_1d_nwc_wcf_CDC(%arg0: tensor, %arg1: tensor } -func.func @entry() { +func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c3 = arith.constant 3 : index @@ -111,23 +111,35 @@ func.func @entry() { : tensor, vector<3x6x1xf32> vector.print %dense_v : vector<3x6x1xf32> - // CHECK: ( ( ( 12 ), ( 28 ), ( 28 ), ( 28 ), ( 12 ), ( 12 ) ), - // CHECK-SAME: ( ( 12 ), ( 12 ), ( 12 ), ( 12 ), ( 12 ), ( 12 ) ), - // CHECK-SAME: ( ( 12 ), ( 12 ), ( 12 ), ( 12 ), ( 12 ), ( 12 ) ) ) - %1 = sparse_tensor.convert %CCC_ret - : tensor to tensor - %v1 = vector.transfer_read %1[%c0, %c0, %c0], %zero - : tensor, vector<3x6x1xf32> - vector.print %v1 : vector<3x6x1xf32> - - // CHECK: ( ( ( 12 ), ( 28 ), ( 28 ), ( 28 ), ( 12 ), ( 12 ) ), - // CHECK-SAME: ( ( 12 ), ( 12 ), ( 12 ), ( 12 ), ( 12 ), ( 12 ) ), - // CHECK-SAME: ( ( 12 ), ( 12 ), ( 12 ), ( 12 ), ( 12 ), ( 12 ) ) ) - %2 = sparse_tensor.convert %CDC_ret - : tensor to tensor - %v2 = vector.transfer_read %2[%c0, %c0, %c0], %zero - : tensor, vector<3x6x1xf32> - vector.print %v2 : vector<3x6x1xf32> + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 18 + // CHECK-NEXT: dim = ( 3, 6, 1 ) + // CHECK-NEXT: lvl = ( 3, 6, 1 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 6, 12, 18 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[2] : ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 + // CHECK-NEXT: crd[2] : ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + // CHECK-NEXT: values : ( 12, 28, 28, 28, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 + // CHECK-NEXT: ---- + // + sparse_tensor.print %CCC_ret : tensor + + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 18 + // CHECK-NEXT: dim = ( 3, 6, 1 ) + // CHECK-NEXT: lvl = ( 3, 6, 1 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[2] : ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 + // CHECK-NEXT: crd[2] : ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + // CHECK-NEXT: values : ( 12, 28, 28, 28, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 + // CHECK-NEXT: ---- + // + sparse_tensor.print %CDC_ret : tensor // Free the resources bufferization.dealloc_tensor %in1D_nwc : tensor @@ -140,8 +152,5 @@ func.func @entry() { bufferization.dealloc_tensor %CCC_ret : tensor bufferization.dealloc_tensor %CDC_ret : tensor - bufferization.dealloc_tensor %1 : tensor - bufferization.dealloc_tensor %2 : tensor - return } diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d.mlir index 41071ea700fb..f8fb8fdf53e3 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -113,7 +113,7 @@ module { return %0 : tensor<6x6xi32, #CSC> } - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %i0 = arith.constant 0 : i32 @@ -181,82 +181,81 @@ module { vector.print %v : vector<6x6xi32> // - // Should be the same as dense output - // CHECK: ( ( 0, 0, -1, -6, -1, 6 ), - // CHECK-SAME: ( -1, 0, 1, 0, 1, 0 ), - // CHECK-SAME: ( 0, -1, 1, 0, 0, 0 ), - // CHECK-SAME: ( -1, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 0, 0, 3, 6, -3, -6 ), - // CHECK-SAME: ( 2, -1, 3, 0, -3, 0 ) ) + // Should be the same as dense output. // - %sparse_ret = sparse_tensor.convert %1 - : tensor<6x6xi32, #DCSR> to tensor<6x6xi32> - %v1 = vector.transfer_read %sparse_ret[%c0, %c0], %i0 - : tensor<6x6xi32>, vector<6x6xi32> - vector.print %v1 : vector<6x6xi32> + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 36 + // CHECK-NEXT: dim = ( 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6 ) + // CHECK-NEXT: pos[0] : ( 0, 6 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[1] : ( 0, 6, 12, 18, 24, 30, 36 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 0, 0, -1, -6, -1, 6, -1, 0, 1, 0, 1, 0, 0, -1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 3, 6, -3, -6, 2, -1, 3, 0, -3, 0 + // CHECK-NEXT: ---- + // + sparse_tensor.print %1 : tensor<6x6xi32, #DCSR> // - // Should be the same as dense output - // CHECK: ( ( 0, 0, -1, -6, -1, 6 ), - // CHECK-SAME: ( -1, 0, 1, 0, 1, 0 ), - // CHECK-SAME: ( 0, -1, 1, 0, 0, 0 ), - // CHECK-SAME: ( -1, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 0, 0, 3, 6, -3, -6 ), - // CHECK-SAME: ( 2, -1, 3, 0, -3, 0 ) ) + // Should be the same as dense output. // - %all_sparse_DCSR = sparse_tensor.convert %2 - : tensor<6x6xi32, #DCSR> to tensor<6x6xi32> - %v2 = vector.transfer_read %all_sparse_DCSR[%c0, %c0], %i0 - : tensor<6x6xi32>, vector<6x6xi32> - vector.print %v2 : vector<6x6xi32> + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 36 + // CHECK-NEXT: dim = ( 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6 ) + // CHECK-NEXT: pos[0] : ( 0, 6 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[1] : ( 0, 6, 12, 18, 24, 30, 36 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 0, 0, -1, -6, -1, 6, -1, 0, 1, 0, 1, 0, 0, -1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 3, 6, -3, -6, 2, -1, 3, 0, -3, 0 + // CHECK-NEXT: ---- + // + sparse_tensor.print %2 : tensor<6x6xi32, #DCSR> // - // Should be the same as dense output - // CHECK: ( ( 0, 0, -1, -6, -1, 6 ), - // CHECK-SAME: ( -1, 0, 1, 0, 1, 0 ), - // CHECK-SAME: ( 0, -1, 1, 0, 0, 0 ), - // CHECK-SAME: ( -1, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 0, 0, 3, 6, -3, -6 ), - // CHECK-SAME: ( 2, -1, 3, 0, -3, 0 ) ) + // Should be the same as dense output. // - %all_sparse_CD = sparse_tensor.convert %4 - : tensor<6x6xi32, #CDR> to tensor<6x6xi32> - %v4 = vector.transfer_read %all_sparse_CD[%c0, %c0], %i0 - : tensor<6x6xi32>, vector<6x6xi32> - vector.print %v4 : vector<6x6xi32> + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 36 + // CHECK-NEXT: dim = ( 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6 ) + // CHECK-NEXT: pos[1] : ( 0, 6, 12, 18, 24, 30, 36 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 0, 0, -1, -6, -1, 6, -1, 0, 1, 0, 1, 0, 0, -1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 3, 6, -3, -6, 2, -1, 3, 0, -3, 0 + // CHECK-NEXT: ---- + // + sparse_tensor.print %3 : tensor<6x6xi32, #CSR> // - // Should be the same as dense output - // CHECK: ( ( 0, 0, -1, -6, -1, 6 ), - // CHECK-SAME: ( -1, 0, 1, 0, 1, 0 ), - // CHECK-SAME: ( 0, -1, 1, 0, 0, 0 ), - // CHECK-SAME: ( -1, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 0, 0, 3, 6, -3, -6 ), - // CHECK-SAME: ( 2, -1, 3, 0, -3, 0 ) ) + // Should be the same as dense output. // - %all_sparse_CSR = sparse_tensor.convert %3 - : tensor<6x6xi32, #CSR> to tensor<6x6xi32> - %v3 = vector.transfer_read %all_sparse_CSR[%c0, %c0], %i0 - : tensor<6x6xi32>, vector<6x6xi32> - vector.print %v3 : vector<6x6xi32> + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 36 + // CHECK-NEXT: dim = ( 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6 ) + // CHECK-NEXT: pos[0] : ( 0, 6 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 0, 0, -1, -6, -1, 6, -1, 0, 1, 0, 1, 0, 0, -1, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 3, 6, -3, -6, 2, -1, 3, 0, -3, 0 + // CHECK-NEXT: ---- + // + sparse_tensor.print %4 : tensor<6x6xi32, #CDR> // - // Should be the same as dense output - // CHECK: ( ( 0, 0, -1, -6, -1, 6 ), - // CHECK-SAME: ( -1, 0, 1, 0, 1, 0 ), - // CHECK-SAME: ( 0, -1, 1, 0, 0, 0 ), - // CHECK-SAME: ( -1, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 0, 0, 3, 6, -3, -6 ), - // CHECK-SAME: ( 2, -1, 3, 0, -3, 0 ) ) + // Should be the same as dense output. // - %all_sparse_CSC = sparse_tensor.convert %5 - : tensor<6x6xi32, #CSC> to tensor<6x6xi32> - %v5 = vector.transfer_read %all_sparse_CSC[%c0, %c0], %i0 - : tensor<6x6xi32>, vector<6x6xi32> - vector.print %v5 : vector<6x6xi32> + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 36 + // CHECK-NEXT: dim = ( 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6 ) + // CHECK-NEXT: pos[1] : ( 0, 6, 12, 18, 24, 30, 36 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 0, -1, 0, -1, 0, 2, 0, 0, -1, 0, 0, -1, -1, 1, 1, 0, 3, 3, -6, 0, 0, 0, 6, 0, -1, 1, 0, 0, -3, -3, 6, 0, 0, 0, -6, 0 + // CHECK-NEXT: ---- + // + sparse_tensor.print %5 : tensor<6x6xi32, #CSC> // - // Should be the same as dense output + // Should be the same as dense output. // CHECK: ( ( 0, 0, -1, -6, -1, 6 ), // CHECK-SAME: ( -1, 0, 1, 0, 1, 0 ), // CHECK-SAME: ( 0, -1, 1, 0, 0, 0 ), diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d_55.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d_55.mlir index a7d7d1c5ed3c..00805d198013 100755 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d_55.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d_55.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -68,7 +68,7 @@ module { return %0 : tensor<6x6xi32> } - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %i0 = arith.constant 0 : i32 diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d_nchw_fchw.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d_nchw_fchw.mlir index 95ce4f1bf48d..9150e97e7248 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d_nchw_fchw.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d_nchw_fchw.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -82,7 +82,7 @@ func.func @conv_2d_nchw_fchw_CCCC_CCCC(%arg0: tensor, %arg1: return %ret : tensor } -func.func @entry() { +func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c3 = arith.constant 3 : index diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d_nhwc_hwcf.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d_nhwc_hwcf.mlir index d0fbce7146fe..d04311e59baf 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d_nhwc_hwcf.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d_nhwc_hwcf.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -93,7 +93,7 @@ func.func @conv_2d_nhwc_hwcf_DCCD(%arg0: tensor, %arg1: tens return %ret : tensor } -func.func @entry() { +func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c3 = arith.constant 3 : index @@ -142,77 +142,93 @@ func.func @entry() { : tensor, vector<3x6x6x1xf32> vector.print %dense_v : vector<3x6x6x1xf32> - // CHECK: ( ( ( ( 108 ), ( 124 ), ( 124 ), ( 124 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ) ) - %1 = sparse_tensor.convert %CCCC_ret - : tensor to tensor - %v1 = vector.transfer_read %1[%c0, %c0, %c0, %c0], %zero - : tensor, vector<3x6x6x1xf32> - vector.print %v1 : vector<3x6x6x1xf32> - - // CHECK: ( ( ( ( 108 ), ( 124 ), ( 124 ), ( 124 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ) ) - %2 = sparse_tensor.convert %CDCD_ret - : tensor to tensor - %v2 = vector.transfer_read %2[%c0, %c0, %c0, %c0], %zero - : tensor, vector<3x6x6x1xf32> - vector.print %v2 : vector<3x6x6x1xf32> - - // CHECK: ( ( ( ( 108 ), ( 124 ), ( 124 ), ( 124 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ) ) - %3 = sparse_tensor.convert %DCCD_ret - : tensor to tensor - %v3 = vector.transfer_read %3[%c0, %c0, %c0, %c0], %zero - : tensor, vector<3x6x6x1xf32> - vector.print %v3 : vector<3x6x6x1xf32> + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 108 + // CHECK-NEXT: dim = ( 3, 6, 6, 1 ) + // CHECK-NEXT: lvl = ( 3, 6, 6, 1 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 6, 12, 18 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[2] : ( 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96, 102, 108 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, + // CHECK-SAME: 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, + // CHECK-SAME: 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[3] : ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + // CHECK-SAME: 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + // CHECK-SAME: 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + // CHECK-SAME: 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + // CHECK-SAME: 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + // CHECK-SAME: 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108 + // CHECK-NEXT: crd[3] : ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0 + // CHECK-NEXT: values : ( 108, 124, 124, 124, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108 + // CHECK-NEXT: ---- + // + sparse_tensor.print %CCCC_ret : tensor + + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 108 + // CHECK-NEXT: dim = ( 3, 6, 6, 1 ) + // CHECK-NEXT: lvl = ( 3, 6, 6, 1 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[2] : ( 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96, 102, 108 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, + // CHECK-SAME: 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, + // CHECK-SAME: 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 108, 124, 124, 124, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108 + // CHECK-NEXT: ---- + // + sparse_tensor.print %CDCD_ret : tensor + + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 108 + // CHECK-NEXT: dim = ( 3, 6, 6, 1 ) + // CHECK-NEXT: lvl = ( 3, 6, 6, 1 ) + // CHECK-NEXT: pos[1] : ( 0, 6, 12, 18 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[2] : ( 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96, 102, 108 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, + // CHECK-SAME: 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, + // CHECK-SAME: 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 108, 124, 124, 124, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108 + // CHECK-NEXT: ---- + // + sparse_tensor.print %DCCD_ret : tensor // Free the resources bufferization.dealloc_tensor %in2D_nhwc : tensor @@ -227,9 +243,5 @@ func.func @entry() { bufferization.dealloc_tensor %CDCD_ret : tensor bufferization.dealloc_tensor %DCCD_ret : tensor - bufferization.dealloc_tensor %1 : tensor - bufferization.dealloc_tensor %2 : tensor - bufferization.dealloc_tensor %3 : tensor - return } diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_3d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_3d.mlir index f0a26dc46b05..5e2d1707a249 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_3d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_3d.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -96,7 +96,7 @@ func.func @conv_3d_DDC(%arg0: tensor, %arg1: tensor) return %ret : tensor } -func.func @entry() { +func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c3 = arith.constant 3 : index @@ -166,173 +166,180 @@ func.func @entry() { : tensor, vector<6x6x6xf32> vector.print %dense_v : vector<6x6x6xf32> - // CHECK-NEXT:( ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 124, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 124, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 124, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ) ) - %1 = sparse_tensor.convert %CCC_ret - : tensor to tensor - %v1 = vector.transfer_read %1[%c0, %c0, %c0], %zero - : tensor, vector<6x6x6xf32> - vector.print %v1 : vector<6x6x6xf32> + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 216 + // CHECK-NEXT: dim = ( 6, 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6, 6 ) + // CHECK-NEXT: pos[0] : ( 0, 6 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[1] : ( 0, 6, 12, 18, 24, 30, 36 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[2] : ( 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, + // CHECK-SAME: 84, 90, 96, 102, 108, 114, 120, 126, 132, 138, 144, 150, + // CHECK-SAME: 156, 162, 168, 174, 180, 186, 192, 198, 204, 210, 216 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, + // CHECK-SAME: 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, + // CHECK-SAME: 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, + // CHECK-SAME: 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, + // CHECK-SAME: 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, + // CHECK-SAME: 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, + // CHECK-SAME: 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 108, 108, 108, 108, 108, 108, 124, 108, 108, 108, 108, 108, + // CHECK-SAME: 124, 108, 108, 108, 108, 108, 124, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108 + // CHECK-NEXT: ---- + // + sparse_tensor.print %CCC_ret : tensor - // CHECK-NEXT:( ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 124, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 124, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 124, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ) ) - %2 = sparse_tensor.convert %CCC_ret - : tensor to tensor - %v2 = vector.transfer_read %2[%c0, %c0, %c0], %zero - : tensor, vector<6x6x6xf32> - vector.print %v2 : vector<6x6x6xf32> + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 216 + // CHECK-NEXT: dim = ( 6, 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6, 6 ) + // CHECK-NEXT: pos[0] : ( 0, 6 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[2] : ( 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, + // CHECK-SAME: 90, 96, 102, 108, 114, 120, 126, 132, 138, 144, 150, 156, + // CHECK-SAME: 162, 168, 174, 180, 186, 192, 198, 204, 210, 216 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 108, 108, 108, 108, 108, 108, 124, 108, 108, 108, 108, 108, + // CHECK-SAME: 124, 108, 108, 108, 108, 108, 124, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108 + // CHECK-NEXT: ---- + // + sparse_tensor.print %CDC_ret : tensor - // CHECK-NEXT:( ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 124, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 124, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 124, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ) ) - %3 = sparse_tensor.convert %DDC_ret - : tensor to tensor - %v3 = vector.transfer_read %3[%c0, %c0, %c0], %zero - : tensor, vector<6x6x6xf32> - vector.print %v2 : vector<6x6x6xf32> + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 216 + // CHECK-NEXT: dim = ( 6, 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6, 6 ) + // CHECK-NEXT: pos[2] : ( 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, + // CHECK-SAME: 96, 102, 108, 114, 120, 126, 132, 138, 144, 150, 156, 162, + // CHECK-SAME: 168, 174, 180, 186, 192, 198, 204, 210, 216 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 108, 108, 108, 108, 108, 108, 124, 108, 108, 108, 108, 108, + // CHECK-SAME: 124, 108, 108, 108, 108, 108, 124, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108 + // CHECK-NEXT: ---- + // + sparse_tensor.print %DDC_ret : tensor - // CHECK-NEXT:( ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 124, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 124, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 124, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ), - // CHECK-SAME: ( ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ), - // CHECK-SAME: ( 108, 108, 108, 108, 108, 108 ) ) ) - %4 = sparse_tensor.convert %DCC_ret - : tensor to tensor - %v4 = vector.transfer_read %3[%c0, %c0, %c0], %zero - : tensor, vector<6x6x6xf32> - vector.print %v2 : vector<6x6x6xf32> + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 216 + // CHECK-NEXT: dim = ( 6, 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6, 6 ) + // CHECK-NEXT: pos[1] : ( 0, 6, 12, 18, 24, 30, 36 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[2] : ( 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, + // CHECK-SAME: 96, 102, 108, 114, 120, 126, 132, 138, 144, 150, 156, 162, + // CHECK-SAME: 168, 174, 180, 186, 192, 198, 204, 210, 216 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 108, 108, 108, 108, 108, 108, 124, 108, 108, 108, 108, 108, + // CHECK-SAME: 124, 108, 108, 108, 108, 108, 124, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108 + // CHECK-NEXT: ---- + // + sparse_tensor.print %DCC_ret : tensor // Free the resources bufferization.dealloc_tensor %in3D : tensor @@ -349,10 +356,5 @@ func.func @entry() { bufferization.dealloc_tensor %DDC_ret : tensor bufferization.dealloc_tensor %DCC_ret : tensor - bufferization.dealloc_tensor %1 : tensor - bufferization.dealloc_tensor %2 : tensor - bufferization.dealloc_tensor %3 : tensor - bufferization.dealloc_tensor %4 : tensor - return } diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_3d_ndhwc_dhwcf.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_3d_ndhwc_dhwcf.mlir index 346a14369289..f68e429a3c82 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_3d_ndhwc_dhwcf.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_3d_ndhwc_dhwcf.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -83,7 +83,7 @@ func.func @conv_3d_ndhwc_dhwcf_CDCDC(%arg0: tensor, return %ret : tensor } -func.func @entry() { +func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c3 = arith.constant 3 : index @@ -150,93 +150,134 @@ func.func @entry() { : (tensor, tensor) -> (tensor) - // CHECK-NEXT:( ( ( ( ( 108 ), ( 124 ), ( 124 ), ( 124 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ) ) ) - %1 = sparse_tensor.convert %CCCCC_ret - : tensor to tensor - %v1 = vector.transfer_read %1[%c0, %c0, %c0, %c0, %c0], %zero - : tensor, vector<1x6x6x6x1xf32> - vector.print %v1 : vector<1x6x6x6x1xf32> + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 216 + // CHECK-NEXT: dim = ( 1, 6, 6, 6, 1 ) + // CHECK-NEXT: lvl = ( 1, 6, 6, 6, 1 ) + // CHECK-NEXT: pos[0] : ( 0, 1 + // CHECK-NEXT: crd[0] : ( 0 + // CHECK-NEXT: pos[1] : ( 0, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[2] : ( 0, 6, 12, 18, 24, 30, 36 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[3] : ( 0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96, + // CHECK-SAME: 102, 108, 114, 120, 126, 132, 138, 144, 150, 156, 162, 168, 174, + // CHECK-SAME: 180, 186, 192, 198, 204, 210, 216 + // CHECK-NEXT: crd[3] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, + // CHECK-SAME: 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[4] : ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + // CHECK-SAME: 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + // CHECK-SAME: 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + // CHECK-SAME: 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + // CHECK-SAME: 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + // CHECK-SAME: 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + // CHECK-SAME: 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + // CHECK-SAME: 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + // CHECK-SAME: 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + // CHECK-SAME: 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, + // CHECK-SAME: 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, + // CHECK-SAME: 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, + // CHECK-SAME: 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, + // CHECK-SAME: 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, + // CHECK-SAME: 215, 216 + // CHECK-NEXT: crd[4] : ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0 + // CHECK-NEXT: values : ( 108, 124, 124, 124, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108 + // CHECK-NEXT: ---- + // + sparse_tensor.print %CCCCC_ret : tensor %CDCDC_ret = call @conv_3d_ndhwc_dhwcf_CDCDC(%in3D_ndhwc_CDCDC, %filter3D_ndhwc) : (tensor, tensor) -> (tensor) - // CHECK-NEXT:( ( ( ( ( 108 ), ( 124 ), ( 124 ), ( 124 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ), - // CHECK-SAME: ( ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ), - // CHECK-SAME: ( ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ), ( 108 ) ) ) ) ) - %2 = sparse_tensor.convert %CDCDC_ret - : tensor to tensor - %v2 = vector.transfer_read %dense_ret[%c0, %c0, %c0, %c0, %c0], %zero - : tensor, vector<1x6x6x6x1xf32> - vector.print %v2 : vector<1x6x6x6x1xf32> + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 216 + // CHECK-NEXT: dim = ( 1, 6, 6, 6, 1 ) + // CHECK-NEXT: lvl = ( 1, 6, 6, 6, 1 ) + // CHECK-NEXT: pos[0] : ( 0, 1 + // CHECK-NEXT: crd[0] : ( 0 + // CHECK-NEXT: pos[2] : ( 0, 6, 12, 18, 24, 30, 36 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[4] : ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + // CHECK-SAME: 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + // CHECK-SAME: 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + // CHECK-SAME: 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + // CHECK-SAME: 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + // CHECK-SAME: 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + // CHECK-SAME: 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + // CHECK-SAME: 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + // CHECK-SAME: 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + // CHECK-SAME: 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, + // CHECK-SAME: 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, + // CHECK-SAME: 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, + // CHECK-SAME: 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, + // CHECK-SAME: 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, + // CHECK-SAME: 215, 216 + // CHECK-NEXT: crd[4] : ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // CHECK-SAME: 0, 0, 0, 0, 0, 0, 0, 0, 0 + // CHECK-NEXT: values : ( 108, 124, 124, 124, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + // CHECK-SAME: 108, 108, 108, 108, 108, 108 + // CHECK-NEXT: ---- + // + sparse_tensor.print %CDCDC_ret : tensor // Free the resources bufferization.dealloc_tensor %in3D_ndhwc : tensor @@ -249,8 +290,5 @@ func.func @entry() { bufferization.dealloc_tensor %CCCCC_ret : tensor bufferization.dealloc_tensor %CDCDC_ret : tensor - bufferization.dealloc_tensor %1 : tensor - bufferization.dealloc_tensor %2 : tensor - return } -- GitLab From ad23127222fe23e28ac3deaa16f3ae64d13b7b6f Mon Sep 17 00:00:00 2001 From: Congcong Cai Date: Tue, 12 Mar 2024 06:49:09 +0800 Subject: [PATCH 188/953] [mlir][inline] avoid inline self-recursive function (#83092) --- mlir/lib/Transforms/Utils/Inliner.cpp | 8 +++++++ .../Transforms/inlining-recursive-self.mlir | 22 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 mlir/test/Transforms/inlining-recursive-self.mlir diff --git a/mlir/lib/Transforms/Utils/Inliner.cpp b/mlir/lib/Transforms/Utils/Inliner.cpp index 74776a73db9a..f227cedb269d 100644 --- a/mlir/lib/Transforms/Utils/Inliner.cpp +++ b/mlir/lib/Transforms/Utils/Inliner.cpp @@ -21,6 +21,7 @@ #include "mlir/Support/DebugStringHelper.h" #include "mlir/Transforms/InliningUtils.h" #include "llvm/ADT/SCCIterator.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Debug.h" @@ -711,6 +712,13 @@ bool Inliner::Impl::shouldInline(ResolvedCall &resolvedCall) { if (resolvedCall.call->hasTrait()) return false; + // Don't allow inlining if the target is a self-recursive function. + if (llvm::count_if(*resolvedCall.targetNode, + [&](CallGraphNode::Edge const &edge) -> bool { + return edge.getTarget() == resolvedCall.targetNode; + }) > 0) + return false; + // Don't allow inlining if the target is an ancestor of the call. This // prevents inlining recursively. Region *callableRegion = resolvedCall.targetNode->getCallableRegion(); diff --git a/mlir/test/Transforms/inlining-recursive-self.mlir b/mlir/test/Transforms/inlining-recursive-self.mlir new file mode 100644 index 000000000000..5cc922db8e97 --- /dev/null +++ b/mlir/test/Transforms/inlining-recursive-self.mlir @@ -0,0 +1,22 @@ +// RUN: mlir-opt %s -inline='default-pipeline=''' | FileCheck %s +// RUN: mlir-opt %s --mlir-disable-threading -inline='default-pipeline=''' | FileCheck %s + +// CHECK-LABEL: func.func @b0 +func.func @b0() { + // CHECK: call @b0 + // CHECK-NEXT: call @b1 + // CHECK-NEXT: call @b0 + // CHECK-NEXT: call @b1 + // CHECK-NEXT: call @b0 + func.call @b0() : () -> () + func.call @b1() : () -> () + func.call @b0() : () -> () + func.call @b1() : () -> () + func.call @b0() : () -> () + return +} +func.func @b1() { + func.call @b1() : () -> () + func.call @b1() : () -> () + return +} -- GitLab From 8d220d109d28dac352c563ab062fb72132b7eca1 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Mon, 11 Mar 2024 16:03:32 -0700 Subject: [PATCH 189/953] workflows: Fix incorrect input name in release-binaries.yml (#84604) In aa02002491333c42060373bc84f1ff5d2c76b4ce the input name was changed from tag to release-version, but the code was never updated. --- .github/workflows/release-binaries.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml index 1dba91746dae..131ad3004f45 100644 --- a/.github/workflows/release-binaries.yml +++ b/.github/workflows/release-binaries.yml @@ -71,8 +71,8 @@ jobs: # | X.Y.Z | -final run: | tag="${{ github.ref_name }}" - trimmed=$(echo ${{ inputs.tag }} | xargs) - [[ "$trimmed" != "" ]] && tag="$trimmed" + trimmed=$(echo ${{ inputs.release-version }} | xargs) + [[ "$trimmed" != "" ]] && tag="llvmorg-$trimmed" if [ "$tag" = "main" ]; then # If tag is main, then we've been triggered by a scheduled so pass so # use the head commit as the tag. -- GitLab From d125d5576ec85eb2517ced0fe4b68da7b8209d0c Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Mon, 11 Mar 2024 16:04:44 -0700 Subject: [PATCH 190/953] github-automation.py: Set maintainer_can_modify=True for backport PRs (#84819) This makes it possible to rebase the branch using the Web UI, which makes it easier to manually merge the PRs. Manual merge is required when squash merge won't preserve author information of the backport. --- llvm/utils/git/github-automation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/utils/git/github-automation.py b/llvm/utils/git/github-automation.py index b2e6843eb9af..b21f14eca445 100755 --- a/llvm/utils/git/github-automation.py +++ b/llvm/utils/git/github-automation.py @@ -586,7 +586,7 @@ class ReleaseWorkflow: body=body, base=release_branch_for_issue, head=head, - maintainer_can_modify=False, + maintainer_can_modify=True, ) pull.as_issue().edit(milestone=self.issue.milestone) -- GitLab From 75790dd2d0cff5b0c3e543e256f6c8f0fb5d0689 Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Mon, 11 Mar 2024 16:05:29 -0700 Subject: [PATCH 191/953] [RemoveDIs] Fix nullptr dereference in getFirstNonPHIIt() (#84595) getFirstNonPHI() returns nullptr for blocks that lack a non-phi (including a terminator) but getFirstNonPHIIt() may dereference its result unconditionally. Return end() instead. This came up for us downstream while correcting our getFirstNonPHI() calls that intended to return the position after the phi's but before the debug info to getFirstNonPHIIt(). The pass in question is populating new BB's and hasn't added terminators yet. --- llvm/lib/IR/BasicBlock.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp index 25aa32611645..c188d2f912d1 100644 --- a/llvm/lib/IR/BasicBlock.cpp +++ b/llvm/lib/IR/BasicBlock.cpp @@ -348,6 +348,8 @@ const Instruction* BasicBlock::getFirstNonPHI() const { BasicBlock::const_iterator BasicBlock::getFirstNonPHIIt() const { const Instruction *I = getFirstNonPHI(); + if (!I) + return end(); BasicBlock::const_iterator It = I->getIterator(); // Set the head-inclusive bit to indicate that this iterator includes // any debug-info at the start of the block. This is a no-op unless the -- GitLab From 9688a6dae4de16e79ba677846df32099ec012627 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Mon, 11 Mar 2024 23:07:49 +0000 Subject: [PATCH 192/953] [MLIR] Add missing MLIRFuncDialect dep to MLIRNVVMToLLVM (#84548) This fixes the following failure when doing a clean build (in particular no .ninja* lying around) of lib/libMLIRNVVMToLLVM.a only: ``` In file included from mlir/lib/Conversion/NVVMToLLVM/NVVMToLLVM.cpp:18: mlir/include/mlir/Dialect/Func/IR/FuncOps.h:29:10: fatal error: mlir/Dialect/Func/IR/FuncOps.h.inc: No such file or directory ``` --- mlir/lib/Conversion/NVVMToLLVM/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/mlir/lib/Conversion/NVVMToLLVM/CMakeLists.txt b/mlir/lib/Conversion/NVVMToLLVM/CMakeLists.txt index 2afff1a4e5f1..23174d112871 100644 --- a/mlir/lib/Conversion/NVVMToLLVM/CMakeLists.txt +++ b/mlir/lib/Conversion/NVVMToLLVM/CMakeLists.txt @@ -11,6 +11,7 @@ add_mlir_conversion_library(MLIRNVVMToLLVM Core LINK_LIBS PUBLIC + MLIRFuncDialect MLIRGPUDialect MLIRLLVMCommonConversion MLIRLLVMDialect -- GitLab From 36cf982d6cddaa65da24fcb853295a99a9154a53 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Mon, 11 Mar 2024 23:08:56 +0000 Subject: [PATCH 193/953] [MLIR] Add missing MLIRFuncDialect dep to MLIRAMDGPUTransforms (#84550) This fixes the following failure when doing a clean build (in particular no .ninja* lying around) of lib/libMLIRAMDGPUTransforms.a only: ``` In file included from mlir/lib/Dialect/AMDGPU/Transforms/OptimizeSharedMemory.cpp:21: mlir/include/mlir/Dialect/Func/IR/FuncOps.h:29:10: fatal error: mlir/Dialect/Func/IR/FuncOps.h.inc: No such file or directory ``` --- mlir/lib/Dialect/AMDGPU/Transforms/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/mlir/lib/Dialect/AMDGPU/Transforms/CMakeLists.txt b/mlir/lib/Dialect/AMDGPU/Transforms/CMakeLists.txt index 2274656e84a5..a955d585b9a1 100644 --- a/mlir/lib/Dialect/AMDGPU/Transforms/CMakeLists.txt +++ b/mlir/lib/Dialect/AMDGPU/Transforms/CMakeLists.txt @@ -14,6 +14,7 @@ add_mlir_dialect_library(MLIRAMDGPUTransforms MLIRAMDGPUUtils MLIRArithDialect MLIRControlFlowDialect + MLIRFuncDialect MLIRIR MLIRPass MLIRTransforms -- GitLab From b2ea04673b782f95ac9841f87df8bb5f7b561067 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Mon, 11 Mar 2024 23:10:26 +0000 Subject: [PATCH 194/953] [MLIR] Add missing omp_gen dep to MLIROpenMPDialect (#84552) This fixes the following failure when doing a clean build (in particular no .ninja* lying around) of lib/libMLIROpenMPDialect.a only: ``` In file included from mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp:29: llvm/include/llvm/Frontend/OpenMP/OMPConstants.h:20:10: fatal error: llvm/Frontend/OpenMP/OMP.h.inc: No such file or directory ``` --- mlir/lib/Dialect/OpenMP/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/mlir/lib/Dialect/OpenMP/CMakeLists.txt b/mlir/lib/Dialect/OpenMP/CMakeLists.txt index 40b4837484a1..57a6d3445c15 100644 --- a/mlir/lib/Dialect/OpenMP/CMakeLists.txt +++ b/mlir/lib/Dialect/OpenMP/CMakeLists.txt @@ -5,6 +5,7 @@ add_mlir_dialect_library(MLIROpenMPDialect ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/OpenMP DEPENDS + omp_gen MLIROpenMPOpsIncGen MLIROpenMPOpsInterfacesIncGen MLIROpenMPTypeInterfacesIncGen -- GitLab From 8d61f82bd3676bc541edfad1014e3ed599cc1390 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 11 Mar 2024 17:31:38 -0700 Subject: [PATCH 195/953] [lld][RISCV] Avoid second map lookup in mergeArch. NFC (#84687) Instead of using find and then inserting into the map, we can use insert and fix up the version using the iterator if the insert fails. --- lld/ELF/Arch/RISCV.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp index 4798c86f7d1b..20de1b9b7bde 100644 --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -1074,12 +1074,12 @@ static void mergeArch(RISCVISAInfo::OrderedExtensionMap &mergedExts, mergedXlen = info.getXLen(); } else { for (const auto &ext : info.getExtensions()) { - if (auto it = mergedExts.find(ext.first); it != mergedExts.end()) { - if (std::tie(it->second.Major, it->second.Minor) >= + auto p = mergedExts.insert(ext); + if (!p.second) { + if (std::tie(p.first->second.Major, p.first->second.Minor) < std::tie(ext.second.Major, ext.second.Minor)) - continue; + p.first->second = ext.second; } - mergedExts[ext.first] = ext.second; } } } -- GitLab From 67ef4ae2c3cc4e2700e873aa6f251b70a09c3fea Mon Sep 17 00:00:00 2001 From: James Newling Date: Mon, 11 Mar 2024 18:11:58 -0700 Subject: [PATCH 196/953] [MLIR][Tensor,MemRef] Fold expand_shape and collapse_shape if identity (#80658) Before: op verifiers failed if the input and output ranks were the same (i.e. no expansion or collapse). This behavior requires users of these shape ops to verify manually that they are not creating identity versions of these ops every time they build them -- problematic. This PR removes this strict verification, and introduces folders for the the identity cases. The PR also removes the special case handling of rank-0 tensors for expand_shape and collapse_shape, there doesn't seem to be any reason to treat them differently. --- .../mlir/Dialect/MemRef/IR/MemRefOps.td | 2 +- .../mlir/Dialect/Tensor/IR/TensorOps.td | 39 +++++------ .../mlir/Dialect/Utils/ReshapeOpsUtils.h | 64 ++++++++----------- mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp | 20 ++++-- mlir/lib/Dialect/Tensor/IR/TensorOps.cpp | 12 ---- mlir/test/Dialect/MemRef/canonicalize.mlir | 29 +++++++++ mlir/test/Dialect/MemRef/invalid.mlir | 42 ++++++++---- mlir/test/Dialect/Tensor/canonicalize.mlir | 39 ++++++++++- mlir/test/Dialect/Tensor/invalid.mlir | 14 ---- 9 files changed, 152 insertions(+), 109 deletions(-) diff --git a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td index c71517666b60..39e66cd9e6e5 100644 --- a/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td +++ b/mlir/include/mlir/Dialect/MemRef/IR/MemRefOps.td @@ -641,7 +641,7 @@ def MemRef_DmaStartOp : MemRef_Op<"dma_start"> { let summary = "non-blocking DMA operation that starts a transfer"; let description = [{ Syntax: - + ``` operation ::= `memref.dma_start` ssa-use`[`ssa-use-list`]` `,` ssa-use`[`ssa-use-list`]` `,` ssa-use `,` diff --git a/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td b/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td index 1c61ece2676a..670202fe4372 100644 --- a/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td +++ b/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td @@ -1098,21 +1098,18 @@ class Tensor_ReassociativeReshapeOp traits = []> : def Tensor_ExpandShapeOp : Tensor_ReassociativeReshapeOp<"expand_shape"> { let summary = "operation to produce a tensor with a higher rank"; let description = [{ - The `tensor.expand_shape` op produces a new tensor with a higher - rank whose sizes are a reassociation of the original `src`. + The `tensor.expand_shape` op produces a tensor of higher (or equal) + rank than the operand `src` whose dimension sizes are a reassociation of + `src`. - A reassociation is defined as a continuous grouping of dimensions and is - represented with an array of DenseI64ArrayAttr attribute. - - The verification rule is that the reassociation maps are applied to the - result tensor with the higher rank to obtain the operand tensor with the - smaller rank. + A reassociation is defined as a continuous grouping of dimensions. It is + represented with an array of DenseI64ArrayAttr attribute. Entries in the + array are referred to as reassociation maps. - The operand tensor type of a reshape can be zero-ranked if the result - tensor type is statically shaped with all dimensions being unit extent. In - such cases the reassociation map is empty. + The reassociation maps are applied to the result shape to obtain the operand + shape. - Examples: + Example: ```mlir // Dimension expansion i -> (i', j') and (k) -> (k') @@ -1150,21 +1147,15 @@ def Tensor_ExpandShapeOp : Tensor_ReassociativeReshapeOp<"expand_shape"> { def Tensor_CollapseShapeOp : Tensor_ReassociativeReshapeOp<"collapse_shape"> { let summary = "operation to produce a tensor with a smaller rank"; let description = [{ - The `tensor.collapse_shape` op produces a new tensor with a smaller - rank whose sizes are a reassociation of the original `src`. + The `tensor.collapse_shape` op produces a new tensor of lower (or equal) + rank whose dimension sizes are a reassociation of the original `src` dimensions. A reassociation is defined as a continuous grouping of dimensions and is - represented with an array of DenseI64ArrayAttr attribute. + represented by an array of DenseI64ArrayAttr attribute. The reassociation + maps are applied to the operand shape to obtain the result shape. - The verification rule is that the reassociation maps are applied to the - operand tensor with the higher rank to obtain the result tensor with the - smaller rank. - The result tensor type of a reshape can be zero-ranked if the operand - tensor type is statically shaped with all dimensions being unit extent. In - such case the reassociation map is empty. - - Examples: + Example: ```mlir // Dimension collapse (i, j) -> i' and k -> k' @@ -1841,7 +1832,7 @@ def Tensor_PackOp : Tensor_RelayoutOp<"pack", [ and optionally transposes the tiled source tensor dimensions. `inner_dims_pos` (mandatory) specifies `k` source tensor dimensions that are - being tiled, where `0 < k <= n`. The order of the dimensions matters: + being tiled, where `0 < k <= n`. The order of the dimensions matters: - The tiled dimensions (of size `inner_tiles`) are added to the end of the result tensor in the order in which they appear in `inner_dims_pos`. - `inner_dims_pos[i]` specifies the source tensor dimension tiled by diff --git a/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h b/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h index 61c929dee0f2..ae9824f728da 100644 --- a/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h +++ b/mlir/include/mlir/Dialect/Utils/ReshapeOpsUtils.h @@ -85,16 +85,21 @@ bool isReassociationValid(ArrayRef reassociation, template static OpFoldResult foldReshapeOp(ReshapeOpTy reshapeOp, ArrayRef operands) { - // Fold producer-consumer reshape ops that where the operand type of the + + if (reshapeOp.getSrcType() == reshapeOp.getType()) + return reshapeOp.getSrc(); + + // Fold producer-consumer reshape ops where the operand type of the // producer is same as the return type of the consumer. auto reshapeSrcOp = reshapeOp.getSrc().template getDefiningOp(); if (reshapeSrcOp && reshapeSrcOp.getSrcType() == reshapeOp.getResultType()) return reshapeSrcOp.getSrc(); + // Reshape of a constant can be replaced with a new constant. - if (auto elements = dyn_cast_or_null(operands.front())) { + if (auto elements = dyn_cast_or_null(operands.front())) return elements.reshape(cast(reshapeOp.getResult().getType())); - } + return nullptr; } @@ -103,41 +108,36 @@ static OpFoldResult foldReshapeOp(ReshapeOpTy reshapeOp, template static LogicalResult verifyReshapeLikeTypes(Op op, T expandedType, T collapsedType, bool isExpansion) { + unsigned expandedRank = expandedType.getRank(); unsigned collapsedRank = collapsedType.getRank(); if (expandedRank < collapsedRank) - return op.emitOpError("expected the type ") - << expandedType - << " to have higher rank than the type = " << collapsedType; - if (expandedRank == 0) - return op.emitOpError("expected non-zero memref ranks"); - if (expandedRank == collapsedRank) - return op.emitOpError("expected to collapse or expand dims"); - - if (collapsedRank == 0) { - // If collapsed rank is 0, then expanded type must be static shaped and of - // sizes 1. - if (llvm::any_of(expandedType.getShape(), - [](int64_t dim) -> bool { return dim != 1; })) - return op.emitOpError("invalid to reshape tensor/memref with non-unit " - "extent dimensions to zero-rank tensor/memref"); - return success(); - } + return op.emitOpError("expected the expanded type, ") + << expandedType << " to have a higher (or same) rank " + << "than the collapsed type, " << collapsedType << '.'; + if (collapsedRank != op.getReassociation().size()) - return op.emitOpError("expected rank of the collapsed type(") - << collapsedRank << ") to be the number of reassociation maps(" - << op.getReassociation().size() << ")"; + return op.emitOpError("expected collapsed rank (") + << collapsedRank << ") to equal the number of reassociation maps (" + << op.getReassociation().size() << ")."; + auto maps = op.getReassociationMaps(); for (auto it : llvm::enumerate(maps)) if (it.value().getNumDims() != expandedRank) return op.emitOpError("expected reassociation map #") - << it.index() << " of same rank as expanded memref(" - << expandedRank << "), but got " << it.value().getNumDims(); + << it.index() << " to have size equal to the expanded rank (" + << expandedRank << "), but it is " << it.value().getNumDims() + << '.'; + int invalidIdx = 0; if (!isReassociationValid(maps, &invalidIdx)) return op.emitOpError("expected reassociation map #") - << invalidIdx << " to be valid and contiguous"; - return verifyReshapeLikeShapes(op, collapsedType, expandedType, isExpansion); + << invalidIdx << " to be valid and contiguous."; + + return reshapeLikeShapesAreCompatible( + [&](const Twine &msg) { return op->emitOpError(msg); }, + collapsedType.getShape(), expandedType.getShape(), + op.getReassociationIndices(), isExpansion); } /// Verify that shapes of the reshaped types using following rules @@ -153,16 +153,6 @@ LogicalResult reshapeLikeShapesAreCompatible( ArrayRef collapsedShape, ArrayRef expandedShape, ArrayRef reassociationMaps, bool isExpandingReshape); -template -static LogicalResult verifyReshapeLikeShapes(OpTy op, ShapedType collapsedType, - ShapedType expandedType, - bool isExpandingReshape) { - return reshapeLikeShapesAreCompatible( - [&](const Twine &msg) { return op->emitOpError(msg); }, - collapsedType.getShape(), expandedType.getShape(), - op.getReassociationIndices(), isExpandingReshape); -} - /// Returns true iff the type is a MemRefType and has a non-identity layout. bool hasNonIdentityLayout(Type type); diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp index 248193481acf..94e0ed319cae 100644 --- a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp +++ b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp @@ -2224,9 +2224,13 @@ LogicalResult ExpandShapeOp::verify() { MemRefType srcType = getSrcType(); MemRefType resultType = getResultType(); - if (srcType.getRank() >= resultType.getRank()) - return emitOpError("expected rank expansion, but found source rank ") - << srcType.getRank() << " >= result rank " << resultType.getRank(); + if (srcType.getRank() > resultType.getRank()) { + auto r0 = srcType.getRank(); + auto r1 = resultType.getRank(); + return emitOpError("has source rank ") + << r0 << " and result rank " << r1 << ". This is not an expansion (" + << r0 << " > " << r1 << ")."; + } // Verify result shape. if (failed(verifyCollapsedShape(getOperation(), srcType.getShape(), @@ -2378,9 +2382,13 @@ LogicalResult CollapseShapeOp::verify() { MemRefType srcType = getSrcType(); MemRefType resultType = getResultType(); - if (srcType.getRank() <= resultType.getRank()) - return emitOpError("expected rank reduction, but found source rank ") - << srcType.getRank() << " <= result rank " << resultType.getRank(); + if (srcType.getRank() < resultType.getRank()) { + auto r0 = srcType.getRank(); + auto r1 = resultType.getRank(); + return emitOpError("has source rank ") + << r0 << " and result rank " << r1 << ". This is not a collapse (" + << r0 << " < " << r1 << ")."; + } // Verify result shape. if (failed(verifyCollapsedShape(getOperation(), resultType.getShape(), diff --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp index fe2f250e6b92..a854da466c31 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp @@ -1656,22 +1656,10 @@ static LogicalResult verifyTensorReshapeOp(TensorReshapeOp op, } LogicalResult ExpandShapeOp::verify() { - auto srcType = getSrcType(); - auto resultType = getResultType(); - if (srcType.getRank() >= resultType.getRank()) - return emitOpError("expected rank expansion, but found source rank ") - << srcType.getRank() << " >= result rank " << resultType.getRank(); - return verifyTensorReshapeOp(*this, getResultType(), getSrcType()); } LogicalResult CollapseShapeOp::verify() { - auto srcType = getSrcType(); - auto resultType = getResultType(); - if (srcType.getRank() <= resultType.getRank()) - return emitOpError("expected rank reduction, but found source rank ") - << srcType.getRank() << " <= result rank " << resultType.getRank(); - return verifyTensorReshapeOp(*this, getSrcType(), getResultType()); } diff --git a/mlir/test/Dialect/MemRef/canonicalize.mlir b/mlir/test/Dialect/MemRef/canonicalize.mlir index a772a25da573..b1e92e54d561 100644 --- a/mlir/test/Dialect/MemRef/canonicalize.mlir +++ b/mlir/test/Dialect/MemRef/canonicalize.mlir @@ -1,5 +1,34 @@ // RUN: mlir-opt %s -canonicalize="test-convergence" --split-input-file -allow-unregistered-dialect | FileCheck %s + +// CHECK-LABEL: collapse_shape_identity_fold +// CHECK-NEXT: return +func.func @collapse_shape_identity_fold(%arg0 : memref<5xi8>) -> memref<5xi8> { + %0 = memref.collapse_shape %arg0 [[0]] : memref<5xi8> into memref<5xi8> + return %0 : memref<5xi8> +} + +// ----- + +// CHECK-LABEL: expand_shape_identity_fold +// CHECK-NEXT: return +func.func @expand_shape_identity_fold(%arg0 : memref<5x4xi8>) -> memref<5x4xi8> { + %0 = memref.expand_shape %arg0 [[0], [1]] : memref<5x4xi8> into memref<5x4xi8> + return %0 : memref<5x4xi8> +} + +// ----- + +// CHECK-LABEL: collapse_expand_rank0_cancel +// CHECK-NEXT: return +func.func @collapse_expand_rank0_cancel(%arg0 : memref<1x1xi8>) -> memref<1x1xi8> { + %0 = memref.collapse_shape %arg0 [] : memref<1x1xi8> into memref + %1 = memref.expand_shape %0 [] : memref into memref<1x1xi8> + return %1 : memref<1x1xi8> +} + +// ----- + // CHECK-LABEL: func @subview_of_size_memcast // CHECK-SAME: %[[ARG0:.[a-z0-9A-Z_]+]]: memref<4x6x16x32xi8> // CHECK: %[[S:.+]] = memref.subview %[[ARG0]][0, 1, 0, 0] [1, 1, 16, 32] [1, 1, 1, 1] : memref<4x6x16x32xi8> to memref<16x32xi8, strided{{.*}}> diff --git a/mlir/test/Dialect/MemRef/invalid.mlir b/mlir/test/Dialect/MemRef/invalid.mlir index 8f5ba5ea8fc7..1aef417549d9 100644 --- a/mlir/test/Dialect/MemRef/invalid.mlir +++ b/mlir/test/Dialect/MemRef/invalid.mlir @@ -415,20 +415,6 @@ func.func @collapse_shape_out_of_bounds(%arg0: memref) { // ----- -func.func @expand_shape_invalid_ranks(%arg0: memref) { - // expected-error @+1 {{op expected rank expansion, but found source rank 2 >= result rank 2}} - %0 = memref.expand_shape %arg0 [[0], [1]] : memref into memref -} - -// ----- - -func.func @collapse_shape_invalid_ranks(%arg0: memref) { - // expected-error @+1 {{op expected rank reduction, but found source rank 2 <= result rank 2}} - %0 = memref.collapse_shape %arg0 [[0], [1]] : memref into memref -} - -// ----- - func.func @expand_shape_out_of_bounds(%arg0: memref) { // expected-error @+1 {{op reassociation index 2 is out of bounds}} %0 = memref.expand_shape %arg0 [[0, 1, 2]] : memref into memref<4x?xf32> @@ -462,6 +448,34 @@ func.func @collapse_shape_invalid_reassociation(%arg0: memref) { // ----- +// An (invalid) attempt at using collapse_shape to increase the rank might look +// like this. Verify that a sensible error is emitted in this case. +func.func @collapse_shape_invalid_reassociation_expansion(%arg0: memref) { + // expected-error @+1 {{'memref.collapse_shape' op has source rank 1 and result rank 2. This is not a collapse (1 < 2)}} + %0 = memref.collapse_shape %arg0 [[0], [0]] : + memref into memref +} + +// ----- + +// An (invalid) attempt at using expand_shape to reduce the rank might look +// like this. Verify that a sensible error is emitted in this case. +func.func @expand_shape_invalid_reassociation(%arg0: memref<2x3x1xf32>) { + // expected-error @+1 {{'memref.expand_shape' op has source rank 3 and result rank 2. This is not an expansion (3 > 2)}} + %0 = memref.expand_shape %arg0 [[0], [1], [1]] : + memref<2x3x1xf32> into memref<2x3xf32> +} + +// ----- + +func.func @collapse_shape_invalid_reassociation_expansion(%arg0: memref) { + // expected-error @+1 {{reassociation indices must be contiguous}} + %0 = memref.collapse_shape %arg0 [[1], [0]] : + memref into memref +} + +// ----- + func.func @collapse_shape_reshaping_non_contiguous( %arg0: memref<3x4x5xf32, strided<[270, 50, 10], offset: 0>>) { // expected-error @+1 {{invalid source layout map or collapsing non-contiguous dims}} diff --git a/mlir/test/Dialect/Tensor/canonicalize.mlir b/mlir/test/Dialect/Tensor/canonicalize.mlir index d17c23adfb14..70f5d61bd802 100644 --- a/mlir/test/Dialect/Tensor/canonicalize.mlir +++ b/mlir/test/Dialect/Tensor/canonicalize.mlir @@ -1,5 +1,42 @@ // RUN: mlir-opt %s -split-input-file -canonicalize="test-convergence" | FileCheck %s + +// CHECK-LABEL: expand_shape_identity_fold +// CHECK-NEXT: return +func.func @expand_shape_identity_fold(%arg0 : tensor<5xf32>) -> tensor<5xf32> { + %0 = tensor.expand_shape %arg0 [[0]] : tensor<5xf32> into tensor<5xf32> + return %0 : tensor<5xf32> +} + +// ----- + +// CHECK-LABEL: expand_shape_rank0_identity_fold +// CHECK-NEXT: return +func.func @expand_shape_rank0_identity_fold(%arg0 : tensor) -> tensor { + %0 = tensor.expand_shape %arg0 [] : tensor into tensor + return %0 : tensor +} + +// ----- + +// CHECK-LABEL: collapse_shape_identity_fold +// CHECK-NEXT: return +func.func @collapse_shape_identity_fold(%arg0 : tensor<5x4xf32>) -> tensor<5x4xf32> { + %0 = tensor.collapse_shape %arg0 [[0], [1]] : tensor<5x4xf32> into tensor<5x4xf32> + return %0 : tensor<5x4xf32> +} + +// ----- + +// CHECK-LABEL: collapse_shape_rank0_identity_fold +// CHECK-NEXT: return +func.func @collapse_shape_rank0_identity_fold(%arg0 : tensor) -> tensor { + %0 = tensor.collapse_shape %arg0 [] : tensor into tensor + return %0 : tensor +} + +// ----- + // CHECK-LABEL: @tensor_bitcast_chain_ok // CHECK-SAME: %[[IN:.*]]: tensor<2xi32> func.func @tensor_bitcast_chain_ok(%input: tensor<2xi32>) -> tensor<2xf32> { @@ -2092,7 +2129,7 @@ func.func @unpack_pack(%t: tensor<128x128xf32>) -> tensor<128x128xf32> { // Chain: NC -> NCnc -> NCnc -> NC // CHECK: func.func @unpack_pack( -// CHECK-SAME: %[[T:.+]]: tensor<128x128xf32>, +// CHECK-SAME: %[[T:.+]]: tensor<128x128xf32>, // CHECK: return %[[T]] : tensor<128x128xf32> func.func @unpack_pack(%t: tensor<128x128xf32>, %tile1: index, %tile2: index) -> tensor<128x128xf32> { %tensor_empty = tensor.empty(%tile1, %tile2) : tensor<16x16x?x?xf32> diff --git a/mlir/test/Dialect/Tensor/invalid.mlir b/mlir/test/Dialect/Tensor/invalid.mlir index 4c534fe936e3..79ca0de68a1e 100644 --- a/mlir/test/Dialect/Tensor/invalid.mlir +++ b/mlir/test/Dialect/Tensor/invalid.mlir @@ -343,20 +343,6 @@ func.func @illegal_collapsing_reshape_mixed_tensor_2(%arg0 : tensor) // ----- -func.func @expand_shape_invalid_ranks(%arg0: tensor) { - // expected-error @+1 {{op expected rank expansion, but found source rank 2 >= result rank 2}} - %0 = tensor.expand_shape %arg0 [[0], [1]] : tensor into tensor -} - -// ----- - -func.func @collapse_shape_invalid_ranks(%arg0: tensor) { - // expected-error @+1 {{op expected rank reduction, but found source rank 2 <= result rank 2}} - %0 = tensor.collapse_shape %arg0 [[0], [1]] : tensor into tensor -} - -// ----- - func.func @rank(%0: f32) { // expected-error@+1 {{'tensor.rank' op operand #0 must be tensor of any type values}} "tensor.rank"(%0): (f32)->index -- GitLab From 672fc89347b831f2845e7825affc30c865758270 Mon Sep 17 00:00:00 2001 From: Florian Mayer Date: Mon, 11 Mar 2024 18:18:49 -0700 Subject: [PATCH 197/953] [NFC] [hwasan] factor out selective instrumentation logic (#84408) sanitizeFunction is long enough already. --- .../Instrumentation/HWAddressSanitizer.cpp | 53 +++++++++++-------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index 422406e46bdb..11a5c29c35f7 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -317,6 +317,8 @@ private: Value *MemTag = nullptr; }; + bool selectiveInstrumentationShouldSkip(Function &F, + FunctionAnalysisManager &FAM); void initializeModule(); void createHwasanCtorComdat(); @@ -1523,6 +1525,31 @@ bool HWAddressSanitizer::instrumentStack(memtag::StackInfo &SInfo, return true; } +bool HWAddressSanitizer::selectiveInstrumentationShouldSkip( + Function &F, FunctionAnalysisManager &FAM) { + if (ClRandomSkipRate.getNumOccurrences()) { + std::bernoulli_distribution D(ClRandomSkipRate); + if (D(*Rng)) + return true; + } else { + auto &MAMProxy = FAM.getResult(F); + ProfileSummaryInfo *PSI = + MAMProxy.getCachedResult(*F.getParent()); + if (PSI && PSI->hasProfileSummary()) { + auto &BFI = FAM.getResult(F); + if ((ClHotPercentileCutoff.getNumOccurrences() && + ClHotPercentileCutoff >= 0) + ? PSI->isFunctionHotInCallGraphNthPercentile( + ClHotPercentileCutoff, &F, BFI) + : PSI->isFunctionHotInCallGraph(&F, BFI)) + return true; + } else { + ++NumNoProfileSummaryFuncs; + } + } + return false; +} + void HWAddressSanitizer::sanitizeFunction(Function &F, FunctionAnalysisManager &FAM) { if (&F == HwasanCtorFunction) @@ -1535,28 +1562,10 @@ void HWAddressSanitizer::sanitizeFunction(Function &F, return; NumTotalFuncs++; - if (CSelectiveInstrumentation) { - if (ClRandomSkipRate.getNumOccurrences()) { - std::bernoulli_distribution D(ClRandomSkipRate); - if (D(*Rng)) - return; - } else { - auto &MAMProxy = FAM.getResult(F); - ProfileSummaryInfo *PSI = - MAMProxy.getCachedResult(*F.getParent()); - if (PSI && PSI->hasProfileSummary()) { - auto &BFI = FAM.getResult(F); - if ((ClHotPercentileCutoff.getNumOccurrences() && - ClHotPercentileCutoff >= 0) - ? PSI->isFunctionHotInCallGraphNthPercentile( - ClHotPercentileCutoff, &F, BFI) - : PSI->isFunctionHotInCallGraph(&F, BFI)) - return; - } else { - ++NumNoProfileSummaryFuncs; - } - } - } + + if (CSelectiveInstrumentation && selectiveInstrumentationShouldSkip(F, FAM)) + return; + NumInstrumentedFuncs++; LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n"); -- GitLab From 41658bafb70680d0aafb7e79c7f694b8c2a5217d Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Mon, 11 Mar 2024 21:39:21 -0400 Subject: [PATCH 198/953] [libc++][hardening] Add iterator validity checks on unordered containers (#80230) These are simply null checks, so use `_LIBCPP_ASSERT_NON_NULL`. This allows us to restore a bunch of the old debug tests. I've extended them to also cover the const iterators, as those run through different codepaths than the const ones. This does the easier (and less important) half of #80212. --- libcxx/include/__hash_table | 40 +++++++++-- .../assert.iterator.dereference.pass.cpp | 52 ++++++++++++++ .../assert.iterator.increment.pass.cpp | 59 ++++++++++++++++ ...assert.local_iterator.dereference.pass.cpp | 50 ++++++++++++++ .../assert.local_iterator.increment.pass.cpp | 66 ++++++++++++++++++ .../debug.iterator.dereference.pass.cpp | 41 ------------ .../debug.iterator.increment.pass.cpp | 46 ------------- .../debug.local_iterator.dereference.pass.cpp | 39 ----------- .../debug.local_iterator.increment.pass.cpp | 49 -------------- .../assert.iterator.dereference.pass.cpp | 52 ++++++++++++++ .../assert.iterator.increment.pass.cpp | 59 ++++++++++++++++ ...assert.local_iterator.dereference.pass.cpp | 50 ++++++++++++++ .../assert.local_iterator.increment.pass.cpp | 67 +++++++++++++++++++ .../debug.iterator.dereference.pass.cpp | 41 ------------ .../debug.iterator.increment.pass.cpp | 46 ------------- .../debug.local_iterator.dereference.pass.cpp | 39 ----------- .../debug.local_iterator.increment.pass.cpp | 50 -------------- .../assert.iterator.dereference.pass.cpp | 46 +++++++++++++ .../assert.iterator.increment.pass.cpp | 58 ++++++++++++++++ ...assert.local_iterator.dereference.pass.cpp | 48 +++++++++++++ .../assert.local_iterator.increment.pass.cpp | 64 ++++++++++++++++++ .../debug.iterator.dereference.pass.cpp | 39 ----------- .../debug.iterator.increment.pass.cpp | 47 ------------- .../debug.local_iterator.dereference.pass.cpp | 41 ------------ .../debug.local_iterator.increment.pass.cpp | 51 -------------- .../assert.iterator.dereference.pass.cpp | 46 +++++++++++++ .../assert.iterator.increment.pass.cpp | 58 ++++++++++++++++ ...assert.local_iterator.dereference.pass.cpp | 48 +++++++++++++ .../assert.local_iterator.increment.pass.cpp | 64 ++++++++++++++++++ .../debug.iterator.dereference.pass.cpp | 39 ----------- .../debug.iterator.increment.pass.cpp | 47 ------------- .../debug.local_iterator.dereference.pass.cpp | 41 ------------ .../debug.local_iterator.increment.pass.cpp | 49 -------------- 33 files changed, 923 insertions(+), 709 deletions(-) create mode 100644 libcxx/test/libcxx/containers/unord/unord.map/assert.iterator.dereference.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.map/assert.iterator.increment.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.map/assert.local_iterator.dereference.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.map/assert.local_iterator.increment.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.dereference.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.increment.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.dereference.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.increment.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.multimap/assert.iterator.dereference.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.multimap/assert.iterator.increment.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.multimap/assert.local_iterator.dereference.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.multimap/assert.local_iterator.increment.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.dereference.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.increment.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.dereference.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.increment.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.multiset/assert.iterator.dereference.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.multiset/assert.iterator.increment.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.multiset/assert.local_iterator.dereference.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.multiset/assert.local_iterator.increment.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.dereference.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.increment.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.dereference.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.increment.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.set/assert.iterator.dereference.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.set/assert.iterator.increment.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.set/assert.local_iterator.dereference.pass.cpp create mode 100644 libcxx/test/libcxx/containers/unord/unord.set/assert.local_iterator.increment.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.dereference.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.increment.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.dereference.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.increment.pass.cpp diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index ec7d694c4a55..e6691e78a267 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -284,13 +284,21 @@ public: _LIBCPP_HIDE_FROM_ABI __hash_iterator() _NOEXCEPT : __node_(nullptr) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __node_->__upcast()->__get_value(); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container iterator"); + return __node_->__upcast()->__get_value(); + } _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container iterator"); return pointer_traits::pointer_to(__node_->__upcast()->__get_value()); } _LIBCPP_HIDE_FROM_ABI __hash_iterator& operator++() { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to increment a non-incrementable unordered container iterator"); __node_ = __node_->__next_; return *this; } @@ -345,12 +353,20 @@ public: _LIBCPP_HIDE_FROM_ABI __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT : __node_(__x.__node_) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __node_->__upcast()->__get_value(); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + return __node_->__upcast()->__get_value(); + } _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); return pointer_traits::pointer_to(__node_->__upcast()->__get_value()); } _LIBCPP_HIDE_FROM_ABI __hash_const_iterator& operator++() { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to increment a non-incrementable unordered container const_iterator"); __node_ = __node_->__next_; return *this; } @@ -400,13 +416,21 @@ public: _LIBCPP_HIDE_FROM_ABI __hash_local_iterator() _NOEXCEPT : __node_(nullptr) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __node_->__upcast()->__get_value(); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container local_iterator"); + return __node_->__upcast()->__get_value(); + } _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container local_iterator"); return pointer_traits::pointer_to(__node_->__upcast()->__get_value()); } _LIBCPP_HIDE_FROM_ABI __hash_local_iterator& operator++() { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to increment a non-incrementable unordered container local_iterator"); __node_ = __node_->__next_; if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) __node_ = nullptr; @@ -475,13 +499,21 @@ public: __bucket_(__x.__bucket_), __bucket_count_(__x.__bucket_count_) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __node_->__upcast()->__get_value(); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + return __node_->__upcast()->__get_value(); + } _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); return pointer_traits::pointer_to(__node_->__upcast()->__get_value()); } _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator& operator++() { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to increment a non-incrementable unordered container const_local_iterator"); __node_ = __node_->__next_; if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) __node_ = nullptr; diff --git a/libcxx/test/libcxx/containers/unord/unord.map/assert.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/assert.iterator.dereference.pass.cpp new file mode 100644 index 000000000000..f57341d64ff3 --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.map/assert.iterator.dereference.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Dereference non-dereferenceable iterator. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef std::unordered_map C; + C c; + c.insert(std::make_pair(1, "one")); + C::iterator i = c.end(); + TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator"); + C::const_iterator i2 = c.cend(); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + } + + { + typedef std::unordered_map, + std::equal_to, + min_allocator>> + C; + C c; + c.insert(std::make_pair(1, "one")); + C::iterator i = c.end(); + TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator"); + C::const_iterator i2 = c.cend(); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.map/assert.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/assert.iterator.increment.pass.cpp new file mode 100644 index 000000000000..3f4d1c2d3bdb --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.map/assert.iterator.increment.pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Increment iterator past end. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include +#include +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef std::unordered_map C; + C c; + c.insert(std::make_pair(1, "one")); + C::iterator i = c.begin(); + ++i; + assert(i == c.end()); + TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator"); + C::const_iterator i2 = c.cbegin(); + ++i2; + assert(i2 == c.cend()); + TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator"); + } + + { + typedef std::unordered_map, + std::equal_to, + min_allocator>> + C; + C c; + c.insert(std::make_pair(1, "one")); + C::iterator i = c.begin(); + ++i; + assert(i == c.end()); + TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator"); + C::const_iterator i2 = c.cbegin(); + ++i2; + assert(i2 == c.cend()); + TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.map/assert.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/assert.local_iterator.dereference.pass.cpp new file mode 100644 index 000000000000..8b47f5489556 --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.map/assert.local_iterator.dereference.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Dereference non-dereferenceable iterator. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef std::unordered_map C; + C c(1); + C::local_iterator i = c.end(0); + TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator"); + C::const_local_iterator i2 = c.cend(0); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + } + + { + typedef std::unordered_map, + std::equal_to, + min_allocator>> + C; + C c(1); + C::local_iterator i = c.end(0); + TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator"); + C::const_local_iterator i2 = c.cend(0); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.map/assert.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/assert.local_iterator.increment.pass.cpp new file mode 100644 index 000000000000..8f8305833e07 --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.map/assert.local_iterator.increment.pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Increment local_iterator past end. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include +#include +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef std::unordered_map C; + C c; + c.insert(std::make_pair(42, std::string())); + C::size_type b = c.bucket(42); + C::local_iterator i = c.begin(b); + assert(i != c.end(b)); + ++i; + assert(i == c.end(b)); + TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator"); + C::const_local_iterator i2 = c.cbegin(b); + assert(i2 != c.cend(b)); + ++i2; + assert(i2 == c.cend(b)); + TEST_LIBCPP_ASSERT_FAILURE( + ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator"); + } + + { + typedef std::unordered_map, + std::equal_to, + min_allocator>> + C; + C c({{42, std::string()}}); + C::size_type b = c.bucket(42); + C::local_iterator i = c.begin(b); + assert(i != c.end(b)); + ++i; + assert(i == c.end(b)); + TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator"); + C::const_local_iterator i2 = c.cbegin(b); + assert(i2 != c.cend(b)); + ++i2; + assert(i2 == c.cend(b)); + TEST_LIBCPP_ASSERT_FAILURE( + ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.dereference.pass.cpp deleted file mode 100644 index 5ea7f4d97fcc..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.dereference.pass.cpp +++ /dev/null @@ -1,41 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Dereference non-dereferenceable iterator. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef std::unordered_map C; - C c; - c.insert(std::make_pair(1, "one")); - C::iterator i = c.end(); - TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator"); - } - - { - typedef std::unordered_map, std::equal_to, - min_allocator>> C; - C c; - c.insert(std::make_pair(1, "one")); - C::iterator i = c.end(); - TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.increment.pass.cpp deleted file mode 100644 index 2ed09bc81aaa..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.increment.pass.cpp +++ /dev/null @@ -1,46 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Increment iterator past end. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include -#include -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef std::unordered_map C; - C c; - c.insert(std::make_pair(1, "one")); - C::iterator i = c.begin(); - ++i; - assert(i == c.end()); - TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator"); - } - - { - typedef std::unordered_map, std::equal_to, - min_allocator>> C; - C c; - c.insert(std::make_pair(1, "one")); - C::iterator i = c.begin(); - ++i; - assert(i == c.end()); - TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.dereference.pass.cpp deleted file mode 100644 index 2e4e62dbb41f..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.dereference.pass.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Dereference non-dereferenceable iterator. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef std::unordered_map C; - C c(1); - C::local_iterator i = c.end(0); - TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator"); - } - - { - typedef std::unordered_map, std::equal_to, - min_allocator>> C; - C c(1); - C::local_iterator i = c.end(0); - TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.increment.pass.cpp deleted file mode 100644 index 28599263447a..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.increment.pass.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Increment local_iterator past end. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include -#include -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef std::unordered_map C; - C c; - c.insert(std::make_pair(42, std::string())); - C::size_type b = c.bucket(42); - C::local_iterator i = c.begin(b); - assert(i != c.end(b)); - ++i; - assert(i == c.end(b)); - TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator"); - } - - { - typedef std::unordered_map, std::equal_to, - min_allocator>> C; - C c({{42, std::string()}}); - C::size_type b = c.bucket(42); - C::local_iterator i = c.begin(b); - assert(i != c.end(b)); - ++i; - assert(i == c.end(b)); - TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/assert.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/assert.iterator.dereference.pass.cpp new file mode 100644 index 000000000000..d295a82a8a1f --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.multimap/assert.iterator.dereference.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Dereference non-dereferenceable iterator. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef std::unordered_multimap C; + C c; + c.insert(std::make_pair(1, "one")); + C::iterator i = c.end(); + TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator"); + C::const_iterator i2 = c.cend(); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + } + + { + typedef std::unordered_multimap, + std::equal_to, + min_allocator>> + C; + C c; + c.insert(std::make_pair(1, "one")); + C::iterator i = c.end(); + TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator"); + C::const_iterator i2 = c.cend(); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/assert.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/assert.iterator.increment.pass.cpp new file mode 100644 index 000000000000..4247edc8def9 --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.multimap/assert.iterator.increment.pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Increment iterator past end. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include +#include +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef std::unordered_multimap C; + C c; + c.insert(std::make_pair(1, "one")); + C::iterator i = c.begin(); + ++i; + assert(i == c.end()); + TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator"); + C::const_iterator i2 = c.cbegin(); + ++i2; + assert(i2 == c.cend()); + TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator"); + } + + { + typedef std::unordered_multimap, + std::equal_to, + min_allocator>> + C; + C c; + c.insert(std::make_pair(1, "one")); + C::iterator i = c.begin(); + ++i; + assert(i == c.end()); + TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator"); + C::const_iterator i2 = c.cbegin(); + ++i2; + assert(i2 == c.cend()); + TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/assert.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/assert.local_iterator.dereference.pass.cpp new file mode 100644 index 000000000000..7ea87964e05f --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.multimap/assert.local_iterator.dereference.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Dereference non-dereferenceable iterator. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef std::unordered_multimap C; + C c(1); + C::local_iterator i = c.end(0); + TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator"); + C::const_local_iterator i2 = c.cend(0); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + } + + { + typedef std::unordered_multimap, + std::equal_to, + min_allocator>> + C; + C c(1); + C::local_iterator i = c.end(0); + TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator"); + C::const_local_iterator i2 = c.cend(0); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/assert.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/assert.local_iterator.increment.pass.cpp new file mode 100644 index 000000000000..ffa3fec0ca1f --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.multimap/assert.local_iterator.increment.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Increment local_iterator past end. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include +#include +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef std::unordered_multimap C; + C c; + c.insert(std::make_pair(42, std::string())); + C::size_type b = c.bucket(42); + C::local_iterator i = c.begin(b); + assert(i != c.end(b)); + ++i; + assert(i == c.end(b)); + TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator"); + C::const_local_iterator i2 = c.cbegin(b); + assert(i2 != c.cend(b)); + ++i2; + assert(i2 == c.cend(b)); + TEST_LIBCPP_ASSERT_FAILURE( + ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator"); + } + + { + typedef std::unordered_multimap, + std::equal_to, + min_allocator>> + C; + C c({{1, std::string()}}); + c.insert(std::make_pair(42, std::string())); + C::size_type b = c.bucket(42); + C::local_iterator i = c.begin(b); + assert(i != c.end(b)); + ++i; + assert(i == c.end(b)); + TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator"); + C::const_local_iterator i2 = c.cbegin(b); + assert(i2 != c.cend(b)); + ++i2; + assert(i2 == c.cend(b)); + TEST_LIBCPP_ASSERT_FAILURE( + ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.dereference.pass.cpp deleted file mode 100644 index 3dad48b3925d..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.dereference.pass.cpp +++ /dev/null @@ -1,41 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Dereference non-dereferenceable iterator. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef std::unordered_multimap C; - C c; - c.insert(std::make_pair(1, "one")); - C::iterator i = c.end(); - TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator"); - } - - { - typedef std::unordered_multimap, std::equal_to, - min_allocator>> C; - C c; - c.insert(std::make_pair(1, "one")); - C::iterator i = c.end(); - TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.increment.pass.cpp deleted file mode 100644 index b02bac6022f7..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.increment.pass.cpp +++ /dev/null @@ -1,46 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Increment iterator past end. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include -#include -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef std::unordered_multimap C; - C c; - c.insert(std::make_pair(1, "one")); - C::iterator i = c.begin(); - ++i; - assert(i == c.end()); - TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator"); - } - - { - typedef std::unordered_multimap, std::equal_to, - min_allocator>> C; - C c; - c.insert(std::make_pair(1, "one")); - C::iterator i = c.begin(); - ++i; - assert(i == c.end()); - TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.dereference.pass.cpp deleted file mode 100644 index 9719ba588975..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.dereference.pass.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Dereference non-dereferenceable iterator. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef std::unordered_multimap C; - C c(1); - C::local_iterator i = c.end(0); - TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator"); - } - - { - typedef std::unordered_multimap, std::equal_to, - min_allocator>> C; - C c(1); - C::local_iterator i = c.end(0); - TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.increment.pass.cpp deleted file mode 100644 index 2f74a191e8ac..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.increment.pass.cpp +++ /dev/null @@ -1,50 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Increment local_iterator past end. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include -#include -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef std::unordered_multimap C; - C c; - c.insert(std::make_pair(42, std::string())); - C::size_type b = c.bucket(42); - C::local_iterator i = c.begin(b); - assert(i != c.end(b)); - ++i; - assert(i == c.end(b)); - TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator"); - } - - { - typedef std::unordered_multimap, std::equal_to, - min_allocator>> C; - C c({{1, std::string()}}); - c.insert(std::make_pair(42, std::string())); - C::size_type b = c.bucket(42); - C::local_iterator i = c.begin(b); - assert(i != c.end(b)); - ++i; - assert(i == c.end(b)); - TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/assert.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/assert.iterator.dereference.pass.cpp new file mode 100644 index 000000000000..31edd6099c96 --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.multiset/assert.iterator.dereference.pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Dereference non-dereferenceable iterator. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef int T; + typedef std::unordered_multiset C; + C c(1); + C::iterator i = c.end(); + TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + C::const_iterator i2 = c.cend(); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + } + + { + typedef int T; + typedef std::unordered_multiset, std::equal_to, min_allocator> C; + C c(1); + C::iterator i = c.end(); + TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + C::const_iterator i2 = c.cend(); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/assert.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/assert.iterator.increment.pass.cpp new file mode 100644 index 000000000000..0e0e4aab303c --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.multiset/assert.iterator.increment.pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Increment iterator past end. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef int T; + typedef std::unordered_multiset C; + C c; + c.insert(42); + C::iterator i = c.begin(); + assert(i != c.end()); + ++i; + assert(i == c.end()); + TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator"); + C::const_iterator i2 = c.cbegin(); + assert(i2 != c.cend()); + ++i2; + assert(i2 == c.cend()); + TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator"); + } + + { + typedef int T; + typedef std::unordered_multiset, std::equal_to, min_allocator> C; + C c({42}); + C::iterator i = c.begin(); + assert(i != c.end()); + ++i; + assert(i == c.end()); + TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator"); + C::const_iterator i2 = c.cbegin(); + assert(i2 != c.cend()); + ++i2; + assert(i2 == c.cend()); + TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/assert.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/assert.local_iterator.dereference.pass.cpp new file mode 100644 index 000000000000..fe833c40bc35 --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.multiset/assert.local_iterator.dereference.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Dereference non-dereferenceable iterator. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef int T; + typedef std::unordered_multiset C; + C c(1); + C::local_iterator i = c.end(0); + TEST_LIBCPP_ASSERT_FAILURE( + *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + C::const_local_iterator i2 = c.cend(0); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + } + + { + typedef int T; + typedef std::unordered_multiset, std::equal_to, min_allocator> C; + C c(1); + C::local_iterator i = c.end(0); + TEST_LIBCPP_ASSERT_FAILURE( + *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + C::const_local_iterator i2 = c.cend(0); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/assert.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/assert.local_iterator.increment.pass.cpp new file mode 100644 index 000000000000..142c07f83c06 --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.multiset/assert.local_iterator.increment.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Increment local_iterator past end. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef int T; + typedef std::unordered_multiset C; + C c; + c.insert(42); + C::size_type b = c.bucket(42); + C::local_iterator i = c.begin(b); + assert(i != c.end(b)); + ++i; + assert(i == c.end(b)); + TEST_LIBCPP_ASSERT_FAILURE( + ++i, "Attempted to increment a non-incrementable unordered container const_local_iterator"); + C::const_local_iterator i2 = c.cbegin(b); + assert(i2 != c.cend(b)); + ++i2; + assert(i2 == c.cend(b)); + TEST_LIBCPP_ASSERT_FAILURE( + ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator"); + } + + { + typedef int T; + typedef std::unordered_multiset, std::equal_to, min_allocator> C; + C c({42}); + C::size_type b = c.bucket(42); + C::local_iterator i = c.begin(b); + assert(i != c.end(b)); + ++i; + assert(i == c.end(b)); + TEST_LIBCPP_ASSERT_FAILURE( + ++i, "Attempted to increment a non-incrementable unordered container const_local_iterator"); + C::const_local_iterator i2 = c.cbegin(b); + assert(i2 != c.cend(b)); + ++i2; + assert(i2 == c.cend(b)); + TEST_LIBCPP_ASSERT_FAILURE( + ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.dereference.pass.cpp deleted file mode 100644 index 51cb9a6bff64..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.dereference.pass.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Dereference non-dereferenceable iterator. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef int T; - typedef std::unordered_multiset C; - C c(1); - C::iterator i = c.end(); - TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); - } - - { - typedef int T; - typedef std::unordered_multiset, std::equal_to, min_allocator> C; - C c(1); - C::iterator i = c.end(); - TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.increment.pass.cpp deleted file mode 100644 index 17b8c77aadd1..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.increment.pass.cpp +++ /dev/null @@ -1,47 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Increment iterator past end. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef int T; - typedef std::unordered_multiset C; - C c; - c.insert(42); - C::iterator i = c.begin(); - assert(i != c.end()); - ++i; - assert(i == c.end()); - TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator"); - } - - { - typedef int T; - typedef std::unordered_multiset, std::equal_to, min_allocator> C; - C c({42}); - C::iterator i = c.begin(); - assert(i != c.end()); - ++i; - assert(i == c.end()); - TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.dereference.pass.cpp deleted file mode 100644 index 24102a47802f..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.dereference.pass.cpp +++ /dev/null @@ -1,41 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Dereference non-dereferenceable iterator. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef int T; - typedef std::unordered_multiset C; - C c(1); - C::local_iterator i = c.end(0); - TEST_LIBCPP_ASSERT_FAILURE( - *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); - } - - { - typedef int T; - typedef std::unordered_multiset, std::equal_to, min_allocator> C; - C c(1); - C::local_iterator i = c.end(0); - TEST_LIBCPP_ASSERT_FAILURE( - *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.increment.pass.cpp deleted file mode 100644 index 3f70ba297158..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.increment.pass.cpp +++ /dev/null @@ -1,51 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Increment local_iterator past end. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef int T; - typedef std::unordered_multiset C; - C c; - c.insert(42); - C::size_type b = c.bucket(42); - C::local_iterator i = c.begin(b); - assert(i != c.end(b)); - ++i; - assert(i == c.end(b)); - TEST_LIBCPP_ASSERT_FAILURE(++i, - "Attempted to increment a non-incrementable unordered container const_local_iterator"); - } - - { - typedef int T; - typedef std::unordered_multiset, std::equal_to, min_allocator> C; - C c({42}); - C::size_type b = c.bucket(42); - C::local_iterator i = c.begin(b); - assert(i != c.end(b)); - ++i; - assert(i == c.end(b)); - TEST_LIBCPP_ASSERT_FAILURE(++i, - "Attempted to increment a non-incrementable unordered container const_local_iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.set/assert.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/assert.iterator.dereference.pass.cpp new file mode 100644 index 000000000000..8464601f6104 --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.set/assert.iterator.dereference.pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Dereference non-dereferenceable iterator. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef int T; + typedef std::unordered_set C; + C c(1); + C::iterator i = c.end(); + TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + C::const_iterator i2 = c.cend(); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + } + + { + typedef int T; + typedef std::unordered_set, std::equal_to, min_allocator> C; + C c(1); + C::iterator i = c.end(); + TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + C::const_iterator i2 = c.cend(); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.set/assert.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/assert.iterator.increment.pass.cpp new file mode 100644 index 000000000000..29446880900b --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.set/assert.iterator.increment.pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Increment iterator past end. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef int T; + typedef std::unordered_set C; + C c; + c.insert(42); + C::iterator i = c.begin(); + assert(i != c.end()); + ++i; + assert(i == c.end()); + TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator"); + C::const_iterator i2 = c.cbegin(); + assert(i2 != c.cend()); + ++i2; + assert(i2 == c.cend()); + TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator"); + } + + { + typedef int T; + typedef std::unordered_set, std::equal_to, min_allocator> C; + C c({42}); + C::iterator i = c.begin(); + assert(i != c.end()); + ++i; + assert(i == c.end()); + TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator"); + C::const_iterator i2 = c.cbegin(); + assert(i2 != c.cend()); + ++i2; + assert(i2 == c.cend()); + TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.set/assert.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/assert.local_iterator.dereference.pass.cpp new file mode 100644 index 000000000000..7163e3735cee --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.set/assert.local_iterator.dereference.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Dereference non-dereferenceable iterator. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef int T; + typedef std::unordered_set C; + C c(1); + C::local_iterator i = c.end(0); + TEST_LIBCPP_ASSERT_FAILURE( + *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + C::const_local_iterator i2 = c.cend(0); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + } + + { + typedef int T; + typedef std::unordered_set, std::equal_to, min_allocator> C; + C c(1); + C::local_iterator i = c.end(0); + TEST_LIBCPP_ASSERT_FAILURE( + *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + C::const_local_iterator i2 = c.cend(0); + TEST_LIBCPP_ASSERT_FAILURE( + *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.set/assert.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/assert.local_iterator.increment.pass.cpp new file mode 100644 index 000000000000..c9fe5afd0970 --- /dev/null +++ b/libcxx/test/libcxx/containers/unord/unord.set/assert.local_iterator.increment.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// Increment local_iterator past end. + +// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include +#include + +#include "check_assertion.h" +#include "min_allocator.h" + +int main(int, char**) { + { + typedef int T; + typedef std::unordered_set C; + C c; + c.insert(42); + C::size_type b = c.bucket(42); + C::local_iterator i = c.begin(b); + assert(i != c.end(b)); + ++i; + assert(i == c.end(b)); + TEST_LIBCPP_ASSERT_FAILURE( + ++i, "Attempted to increment a non-incrementable unordered container const_local_iterator"); + C::const_local_iterator i2 = c.cbegin(b); + assert(i2 != c.cend(b)); + ++i2; + assert(i2 == c.cend(b)); + TEST_LIBCPP_ASSERT_FAILURE( + ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator"); + } + + { + typedef int T; + typedef std::unordered_set, std::equal_to, min_allocator> C; + C c({42}); + C::size_type b = c.bucket(42); + C::local_iterator i = c.begin(b); + assert(i != c.end(b)); + ++i; + assert(i == c.end(b)); + TEST_LIBCPP_ASSERT_FAILURE( + ++i, "Attempted to increment a non-incrementable unordered container const_local_iterator"); + C::const_local_iterator i2 = c.cbegin(b); + assert(i2 != c.cend(b)); + ++i2; + assert(i2 == c.cend(b)); + TEST_LIBCPP_ASSERT_FAILURE( + ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.dereference.pass.cpp deleted file mode 100644 index 49663b4f824a..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.dereference.pass.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Dereference non-dereferenceable iterator. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef int T; - typedef std::unordered_set C; - C c(1); - C::iterator i = c.end(); - TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); - } - - { - typedef int T; - typedef std::unordered_set, std::equal_to, min_allocator> C; - C c(1); - C::iterator i = c.end(); - TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.increment.pass.cpp deleted file mode 100644 index da3fbdc5a6e8..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.increment.pass.cpp +++ /dev/null @@ -1,47 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Increment iterator past end. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef int T; - typedef std::unordered_set C; - C c; - c.insert(42); - C::iterator i = c.begin(); - assert(i != c.end()); - ++i; - assert(i == c.end()); - TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator"); - } - - { - typedef int T; - typedef std::unordered_set, std::equal_to, min_allocator> C; - C c({42}); - C::iterator i = c.begin(); - assert(i != c.end()); - ++i; - assert(i == c.end()); - TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.dereference.pass.cpp deleted file mode 100644 index 912edc2e4bf4..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.dereference.pass.cpp +++ /dev/null @@ -1,41 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Dereference non-dereferenceable iterator. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef int T; - typedef std::unordered_set C; - C c(1); - C::local_iterator i = c.end(0); - TEST_LIBCPP_ASSERT_FAILURE( - *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); - } - - { - typedef int T; - typedef std::unordered_set, std::equal_to, min_allocator> C; - C c(1); - C::local_iterator i = c.end(0); - TEST_LIBCPP_ASSERT_FAILURE( - *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); - } - - return 0; -} diff --git a/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.increment.pass.cpp deleted file mode 100644 index 42a62aed472c..000000000000 --- a/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.increment.pass.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// - -// Increment local_iterator past end. - -// REQUIRES: has-unix-headers -// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03 - -#include -#include - -#include "check_assertion.h" -#include "min_allocator.h" - -int main(int, char**) { - { - typedef int T; - typedef std::unordered_set C; - C c; - c.insert(42); - C::size_type b = c.bucket(42); - C::local_iterator i = c.begin(b); - assert(i != c.end(b)); - ++i; - assert(i == c.end(b)); - TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_local_iterator"); - } - - { - typedef int T; - typedef std::unordered_set, std::equal_to, min_allocator> C; - C c({42}); - C::size_type b = c.bucket(42); - C::local_iterator i = c.begin(b); - assert(i != c.end(b)); - ++i; - assert(i == c.end(b)); - TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_local_iterator"); - } - - return 0; -} -- GitLab From 2a3068455716a1a37da9155d4d96107901bba4a8 Mon Sep 17 00:00:00 2001 From: Matthias Springer Date: Tue, 12 Mar 2024 10:51:11 +0900 Subject: [PATCH 199/953] [mlir][Transforms] Use correct listener in dialect conversion (#84861) There was a typo in the dialect conversion: `RewriterBase::Listener` should be used instead of `ForwardingListener`. --- mlir/lib/Transforms/Utils/DialectConversion.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp b/mlir/lib/Transforms/Utils/DialectConversion.cpp index cd49bd121a62..2ec0b964b304 100644 --- a/mlir/lib/Transforms/Utils/DialectConversion.cpp +++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp @@ -1020,8 +1020,8 @@ void BlockTypeConversionRewrite::commit(RewriterBase &rewriter) { // Inform the listener about all IR modifications that have already taken // place: References to the original block have been replaced with the new // block. - if (auto *listener = dyn_cast_or_null( - rewriter.getListener())) + if (auto *listener = + dyn_cast_or_null(rewriter.getListener())) for (Operation *op : block->getUsers()) listener->notifyOperationModified(op); @@ -1123,8 +1123,8 @@ void ReplaceBlockArgRewrite::commit(RewriterBase &rewriter) { void ReplaceBlockArgRewrite::rollback() { rewriterImpl.mapping.erase(arg); } void ReplaceOperationRewrite::commit(RewriterBase &rewriter) { - auto *listener = dyn_cast_or_null( - rewriter.getListener()); + auto *listener = + dyn_cast_or_null(rewriter.getListener()); // Compute replacement values. SmallVector replacements = -- GitLab From 26722f5b61575fb0e58ff2933e7bea03353ff441 Mon Sep 17 00:00:00 2001 From: Sayan Saha Date: Mon, 11 Mar 2024 22:37:33 -0400 Subject: [PATCH 200/953] [MLIR] Fix incorrect memref::DimOp canonicalization, add tensor::DimOp canonicalization (#84225) The current canonicalization of `memref.dim` operating on the result of `memref.reshape` into `memref.load` is incorrect as it doesn't check whether the `index` operand of `memref.dim` dominates the source `memref.reshape` op. It always introduces `memref.load` right after `memref.reshape` to ensure the `memref` is not mutated before the `memref.load` call. As a result, the following error is observed: ``` $> mlir-opt --canonicalize input.mlir func.func @reshape_dim(%arg0: memref<*xf32>, %arg1: memref, %arg2: index) -> index { %c4 = arith.constant 4 : index %reshape = memref.reshape %arg0(%arg1) : (memref<*xf32>, memref) -> memref<*xf32> %0 = arith.muli %arg2, %c4 : index %dim = memref.dim %reshape, %0 : memref<*xf32> return %dim : index } ``` results in: ``` dominator.mlir:22:12: error: operand #1 does not dominate this use %dim = memref.dim %reshape, %0 : memref<*xf32> ^ dominator.mlir:22:12: note: see current operation: %1 = "memref.load"(%arg1, %2) <{nontemporal = false}> : (memref, index) -> index dominator.mlir:21:10: note: operand defined here (op in the same block) %0 = arith.muli %arg2, %c4 : index ``` Properly fixing this issue requires a dominator analysis which is expensive to run within a canonicalization pattern. So, this patch fixes the canonicalization pattern by being more strict/conservative about the legality condition in which we perform this canonicalization. The more general pattern is also added to `tensor.dim`. Since tensors are immutable we don't need to worry about where to introduce the `tensor.extract` call after canonicalization. --- mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp | 32 ++++++++- mlir/lib/Dialect/Tensor/IR/TensorOps.cpp | 28 +++++++- mlir/test/Dialect/MemRef/canonicalize.mlir | 53 ++++++++++++++ mlir/test/Dialect/Tensor/canonicalize.mlir | 80 ++++++++++++++++++++++ 4 files changed, 191 insertions(+), 2 deletions(-) diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp index 94e0ed319cae..836dcb8f329e 100644 --- a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp +++ b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp @@ -1080,7 +1080,37 @@ struct DimOfMemRefReshape : public OpRewritePattern { auto reshape = dim.getSource().getDefiningOp(); if (!reshape) - return failure(); + return rewriter.notifyMatchFailure( + dim, "Dim op is not defined by a reshape op."); + + // dim of a memref reshape can be folded if dim.getIndex() dominates the + // reshape. Instead of using `DominanceInfo` (which is usually costly) we + // cheaply check that either of the following conditions hold: + // 1. dim.getIndex() is defined in the same block as reshape but before + // reshape. + // 2. dim.getIndex() is defined in a parent block of + // reshape. + + // Check condition 1 + if (dim.getIndex().getParentBlock() == reshape->getBlock()) { + if (auto *definingOp = dim.getIndex().getDefiningOp()) { + if (reshape->isBeforeInBlock(definingOp)) { + return rewriter.notifyMatchFailure( + dim, + "dim.getIndex is not defined before reshape in the same block."); + } + } // else dim.getIndex is a block argument to reshape->getBlock and + // dominates reshape + } // Check condition 2 + else if (dim->getBlock() != reshape->getBlock() && + !dim.getIndex().getParentRegion()->isProperAncestor( + reshape->getParentRegion())) { + // If dim and reshape are in the same block but dim.getIndex() isn't, we + // already know dim.getIndex() dominates reshape without calling + // `isProperAncestor` + return rewriter.notifyMatchFailure( + dim, "dim.getIndex does not dominate reshape."); + } // Place the load directly after the reshape to ensure that the shape memref // was not mutated. diff --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp index a854da466c31..dc8843aa4e1e 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp @@ -824,11 +824,37 @@ struct DimOfDestStyleOp : public OpRewritePattern { return success(); } }; + +/// Fold dim of a tensor reshape operation to a extract into the reshape's shape +/// operand. +struct DimOfReshapeOp : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(DimOp dim, + PatternRewriter &rewriter) const override { + auto reshape = dim.getSource().getDefiningOp(); + + if (!reshape) + return failure(); + + // Since tensors are immutable we don't need to worry about where to place + // the extract call + rewriter.setInsertionPointAfter(dim); + Location loc = dim.getLoc(); + Value extract = + rewriter.create(loc, reshape.getShape(), dim.getIndex()); + if (extract.getType() != dim.getType()) + extract = + rewriter.create(loc, dim.getType(), extract); + rewriter.replaceOp(dim, extract); + return success(); + } +}; } // namespace void DimOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { - results.add(context); + results.add(context); } //===----------------------------------------------------------------------===// diff --git a/mlir/test/Dialect/MemRef/canonicalize.mlir b/mlir/test/Dialect/MemRef/canonicalize.mlir index b1e92e54d561..506ed1f1c10b 100644 --- a/mlir/test/Dialect/MemRef/canonicalize.mlir +++ b/mlir/test/Dialect/MemRef/canonicalize.mlir @@ -313,6 +313,59 @@ func.func @dim_of_memref_reshape_i32(%arg0: memref<*xf32>, %arg1: memref) // ----- +// Test case: memref.dim(memref.reshape %v %shp, %idx) -> memref.load %shp[%idx] +// CHECK-LABEL: func @dim_of_memref_reshape_block_arg_index( +// CHECK-SAME: %[[MEM:[0-9a-z]+]]: memref<*xf32>, +// CHECK-SAME: %[[SHP:[0-9a-z]+]]: memref, +// CHECK-SAME: %[[IDX:[0-9a-z]+]]: index +// CHECK-NEXT: %[[DIM:.*]] = memref.load %[[SHP]][%[[IDX]]] +// CHECK-NOT: memref.dim +// CHECK: return %[[DIM]] : index +func.func @dim_of_memref_reshape_block_arg_index(%arg0: memref<*xf32>, %arg1: memref, %arg2: index) -> index { + %reshape = memref.reshape %arg0(%arg1) : (memref<*xf32>, memref) -> memref<*xf32> + %dim = memref.dim %reshape, %arg2 : memref<*xf32> + return %dim : index +} + +// ----- + +// Test case: memref.dim(memref.reshape %v %shp, %idx) is not folded into memref.load %shp[%idx] +// CHECK-LABEL: func @dim_of_memref_reshape_for( +// CHECK: memref.reshape +// CHECK: memref.dim +// CHECK-NOT: memref.load +func.func @dim_of_memref_reshape_for( %arg0: memref<*xf32>, %arg1: memref) -> index { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %c4 = arith.constant 4 : index + + %0 = memref.reshape %arg0(%arg1) : (memref<*xf32>, memref) -> memref<*xf32> + + %1 = scf.for %arg2 = %c0 to %c4 step %c1 iter_args(%arg3 = %c1) -> (index) { + %2 = memref.dim %0, %arg2 : memref<*xf32> + %3 = arith.muli %arg3, %2 : index + scf.yield %3 : index + } + return %1 : index +} + +// ----- + +// Test case: memref.dim(memref.reshape %v %shp, %idx) is not folded into memref.load %shp[%idx] +// CHECK-LABEL: func @dim_of_memref_reshape_undominated( +// CHECK: memref.reshape +// CHECK: memref.dim +// CHECK-NOT: memref.load +func.func @dim_of_memref_reshape_undominated(%arg0: memref<*xf32>, %arg1: memref, %arg2: index) -> index { + %c4 = arith.constant 4 : index + %reshape = memref.reshape %arg0(%arg1) : (memref<*xf32>, memref) -> memref<*xf32> + %0 = arith.muli %arg2, %c4 : index + %dim = memref.dim %reshape, %0 : memref<*xf32> + return %dim : index + } + +// ----- + // CHECK-LABEL: func @alloc_const_fold func.func @alloc_const_fold() -> memref { // CHECK-NEXT: memref.alloc() : memref<4xf32> diff --git a/mlir/test/Dialect/Tensor/canonicalize.mlir b/mlir/test/Dialect/Tensor/canonicalize.mlir index 70f5d61bd802..e5374f031be5 100644 --- a/mlir/test/Dialect/Tensor/canonicalize.mlir +++ b/mlir/test/Dialect/Tensor/canonicalize.mlir @@ -2287,3 +2287,83 @@ func.func @infer_and_fold_pack_unpack_same_tiles(%t: tensor<10x20x4x4xf32>) -> t // CHECK-LABEL: func.func @infer_and_fold_pack_unpack_same_tiles // CHECK-SAME: %[[SRC:[0-9a-zA-Z]+]] // CHECK: return %[[SRC]] + +// ----- + +// Test case: Folding of tensor.dim(tensor.reshape %v %shp, %idx) -> tensor.extract %shp[%idx] +// CHECK-LABEL: func @dim_of_reshape( +// CHECK-SAME: %[[MEM:[0-9a-z]+]]: tensor<*xf32>, +// CHECK-SAME: %[[SHP:[0-9a-z]+]]: tensor +// CHECK-NEXT: %[[IDX:.*]] = arith.constant 3 +// CHECK-NEXT: %[[DIM:.*]] = tensor.extract %[[SHP]][%[[IDX]]] +// CHECK-NOT: tensor.store +// CHECK-NOT: tensor.dim +// CHECK-NOT: tensor.reshape +// CHECK: return %[[DIM]] : index +func.func @dim_of_reshape(%arg0: tensor<*xf32>, %arg1: tensor) + -> index { + %c3 = arith.constant 3 : index + %0 = tensor.reshape %arg0(%arg1) + : (tensor<*xf32>, tensor) -> tensor<*xf32> + // Update the shape to test that the load ends up in the right place. + tensor.insert %c3 into %arg1[%c3] : tensor + %1 = tensor.dim %0, %c3 : tensor<*xf32> + return %1 : index +} + +// ----- + +// Test case: Folding of tensor.dim(tensor.reshape %v %shp, %idx) -> tensor.extract %shp[%idx] +// CHECK-LABEL: func @dim_of_reshape_i32( +// CHECK: tensor.extract +// CHECK-NEXT: %[[CAST:.*]] = arith.index_cast +// CHECK-NOT: tensor.dim +// CHECK-NOT: tensor.reshape +// CHECK: return %[[CAST]] : index +func.func @dim_of_reshape_i32(%arg0: tensor<*xf32>, %arg1: tensor) + -> index { + %c3 = arith.constant 3 : index + %0 = tensor.reshape %arg0(%arg1) + : (tensor<*xf32>, tensor) -> tensor<*xf32> + %1 = tensor.dim %0, %c3 : tensor<*xf32> + return %1 : index +} + +// ----- + +// Test case: tensor.dim(tensor.reshape %v %shp, %idx) is folded into tensor.extract %shp[%idx] +// CHECK-LABEL: func @dim_of_reshape_for( +// CHECK: scf.for +// CHECK-NEXT: tensor.extract +// CHECK-NOT: tensor.dim +// CHECK-NOT: tensor.reshape +func.func @dim_of_reshape_for( %arg0: tensor<*xf32>, %arg1: tensor) -> index { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %c4 = arith.constant 4 : index + + %0 = tensor.reshape %arg0(%arg1) : (tensor<*xf32>, tensor) -> tensor<*xf32> + + %1 = scf.for %arg2 = %c0 to %c4 step %c1 iter_args(%arg3 = %c1) -> (index) { + %2 = tensor.dim %0, %arg2 : tensor<*xf32> + %3 = arith.muli %arg3, %2 : index + scf.yield %3 : index + } + return %1 : index +} + +// ----- + +// Test case: tensor.dim(tensor.reshape %v %shp, %idx) is folded into tensor.extract %shp[%idx] +// CHECK-LABEL: func @dim_of_reshape_undominated( +// CHECK: arith.muli +// CHECK-NEXT: tensor.extract +// CHECK-NOT: tensor.dim +// CHECK-NOT: tensor.reshape +func.func @dim_of_reshape_undominated(%arg0: tensor<*xf32>, %arg1: tensor, %arg2: index) -> index { + %c4 = arith.constant 4 : index + %reshape = tensor.reshape %arg0(%arg1) : (tensor<*xf32>, tensor) -> tensor<*xf32> + %0 = arith.muli %arg2, %c4 : index + %dim = tensor.dim %reshape, %0 : tensor<*xf32> + return %dim : index + } -- GitLab From e40cabfea48c617fe6efaace588e80474bc80fe8 Mon Sep 17 00:00:00 2001 From: lifengxiang1025 Date: Tue, 12 Mar 2024 11:00:02 +0800 Subject: [PATCH 201/953] [MemProf] Match function's summary and definition strictly (#83665) Problem description: https://github.com/llvm/llvm-project/pull/81008#issuecomment-1933468520 Solution: https://github.com/llvm/llvm-project/pull/81008#issuecomment-1934192548 (choose plan2) --- llvm/lib/Passes/PassBuilderPipelines.cpp | 4 +- llvm/lib/Transforms/IPO/FunctionImport.cpp | 10 +- .../IPO/MemProfContextDisambiguation.cpp | 24 +- llvm/test/ThinLTO/X86/summary-matching.ll | 387 ++++++++++++++++++ 4 files changed, 416 insertions(+), 9 deletions(-) create mode 100644 llvm/test/ThinLTO/X86/summary-matching.ll diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp index cbbbec0ccc8c..cb892e30c4a0 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -299,9 +299,7 @@ static cl::opt UseLoopVersioningLICM( cl::desc("Enable the experimental Loop Versioning LICM pass")); namespace llvm { -cl::opt EnableMemProfContextDisambiguation( - "enable-memprof-context-disambiguation", cl::init(false), cl::Hidden, - cl::ZeroOrMore, cl::desc("Enable MemProf context disambiguation")); +extern cl::opt EnableMemProfContextDisambiguation; extern cl::opt EnableInferAlignmentPass; } // namespace llvm diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp index 5c7a74dadb46..68f9799616ae 100644 --- a/llvm/lib/Transforms/IPO/FunctionImport.cpp +++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp @@ -163,6 +163,10 @@ static cl::opt WorkloadDefinitions( "}"), cl::Hidden); +namespace llvm { +extern cl::opt EnableMemProfContextDisambiguation; +} + // Load lazily a module from \p FileName in \p Context. static std::unique_ptr loadFile(const std::string &FileName, LLVMContext &Context) { @@ -1643,7 +1647,9 @@ Expected FunctionImporter::importFunctions( if (Import) { if (Error Err = F.materialize()) return std::move(Err); - if (EnableImportMetadata) { + // MemProf should match function's definition and summary, + // 'thinlto_src_module' is needed. + if (EnableImportMetadata || EnableMemProfContextDisambiguation) { // Add 'thinlto_src_module' and 'thinlto_src_file' metadata for // statistics and debugging. F.setMetadata( @@ -1693,7 +1699,7 @@ Expected FunctionImporter::importFunctions( LLVM_DEBUG(dbgs() << "Is importing aliasee fn " << GO->getGUID() << " " << GO->getName() << " from " << SrcModule->getSourceFileName() << "\n"); - if (EnableImportMetadata) { + if (EnableImportMetadata || EnableMemProfContextDisambiguation) { // Add 'thinlto_src_module' and 'thinlto_src_file' metadata for // statistics and debugging. Fn->setMetadata( diff --git a/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp b/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp index 271d3ed40030..ba5e3b637db7 100644 --- a/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp +++ b/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp @@ -122,6 +122,10 @@ static cl::opt "frames through tail calls.")); namespace llvm { +cl::opt EnableMemProfContextDisambiguation( + "enable-memprof-context-disambiguation", cl::init(false), cl::Hidden, + cl::ZeroOrMore, cl::desc("Enable MemProf context disambiguation")); + // Indicate we are linking with an allocator that supports hot/cold operator // new interfaces. cl::opt SupportsHotColdNew( @@ -3375,10 +3379,22 @@ bool MemProfContextDisambiguation::applyImport(Module &M) { auto *GVSummary = ImportSummary->findSummaryInModule(TheFnVI, M.getModuleIdentifier()); - if (!GVSummary) - // Must have been imported, use the first summary (might be multiple if - // this was a linkonce_odr). - GVSummary = TheFnVI.getSummaryList().front().get(); + if (!GVSummary) { + // Must have been imported, use the summary which matches the definition。 + // (might be multiple if this was a linkonce_odr). + auto SrcModuleMD = F.getMetadata("thinlto_src_module"); + assert(SrcModuleMD && + "enable-import-metadata is needed to emit thinlto_src_module"); + StringRef SrcModule = + dyn_cast(SrcModuleMD->getOperand(0))->getString(); + for (auto &GVS : TheFnVI.getSummaryList()) { + if (GVS->modulePath() == SrcModule) { + GVSummary = GVS.get(); + break; + } + } + assert(GVSummary && GVSummary->modulePath() == SrcModule); + } // If this was an imported alias skip it as we won't have the function // summary, and it should be cloned in the original module. diff --git a/llvm/test/ThinLTO/X86/summary-matching.ll b/llvm/test/ThinLTO/X86/summary-matching.ll new file mode 100644 index 000000000000..60dc51b965d5 --- /dev/null +++ b/llvm/test/ThinLTO/X86/summary-matching.ll @@ -0,0 +1,387 @@ +;; Test to make sure that function's definiton and summary matches. +; RUN: split-file %s %t +; RUN: opt -thinlto-bc %t/main.ll >%t/main.o +; RUN: opt -thinlto-bc %t/b.ll >%t/b.o +; RUN: opt -thinlto-bc %t/c.ll >%t/c.o + +; RUN: llvm-lto2 run %t/b.o %t/c.o %t/main.o -enable-memprof-context-disambiguation \ +; RUN: -supports-hot-cold-new -o %t/a.out \ +; RUN: -r=%t/main.o,main,plx \ +; RUN: -r=%t/b.o,_Z1bv,plx \ +; RUN: -r=%t/b.o,_Z3fooIiET_S0_S0_,plx \ +; RUN: -r=%t/b.o,_Znwm \ +; RUN: -r=%t/c.o,_Z1cv,plx \ +; RUN: -r=%t/c.o,_Z3fooIiET_S0_S0_ \ +; RUN: -r=%t/c.o,_Z3barIiET_S0_S0_,plx \ +; RUN: -r=%t/c.o,_Znwm \ +; RUN: -r=%t/main.o,_Z1bv \ +; RUN: -r=%t/main.o,_Z1cv \ +; RUN: -r=%t/main.o,_Z3fooIiET_S0_S0_ + +;; foo has two copys: +;; foo in b.ll is prevailing and inlines bar. +;; foo in c.ll isn't prevailing and doesn't inline bar. +;; main will import foo in c.ll and foo's summary in b.ll default. + +;--- main.ll +; ModuleID = 'main.cc' +source_filename = "main.cc" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function Attrs: mustprogress norecurse uwtable +define dso_local noundef i32 @main() #0 { +entry: + %retval = alloca i32, align 4 + store i32 0, ptr %retval, align 4 + %call = call noundef i32 @_Z1bv(), !callsite !6 + %call1 = call noundef i32 @_Z1cv(), !callsite !7 + %add = add nsw i32 %call, %call1 + %call2 = call noundef i32 @_Z3fooIiET_S0_S0_(i32 noundef 1, i32 noundef 2), !callsite !8 + %add3 = add nsw i32 %add, %call2 + ret i32 %add3 +} + +declare noundef i32 @_Z1bv() #1 + +declare noundef i32 @_Z1cv() #1 + +declare noundef i32 @_Z3fooIiET_S0_S0_(i32 noundef, i32 noundef) #1 + +attributes #0 = { mustprogress norecurse uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + +!llvm.module.flags = !{!0, !1, !2, !3, !4} +!llvm.ident = !{!5} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 8, !"PIC Level", i32 2} +!2 = !{i32 7, !"PIE Level", i32 2} +!3 = !{i32 7, !"uwtable", i32 2} +!4 = !{i32 7, !"frame-pointer", i32 2} +!5 = !{!"clang version 19.0.0"} +!6 = !{i64 1} +!7 = !{i64 5} +!8 = !{i64 7} + +;--- c.ll +; ModuleID = 'c.cc' +source_filename = "c.cc" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +$_Z3fooIiET_S0_S0_ = comdat any + +$_Z3barIiET_S0_S0_ = comdat any + +; Function Attrs: mustprogress noinline optnone uwtable +define dso_local noundef i32 @_Z1cv() #0 { +entry: + %num1 = alloca i32, align 4 + %num2 = alloca i32, align 4 + store i32 1, ptr %num1, align 4 + store i32 1, ptr %num2, align 4 + %0 = load i32, ptr %num1, align 4 + %1 = load i32, ptr %num2, align 4 + %call = call noundef i32 @_Z3fooIiET_S0_S0_(i32 noundef %0, i32 noundef %1), !callsite !6 + ret i32 %call +} + +; Function Attrs: mustprogress uwtable +define linkonce_odr dso_local noundef i32 @_Z3fooIiET_S0_S0_(i32 noundef %a, i32 noundef %b) #3 comdat { +entry: + %a.addr = alloca i32, align 4 + %b.addr = alloca i32, align 4 + %rtn = alloca i32, align 4 + store i32 %a, ptr %a.addr, align 4 + store i32 %b, ptr %b.addr, align 4 + %0 = load i32, ptr %a.addr, align 4 + %1 = load i32, ptr %b.addr, align 4 + %call = call noundef i32 @_Z3barIiET_S0_S0_(i32 noundef %0, i32 noundef %1), !callsite !7 + store i32 %call, ptr %rtn, align 4 + %2 = load i32, ptr %rtn, align 4 + ret i32 %2 +} + +; Function Attrs: mustprogress noinline optnone uwtable +define linkonce_odr dso_local noundef i32 @_Z3barIiET_S0_S0_(i32 noundef %a, i32 noundef %b) #0 comdat { +entry: + %a.addr = alloca i32, align 4 + %b.addr = alloca i32, align 4 + %c = alloca ptr, align 8 + %d = alloca ptr, align 8 + store i32 %a, ptr %a.addr, align 4 + store i32 %b, ptr %b.addr, align 4 + %0 = load i32, ptr %a.addr, align 4 + %add = add nsw i32 %0, 1 + store i32 %add, ptr %a.addr, align 4 + %1 = load i32, ptr %b.addr, align 4 + %add1 = add nsw i32 %1, 1 + store i32 %add1, ptr %b.addr, align 4 + %2 = load i32, ptr %a.addr, align 4 + %add2 = add nsw i32 %2, 1 + store i32 %add2, ptr %a.addr, align 4 + %3 = load i32, ptr %b.addr, align 4 + %add3 = add nsw i32 %3, 1 + store i32 %add3, ptr %b.addr, align 4 + %4 = load i32, ptr %a.addr, align 4 + %add4 = add nsw i32 %4, 1 + store i32 %add4, ptr %a.addr, align 4 + %5 = load i32, ptr %b.addr, align 4 + %add5 = add nsw i32 %5, 1 + store i32 %add5, ptr %b.addr, align 4 + %6 = load i32, ptr %a.addr, align 4 + %add6 = add nsw i32 %6, 1 + store i32 %add6, ptr %a.addr, align 4 + %7 = load i32, ptr %b.addr, align 4 + %add7 = add nsw i32 %7, 1 + store i32 %add7, ptr %b.addr, align 4 + %8 = load i32, ptr %a.addr, align 4 + %add8 = add nsw i32 %8, 1 + store i32 %add8, ptr %a.addr, align 4 + %9 = load i32, ptr %b.addr, align 4 + %add9 = add nsw i32 %9, 1 + store i32 %add9, ptr %b.addr, align 4 + %10 = load i32, ptr %a.addr, align 4 + %add10 = add nsw i32 %10, 1 + store i32 %add10, ptr %a.addr, align 4 + %11 = load i32, ptr %b.addr, align 4 + %add11 = add nsw i32 %11, 1 + store i32 %add11, ptr %b.addr, align 4 + %12 = load i32, ptr %a.addr, align 4 + %add12 = add nsw i32 %12, 1 + store i32 %add12, ptr %a.addr, align 4 + %13 = load i32, ptr %b.addr, align 4 + %add13 = add nsw i32 %13, 1 + store i32 %add13, ptr %b.addr, align 4 + %14 = load i32, ptr %a.addr, align 4 + %add14 = add nsw i32 %14, 1 + store i32 %add14, ptr %a.addr, align 4 + %15 = load i32, ptr %b.addr, align 4 + %add15 = add nsw i32 %15, 1 + store i32 %add15, ptr %b.addr, align 4 + %16 = load i32, ptr %a.addr, align 4 + %add16 = add nsw i32 %16, 1 + store i32 %add16, ptr %a.addr, align 4 + %17 = load i32, ptr %b.addr, align 4 + %add17 = add nsw i32 %17, 1 + store i32 %add17, ptr %b.addr, align 4 + %18 = load i32, ptr %a.addr, align 4 + %add18 = add nsw i32 %18, 1 + store i32 %add18, ptr %a.addr, align 4 + %19 = load i32, ptr %b.addr, align 4 + %add19 = add nsw i32 %19, 1 + store i32 %add19, ptr %b.addr, align 4 + %20 = load i32, ptr %a.addr, align 4 + %add20 = add nsw i32 %20, 1 + store i32 %add20, ptr %a.addr, align 4 + %21 = load i32, ptr %b.addr, align 4 + %add21 = add nsw i32 %21, 1 + store i32 %add21, ptr %b.addr, align 4 + %22 = load i32, ptr %a.addr, align 4 + %add22 = add nsw i32 %22, 1 + store i32 %add22, ptr %a.addr, align 4 + %23 = load i32, ptr %b.addr, align 4 + %add23 = add nsw i32 %23, 1 + store i32 %add23, ptr %b.addr, align 4 + %call = call noalias noundef nonnull ptr @_Znwm(i64 noundef 4) #2, !callsite !8 + store i32 1, ptr %call, align 4 + store ptr %call, ptr %c, align 8 + %call24 = call noalias noundef nonnull ptr @_Znwm(i64 noundef 4) #2, !callsite !9 + store i32 1, ptr %call24, align 4 + store ptr %call24, ptr %d, align 8 + %24 = load i32, ptr %a.addr, align 4 + %25 = load i32, ptr %b.addr, align 4 + %cmp = icmp sgt i32 %24, %25 + br i1 %cmp, label %cond.true, label %cond.false + +cond.true: ; preds = %entry + %26 = load i32, ptr %a.addr, align 4 + br label %cond.end + +cond.false: ; preds = %entry + %27 = load i32, ptr %b.addr, align 4 + br label %cond.end + +cond.end: ; preds = %cond.false, %cond.true + %cond = phi i32 [ %26, %cond.true ], [ %27, %cond.false ] + ret i32 %cond +} + +; Function Attrs: nobuiltin allocsize(0) +declare noundef nonnull ptr @_Znwm(i64 noundef) #1 + +attributes #0 = { mustprogress noinline optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nobuiltin allocsize(0) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #2 = { builtin allocsize(0) } +attributes #3 = { mustprogress uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + +!llvm.module.flags = !{!0, !1, !2, !3, !4} +!llvm.ident = !{!5} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 8, !"PIC Level", i32 2} +!2 = !{i32 7, !"PIE Level", i32 2} +!3 = !{i32 7, !"uwtable", i32 2} +!4 = !{i32 7, !"frame-pointer", i32 2} +!5 = !{!"clang version 19.0.0"} +!6 = !{i64 6} +!7 = !{i64 3} +!8 = !{i64 4} +!9 = !{i64 9} + +;--- b.ll +; ModuleID = 'b.cc' +source_filename = "b.cc" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +$_Z3fooIiET_S0_S0_ = comdat any + +; Function Attrs: mustprogress noinline optnone uwtable +define dso_local noundef i32 @_Z1bv() #0 { +entry: + %num1 = alloca i32, align 4 + %num2 = alloca i32, align 4 + store i32 0, ptr %num1, align 4 + store i32 0, ptr %num2, align 4 + %0 = load i32, ptr %num1, align 4 + %1 = load i32, ptr %num2, align 4 + %call = call noundef i32 @_Z3fooIiET_S0_S0_(i32 noundef %0, i32 noundef %1), !callsite !6 + ret i32 %call +} + +; Function Attrs: mustprogress uwtable +define linkonce_odr dso_local noundef i32 @_Z3fooIiET_S0_S0_(i32 noundef %a, i32 noundef %b) #3 comdat { +entry: + %a.addr.i = alloca i32, align 4 + %b.addr.i = alloca i32, align 4 + %c.i = alloca ptr, align 8 + %d.i = alloca ptr, align 8 + %a.addr = alloca i32, align 4 + %b.addr = alloca i32, align 4 + %rtn = alloca i32, align 4 + store i32 %a, ptr %a.addr, align 4 + store i32 %b, ptr %b.addr, align 4 + %0 = load i32, ptr %a.addr, align 4 + %1 = load i32, ptr %b.addr, align 4 + store i32 %0, ptr %a.addr.i, align 4 + store i32 %1, ptr %b.addr.i, align 4 + %2 = load i32, ptr %a.addr.i, align 4 + %add.i = add nsw i32 %2, 1 + store i32 %add.i, ptr %a.addr.i, align 4 + %3 = load i32, ptr %b.addr.i, align 4 + %add1.i = add nsw i32 %3, 1 + store i32 %add1.i, ptr %b.addr.i, align 4 + %4 = load i32, ptr %a.addr.i, align 4 + %add2.i = add nsw i32 %4, 1 + store i32 %add2.i, ptr %a.addr.i, align 4 + %5 = load i32, ptr %b.addr.i, align 4 + %add3.i = add nsw i32 %5, 1 + store i32 %add3.i, ptr %b.addr.i, align 4 + %6 = load i32, ptr %a.addr.i, align 4 + %add4.i = add nsw i32 %6, 1 + store i32 %add4.i, ptr %a.addr.i, align 4 + %7 = load i32, ptr %b.addr.i, align 4 + %add5.i = add nsw i32 %7, 1 + store i32 %add5.i, ptr %b.addr.i, align 4 + %8 = load i32, ptr %a.addr.i, align 4 + %add6.i = add nsw i32 %8, 1 + store i32 %add6.i, ptr %a.addr.i, align 4 + %9 = load i32, ptr %b.addr.i, align 4 + %add7.i = add nsw i32 %9, 1 + store i32 %add7.i, ptr %b.addr.i, align 4 + %10 = load i32, ptr %a.addr.i, align 4 + %add8.i = add nsw i32 %10, 1 + store i32 %add8.i, ptr %a.addr.i, align 4 + %11 = load i32, ptr %b.addr.i, align 4 + %add9.i = add nsw i32 %11, 1 + store i32 %add9.i, ptr %b.addr.i, align 4 + %12 = load i32, ptr %a.addr.i, align 4 + %add10.i = add nsw i32 %12, 1 + store i32 %add10.i, ptr %a.addr.i, align 4 + %13 = load i32, ptr %b.addr.i, align 4 + %add11.i = add nsw i32 %13, 1 + store i32 %add11.i, ptr %b.addr.i, align 4 + %14 = load i32, ptr %a.addr.i, align 4 + %add12.i = add nsw i32 %14, 1 + store i32 %add12.i, ptr %a.addr.i, align 4 + %15 = load i32, ptr %b.addr.i, align 4 + %add13.i = add nsw i32 %15, 1 + store i32 %add13.i, ptr %b.addr.i, align 4 + %16 = load i32, ptr %a.addr.i, align 4 + %add14.i = add nsw i32 %16, 1 + store i32 %add14.i, ptr %a.addr.i, align 4 + %17 = load i32, ptr %b.addr.i, align 4 + %add15.i = add nsw i32 %17, 1 + store i32 %add15.i, ptr %b.addr.i, align 4 + %18 = load i32, ptr %a.addr.i, align 4 + %add16.i = add nsw i32 %18, 1 + store i32 %add16.i, ptr %a.addr.i, align 4 + %19 = load i32, ptr %b.addr.i, align 4 + %add17.i = add nsw i32 %19, 1 + store i32 %add17.i, ptr %b.addr.i, align 4 + %20 = load i32, ptr %a.addr.i, align 4 + %add18.i = add nsw i32 %20, 1 + store i32 %add18.i, ptr %a.addr.i, align 4 + %21 = load i32, ptr %b.addr.i, align 4 + %add19.i = add nsw i32 %21, 1 + store i32 %add19.i, ptr %b.addr.i, align 4 + %22 = load i32, ptr %a.addr.i, align 4 + %add20.i = add nsw i32 %22, 1 + store i32 %add20.i, ptr %a.addr.i, align 4 + %23 = load i32, ptr %b.addr.i, align 4 + %add21.i = add nsw i32 %23, 1 + store i32 %add21.i, ptr %b.addr.i, align 4 + %24 = load i32, ptr %a.addr.i, align 4 + %add22.i = add nsw i32 %24, 1 + store i32 %add22.i, ptr %a.addr.i, align 4 + %25 = load i32, ptr %b.addr.i, align 4 + %add23.i = add nsw i32 %25, 1 + store i32 %add23.i, ptr %b.addr.i, align 4 + %call.i = call noalias noundef nonnull ptr @_Znwm(i64 noundef 4) #2, !callsite !7 + store i32 1, ptr %call.i, align 4 + store ptr %call.i, ptr %c.i, align 8 + %call24.i = call noalias noundef nonnull ptr @_Znwm(i64 noundef 4) #2, !callsite !8 + store i32 1, ptr %call24.i, align 4 + store ptr %call24.i, ptr %d.i, align 8 + %26 = load i32, ptr %a.addr.i, align 4 + %27 = load i32, ptr %b.addr.i, align 4 + %cmp.i = icmp sgt i32 %26, %27 + br i1 %cmp.i, label %cond.true.i, label %cond.false.i + +cond.true.i: ; preds = %entry + %28 = load i32, ptr %a.addr.i, align 4 + br label %_Z3barIiET_S0_S0_.exit + +cond.false.i: ; preds = %entry + %29 = load i32, ptr %b.addr.i, align 4 + br label %_Z3barIiET_S0_S0_.exit + +_Z3barIiET_S0_S0_.exit: ; preds = %cond.true.i, %cond.false.i + %cond.i = phi i32 [ %28, %cond.true.i ], [ %29, %cond.false.i ] + store i32 %cond.i, ptr %rtn, align 4 + %30 = load i32, ptr %rtn, align 4 + ret i32 %30 +} + +; Function Attrs: nobuiltin allocsize(0) +declare noundef nonnull ptr @_Znwm(i64 noundef) #1 + +attributes #0 = { mustprogress noinline optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nobuiltin allocsize(0) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #2 = { builtin allocsize(0) } +attributes #3 = { mustprogress uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + +!llvm.module.flags = !{!0, !1, !2, !3, !4} +!llvm.ident = !{!5} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 8, !"PIC Level", i32 2} +!2 = !{i32 7, !"PIE Level", i32 2} +!3 = !{i32 7, !"uwtable", i32 2} +!4 = !{i32 7, !"frame-pointer", i32 2} +!5 = !{!"clang version 19.0.0"} +!6 = !{i64 2} +!7 = !{i64 4, i64 3} +!8 = !{i64 9, i64 3} -- GitLab From e4a546756c15a609be2f65d99c8b2be13ca9ddbf Mon Sep 17 00:00:00 2001 From: Walter Erquinigo Date: Mon, 11 Mar 2024 23:02:32 -0400 Subject: [PATCH 202/953] [MLIR][LSP][NFC] Fix a header guard (#84862) This header guard is wrong and conflicts with the one from Transport.h --- mlir/include/mlir/Tools/lsp-server-support/SourceMgrUtils.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mlir/include/mlir/Tools/lsp-server-support/SourceMgrUtils.h b/mlir/include/mlir/Tools/lsp-server-support/SourceMgrUtils.h index 969058b02288..9ed8326a602e 100644 --- a/mlir/include/mlir/Tools/lsp-server-support/SourceMgrUtils.h +++ b/mlir/include/mlir/Tools/lsp-server-support/SourceMgrUtils.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MLIR_TOOLS_LSPSERVERSUPPORT_TRANSPORT_H -#define MLIR_TOOLS_LSPSERVERSUPPORT_TRANSPORT_H +#ifndef MLIR_TOOLS_LSPSERVERSUPPORT_SOURCEMGRUTILS_H +#define MLIR_TOOLS_LSPSERVERSUPPORT_SOURCEMGRUTILS_H #include "mlir/Tools/lsp-server-support/Protocol.h" #include "llvm/Support/SourceMgr.h" -- GitLab From a83f8e0314fcdda162e54cbba1c9dcf230dff093 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Mon, 11 Mar 2024 23:40:47 -0400 Subject: [PATCH 203/953] [libc++][hardening] Check bounds on arithmetic in __bounded_iter (#78876) Previously, `__bounded_iter` only checked `operator*`. It allowed the pointer to go out of bounds with `operator++`, etc., and relied on `operator*` (which checked `begin <= current < end`) to handle everything. This has several unfortunate consequences: First, pointer arithmetic is UB if it goes out of bounds. So by the time `operator*` checks, it may be too late and the optimizer may have done something bad. Checking both operations is safer. Second, `std::copy` and friends currently bypass bounded iterator checks. I think the only hope we have to fix this is to key on `iter + n` doing a check. See #78771 for further discussion. Note this PR is not sufficient to fix this. It adds the output bounds check, but ends up doing it after the `memmove`, which is too late. Finally, doing these checks is actually *more* optimizable. See #78829, which is fixed by this PR. Keeping the iterator always in bounds means `operator*` can rely on some invariants and only needs to check `current != end`. This aligns better with common iterator patterns, which use `!=` instead of `<`, so it's easier to delete checks with local reasoning. See https://godbolt.org/z/vEWrWEf8h for how this new `__bounded_iter` impacts compiler output. The old `__bounded_iter` injected checks inside the loops for all the `sum()` functions, which not only added a check inside a loop, but also impeded Clang's vectorization. The new `__bounded_iter` allows all the checks to be optimized out and we emit the same code as if it wasn't here. Not everything is ideal however. `add_and_deref` ends up emitting two comparisons now instead of one. This is because a missed optimization in Clang. I've filed #78875 for that. I suspect (with no data) that this PR is still a net performance win because impeding ranged-for loops is particularly egregious. But ideally we'd fix the optimizer and make `add_and_deref` fine too. There's also something funny going on with `std::ranges::find` which I have not yet figured out yet, but I suspect there are some further missed optimization opportunities. Fixes #78829. (CC @danakj) --- libcxx/include/__iterator/bounded_iter.h | 71 ++++--- .../assert.iterator-indexing.pass.cpp | 174 ++++++++++++++++++ .../debug.iterator-indexing.pass.cpp | 97 ---------- .../bounded_iter/dereference.pass.cpp | 14 +- .../assert.iterator-indexing.pass.cpp | 158 ++++++++++++++++ .../debug.iterator-indexing.pass.cpp | 92 --------- 6 files changed, 385 insertions(+), 221 deletions(-) create mode 100644 libcxx/test/libcxx/containers/views/views.span/assert.iterator-indexing.pass.cpp delete mode 100644 libcxx/test/libcxx/containers/views/views.span/debug.iterator-indexing.pass.cpp create mode 100644 libcxx/test/libcxx/strings/string.view/string.view.iterators/assert.iterator-indexing.pass.cpp delete mode 100644 libcxx/test/libcxx/strings/string.view/string.view.iterators/debug.iterator-indexing.pass.cpp diff --git a/libcxx/include/__iterator/bounded_iter.h b/libcxx/include/__iterator/bounded_iter.h index 906ba3df0c57..a1a941ffbaaf 100644 --- a/libcxx/include/__iterator/bounded_iter.h +++ b/libcxx/include/__iterator/bounded_iter.h @@ -31,13 +31,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD // Iterator wrapper that carries the valid range it is allowed to access. // // This is a simple iterator wrapper for contiguous iterators that points -// within a [begin, end) range and carries these bounds with it. The iterator -// ensures that it is pointing within that [begin, end) range when it is -// dereferenced. +// within a [begin, end] range and carries these bounds with it. The iterator +// ensures that it is pointing within [begin, end) range when it is +// dereferenced. It also ensures that it is never iterated outside of +// [begin, end]. This is important for two reasons: // -// Arithmetic operations are allowed and the bounds of the resulting iterator -// are not checked. Hence, it is possible to create an iterator pointing outside -// its range, but it is not possible to dereference it. +// 1. It allows `operator*` and `operator++` bounds checks to be `iter != end`. +// This is both less for the optimizer to prove, and aligns with how callers +// typically use iterators. +// +// 2. Advancing an iterator out of bounds is undefined behavior (see the table +// in [input.iterators]). In particular, when the underlying iterator is a +// pointer, it is undefined at the language level (see [expr.add]). If +// bounded iterators exhibited this undefined behavior, we risk compiler +// optimizations deleting non-redundant bounds checks. template ::value > > struct __bounded_iter { using value_type = typename iterator_traits<_Iterator>::value_type; @@ -51,8 +58,8 @@ struct __bounded_iter { // Create a singular iterator. // - // Such an iterator does not point to any object and is conceptually out of bounds, so it is - // not dereferenceable. Observing operations like comparison and assignment are valid. + // Such an iterator points past the end of an empty span, so it is not dereferenceable. + // Observing operations like comparison and assignment are valid. _LIBCPP_HIDE_FROM_ABI __bounded_iter() = default; _LIBCPP_HIDE_FROM_ABI __bounded_iter(__bounded_iter const&) = default; @@ -70,18 +77,20 @@ struct __bounded_iter { private: // Create an iterator wrapping the given iterator, and whose bounds are described - // by the provided [begin, end) range. + // by the provided [begin, end] range. // - // This constructor does not check whether the resulting iterator is within its bounds. - // However, it does check that the provided [begin, end) range is a valid range (that - // is, begin <= end). + // The constructor does not check whether the resulting iterator is within its bounds. It is a + // responsibility of the container to ensure that the given bounds are valid. // // Since it is non-standard for iterators to have this constructor, __bounded_iter must // be created via `std::__make_bounded_iter`. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __bounded_iter( _Iterator __current, _Iterator __begin, _Iterator __end) : __current_(__current), __begin_(__begin), __end_(__end) { - _LIBCPP_ASSERT_INTERNAL(__begin <= __end, "__bounded_iter(current, begin, end): [begin, end) is not a valid range"); + _LIBCPP_ASSERT_INTERNAL( + __begin <= __current, "__bounded_iter(current, begin, end): current and begin are inconsistent"); + _LIBCPP_ASSERT_INTERNAL( + __current <= __end, "__bounded_iter(current, begin, end): current and end are inconsistent"); } template @@ -90,30 +99,37 @@ private: public: // Dereference and indexing operations. // - // These operations check that the iterator is dereferenceable, that is within [begin, end). + // These operations check that the iterator is dereferenceable. Since the class invariant is + // that the iterator is always within `[begin, end]`, we only need to check it's not pointing to + // `end`. This is easier for the optimizer because it aligns with the `iter != container.end()` + // checks that typical callers already use (see + // https://github.com/llvm/llvm-project/issues/78829). _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator*() const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( - __in_bounds(__current_), "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); + __current_ != __end_, "__bounded_iter::operator*: Attempt to dereference an iterator at the end"); return *__current_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pointer operator->() const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( - __in_bounds(__current_), "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator"); + __current_ != __end_, "__bounded_iter::operator->: Attempt to dereference an iterator at the end"); return std::__to_address(__current_); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator[](difference_type __n) const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( - __in_bounds(__current_ + __n), "__bounded_iter::operator[]: Attempt to index an iterator out-of-range"); + __n >= __begin_ - __current_, "__bounded_iter::operator[]: Attempt to index an iterator past the start"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __n < __end_ - __current_, "__bounded_iter::operator[]: Attempt to index an iterator at or past the end"); return __current_[__n]; } // Arithmetic operations. // - // These operations do not check that the resulting iterator is within the bounds, since that - // would make it impossible to create a past-the-end iterator. + // These operations check that the iterator remains within `[begin, end]`. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __bounded_iter& operator++() _NOEXCEPT { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __current_ != __end_, "__bounded_iter::operator++: Attempt to advance an iterator past the end"); ++__current_; return *this; } @@ -124,6 +140,8 @@ public: } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __bounded_iter& operator--() _NOEXCEPT { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __current_ != __begin_, "__bounded_iter::operator--: Attempt to rewind an iterator past the start"); --__current_; return *this; } @@ -134,6 +152,10 @@ public: } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __bounded_iter& operator+=(difference_type __n) _NOEXCEPT { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __n >= __begin_ - __current_, "__bounded_iter::operator+=: Attempt to rewind an iterator past the start"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __n <= __end_ - __current_, "__bounded_iter::operator+=: Attempt to advance an iterator past the end"); __current_ += __n; return *this; } @@ -151,6 +173,10 @@ public: } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __bounded_iter& operator-=(difference_type __n) _NOEXCEPT { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __n <= __current_ - __begin_, "__bounded_iter::operator-=: Attempt to rewind an iterator past the start"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __n >= __current_ - __end_, "__bounded_iter::operator-=: Attempt to advance an iterator past the end"); __current_ -= __n; return *this; } @@ -197,15 +223,10 @@ public: } private: - // Return whether the given iterator is in the bounds of this __bounded_iter. - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Iterator const& __iter) const { - return __iter >= __begin_ && __iter < __end_; - } - template friend struct pointer_traits; _Iterator __current_; // current iterator - _Iterator __begin_, __end_; // valid range represented as [begin, end) + _Iterator __begin_, __end_; // valid range represented as [begin, end] }; template diff --git a/libcxx/test/libcxx/containers/views/views.span/assert.iterator-indexing.pass.cpp b/libcxx/test/libcxx/containers/views/views.span/assert.iterator-indexing.pass.cpp new file mode 100644 index 000000000000..d4dacb1f2f1c --- /dev/null +++ b/libcxx/test/libcxx/containers/views/views.span/assert.iterator-indexing.pass.cpp @@ -0,0 +1,174 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// Make sure that std::span's iterators check for OOB accesses when the debug mode is enabled. + +// REQUIRES: has-unix-headers, libcpp-has-abi-bounded-iterators +// UNSUPPORTED: libcpp-hardening-mode=none + +#include + +#include "check_assertion.h" + +struct Foo { + int x; +}; + +template +void test_iterator(Iter begin, Iter end, bool reverse) { + std::ptrdiff_t distance = std::distance(begin, end); + + // Dereferencing an iterator at the end. + { + TEST_LIBCPP_ASSERT_FAILURE( + *end, + reverse ? "__bounded_iter::operator--: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator*: Attempt to dereference an iterator at the end"); +#if _LIBCPP_STD_VER >= 20 + // In C++20 mode, std::reverse_iterator implements operator->, but not operator*, with + // std::prev instead of operator--. std::prev ultimately calls operator+ + TEST_LIBCPP_ASSERT_FAILURE( + end->x, + reverse ? "__bounded_iter::operator+=: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator->: Attempt to dereference an iterator at the end"); +#else + TEST_LIBCPP_ASSERT_FAILURE( + end->x, + reverse ? "__bounded_iter::operator--: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator->: Attempt to dereference an iterator at the end"); +#endif + } + + // Incrementing an iterator past the end. + { + [[maybe_unused]] const char* msg = + reverse ? "__bounded_iter::operator--: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator++: Attempt to advance an iterator past the end"; + auto it = end; + TEST_LIBCPP_ASSERT_FAILURE(it++, msg); + TEST_LIBCPP_ASSERT_FAILURE(++it, msg); + } + + // Decrementing an iterator past the start. + { + [[maybe_unused]] const char* msg = + reverse ? "__bounded_iter::operator++: Attempt to advance an iterator past the end" + : "__bounded_iter::operator--: Attempt to rewind an iterator past the start"; + auto it = begin; + TEST_LIBCPP_ASSERT_FAILURE(it--, msg); + TEST_LIBCPP_ASSERT_FAILURE(--it, msg); + } + + // Advancing past the end with operator+= and operator+. + { + [[maybe_unused]] const char* msg = + reverse ? "__bounded_iter::operator-=: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator+=: Attempt to advance an iterator past the end"; + auto it = end; + TEST_LIBCPP_ASSERT_FAILURE(it += 1, msg); + TEST_LIBCPP_ASSERT_FAILURE(end + 1, msg); + it = begin; + TEST_LIBCPP_ASSERT_FAILURE(it += (distance + 1), msg); + TEST_LIBCPP_ASSERT_FAILURE(begin + (distance + 1), msg); + } + + // Advancing past the end with operator-= and operator-. + { + [[maybe_unused]] const char* msg = + reverse ? "__bounded_iter::operator+=: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator-=: Attempt to advance an iterator past the end"; + auto it = end; + TEST_LIBCPP_ASSERT_FAILURE(it -= (-1), msg); + TEST_LIBCPP_ASSERT_FAILURE(end - (-1), msg); + it = begin; + TEST_LIBCPP_ASSERT_FAILURE(it -= (-distance - 1), msg); + TEST_LIBCPP_ASSERT_FAILURE(begin - (-distance - 1), msg); + } + + // Rewinding past the start with operator+= and operator+. + { + [[maybe_unused]] const char* msg = + reverse ? "__bounded_iter::operator-=: Attempt to advance an iterator past the end" + : "__bounded_iter::operator+=: Attempt to rewind an iterator past the start"; + auto it = begin; + TEST_LIBCPP_ASSERT_FAILURE(it += (-1), msg); + TEST_LIBCPP_ASSERT_FAILURE(begin + (-1), msg); + it = end; + TEST_LIBCPP_ASSERT_FAILURE(it += (-distance - 1), msg); + TEST_LIBCPP_ASSERT_FAILURE(end + (-distance - 1), msg); + } + + // Rewinding past the start with operator-= and operator-. + { + [[maybe_unused]] const char* msg = + reverse ? "__bounded_iter::operator+=: Attempt to advance an iterator past the end" + : "__bounded_iter::operator-=: Attempt to rewind an iterator past the start"; + auto it = begin; + TEST_LIBCPP_ASSERT_FAILURE(it -= 1, msg); + TEST_LIBCPP_ASSERT_FAILURE(begin - 1, msg); + it = end; + TEST_LIBCPP_ASSERT_FAILURE(it -= (distance + 1), msg); + TEST_LIBCPP_ASSERT_FAILURE(end - (distance + 1), msg); + } + + // Out-of-bounds operator[]. + { + [[maybe_unused]] const char* end_msg = + reverse ? "__bounded_iter::operator--: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator[]: Attempt to index an iterator at or past the end"; + [[maybe_unused]] const char* past_end_msg = + reverse ? "__bounded_iter::operator-=: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator[]: Attempt to index an iterator at or past the end"; + [[maybe_unused]] const char* past_start_msg = + reverse ? "__bounded_iter::operator-=: Attempt to advance an iterator past the end" + : "__bounded_iter::operator[]: Attempt to index an iterator past the start"; + TEST_LIBCPP_ASSERT_FAILURE(begin[distance], end_msg); + TEST_LIBCPP_ASSERT_FAILURE(begin[distance + 1], past_end_msg); + TEST_LIBCPP_ASSERT_FAILURE(begin[-1], past_start_msg); + TEST_LIBCPP_ASSERT_FAILURE(begin[-99], past_start_msg); + + auto it = begin + 1; + TEST_LIBCPP_ASSERT_FAILURE(it[distance - 1], end_msg); + TEST_LIBCPP_ASSERT_FAILURE(it[distance], past_end_msg); + TEST_LIBCPP_ASSERT_FAILURE(it[-2], past_start_msg); + TEST_LIBCPP_ASSERT_FAILURE(it[-99], past_start_msg); + } +} + +int main(int, char**) { + // span::iterator + { + Foo array[] = {{0}, {1}, {2}}; + std::span const span(array, 3); + test_iterator(span.begin(), span.end(), /*reverse=*/false); + } + + // span::iterator + { + Foo array[] = {{0}, {1}, {2}}; + std::span const span(array, 3); + test_iterator(span.begin(), span.end(), /*reverse=*/false); + } + + // span::reverse_iterator + { + Foo array[] = {{0}, {1}, {2}}; + std::span const span(array, 3); + test_iterator(span.rbegin(), span.rend(), /*reverse=*/true); + } + + // span::reverse_iterator + { + Foo array[] = {{0}, {1}, {2}}; + std::span const span(array, 3); + test_iterator(span.rbegin(), span.rend(), /*reverse=*/true); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/views/views.span/debug.iterator-indexing.pass.cpp b/libcxx/test/libcxx/containers/views/views.span/debug.iterator-indexing.pass.cpp deleted file mode 100644 index 360e7a981a0d..000000000000 --- a/libcxx/test/libcxx/containers/views/views.span/debug.iterator-indexing.pass.cpp +++ /dev/null @@ -1,97 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// UNSUPPORTED: c++03, c++11, c++14, c++17 - -// Make sure that std::span's iterators check for OOB accesses when the debug mode is enabled. - -// REQUIRES: has-unix-headers, libcpp-has-abi-bounded-iterators -// UNSUPPORTED: libcpp-hardening-mode=none - -#include - -#include "check_assertion.h" - -struct Foo { - int x; -}; - -int main(int, char**) { - // span::iterator - { - Foo array[] = {{0}, {1}, {2}}; - std::span const span(array, 3); - { - auto it = span.end(); - TEST_LIBCPP_ASSERT_FAILURE(*it, "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); - } - { - auto it = span.end(); - TEST_LIBCPP_ASSERT_FAILURE(it->x, "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator"); - } - { - auto it = span.begin(); - TEST_LIBCPP_ASSERT_FAILURE(it[3], "__bounded_iter::operator[]: Attempt to index an iterator out-of-range"); - } - } - - // span::iterator - { - Foo array[] = {{0}, {1}, {2}}; - std::span const span(array, 3); - { - auto it = span.end(); - TEST_LIBCPP_ASSERT_FAILURE(*it, "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); - } - { - auto it = span.end(); - TEST_LIBCPP_ASSERT_FAILURE(it->x, "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator"); - } - { - auto it = span.begin(); - TEST_LIBCPP_ASSERT_FAILURE(it[3], "__bounded_iter::operator[]: Attempt to index an iterator out-of-range"); - } - } - - // span::reverse_iterator - { - Foo array[] = {{0}, {1}, {2}}; - std::span const span(array, 3); - { - auto it = span.rend(); - TEST_LIBCPP_ASSERT_FAILURE(*it, "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); - } - { - auto it = span.rend(); - TEST_LIBCPP_ASSERT_FAILURE(it->x, "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator"); - } - { - auto it = span.rbegin(); - TEST_LIBCPP_ASSERT_FAILURE(it[3], "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); - } - } - - // span::reverse_iterator - { - Foo array[] = {{0}, {1}, {2}}; - std::span const span(array, 3); - { - auto it = span.rend(); - TEST_LIBCPP_ASSERT_FAILURE(*it, "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); - } - { - auto it = span.rend(); - TEST_LIBCPP_ASSERT_FAILURE(it->x, "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator"); - } - { - auto it = span.rbegin(); - TEST_LIBCPP_ASSERT_FAILURE(it[3], "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); - } - } - - return 0; -} diff --git a/libcxx/test/libcxx/iterators/bounded_iter/dereference.pass.cpp b/libcxx/test/libcxx/iterators/bounded_iter/dereference.pass.cpp index 8eee4ad2f319..bf723f14e80a 100644 --- a/libcxx/test/libcxx/iterators/bounded_iter/dereference.pass.cpp +++ b/libcxx/test/libcxx/iterators/bounded_iter/dereference.pass.cpp @@ -58,15 +58,15 @@ void test_death() { std::__bounded_iter const oob = std::__make_bounded_iter(Iter(e), Iter(b), Iter(e)); // operator* - TEST_LIBCPP_ASSERT_FAILURE(*oob, "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); + TEST_LIBCPP_ASSERT_FAILURE(*oob, "__bounded_iter::operator*: Attempt to dereference an iterator at the end"); // operator-> - TEST_LIBCPP_ASSERT_FAILURE(oob->x, "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator"); + TEST_LIBCPP_ASSERT_FAILURE(oob->x, "__bounded_iter::operator->: Attempt to dereference an iterator at the end"); // operator[] - TEST_LIBCPP_ASSERT_FAILURE(iter[-1], "__bounded_iter::operator[]: Attempt to index an iterator out-of-range"); - TEST_LIBCPP_ASSERT_FAILURE(iter[5], "__bounded_iter::operator[]: Attempt to index an iterator out-of-range"); - TEST_LIBCPP_ASSERT_FAILURE(oob[0], "__bounded_iter::operator[]: Attempt to index an iterator out-of-range"); - TEST_LIBCPP_ASSERT_FAILURE(oob[1], "__bounded_iter::operator[]: Attempt to index an iterator out-of-range"); - TEST_LIBCPP_ASSERT_FAILURE(oob[-6], "__bounded_iter::operator[]: Attempt to index an iterator out-of-range"); + TEST_LIBCPP_ASSERT_FAILURE(iter[-1], "__bounded_iter::operator[]: Attempt to index an iterator past the start"); + TEST_LIBCPP_ASSERT_FAILURE(iter[5], "__bounded_iter::operator[]: Attempt to index an iterator at or past the end"); + TEST_LIBCPP_ASSERT_FAILURE(oob[0], "__bounded_iter::operator[]: Attempt to index an iterator at or past the end"); + TEST_LIBCPP_ASSERT_FAILURE(oob[1], "__bounded_iter::operator[]: Attempt to index an iterator at or past the end"); + TEST_LIBCPP_ASSERT_FAILURE(oob[-6], "__bounded_iter::operator[]: Attempt to index an iterator past the start"); } int main(int, char**) { diff --git a/libcxx/test/libcxx/strings/string.view/string.view.iterators/assert.iterator-indexing.pass.cpp b/libcxx/test/libcxx/strings/string.view/string.view.iterators/assert.iterator-indexing.pass.cpp new file mode 100644 index 000000000000..5043a88cbc3d --- /dev/null +++ b/libcxx/test/libcxx/strings/string.view/string.view.iterators/assert.iterator-indexing.pass.cpp @@ -0,0 +1,158 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Make sure that std::string_view's iterators check for OOB accesses when the debug mode is enabled. + +// REQUIRES: has-unix-headers, libcpp-has-abi-bounded-iterators +// UNSUPPORTED: libcpp-hardening-mode=none + +#include +#include + +#include "check_assertion.h" + +template +void test_iterator(Iter begin, Iter end, bool reverse) { + ptrdiff_t distance = std::distance(begin, end); + + // Dereferencing an iterator at the end. + { + TEST_LIBCPP_ASSERT_FAILURE( + *end, + reverse ? "__bounded_iter::operator--: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator*: Attempt to dereference an iterator at the end"); +#if _LIBCPP_STD_VER >= 20 + // In C++20 mode, std::reverse_iterator implements operator->, but not operator*, with + // std::prev instead of operator--. std::prev ultimately calls operator+ + TEST_LIBCPP_ASSERT_FAILURE( + end.operator->(), + reverse ? "__bounded_iter::operator+=: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator->: Attempt to dereference an iterator at the end"); +#else + TEST_LIBCPP_ASSERT_FAILURE( + end.operator->(), + reverse ? "__bounded_iter::operator--: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator->: Attempt to dereference an iterator at the end"); +#endif + } + + // Incrementing an iterator past the end. + { + [[maybe_unused]] const char* msg = + reverse ? "__bounded_iter::operator--: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator++: Attempt to advance an iterator past the end"; + auto it = end; + TEST_LIBCPP_ASSERT_FAILURE(it++, msg); + it = end; + TEST_LIBCPP_ASSERT_FAILURE(++it, msg); + } + + // Decrementing an iterator past the start. + { + [[maybe_unused]] const char* msg = + reverse ? "__bounded_iter::operator++: Attempt to advance an iterator past the end" + : "__bounded_iter::operator--: Attempt to rewind an iterator past the start"; + auto it = begin; + TEST_LIBCPP_ASSERT_FAILURE(it--, msg); + it = begin; + TEST_LIBCPP_ASSERT_FAILURE(--it, msg); + } + + // Advancing past the end with operator+= and operator+. + { + [[maybe_unused]] const char* msg = + reverse ? "__bounded_iter::operator-=: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator+=: Attempt to advance an iterator past the end"; + auto it = end; + TEST_LIBCPP_ASSERT_FAILURE(it += 1, msg); + TEST_LIBCPP_ASSERT_FAILURE(end + 1, msg); + it = begin; + TEST_LIBCPP_ASSERT_FAILURE(it += (distance + 1), msg); + TEST_LIBCPP_ASSERT_FAILURE(begin + (distance + 1), msg); + } + + // Advancing past the end with operator-= and operator-. + { + [[maybe_unused]] const char* msg = + reverse ? "__bounded_iter::operator+=: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator-=: Attempt to advance an iterator past the end"; + auto it = end; + TEST_LIBCPP_ASSERT_FAILURE(it -= (-1), msg); + TEST_LIBCPP_ASSERT_FAILURE(end - (-1), msg); + it = begin; + TEST_LIBCPP_ASSERT_FAILURE(it -= (-distance - 1), msg); + TEST_LIBCPP_ASSERT_FAILURE(begin - (-distance - 1), msg); + } + + // Rewinding past the start with operator+= and operator+. + { + [[maybe_unused]] const char* msg = + reverse ? "__bounded_iter::operator-=: Attempt to advance an iterator past the end" + : "__bounded_iter::operator+=: Attempt to rewind an iterator past the start"; + auto it = begin; + TEST_LIBCPP_ASSERT_FAILURE(it += (-1), msg); + TEST_LIBCPP_ASSERT_FAILURE(begin + (-1), msg); + it = end; + TEST_LIBCPP_ASSERT_FAILURE(it += (-distance - 1), msg); + TEST_LIBCPP_ASSERT_FAILURE(end + (-distance - 1), msg); + } + + // Rewinding past the start with operator-= and operator-. + { + [[maybe_unused]] const char* msg = + reverse ? "__bounded_iter::operator+=: Attempt to advance an iterator past the end" + : "__bounded_iter::operator-=: Attempt to rewind an iterator past the start"; + auto it = begin; + TEST_LIBCPP_ASSERT_FAILURE(it -= 1, msg); + TEST_LIBCPP_ASSERT_FAILURE(begin - 1, msg); + it = end; + TEST_LIBCPP_ASSERT_FAILURE(it -= (distance + 1), msg); + TEST_LIBCPP_ASSERT_FAILURE(end - (distance + 1), msg); + } + + // Out-of-bounds operator[]. + { + [[maybe_unused]] const char* end_msg = + reverse ? "__bounded_iter::operator--: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator[]: Attempt to index an iterator at or past the end"; + [[maybe_unused]] const char* past_end_msg = + reverse ? "__bounded_iter::operator-=: Attempt to rewind an iterator past the start" + : "__bounded_iter::operator[]: Attempt to index an iterator at or past the end"; + [[maybe_unused]] const char* past_start_msg = + reverse ? "__bounded_iter::operator-=: Attempt to advance an iterator past the end" + : "__bounded_iter::operator[]: Attempt to index an iterator past the start"; + TEST_LIBCPP_ASSERT_FAILURE(begin[distance], end_msg); + TEST_LIBCPP_ASSERT_FAILURE(begin[distance + 1], past_end_msg); + TEST_LIBCPP_ASSERT_FAILURE(begin[-1], past_start_msg); + TEST_LIBCPP_ASSERT_FAILURE(begin[-99], past_start_msg); + + auto it = begin + 1; + TEST_LIBCPP_ASSERT_FAILURE(it[distance - 1], end_msg); + TEST_LIBCPP_ASSERT_FAILURE(it[distance], past_end_msg); + TEST_LIBCPP_ASSERT_FAILURE(it[-2], past_start_msg); + TEST_LIBCPP_ASSERT_FAILURE(it[-99], past_start_msg); + } +} + +int main(int, char**) { + std::string_view const str("hello world"); + + // string_view::iterator + test_iterator(str.begin(), str.end(), /*reverse=*/false); + + // string_view::const_iterator + test_iterator(str.cbegin(), str.cend(), /*reverse=*/false); + + // string_view::reverse_iterator + test_iterator(str.rbegin(), str.rend(), /*reverse=*/true); + + // string_view::const_reverse_iterator + test_iterator(str.crbegin(), str.crend(), /*reverse=*/true); + + return 0; +} diff --git a/libcxx/test/libcxx/strings/string.view/string.view.iterators/debug.iterator-indexing.pass.cpp b/libcxx/test/libcxx/strings/string.view/string.view.iterators/debug.iterator-indexing.pass.cpp deleted file mode 100644 index 5064319a0aee..000000000000 --- a/libcxx/test/libcxx/strings/string.view/string.view.iterators/debug.iterator-indexing.pass.cpp +++ /dev/null @@ -1,92 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// Make sure that std::string_view's iterators check for OOB accesses when the debug mode is enabled. - -// REQUIRES: has-unix-headers, libcpp-has-abi-bounded-iterators -// UNSUPPORTED: libcpp-hardening-mode=none - -#include - -#include "check_assertion.h" - -int main(int, char**) { - // string_view::iterator - { - std::string_view const str("hello world"); - { - auto it = str.end(); - TEST_LIBCPP_ASSERT_FAILURE(*it, "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); - } - { - auto it = str.end(); - TEST_LIBCPP_ASSERT_FAILURE( - it.operator->(), "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator"); - } - { - auto it = str.begin(); - TEST_LIBCPP_ASSERT_FAILURE(it[99], "__bounded_iter::operator[]: Attempt to index an iterator out-of-range"); - } - } - - // string_view::const_iterator - { - std::string_view const str("hello world"); - { - auto it = str.cend(); - TEST_LIBCPP_ASSERT_FAILURE(*it, "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); - } - { - auto it = str.cend(); - TEST_LIBCPP_ASSERT_FAILURE( - it.operator->(), "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator"); - } - { - auto it = str.cbegin(); - TEST_LIBCPP_ASSERT_FAILURE(it[99], "__bounded_iter::operator[]: Attempt to index an iterator out-of-range"); - } - } - - // string_view::reverse_iterator - { - std::string_view const str("hello world"); - { - auto it = str.rend(); - TEST_LIBCPP_ASSERT_FAILURE(*it, "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); - } - { - auto it = str.rend(); - TEST_LIBCPP_ASSERT_FAILURE( - it.operator->(), "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator"); - } - { - auto it = str.rbegin(); - TEST_LIBCPP_ASSERT_FAILURE(it[99], "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); - } - } - - // string_view::const_reverse_iterator - { - std::string_view const str("hello world"); - { - auto it = str.crend(); - TEST_LIBCPP_ASSERT_FAILURE(*it, "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); - } - { - auto it = str.crend(); - TEST_LIBCPP_ASSERT_FAILURE( - it.operator->(), "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator"); - } - { - auto it = str.crbegin(); - TEST_LIBCPP_ASSERT_FAILURE(it[99], "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); - } - } - - return 0; -} -- GitLab From d02d8df0cd797342f7042440e07133e99ad5e0a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 11 Mar 2024 15:42:02 +0100 Subject: [PATCH 204/953] [clang][Interp] Implement _Complex negation Factor complex unary operations into their own function. --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 89 ++++++++++++++++++++---- clang/lib/AST/Interp/ByteCodeExprGen.h | 1 + 2 files changed, 78 insertions(+), 12 deletions(-) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index a384e191464f..0dd645990d1d 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2959,6 +2959,8 @@ bool ByteCodeExprGen::VisitCXXThisExpr(const CXXThisExpr *E) { template bool ByteCodeExprGen::VisitUnaryOperator(const UnaryOperator *E) { const Expr *SubExpr = E->getSubExpr(); + if (SubExpr->getType()->isAnyComplexType()) + return this->VisitComplexUnaryOperator(E); std::optional T = classify(SubExpr->getType()); switch (E->getOpcode()) { @@ -3109,16 +3111,81 @@ bool ByteCodeExprGen::VisitUnaryOperator(const UnaryOperator *E) { return false; return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E); case UO_Real: // __real x - if (T) - return this->delegate(SubExpr); - return this->emitComplexReal(SubExpr); + assert(T); + return this->delegate(SubExpr); case UO_Imag: { // __imag x - if (T) { - if (!this->discard(SubExpr)) + assert(T); + if (!this->discard(SubExpr)) + return false; + return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr); + } + case UO_Extension: + return this->delegate(SubExpr); + case UO_Coawait: + assert(false && "Unhandled opcode"); + } + + return false; +} + +template +bool ByteCodeExprGen::VisitComplexUnaryOperator( + const UnaryOperator *E) { + const Expr *SubExpr = E->getSubExpr(); + assert(SubExpr->getType()->isAnyComplexType()); + + if (DiscardResult) + return this->discard(SubExpr); + + std::optional ResT = classify(E); + + // Prepare storage for result. + if (!ResT && !Initializing) { + std::optional LocalIndex = + allocateLocal(SubExpr, /*IsExtended=*/false); + if (!LocalIndex) + return false; + if (!this->emitGetPtrLocal(*LocalIndex, E)) + return false; + } + + // The offset of the temporary, if we created one. + unsigned SubExprOffset = ~0u; + auto createTemp = [=, &SubExprOffset]() -> bool { + SubExprOffset = this->allocateLocalPrimitive(SubExpr, PT_Ptr, true, false); + if (!this->visit(SubExpr)) + return false; + return this->emitSetLocal(PT_Ptr, SubExprOffset, E); + }; + + PrimType ElemT = classifyComplexElementType(SubExpr->getType()); + auto getElem = [=](unsigned Offset, unsigned Index) -> bool { + if (!this->emitGetLocal(PT_Ptr, Offset, E)) + return false; + return this->emitArrayElemPop(ElemT, Index, E); + }; + + switch (E->getOpcode()) { + case UO_Minus: + if (!createTemp()) + return false; + for (unsigned I = 0; I != 2; ++I) { + if (!getElem(SubExprOffset, I)) + return false; + if (!this->emitNeg(ElemT, E)) + return false; + if (!this->emitInitElem(ElemT, I, E)) return false; - return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr); } + break; + + case UO_AddrOf: + return this->delegate(SubExpr); + case UO_Real: + return this->emitComplexReal(SubExpr); + + case UO_Imag: if (!this->visit(SubExpr)) return false; @@ -3131,14 +3198,12 @@ bool ByteCodeExprGen::VisitUnaryOperator(const UnaryOperator *E) { // Since our _Complex implementation does not map to a primitive type, // we sometimes have to do the lvalue-to-rvalue conversion here manually. return this->emitArrayElemPop(classifyPrim(E->getType()), 1, E); - } - case UO_Extension: - return this->delegate(SubExpr); - case UO_Coawait: - assert(false && "Unhandled opcode"); + + default: + return this->emitInvalid(E); } - return false; + return true; } template diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 5977bb5e6ff2..5ad2e74d7c26 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -75,6 +75,7 @@ public: bool VisitGNUNullExpr(const GNUNullExpr *E); bool VisitCXXThisExpr(const CXXThisExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); + bool VisitComplexUnaryOperator(const UnaryOperator *E); bool VisitDeclRefExpr(const DeclRefExpr *E); bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E); bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E); -- GitLab From 71590e7d1ec29c3ba9f6f5b4cfe36345a7ccd25b Mon Sep 17 00:00:00 2001 From: Shengchen Kan Date: Tue, 12 Mar 2024 13:08:44 +0800 Subject: [PATCH 205/953] [X86][test] Add missing enc/dec tests for CTEST These tests were accidentally missed in #83863 --- llvm/test/MC/Disassembler/X86/apx/ctest.txt | 1026 +++++++++++++++++++ llvm/test/MC/X86/apx/ctest-att.s | 773 ++++++++++++++ llvm/test/MC/X86/apx/ctest-intel.s | 770 ++++++++++++++ 3 files changed, 2569 insertions(+) create mode 100644 llvm/test/MC/Disassembler/X86/apx/ctest.txt create mode 100644 llvm/test/MC/X86/apx/ctest-att.s create mode 100644 llvm/test/MC/X86/apx/ctest-intel.s diff --git a/llvm/test/MC/Disassembler/X86/apx/ctest.txt b/llvm/test/MC/Disassembler/X86/apx/ctest.txt new file mode 100644 index 000000000000..9a29a98b5d78 --- /dev/null +++ b/llvm/test/MC/Disassembler/X86/apx/ctest.txt @@ -0,0 +1,1026 @@ +# RUN: llvm-mc -triple x86_64 -disassemble %s | FileCheck %s --check-prefix=ATT +# RUN: llvm-mc -triple x86_64 -disassemble -output-asm-variant=1 %s | FileCheck %s --check-prefix=INTEL + +# ATT: ctestbb {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctestb {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x02,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestbw {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctestb {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x02,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestbl {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestb {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x02,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestbq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestb {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x02,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestbb {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctestb {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x02,0x84,0x5c,0x80,0x7b + +# ATT: ctestbw {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctestb {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x02,0x85,0x54,0x80,0x7b + +# ATT: ctestbl {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctestb {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x02,0x85,0x4c,0x80,0x7b + +# ATT: ctestbq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctestb {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x02,0x85,0x4c,0x80,0x7b + +# ATT: ctestbb {dfv=of} $123, %bl +# INTEL: ctestb {dfv=of} bl, 123 +0x62,0xf4,0x44,0x02,0xf6,0xc3,0x7b + +# ATT: ctestbw {dfv=of} $1234, %dx +# INTEL: ctestb {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x02,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestbl {dfv=of} $123456, %ecx +# INTEL: ctestb {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x02,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestbq {dfv=of} $123456, %r9 +# INTEL: ctestb {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x02,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestbb {dfv=of} %bl, %dl +# INTEL: ctestb {dfv=of} dl, bl +0x62,0xf4,0x44,0x02,0x84,0xda + +# ATT: ctestbw {dfv=of} %dx, %ax +# INTEL: ctestb {dfv=of} ax, dx +0x62,0xf4,0x45,0x02,0x85,0xd0 + +# ATT: ctestbl {dfv=of} %ecx, %edx +# INTEL: ctestb {dfv=of} edx, ecx +0x62,0xf4,0x44,0x02,0x85,0xca + +# ATT: ctestbq {dfv=of} %r9, %r15 +# INTEL: ctestb {dfv=of} r15, r9 +0x62,0x54,0xc4,0x02,0x85,0xcf + +# ATT: ctestbeb {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctestbe {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x06,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestbew {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctestbe {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x06,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestbel {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestbe {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x06,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestbeq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestbe {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x06,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestbeb {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctestbe {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x06,0x84,0x5c,0x80,0x7b + +# ATT: ctestbew {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctestbe {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x06,0x85,0x54,0x80,0x7b + +# ATT: ctestbel {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctestbe {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x06,0x85,0x4c,0x80,0x7b + +# ATT: ctestbeq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctestbe {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x06,0x85,0x4c,0x80,0x7b + +# ATT: ctestbeb {dfv=of} $123, %bl +# INTEL: ctestbe {dfv=of} bl, 123 +0x62,0xf4,0x44,0x06,0xf6,0xc3,0x7b + +# ATT: ctestbew {dfv=of} $1234, %dx +# INTEL: ctestbe {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x06,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestbel {dfv=of} $123456, %ecx +# INTEL: ctestbe {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x06,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestbeq {dfv=of} $123456, %r9 +# INTEL: ctestbe {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x06,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestbeb {dfv=of} %bl, %dl +# INTEL: ctestbe {dfv=of} dl, bl +0x62,0xf4,0x44,0x06,0x84,0xda + +# ATT: ctestbew {dfv=of} %dx, %ax +# INTEL: ctestbe {dfv=of} ax, dx +0x62,0xf4,0x45,0x06,0x85,0xd0 + +# ATT: ctestbel {dfv=of} %ecx, %edx +# INTEL: ctestbe {dfv=of} edx, ecx +0x62,0xf4,0x44,0x06,0x85,0xca + +# ATT: ctestbeq {dfv=of} %r9, %r15 +# INTEL: ctestbe {dfv=of} r15, r9 +0x62,0x54,0xc4,0x06,0x85,0xcf + +# ATT: ctestfb {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctestf {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x0b,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestfw {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctestf {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x0b,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestfl {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestf {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x0b,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestfq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestf {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x0b,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestfb {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctestf {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x0b,0x84,0x5c,0x80,0x7b + +# ATT: ctestfw {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctestf {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x0b,0x85,0x54,0x80,0x7b + +# ATT: ctestfl {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctestf {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x0b,0x85,0x4c,0x80,0x7b + +# ATT: ctestfq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctestf {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x0b,0x85,0x4c,0x80,0x7b + +# ATT: ctestfb {dfv=of} $123, %bl +# INTEL: ctestf {dfv=of} bl, 123 +0x62,0xf4,0x44,0x0b,0xf6,0xc3,0x7b + +# ATT: ctestfw {dfv=of} $1234, %dx +# INTEL: ctestf {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x0b,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestfl {dfv=of} $123456, %ecx +# INTEL: ctestf {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x0b,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestfq {dfv=of} $123456, %r9 +# INTEL: ctestf {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x0b,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestfb {dfv=of} %bl, %dl +# INTEL: ctestf {dfv=of} dl, bl +0x62,0xf4,0x44,0x0b,0x84,0xda + +# ATT: ctestfw {dfv=of} %dx, %ax +# INTEL: ctestf {dfv=of} ax, dx +0x62,0xf4,0x45,0x0b,0x85,0xd0 + +# ATT: ctestfl {dfv=of} %ecx, %edx +# INTEL: ctestf {dfv=of} edx, ecx +0x62,0xf4,0x44,0x0b,0x85,0xca + +# ATT: ctestfq {dfv=of} %r9, %r15 +# INTEL: ctestf {dfv=of} r15, r9 +0x62,0x54,0xc4,0x0b,0x85,0xcf + +# ATT: ctestlb {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctestl {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x0c,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestlw {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctestl {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x0c,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestll {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestl {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x0c,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestlq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestl {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x0c,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestlb {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctestl {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x0c,0x84,0x5c,0x80,0x7b + +# ATT: ctestlw {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctestl {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x0c,0x85,0x54,0x80,0x7b + +# ATT: ctestll {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctestl {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x0c,0x85,0x4c,0x80,0x7b + +# ATT: ctestlq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctestl {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x0c,0x85,0x4c,0x80,0x7b + +# ATT: ctestlb {dfv=of} $123, %bl +# INTEL: ctestl {dfv=of} bl, 123 +0x62,0xf4,0x44,0x0c,0xf6,0xc3,0x7b + +# ATT: ctestlw {dfv=of} $1234, %dx +# INTEL: ctestl {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x0c,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestll {dfv=of} $123456, %ecx +# INTEL: ctestl {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x0c,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestlq {dfv=of} $123456, %r9 +# INTEL: ctestl {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x0c,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestlb {dfv=of} %bl, %dl +# INTEL: ctestl {dfv=of} dl, bl +0x62,0xf4,0x44,0x0c,0x84,0xda + +# ATT: ctestlw {dfv=of} %dx, %ax +# INTEL: ctestl {dfv=of} ax, dx +0x62,0xf4,0x45,0x0c,0x85,0xd0 + +# ATT: ctestll {dfv=of} %ecx, %edx +# INTEL: ctestl {dfv=of} edx, ecx +0x62,0xf4,0x44,0x0c,0x85,0xca + +# ATT: ctestlq {dfv=of} %r9, %r15 +# INTEL: ctestl {dfv=of} r15, r9 +0x62,0x54,0xc4,0x0c,0x85,0xcf + +# ATT: ctestleb {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctestle {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x0e,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestlew {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctestle {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x0e,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestlel {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestle {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x0e,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestleq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestle {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x0e,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestleb {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctestle {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x0e,0x84,0x5c,0x80,0x7b + +# ATT: ctestlew {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctestle {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x0e,0x85,0x54,0x80,0x7b + +# ATT: ctestlel {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctestle {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x0e,0x85,0x4c,0x80,0x7b + +# ATT: ctestleq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctestle {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x0e,0x85,0x4c,0x80,0x7b + +# ATT: ctestleb {dfv=of} $123, %bl +# INTEL: ctestle {dfv=of} bl, 123 +0x62,0xf4,0x44,0x0e,0xf6,0xc3,0x7b + +# ATT: ctestlew {dfv=of} $1234, %dx +# INTEL: ctestle {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x0e,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestlel {dfv=of} $123456, %ecx +# INTEL: ctestle {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x0e,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestleq {dfv=of} $123456, %r9 +# INTEL: ctestle {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x0e,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestleb {dfv=of} %bl, %dl +# INTEL: ctestle {dfv=of} dl, bl +0x62,0xf4,0x44,0x0e,0x84,0xda + +# ATT: ctestlew {dfv=of} %dx, %ax +# INTEL: ctestle {dfv=of} ax, dx +0x62,0xf4,0x45,0x0e,0x85,0xd0 + +# ATT: ctestlel {dfv=of} %ecx, %edx +# INTEL: ctestle {dfv=of} edx, ecx +0x62,0xf4,0x44,0x0e,0x85,0xca + +# ATT: ctestleq {dfv=of} %r9, %r15 +# INTEL: ctestle {dfv=of} r15, r9 +0x62,0x54,0xc4,0x0e,0x85,0xcf + +# ATT: ctestaeb {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctestae {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x03,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestaew {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctestae {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x03,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestael {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestae {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x03,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestaeq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestae {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x03,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestaeb {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctestae {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x03,0x84,0x5c,0x80,0x7b + +# ATT: ctestaew {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctestae {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x03,0x85,0x54,0x80,0x7b + +# ATT: ctestael {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctestae {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x03,0x85,0x4c,0x80,0x7b + +# ATT: ctestaeq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctestae {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x03,0x85,0x4c,0x80,0x7b + +# ATT: ctestaeb {dfv=of} $123, %bl +# INTEL: ctestae {dfv=of} bl, 123 +0x62,0xf4,0x44,0x03,0xf6,0xc3,0x7b + +# ATT: ctestaew {dfv=of} $1234, %dx +# INTEL: ctestae {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x03,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestael {dfv=of} $123456, %ecx +# INTEL: ctestae {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x03,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestaeq {dfv=of} $123456, %r9 +# INTEL: ctestae {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x03,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestaeb {dfv=of} %bl, %dl +# INTEL: ctestae {dfv=of} dl, bl +0x62,0xf4,0x44,0x03,0x84,0xda + +# ATT: ctestaew {dfv=of} %dx, %ax +# INTEL: ctestae {dfv=of} ax, dx +0x62,0xf4,0x45,0x03,0x85,0xd0 + +# ATT: ctestael {dfv=of} %ecx, %edx +# INTEL: ctestae {dfv=of} edx, ecx +0x62,0xf4,0x44,0x03,0x85,0xca + +# ATT: ctestaeq {dfv=of} %r9, %r15 +# INTEL: ctestae {dfv=of} r15, r9 +0x62,0x54,0xc4,0x03,0x85,0xcf + +# ATT: ctestab {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctesta {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x07,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestaw {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctesta {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x07,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestal {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctesta {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x07,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestaq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctesta {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x07,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestab {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctesta {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x07,0x84,0x5c,0x80,0x7b + +# ATT: ctestaw {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctesta {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x07,0x85,0x54,0x80,0x7b + +# ATT: ctestal {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctesta {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x07,0x85,0x4c,0x80,0x7b + +# ATT: ctestaq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctesta {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x07,0x85,0x4c,0x80,0x7b + +# ATT: ctestab {dfv=of} $123, %bl +# INTEL: ctesta {dfv=of} bl, 123 +0x62,0xf4,0x44,0x07,0xf6,0xc3,0x7b + +# ATT: ctestaw {dfv=of} $1234, %dx +# INTEL: ctesta {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x07,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestal {dfv=of} $123456, %ecx +# INTEL: ctesta {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x07,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestaq {dfv=of} $123456, %r9 +# INTEL: ctesta {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x07,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestab {dfv=of} %bl, %dl +# INTEL: ctesta {dfv=of} dl, bl +0x62,0xf4,0x44,0x07,0x84,0xda + +# ATT: ctestaw {dfv=of} %dx, %ax +# INTEL: ctesta {dfv=of} ax, dx +0x62,0xf4,0x45,0x07,0x85,0xd0 + +# ATT: ctestal {dfv=of} %ecx, %edx +# INTEL: ctesta {dfv=of} edx, ecx +0x62,0xf4,0x44,0x07,0x85,0xca + +# ATT: ctestaq {dfv=of} %r9, %r15 +# INTEL: ctesta {dfv=of} r15, r9 +0x62,0x54,0xc4,0x07,0x85,0xcf + +# ATT: ctestgeb {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctestge {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x0d,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestgew {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctestge {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x0d,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestgel {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestge {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x0d,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestgeq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestge {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x0d,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestgeb {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctestge {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x0d,0x84,0x5c,0x80,0x7b + +# ATT: ctestgew {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctestge {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x0d,0x85,0x54,0x80,0x7b + +# ATT: ctestgel {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctestge {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x0d,0x85,0x4c,0x80,0x7b + +# ATT: ctestgeq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctestge {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x0d,0x85,0x4c,0x80,0x7b + +# ATT: ctestgeb {dfv=of} $123, %bl +# INTEL: ctestge {dfv=of} bl, 123 +0x62,0xf4,0x44,0x0d,0xf6,0xc3,0x7b + +# ATT: ctestgew {dfv=of} $1234, %dx +# INTEL: ctestge {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x0d,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestgel {dfv=of} $123456, %ecx +# INTEL: ctestge {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x0d,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestgeq {dfv=of} $123456, %r9 +# INTEL: ctestge {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x0d,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestgeb {dfv=of} %bl, %dl +# INTEL: ctestge {dfv=of} dl, bl +0x62,0xf4,0x44,0x0d,0x84,0xda + +# ATT: ctestgew {dfv=of} %dx, %ax +# INTEL: ctestge {dfv=of} ax, dx +0x62,0xf4,0x45,0x0d,0x85,0xd0 + +# ATT: ctestgel {dfv=of} %ecx, %edx +# INTEL: ctestge {dfv=of} edx, ecx +0x62,0xf4,0x44,0x0d,0x85,0xca + +# ATT: ctestgeq {dfv=of} %r9, %r15 +# INTEL: ctestge {dfv=of} r15, r9 +0x62,0x54,0xc4,0x0d,0x85,0xcf + +# ATT: ctestgb {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctestg {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x0f,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestgw {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctestg {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x0f,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestgl {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestg {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x0f,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestgq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestg {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x0f,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestgb {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctestg {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x0f,0x84,0x5c,0x80,0x7b + +# ATT: ctestgw {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctestg {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x0f,0x85,0x54,0x80,0x7b + +# ATT: ctestgl {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctestg {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x0f,0x85,0x4c,0x80,0x7b + +# ATT: ctestgq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctestg {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x0f,0x85,0x4c,0x80,0x7b + +# ATT: ctestgb {dfv=of} $123, %bl +# INTEL: ctestg {dfv=of} bl, 123 +0x62,0xf4,0x44,0x0f,0xf6,0xc3,0x7b + +# ATT: ctestgw {dfv=of} $1234, %dx +# INTEL: ctestg {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x0f,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestgl {dfv=of} $123456, %ecx +# INTEL: ctestg {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x0f,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestgq {dfv=of} $123456, %r9 +# INTEL: ctestg {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x0f,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestgb {dfv=of} %bl, %dl +# INTEL: ctestg {dfv=of} dl, bl +0x62,0xf4,0x44,0x0f,0x84,0xda + +# ATT: ctestgw {dfv=of} %dx, %ax +# INTEL: ctestg {dfv=of} ax, dx +0x62,0xf4,0x45,0x0f,0x85,0xd0 + +# ATT: ctestgl {dfv=of} %ecx, %edx +# INTEL: ctestg {dfv=of} edx, ecx +0x62,0xf4,0x44,0x0f,0x85,0xca + +# ATT: ctestgq {dfv=of} %r9, %r15 +# INTEL: ctestg {dfv=of} r15, r9 +0x62,0x54,0xc4,0x0f,0x85,0xcf + +# ATT: ctestnob {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctestno {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x01,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestnow {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctestno {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x01,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestnol {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestno {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x01,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestnoq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestno {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x01,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestnob {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctestno {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x01,0x84,0x5c,0x80,0x7b + +# ATT: ctestnow {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctestno {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x01,0x85,0x54,0x80,0x7b + +# ATT: ctestnol {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctestno {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x01,0x85,0x4c,0x80,0x7b + +# ATT: ctestnoq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctestno {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x01,0x85,0x4c,0x80,0x7b + +# ATT: ctestnob {dfv=of} $123, %bl +# INTEL: ctestno {dfv=of} bl, 123 +0x62,0xf4,0x44,0x01,0xf6,0xc3,0x7b + +# ATT: ctestnow {dfv=of} $1234, %dx +# INTEL: ctestno {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x01,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestnol {dfv=of} $123456, %ecx +# INTEL: ctestno {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x01,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestnoq {dfv=of} $123456, %r9 +# INTEL: ctestno {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x01,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestnob {dfv=of} %bl, %dl +# INTEL: ctestno {dfv=of} dl, bl +0x62,0xf4,0x44,0x01,0x84,0xda + +# ATT: ctestnow {dfv=of} %dx, %ax +# INTEL: ctestno {dfv=of} ax, dx +0x62,0xf4,0x45,0x01,0x85,0xd0 + +# ATT: ctestnol {dfv=of} %ecx, %edx +# INTEL: ctestno {dfv=of} edx, ecx +0x62,0xf4,0x44,0x01,0x85,0xca + +# ATT: ctestnoq {dfv=of} %r9, %r15 +# INTEL: ctestno {dfv=of} r15, r9 +0x62,0x54,0xc4,0x01,0x85,0xcf + +# ATT: ctestnsb {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctestns {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x09,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestnsw {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctestns {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x09,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestnsl {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestns {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x09,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestnsq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestns {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x09,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestnsb {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctestns {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x09,0x84,0x5c,0x80,0x7b + +# ATT: ctestnsw {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctestns {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x09,0x85,0x54,0x80,0x7b + +# ATT: ctestnsl {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctestns {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x09,0x85,0x4c,0x80,0x7b + +# ATT: ctestnsq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctestns {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x09,0x85,0x4c,0x80,0x7b + +# ATT: ctestnsb {dfv=of} $123, %bl +# INTEL: ctestns {dfv=of} bl, 123 +0x62,0xf4,0x44,0x09,0xf6,0xc3,0x7b + +# ATT: ctestnsw {dfv=of} $1234, %dx +# INTEL: ctestns {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x09,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestnsl {dfv=of} $123456, %ecx +# INTEL: ctestns {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x09,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestnsq {dfv=of} $123456, %r9 +# INTEL: ctestns {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x09,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestnsb {dfv=of} %bl, %dl +# INTEL: ctestns {dfv=of} dl, bl +0x62,0xf4,0x44,0x09,0x84,0xda + +# ATT: ctestnsw {dfv=of} %dx, %ax +# INTEL: ctestns {dfv=of} ax, dx +0x62,0xf4,0x45,0x09,0x85,0xd0 + +# ATT: ctestnsl {dfv=of} %ecx, %edx +# INTEL: ctestns {dfv=of} edx, ecx +0x62,0xf4,0x44,0x09,0x85,0xca + +# ATT: ctestnsq {dfv=of} %r9, %r15 +# INTEL: ctestns {dfv=of} r15, r9 +0x62,0x54,0xc4,0x09,0x85,0xcf + +# ATT: ctestneb {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctestne {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x05,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestnew {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctestne {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x05,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestnel {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestne {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x05,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestneq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestne {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x05,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestneb {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctestne {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x05,0x84,0x5c,0x80,0x7b + +# ATT: ctestnew {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctestne {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x05,0x85,0x54,0x80,0x7b + +# ATT: ctestnel {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctestne {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x05,0x85,0x4c,0x80,0x7b + +# ATT: ctestneq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctestne {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x05,0x85,0x4c,0x80,0x7b + +# ATT: ctestneb {dfv=of} $123, %bl +# INTEL: ctestne {dfv=of} bl, 123 +0x62,0xf4,0x44,0x05,0xf6,0xc3,0x7b + +# ATT: ctestnew {dfv=of} $1234, %dx +# INTEL: ctestne {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x05,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestnel {dfv=of} $123456, %ecx +# INTEL: ctestne {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x05,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestneq {dfv=of} $123456, %r9 +# INTEL: ctestne {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x05,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestneb {dfv=of} %bl, %dl +# INTEL: ctestne {dfv=of} dl, bl +0x62,0xf4,0x44,0x05,0x84,0xda + +# ATT: ctestnew {dfv=of} %dx, %ax +# INTEL: ctestne {dfv=of} ax, dx +0x62,0xf4,0x45,0x05,0x85,0xd0 + +# ATT: ctestnel {dfv=of} %ecx, %edx +# INTEL: ctestne {dfv=of} edx, ecx +0x62,0xf4,0x44,0x05,0x85,0xca + +# ATT: ctestneq {dfv=of} %r9, %r15 +# INTEL: ctestne {dfv=of} r15, r9 +0x62,0x54,0xc4,0x05,0x85,0xcf + +# ATT: ctestob {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctesto {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x00,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestow {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctesto {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x00,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestol {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctesto {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x00,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestoq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctesto {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x00,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestob {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctesto {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x00,0x84,0x5c,0x80,0x7b + +# ATT: ctestow {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctesto {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x00,0x85,0x54,0x80,0x7b + +# ATT: ctestol {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctesto {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x00,0x85,0x4c,0x80,0x7b + +# ATT: ctestoq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctesto {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x00,0x85,0x4c,0x80,0x7b + +# ATT: ctestob {dfv=of} $123, %bl +# INTEL: ctesto {dfv=of} bl, 123 +0x62,0xf4,0x44,0x00,0xf6,0xc3,0x7b + +# ATT: ctestow {dfv=of} $1234, %dx +# INTEL: ctesto {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x00,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestol {dfv=of} $123456, %ecx +# INTEL: ctesto {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x00,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestoq {dfv=of} $123456, %r9 +# INTEL: ctesto {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x00,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestob {dfv=of} %bl, %dl +# INTEL: ctesto {dfv=of} dl, bl +0x62,0xf4,0x44,0x00,0x84,0xda + +# ATT: ctestow {dfv=of} %dx, %ax +# INTEL: ctesto {dfv=of} ax, dx +0x62,0xf4,0x45,0x00,0x85,0xd0 + +# ATT: ctestol {dfv=of} %ecx, %edx +# INTEL: ctesto {dfv=of} edx, ecx +0x62,0xf4,0x44,0x00,0x85,0xca + +# ATT: ctestoq {dfv=of} %r9, %r15 +# INTEL: ctesto {dfv=of} r15, r9 +0x62,0x54,0xc4,0x00,0x85,0xcf + +# ATT: ctestsb {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctests {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x08,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestsw {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctests {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x08,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestsl {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctests {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x08,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestsq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctests {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x08,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctestsb {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctests {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x08,0x84,0x5c,0x80,0x7b + +# ATT: ctestsw {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctests {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x08,0x85,0x54,0x80,0x7b + +# ATT: ctestsl {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctests {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x08,0x85,0x4c,0x80,0x7b + +# ATT: ctestsq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctests {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x08,0x85,0x4c,0x80,0x7b + +# ATT: ctestsb {dfv=of} $123, %bl +# INTEL: ctests {dfv=of} bl, 123 +0x62,0xf4,0x44,0x08,0xf6,0xc3,0x7b + +# ATT: ctestsw {dfv=of} $1234, %dx +# INTEL: ctests {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x08,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestsl {dfv=of} $123456, %ecx +# INTEL: ctests {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x08,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestsq {dfv=of} $123456, %r9 +# INTEL: ctests {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x08,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctestsb {dfv=of} %bl, %dl +# INTEL: ctests {dfv=of} dl, bl +0x62,0xf4,0x44,0x08,0x84,0xda + +# ATT: ctestsw {dfv=of} %dx, %ax +# INTEL: ctests {dfv=of} ax, dx +0x62,0xf4,0x45,0x08,0x85,0xd0 + +# ATT: ctestsl {dfv=of} %ecx, %edx +# INTEL: ctests {dfv=of} edx, ecx +0x62,0xf4,0x44,0x08,0x85,0xca + +# ATT: ctestsq {dfv=of} %r9, %r15 +# INTEL: ctests {dfv=of} r15, r9 +0x62,0x54,0xc4,0x08,0x85,0xcf + +# ATT: ctesttb {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: ctestt {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x0a,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctesttw {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: ctestt {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x0a,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctesttl {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestt {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x0a,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctesttq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: ctestt {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x0a,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctesttb {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: ctestt {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x0a,0x84,0x5c,0x80,0x7b + +# ATT: ctesttw {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: ctestt {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x0a,0x85,0x54,0x80,0x7b + +# ATT: ctesttl {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: ctestt {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x0a,0x85,0x4c,0x80,0x7b + +# ATT: ctesttq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: ctestt {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x0a,0x85,0x4c,0x80,0x7b + +# ATT: ctesttb {dfv=of} $123, %bl +# INTEL: ctestt {dfv=of} bl, 123 +0x62,0xf4,0x44,0x0a,0xf6,0xc3,0x7b + +# ATT: ctesttw {dfv=of} $1234, %dx +# INTEL: ctestt {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x0a,0xf7,0xc2,0xd2,0x04 + +# ATT: ctesttl {dfv=of} $123456, %ecx +# INTEL: ctestt {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x0a,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctesttq {dfv=of} $123456, %r9 +# INTEL: ctestt {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x0a,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctesttb {dfv=of} %bl, %dl +# INTEL: ctestt {dfv=of} dl, bl +0x62,0xf4,0x44,0x0a,0x84,0xda + +# ATT: ctesttw {dfv=of} %dx, %ax +# INTEL: ctestt {dfv=of} ax, dx +0x62,0xf4,0x45,0x0a,0x85,0xd0 + +# ATT: ctesttl {dfv=of} %ecx, %edx +# INTEL: ctestt {dfv=of} edx, ecx +0x62,0xf4,0x44,0x0a,0x85,0xca + +# ATT: ctesttq {dfv=of} %r9, %r15 +# INTEL: ctestt {dfv=of} r15, r9 +0x62,0x54,0xc4,0x0a,0x85,0xcf + +# ATT: ctesteb {dfv=of} $123, 123(%r8,%rax,4) +# INTEL: cteste {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +0x62,0xd4,0x44,0x04,0xf6,0x44,0x80,0x7b,0x7b + +# ATT: ctestew {dfv=of} $1234, 123(%r8,%rax,4) +# INTEL: cteste {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +0x62,0xd4,0x45,0x04,0xf7,0x44,0x80,0x7b,0xd2,0x04 + +# ATT: ctestel {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: cteste {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0x44,0x04,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctesteq {dfv=of} $123456, 123(%r8,%rax,4) +# INTEL: cteste {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +0x62,0xd4,0xc4,0x04,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00 + +# ATT: ctesteb {dfv=of} %bl, 123(%r8,%rax,4) +# INTEL: cteste {dfv=of} byte ptr [r8 + 4*rax + 123], bl +0x62,0xd4,0x44,0x04,0x84,0x5c,0x80,0x7b + +# ATT: ctestew {dfv=of} %dx, 123(%r8,%rax,4) +# INTEL: cteste {dfv=of} word ptr [r8 + 4*rax + 123], dx +0x62,0xd4,0x45,0x04,0x85,0x54,0x80,0x7b + +# ATT: ctestel {dfv=of} %ecx, 123(%r8,%rax,4) +# INTEL: cteste {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +0x62,0xd4,0x44,0x04,0x85,0x4c,0x80,0x7b + +# ATT: ctesteq {dfv=of} %r9, 123(%r8,%rax,4) +# INTEL: cteste {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +0x62,0x54,0xc4,0x04,0x85,0x4c,0x80,0x7b + +# ATT: ctesteb {dfv=of} $123, %bl +# INTEL: cteste {dfv=of} bl, 123 +0x62,0xf4,0x44,0x04,0xf6,0xc3,0x7b + +# ATT: ctestew {dfv=of} $1234, %dx +# INTEL: cteste {dfv=of} dx, 1234 +0x62,0xf4,0x45,0x04,0xf7,0xc2,0xd2,0x04 + +# ATT: ctestel {dfv=of} $123456, %ecx +# INTEL: cteste {dfv=of} ecx, 123456 +0x62,0xf4,0x44,0x04,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctesteq {dfv=of} $123456, %r9 +# INTEL: cteste {dfv=of} r9, 123456 +0x62,0xd4,0xc4,0x04,0xf7,0xc1,0x40,0xe2,0x01,0x00 + +# ATT: ctesteb {dfv=of} %bl, %dl +# INTEL: cteste {dfv=of} dl, bl +0x62,0xf4,0x44,0x04,0x84,0xda + +# ATT: ctestew {dfv=of} %dx, %ax +# INTEL: cteste {dfv=of} ax, dx +0x62,0xf4,0x45,0x04,0x85,0xd0 + +# ATT: ctestel {dfv=of} %ecx, %edx +# INTEL: cteste {dfv=of} edx, ecx +0x62,0xf4,0x44,0x04,0x85,0xca + +# ATT: ctesteq {dfv=of} %r9, %r15 +# INTEL: cteste {dfv=of} r15, r9 +0x62,0x54,0xc4,0x04,0x85,0xcf diff --git a/llvm/test/MC/X86/apx/ctest-att.s b/llvm/test/MC/X86/apx/ctest-att.s new file mode 100644 index 000000000000..b9e98adc9841 --- /dev/null +++ b/llvm/test/MC/X86/apx/ctest-att.s @@ -0,0 +1,773 @@ +# RUN: llvm-mc -triple x86_64 -show-encoding %s | FileCheck %s +# RUN: not llvm-mc -triple i386 -show-encoding %s 2>&1 | FileCheck %s --check-prefix=ERROR + +# ERROR-COUNT-256: error: +# ERROR-NOT: error: +# CHECK: ctestbb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x02,0xf6,0x44,0x80,0x7b,0x7b] + ctestbb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestbw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x02,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestbw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestbl {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x02,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestbl {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestbq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x02,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestbq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestbb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x02,0x84,0x5c,0x80,0x7b] + ctestbb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestbw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x02,0x85,0x54,0x80,0x7b] + ctestbw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestbl {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x02,0x85,0x4c,0x80,0x7b] + ctestbl {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctestbq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x02,0x85,0x4c,0x80,0x7b] + ctestbq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctestbb {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x02,0xf6,0xc3,0x7b] + ctestbb {dfv=of} $123, %bl +# CHECK: ctestbw {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x02,0xf7,0xc2,0xd2,0x04] + ctestbw {dfv=of} $1234, %dx +# CHECK: ctestbl {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x02,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestbl {dfv=of} $123456, %ecx +# CHECK: ctestbq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x02,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestbq {dfv=of} $123456, %r9 +# CHECK: ctestbb {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x02,0x84,0xda] + ctestbb {dfv=of} %bl, %dl +# CHECK: ctestbw {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x02,0x85,0xd0] + ctestbw {dfv=of} %dx, %ax +# CHECK: ctestbl {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x02,0x85,0xca] + ctestbl {dfv=of} %ecx, %edx +# CHECK: ctestbq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x02,0x85,0xcf] + ctestbq {dfv=of} %r9, %r15 +# CHECK: ctestbeb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x06,0xf6,0x44,0x80,0x7b,0x7b] + ctestbeb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestbew {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x06,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestbew {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestbel {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x06,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestbel {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestbeq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x06,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestbeq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestbeb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x06,0x84,0x5c,0x80,0x7b] + ctestbeb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestbew {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x06,0x85,0x54,0x80,0x7b] + ctestbew {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestbel {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x06,0x85,0x4c,0x80,0x7b] + ctestbel {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctestbeq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x06,0x85,0x4c,0x80,0x7b] + ctestbeq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctestbeb {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x06,0xf6,0xc3,0x7b] + ctestbeb {dfv=of} $123, %bl +# CHECK: ctestbew {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x06,0xf7,0xc2,0xd2,0x04] + ctestbew {dfv=of} $1234, %dx +# CHECK: ctestbel {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x06,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestbel {dfv=of} $123456, %ecx +# CHECK: ctestbeq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x06,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestbeq {dfv=of} $123456, %r9 +# CHECK: ctestbeb {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x06,0x84,0xda] + ctestbeb {dfv=of} %bl, %dl +# CHECK: ctestbew {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x06,0x85,0xd0] + ctestbew {dfv=of} %dx, %ax +# CHECK: ctestbel {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x06,0x85,0xca] + ctestbel {dfv=of} %ecx, %edx +# CHECK: ctestbeq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x06,0x85,0xcf] + ctestbeq {dfv=of} %r9, %r15 +# CHECK: ctestfb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0b,0xf6,0x44,0x80,0x7b,0x7b] + ctestfb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestfw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x0b,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestfw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestfl {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0b,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestfl {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestfq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x0b,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestfq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestfb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0b,0x84,0x5c,0x80,0x7b] + ctestfb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestfw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x0b,0x85,0x54,0x80,0x7b] + ctestfw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestfl {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0b,0x85,0x4c,0x80,0x7b] + ctestfl {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctestfq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x0b,0x85,0x4c,0x80,0x7b] + ctestfq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctestfb {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x0b,0xf6,0xc3,0x7b] + ctestfb {dfv=of} $123, %bl +# CHECK: ctestfw {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x0b,0xf7,0xc2,0xd2,0x04] + ctestfw {dfv=of} $1234, %dx +# CHECK: ctestfl {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x0b,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestfl {dfv=of} $123456, %ecx +# CHECK: ctestfq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0b,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestfq {dfv=of} $123456, %r9 +# CHECK: ctestfb {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x0b,0x84,0xda] + ctestfb {dfv=of} %bl, %dl +# CHECK: ctestfw {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x0b,0x85,0xd0] + ctestfw {dfv=of} %dx, %ax +# CHECK: ctestfl {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x0b,0x85,0xca] + ctestfl {dfv=of} %ecx, %edx +# CHECK: ctestfq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x0b,0x85,0xcf] + ctestfq {dfv=of} %r9, %r15 +# CHECK: ctestlb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0c,0xf6,0x44,0x80,0x7b,0x7b] + ctestlb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestlw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x0c,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestlw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestll {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0c,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestll {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestlq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x0c,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestlq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestlb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0c,0x84,0x5c,0x80,0x7b] + ctestlb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestlw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x0c,0x85,0x54,0x80,0x7b] + ctestlw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestll {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0c,0x85,0x4c,0x80,0x7b] + ctestll {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctestlq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x0c,0x85,0x4c,0x80,0x7b] + ctestlq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctestlb {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x0c,0xf6,0xc3,0x7b] + ctestlb {dfv=of} $123, %bl +# CHECK: ctestlw {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x0c,0xf7,0xc2,0xd2,0x04] + ctestlw {dfv=of} $1234, %dx +# CHECK: ctestll {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x0c,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestll {dfv=of} $123456, %ecx +# CHECK: ctestlq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0c,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestlq {dfv=of} $123456, %r9 +# CHECK: ctestlb {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x0c,0x84,0xda] + ctestlb {dfv=of} %bl, %dl +# CHECK: ctestlw {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x0c,0x85,0xd0] + ctestlw {dfv=of} %dx, %ax +# CHECK: ctestll {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x0c,0x85,0xca] + ctestll {dfv=of} %ecx, %edx +# CHECK: ctestlq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x0c,0x85,0xcf] + ctestlq {dfv=of} %r9, %r15 +# CHECK: ctestleb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0e,0xf6,0x44,0x80,0x7b,0x7b] + ctestleb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestlew {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x0e,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestlew {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestlel {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0e,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestlel {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestleq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x0e,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestleq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestleb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0e,0x84,0x5c,0x80,0x7b] + ctestleb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestlew {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x0e,0x85,0x54,0x80,0x7b] + ctestlew {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestlel {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0e,0x85,0x4c,0x80,0x7b] + ctestlel {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctestleq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x0e,0x85,0x4c,0x80,0x7b] + ctestleq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctestleb {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x0e,0xf6,0xc3,0x7b] + ctestleb {dfv=of} $123, %bl +# CHECK: ctestlew {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x0e,0xf7,0xc2,0xd2,0x04] + ctestlew {dfv=of} $1234, %dx +# CHECK: ctestlel {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x0e,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestlel {dfv=of} $123456, %ecx +# CHECK: ctestleq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0e,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestleq {dfv=of} $123456, %r9 +# CHECK: ctestleb {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x0e,0x84,0xda] + ctestleb {dfv=of} %bl, %dl +# CHECK: ctestlew {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x0e,0x85,0xd0] + ctestlew {dfv=of} %dx, %ax +# CHECK: ctestlel {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x0e,0x85,0xca] + ctestlel {dfv=of} %ecx, %edx +# CHECK: ctestleq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x0e,0x85,0xcf] + ctestleq {dfv=of} %r9, %r15 +# CHECK: ctestaeb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x03,0xf6,0x44,0x80,0x7b,0x7b] + ctestaeb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestaew {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x03,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestaew {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestael {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x03,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestael {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestaeq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x03,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestaeq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestaeb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x03,0x84,0x5c,0x80,0x7b] + ctestaeb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestaew {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x03,0x85,0x54,0x80,0x7b] + ctestaew {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestael {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x03,0x85,0x4c,0x80,0x7b] + ctestael {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctestaeq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x03,0x85,0x4c,0x80,0x7b] + ctestaeq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctestaeb {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x03,0xf6,0xc3,0x7b] + ctestaeb {dfv=of} $123, %bl +# CHECK: ctestaew {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x03,0xf7,0xc2,0xd2,0x04] + ctestaew {dfv=of} $1234, %dx +# CHECK: ctestael {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x03,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestael {dfv=of} $123456, %ecx +# CHECK: ctestaeq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x03,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestaeq {dfv=of} $123456, %r9 +# CHECK: ctestaeb {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x03,0x84,0xda] + ctestaeb {dfv=of} %bl, %dl +# CHECK: ctestaew {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x03,0x85,0xd0] + ctestaew {dfv=of} %dx, %ax +# CHECK: ctestael {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x03,0x85,0xca] + ctestael {dfv=of} %ecx, %edx +# CHECK: ctestaeq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x03,0x85,0xcf] + ctestaeq {dfv=of} %r9, %r15 +# CHECK: ctestab {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x07,0xf6,0x44,0x80,0x7b,0x7b] + ctestab {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestaw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x07,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestaw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestal {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x07,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestal {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestaq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x07,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestaq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestab {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x07,0x84,0x5c,0x80,0x7b] + ctestab {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestaw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x07,0x85,0x54,0x80,0x7b] + ctestaw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestal {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x07,0x85,0x4c,0x80,0x7b] + ctestal {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctestaq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x07,0x85,0x4c,0x80,0x7b] + ctestaq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctestab {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x07,0xf6,0xc3,0x7b] + ctestab {dfv=of} $123, %bl +# CHECK: ctestaw {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x07,0xf7,0xc2,0xd2,0x04] + ctestaw {dfv=of} $1234, %dx +# CHECK: ctestal {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x07,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestal {dfv=of} $123456, %ecx +# CHECK: ctestaq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x07,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestaq {dfv=of} $123456, %r9 +# CHECK: ctestab {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x07,0x84,0xda] + ctestab {dfv=of} %bl, %dl +# CHECK: ctestaw {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x07,0x85,0xd0] + ctestaw {dfv=of} %dx, %ax +# CHECK: ctestal {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x07,0x85,0xca] + ctestal {dfv=of} %ecx, %edx +# CHECK: ctestaq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x07,0x85,0xcf] + ctestaq {dfv=of} %r9, %r15 +# CHECK: ctestgeb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0d,0xf6,0x44,0x80,0x7b,0x7b] + ctestgeb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestgew {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x0d,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestgew {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestgel {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0d,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestgel {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestgeq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x0d,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestgeq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestgeb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0d,0x84,0x5c,0x80,0x7b] + ctestgeb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestgew {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x0d,0x85,0x54,0x80,0x7b] + ctestgew {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestgel {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0d,0x85,0x4c,0x80,0x7b] + ctestgel {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctestgeq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x0d,0x85,0x4c,0x80,0x7b] + ctestgeq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctestgeb {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x0d,0xf6,0xc3,0x7b] + ctestgeb {dfv=of} $123, %bl +# CHECK: ctestgew {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x0d,0xf7,0xc2,0xd2,0x04] + ctestgew {dfv=of} $1234, %dx +# CHECK: ctestgel {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x0d,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestgel {dfv=of} $123456, %ecx +# CHECK: ctestgeq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0d,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestgeq {dfv=of} $123456, %r9 +# CHECK: ctestgeb {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x0d,0x84,0xda] + ctestgeb {dfv=of} %bl, %dl +# CHECK: ctestgew {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x0d,0x85,0xd0] + ctestgew {dfv=of} %dx, %ax +# CHECK: ctestgel {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x0d,0x85,0xca] + ctestgel {dfv=of} %ecx, %edx +# CHECK: ctestgeq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x0d,0x85,0xcf] + ctestgeq {dfv=of} %r9, %r15 +# CHECK: ctestgb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0f,0xf6,0x44,0x80,0x7b,0x7b] + ctestgb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestgw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x0f,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestgw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestgl {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0f,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestgl {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestgq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x0f,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestgq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestgb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0f,0x84,0x5c,0x80,0x7b] + ctestgb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestgw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x0f,0x85,0x54,0x80,0x7b] + ctestgw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestgl {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0f,0x85,0x4c,0x80,0x7b] + ctestgl {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctestgq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x0f,0x85,0x4c,0x80,0x7b] + ctestgq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctestgb {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x0f,0xf6,0xc3,0x7b] + ctestgb {dfv=of} $123, %bl +# CHECK: ctestgw {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x0f,0xf7,0xc2,0xd2,0x04] + ctestgw {dfv=of} $1234, %dx +# CHECK: ctestgl {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x0f,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestgl {dfv=of} $123456, %ecx +# CHECK: ctestgq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0f,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestgq {dfv=of} $123456, %r9 +# CHECK: ctestgb {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x0f,0x84,0xda] + ctestgb {dfv=of} %bl, %dl +# CHECK: ctestgw {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x0f,0x85,0xd0] + ctestgw {dfv=of} %dx, %ax +# CHECK: ctestgl {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x0f,0x85,0xca] + ctestgl {dfv=of} %ecx, %edx +# CHECK: ctestgq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x0f,0x85,0xcf] + ctestgq {dfv=of} %r9, %r15 +# CHECK: ctestnob {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x01,0xf6,0x44,0x80,0x7b,0x7b] + ctestnob {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestnow {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x01,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestnow {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestnol {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x01,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestnol {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestnoq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x01,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestnoq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestnob {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x01,0x84,0x5c,0x80,0x7b] + ctestnob {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestnow {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x01,0x85,0x54,0x80,0x7b] + ctestnow {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestnol {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x01,0x85,0x4c,0x80,0x7b] + ctestnol {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctestnoq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x01,0x85,0x4c,0x80,0x7b] + ctestnoq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctestnob {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x01,0xf6,0xc3,0x7b] + ctestnob {dfv=of} $123, %bl +# CHECK: ctestnow {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x01,0xf7,0xc2,0xd2,0x04] + ctestnow {dfv=of} $1234, %dx +# CHECK: ctestnol {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x01,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestnol {dfv=of} $123456, %ecx +# CHECK: ctestnoq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x01,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestnoq {dfv=of} $123456, %r9 +# CHECK: ctestnob {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x01,0x84,0xda] + ctestnob {dfv=of} %bl, %dl +# CHECK: ctestnow {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x01,0x85,0xd0] + ctestnow {dfv=of} %dx, %ax +# CHECK: ctestnol {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x01,0x85,0xca] + ctestnol {dfv=of} %ecx, %edx +# CHECK: ctestnoq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x01,0x85,0xcf] + ctestnoq {dfv=of} %r9, %r15 +# CHECK: ctestnsb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x09,0xf6,0x44,0x80,0x7b,0x7b] + ctestnsb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestnsw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x09,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestnsw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestnsl {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x09,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestnsl {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestnsq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x09,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestnsq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestnsb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x09,0x84,0x5c,0x80,0x7b] + ctestnsb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestnsw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x09,0x85,0x54,0x80,0x7b] + ctestnsw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestnsl {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x09,0x85,0x4c,0x80,0x7b] + ctestnsl {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctestnsq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x09,0x85,0x4c,0x80,0x7b] + ctestnsq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctestnsb {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x09,0xf6,0xc3,0x7b] + ctestnsb {dfv=of} $123, %bl +# CHECK: ctestnsw {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x09,0xf7,0xc2,0xd2,0x04] + ctestnsw {dfv=of} $1234, %dx +# CHECK: ctestnsl {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x09,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestnsl {dfv=of} $123456, %ecx +# CHECK: ctestnsq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x09,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestnsq {dfv=of} $123456, %r9 +# CHECK: ctestnsb {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x09,0x84,0xda] + ctestnsb {dfv=of} %bl, %dl +# CHECK: ctestnsw {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x09,0x85,0xd0] + ctestnsw {dfv=of} %dx, %ax +# CHECK: ctestnsl {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x09,0x85,0xca] + ctestnsl {dfv=of} %ecx, %edx +# CHECK: ctestnsq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x09,0x85,0xcf] + ctestnsq {dfv=of} %r9, %r15 +# CHECK: ctestneb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x05,0xf6,0x44,0x80,0x7b,0x7b] + ctestneb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestnew {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x05,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestnew {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestnel {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x05,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestnel {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestneq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x05,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestneq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestneb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x05,0x84,0x5c,0x80,0x7b] + ctestneb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestnew {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x05,0x85,0x54,0x80,0x7b] + ctestnew {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestnel {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x05,0x85,0x4c,0x80,0x7b] + ctestnel {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctestneq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x05,0x85,0x4c,0x80,0x7b] + ctestneq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctestneb {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x05,0xf6,0xc3,0x7b] + ctestneb {dfv=of} $123, %bl +# CHECK: ctestnew {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x05,0xf7,0xc2,0xd2,0x04] + ctestnew {dfv=of} $1234, %dx +# CHECK: ctestnel {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x05,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestnel {dfv=of} $123456, %ecx +# CHECK: ctestneq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x05,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestneq {dfv=of} $123456, %r9 +# CHECK: ctestneb {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x05,0x84,0xda] + ctestneb {dfv=of} %bl, %dl +# CHECK: ctestnew {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x05,0x85,0xd0] + ctestnew {dfv=of} %dx, %ax +# CHECK: ctestnel {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x05,0x85,0xca] + ctestnel {dfv=of} %ecx, %edx +# CHECK: ctestneq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x05,0x85,0xcf] + ctestneq {dfv=of} %r9, %r15 +# CHECK: ctestob {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x00,0xf6,0x44,0x80,0x7b,0x7b] + ctestob {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestow {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x00,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestow {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestol {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x00,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestol {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestoq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x00,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestoq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestob {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x00,0x84,0x5c,0x80,0x7b] + ctestob {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestow {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x00,0x85,0x54,0x80,0x7b] + ctestow {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestol {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x00,0x85,0x4c,0x80,0x7b] + ctestol {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctestoq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x00,0x85,0x4c,0x80,0x7b] + ctestoq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctestob {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x00,0xf6,0xc3,0x7b] + ctestob {dfv=of} $123, %bl +# CHECK: ctestow {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x00,0xf7,0xc2,0xd2,0x04] + ctestow {dfv=of} $1234, %dx +# CHECK: ctestol {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x00,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestol {dfv=of} $123456, %ecx +# CHECK: ctestoq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x00,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestoq {dfv=of} $123456, %r9 +# CHECK: ctestob {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x00,0x84,0xda] + ctestob {dfv=of} %bl, %dl +# CHECK: ctestow {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x00,0x85,0xd0] + ctestow {dfv=of} %dx, %ax +# CHECK: ctestol {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x00,0x85,0xca] + ctestol {dfv=of} %ecx, %edx +# CHECK: ctestoq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x00,0x85,0xcf] + ctestoq {dfv=of} %r9, %r15 +# CHECK: ctestsb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x08,0xf6,0x44,0x80,0x7b,0x7b] + ctestsb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestsw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x08,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestsw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestsl {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x08,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestsl {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestsq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x08,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestsq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctestsb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x08,0x84,0x5c,0x80,0x7b] + ctestsb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestsw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x08,0x85,0x54,0x80,0x7b] + ctestsw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestsl {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x08,0x85,0x4c,0x80,0x7b] + ctestsl {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctestsq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x08,0x85,0x4c,0x80,0x7b] + ctestsq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctestsb {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x08,0xf6,0xc3,0x7b] + ctestsb {dfv=of} $123, %bl +# CHECK: ctestsw {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x08,0xf7,0xc2,0xd2,0x04] + ctestsw {dfv=of} $1234, %dx +# CHECK: ctestsl {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x08,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestsl {dfv=of} $123456, %ecx +# CHECK: ctestsq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x08,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestsq {dfv=of} $123456, %r9 +# CHECK: ctestsb {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x08,0x84,0xda] + ctestsb {dfv=of} %bl, %dl +# CHECK: ctestsw {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x08,0x85,0xd0] + ctestsw {dfv=of} %dx, %ax +# CHECK: ctestsl {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x08,0x85,0xca] + ctestsl {dfv=of} %ecx, %edx +# CHECK: ctestsq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x08,0x85,0xcf] + ctestsq {dfv=of} %r9, %r15 +# CHECK: ctesttb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0a,0xf6,0x44,0x80,0x7b,0x7b] + ctesttb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctesttw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x0a,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctesttw {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctesttl {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0a,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctesttl {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctesttq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x0a,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctesttq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctesttb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0a,0x84,0x5c,0x80,0x7b] + ctesttb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctesttw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x0a,0x85,0x54,0x80,0x7b] + ctesttw {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctesttl {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x0a,0x85,0x4c,0x80,0x7b] + ctesttl {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctesttq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x0a,0x85,0x4c,0x80,0x7b] + ctesttq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctesttb {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x0a,0xf6,0xc3,0x7b] + ctesttb {dfv=of} $123, %bl +# CHECK: ctesttw {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x0a,0xf7,0xc2,0xd2,0x04] + ctesttw {dfv=of} $1234, %dx +# CHECK: ctesttl {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x0a,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctesttl {dfv=of} $123456, %ecx +# CHECK: ctesttq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0a,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctesttq {dfv=of} $123456, %r9 +# CHECK: ctesttb {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x0a,0x84,0xda] + ctesttb {dfv=of} %bl, %dl +# CHECK: ctesttw {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x0a,0x85,0xd0] + ctesttw {dfv=of} %dx, %ax +# CHECK: ctesttl {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x0a,0x85,0xca] + ctesttl {dfv=of} %ecx, %edx +# CHECK: ctesttq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x0a,0x85,0xcf] + ctesttq {dfv=of} %r9, %r15 +# CHECK: ctesteb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x04,0xf6,0x44,0x80,0x7b,0x7b] + ctesteb {dfv=of} $123, 123(%r8,%rax,4) +# CHECK: ctestew {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x04,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestew {dfv=of} $1234, 123(%r8,%rax,4) +# CHECK: ctestel {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x04,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestel {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctesteq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0xc4,0x04,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctesteq {dfv=of} $123456, 123(%r8,%rax,4) +# CHECK: ctesteb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x04,0x84,0x5c,0x80,0x7b] + ctesteb {dfv=of} %bl, 123(%r8,%rax,4) +# CHECK: ctestew {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x45,0x04,0x85,0x54,0x80,0x7b] + ctestew {dfv=of} %dx, 123(%r8,%rax,4) +# CHECK: ctestel {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0xd4,0x44,0x04,0x85,0x4c,0x80,0x7b] + ctestel {dfv=of} %ecx, 123(%r8,%rax,4) +# CHECK: ctesteq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: encoding: [0x62,0x54,0xc4,0x04,0x85,0x4c,0x80,0x7b] + ctesteq {dfv=of} %r9, 123(%r8,%rax,4) +# CHECK: ctesteb {dfv=of} $123, %bl +# CHECK: encoding: [0x62,0xf4,0x44,0x04,0xf6,0xc3,0x7b] + ctesteb {dfv=of} $123, %bl +# CHECK: ctestew {dfv=of} $1234, %dx +# CHECK: encoding: [0x62,0xf4,0x45,0x04,0xf7,0xc2,0xd2,0x04] + ctestew {dfv=of} $1234, %dx +# CHECK: ctestel {dfv=of} $123456, %ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x04,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestel {dfv=of} $123456, %ecx +# CHECK: ctesteq {dfv=of} $123456, %r9 +# CHECK: encoding: [0x62,0xd4,0xc4,0x04,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctesteq {dfv=of} $123456, %r9 +# CHECK: ctesteb {dfv=of} %bl, %dl +# CHECK: encoding: [0x62,0xf4,0x44,0x04,0x84,0xda] + ctesteb {dfv=of} %bl, %dl +# CHECK: ctestew {dfv=of} %dx, %ax +# CHECK: encoding: [0x62,0xf4,0x45,0x04,0x85,0xd0] + ctestew {dfv=of} %dx, %ax +# CHECK: ctestel {dfv=of} %ecx, %edx +# CHECK: encoding: [0x62,0xf4,0x44,0x04,0x85,0xca] + ctestel {dfv=of} %ecx, %edx +# CHECK: ctesteq {dfv=of} %r9, %r15 +# CHECK: encoding: [0x62,0x54,0xc4,0x04,0x85,0xcf] + ctesteq {dfv=of} %r9, %r15 diff --git a/llvm/test/MC/X86/apx/ctest-intel.s b/llvm/test/MC/X86/apx/ctest-intel.s new file mode 100644 index 000000000000..17cea489b476 --- /dev/null +++ b/llvm/test/MC/X86/apx/ctest-intel.s @@ -0,0 +1,770 @@ +# RUN: llvm-mc -triple x86_64 -show-encoding -x86-asm-syntax=intel -output-asm-variant=1 %s | FileCheck %s + +# CHECK: ctestb {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x02,0xf6,0x44,0x80,0x7b,0x7b] + ctestb {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctestb {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x02,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestb {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctestb {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x02,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestb {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestb {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x02,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestb {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestb {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x02,0x84,0x5c,0x80,0x7b] + ctestb {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctestb {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x02,0x85,0x54,0x80,0x7b] + ctestb {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctestb {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x02,0x85,0x4c,0x80,0x7b] + ctestb {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctestb {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x02,0x85,0x4c,0x80,0x7b] + ctestb {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctestb {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x02,0xf6,0xc3,0x7b] + ctestb {dfv=of} bl, 123 +# CHECK: ctestb {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x02,0xf7,0xc2,0xd2,0x04] + ctestb {dfv=of} dx, 1234 +# CHECK: ctestb {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x02,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestb {dfv=of} ecx, 123456 +# CHECK: ctestb {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x02,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestb {dfv=of} r9, 123456 +# CHECK: ctestb {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x02,0x84,0xda] + ctestb {dfv=of} dl, bl +# CHECK: ctestb {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x02,0x85,0xd0] + ctestb {dfv=of} ax, dx +# CHECK: ctestb {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x02,0x85,0xca] + ctestb {dfv=of} edx, ecx +# CHECK: ctestb {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x02,0x85,0xcf] + ctestb {dfv=of} r15, r9 +# CHECK: ctestbe {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x06,0xf6,0x44,0x80,0x7b,0x7b] + ctestbe {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctestbe {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x06,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestbe {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctestbe {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x06,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestbe {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestbe {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x06,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestbe {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestbe {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x06,0x84,0x5c,0x80,0x7b] + ctestbe {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctestbe {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x06,0x85,0x54,0x80,0x7b] + ctestbe {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctestbe {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x06,0x85,0x4c,0x80,0x7b] + ctestbe {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctestbe {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x06,0x85,0x4c,0x80,0x7b] + ctestbe {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctestbe {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x06,0xf6,0xc3,0x7b] + ctestbe {dfv=of} bl, 123 +# CHECK: ctestbe {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x06,0xf7,0xc2,0xd2,0x04] + ctestbe {dfv=of} dx, 1234 +# CHECK: ctestbe {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x06,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestbe {dfv=of} ecx, 123456 +# CHECK: ctestbe {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x06,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestbe {dfv=of} r9, 123456 +# CHECK: ctestbe {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x06,0x84,0xda] + ctestbe {dfv=of} dl, bl +# CHECK: ctestbe {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x06,0x85,0xd0] + ctestbe {dfv=of} ax, dx +# CHECK: ctestbe {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x06,0x85,0xca] + ctestbe {dfv=of} edx, ecx +# CHECK: ctestbe {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x06,0x85,0xcf] + ctestbe {dfv=of} r15, r9 +# CHECK: ctestf {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x0b,0xf6,0x44,0x80,0x7b,0x7b] + ctestf {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctestf {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x0b,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestf {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctestf {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0b,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestf {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestf {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x0b,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestf {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestf {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x0b,0x84,0x5c,0x80,0x7b] + ctestf {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctestf {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x0b,0x85,0x54,0x80,0x7b] + ctestf {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctestf {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x0b,0x85,0x4c,0x80,0x7b] + ctestf {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctestf {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x0b,0x85,0x4c,0x80,0x7b] + ctestf {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctestf {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x0b,0xf6,0xc3,0x7b] + ctestf {dfv=of} bl, 123 +# CHECK: ctestf {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x0b,0xf7,0xc2,0xd2,0x04] + ctestf {dfv=of} dx, 1234 +# CHECK: ctestf {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x0b,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestf {dfv=of} ecx, 123456 +# CHECK: ctestf {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0b,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestf {dfv=of} r9, 123456 +# CHECK: ctestf {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x0b,0x84,0xda] + ctestf {dfv=of} dl, bl +# CHECK: ctestf {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x0b,0x85,0xd0] + ctestf {dfv=of} ax, dx +# CHECK: ctestf {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x0b,0x85,0xca] + ctestf {dfv=of} edx, ecx +# CHECK: ctestf {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x0b,0x85,0xcf] + ctestf {dfv=of} r15, r9 +# CHECK: ctestl {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x0c,0xf6,0x44,0x80,0x7b,0x7b] + ctestl {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctestl {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x0c,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestl {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctestl {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0c,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestl {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestl {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x0c,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestl {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestl {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x0c,0x84,0x5c,0x80,0x7b] + ctestl {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctestl {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x0c,0x85,0x54,0x80,0x7b] + ctestl {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctestl {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x0c,0x85,0x4c,0x80,0x7b] + ctestl {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctestl {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x0c,0x85,0x4c,0x80,0x7b] + ctestl {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctestl {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x0c,0xf6,0xc3,0x7b] + ctestl {dfv=of} bl, 123 +# CHECK: ctestl {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x0c,0xf7,0xc2,0xd2,0x04] + ctestl {dfv=of} dx, 1234 +# CHECK: ctestl {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x0c,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestl {dfv=of} ecx, 123456 +# CHECK: ctestl {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0c,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestl {dfv=of} r9, 123456 +# CHECK: ctestl {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x0c,0x84,0xda] + ctestl {dfv=of} dl, bl +# CHECK: ctestl {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x0c,0x85,0xd0] + ctestl {dfv=of} ax, dx +# CHECK: ctestl {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x0c,0x85,0xca] + ctestl {dfv=of} edx, ecx +# CHECK: ctestl {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x0c,0x85,0xcf] + ctestl {dfv=of} r15, r9 +# CHECK: ctestle {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x0e,0xf6,0x44,0x80,0x7b,0x7b] + ctestle {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctestle {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x0e,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestle {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctestle {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0e,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestle {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestle {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x0e,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestle {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestle {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x0e,0x84,0x5c,0x80,0x7b] + ctestle {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctestle {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x0e,0x85,0x54,0x80,0x7b] + ctestle {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctestle {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x0e,0x85,0x4c,0x80,0x7b] + ctestle {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctestle {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x0e,0x85,0x4c,0x80,0x7b] + ctestle {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctestle {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x0e,0xf6,0xc3,0x7b] + ctestle {dfv=of} bl, 123 +# CHECK: ctestle {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x0e,0xf7,0xc2,0xd2,0x04] + ctestle {dfv=of} dx, 1234 +# CHECK: ctestle {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x0e,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestle {dfv=of} ecx, 123456 +# CHECK: ctestle {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0e,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestle {dfv=of} r9, 123456 +# CHECK: ctestle {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x0e,0x84,0xda] + ctestle {dfv=of} dl, bl +# CHECK: ctestle {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x0e,0x85,0xd0] + ctestle {dfv=of} ax, dx +# CHECK: ctestle {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x0e,0x85,0xca] + ctestle {dfv=of} edx, ecx +# CHECK: ctestle {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x0e,0x85,0xcf] + ctestle {dfv=of} r15, r9 +# CHECK: ctestae {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x03,0xf6,0x44,0x80,0x7b,0x7b] + ctestae {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctestae {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x03,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestae {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctestae {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x03,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestae {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestae {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x03,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestae {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestae {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x03,0x84,0x5c,0x80,0x7b] + ctestae {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctestae {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x03,0x85,0x54,0x80,0x7b] + ctestae {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctestae {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x03,0x85,0x4c,0x80,0x7b] + ctestae {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctestae {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x03,0x85,0x4c,0x80,0x7b] + ctestae {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctestae {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x03,0xf6,0xc3,0x7b] + ctestae {dfv=of} bl, 123 +# CHECK: ctestae {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x03,0xf7,0xc2,0xd2,0x04] + ctestae {dfv=of} dx, 1234 +# CHECK: ctestae {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x03,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestae {dfv=of} ecx, 123456 +# CHECK: ctestae {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x03,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestae {dfv=of} r9, 123456 +# CHECK: ctestae {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x03,0x84,0xda] + ctestae {dfv=of} dl, bl +# CHECK: ctestae {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x03,0x85,0xd0] + ctestae {dfv=of} ax, dx +# CHECK: ctestae {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x03,0x85,0xca] + ctestae {dfv=of} edx, ecx +# CHECK: ctestae {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x03,0x85,0xcf] + ctestae {dfv=of} r15, r9 +# CHECK: ctesta {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x07,0xf6,0x44,0x80,0x7b,0x7b] + ctesta {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctesta {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x07,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctesta {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctesta {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x07,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctesta {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctesta {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x07,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctesta {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctesta {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x07,0x84,0x5c,0x80,0x7b] + ctesta {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctesta {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x07,0x85,0x54,0x80,0x7b] + ctesta {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctesta {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x07,0x85,0x4c,0x80,0x7b] + ctesta {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctesta {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x07,0x85,0x4c,0x80,0x7b] + ctesta {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctesta {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x07,0xf6,0xc3,0x7b] + ctesta {dfv=of} bl, 123 +# CHECK: ctesta {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x07,0xf7,0xc2,0xd2,0x04] + ctesta {dfv=of} dx, 1234 +# CHECK: ctesta {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x07,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctesta {dfv=of} ecx, 123456 +# CHECK: ctesta {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x07,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctesta {dfv=of} r9, 123456 +# CHECK: ctesta {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x07,0x84,0xda] + ctesta {dfv=of} dl, bl +# CHECK: ctesta {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x07,0x85,0xd0] + ctesta {dfv=of} ax, dx +# CHECK: ctesta {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x07,0x85,0xca] + ctesta {dfv=of} edx, ecx +# CHECK: ctesta {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x07,0x85,0xcf] + ctesta {dfv=of} r15, r9 +# CHECK: ctestge {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x0d,0xf6,0x44,0x80,0x7b,0x7b] + ctestge {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctestge {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x0d,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestge {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctestge {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0d,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestge {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestge {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x0d,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestge {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestge {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x0d,0x84,0x5c,0x80,0x7b] + ctestge {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctestge {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x0d,0x85,0x54,0x80,0x7b] + ctestge {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctestge {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x0d,0x85,0x4c,0x80,0x7b] + ctestge {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctestge {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x0d,0x85,0x4c,0x80,0x7b] + ctestge {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctestge {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x0d,0xf6,0xc3,0x7b] + ctestge {dfv=of} bl, 123 +# CHECK: ctestge {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x0d,0xf7,0xc2,0xd2,0x04] + ctestge {dfv=of} dx, 1234 +# CHECK: ctestge {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x0d,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestge {dfv=of} ecx, 123456 +# CHECK: ctestge {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0d,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestge {dfv=of} r9, 123456 +# CHECK: ctestge {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x0d,0x84,0xda] + ctestge {dfv=of} dl, bl +# CHECK: ctestge {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x0d,0x85,0xd0] + ctestge {dfv=of} ax, dx +# CHECK: ctestge {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x0d,0x85,0xca] + ctestge {dfv=of} edx, ecx +# CHECK: ctestge {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x0d,0x85,0xcf] + ctestge {dfv=of} r15, r9 +# CHECK: ctestg {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x0f,0xf6,0x44,0x80,0x7b,0x7b] + ctestg {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctestg {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x0f,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestg {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctestg {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0f,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestg {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestg {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x0f,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestg {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestg {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x0f,0x84,0x5c,0x80,0x7b] + ctestg {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctestg {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x0f,0x85,0x54,0x80,0x7b] + ctestg {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctestg {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x0f,0x85,0x4c,0x80,0x7b] + ctestg {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctestg {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x0f,0x85,0x4c,0x80,0x7b] + ctestg {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctestg {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x0f,0xf6,0xc3,0x7b] + ctestg {dfv=of} bl, 123 +# CHECK: ctestg {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x0f,0xf7,0xc2,0xd2,0x04] + ctestg {dfv=of} dx, 1234 +# CHECK: ctestg {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x0f,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestg {dfv=of} ecx, 123456 +# CHECK: ctestg {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0f,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestg {dfv=of} r9, 123456 +# CHECK: ctestg {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x0f,0x84,0xda] + ctestg {dfv=of} dl, bl +# CHECK: ctestg {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x0f,0x85,0xd0] + ctestg {dfv=of} ax, dx +# CHECK: ctestg {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x0f,0x85,0xca] + ctestg {dfv=of} edx, ecx +# CHECK: ctestg {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x0f,0x85,0xcf] + ctestg {dfv=of} r15, r9 +# CHECK: ctestno {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x01,0xf6,0x44,0x80,0x7b,0x7b] + ctestno {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctestno {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x01,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestno {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctestno {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x01,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestno {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestno {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x01,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestno {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestno {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x01,0x84,0x5c,0x80,0x7b] + ctestno {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctestno {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x01,0x85,0x54,0x80,0x7b] + ctestno {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctestno {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x01,0x85,0x4c,0x80,0x7b] + ctestno {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctestno {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x01,0x85,0x4c,0x80,0x7b] + ctestno {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctestno {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x01,0xf6,0xc3,0x7b] + ctestno {dfv=of} bl, 123 +# CHECK: ctestno {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x01,0xf7,0xc2,0xd2,0x04] + ctestno {dfv=of} dx, 1234 +# CHECK: ctestno {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x01,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestno {dfv=of} ecx, 123456 +# CHECK: ctestno {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x01,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestno {dfv=of} r9, 123456 +# CHECK: ctestno {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x01,0x84,0xda] + ctestno {dfv=of} dl, bl +# CHECK: ctestno {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x01,0x85,0xd0] + ctestno {dfv=of} ax, dx +# CHECK: ctestno {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x01,0x85,0xca] + ctestno {dfv=of} edx, ecx +# CHECK: ctestno {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x01,0x85,0xcf] + ctestno {dfv=of} r15, r9 +# CHECK: ctestns {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x09,0xf6,0x44,0x80,0x7b,0x7b] + ctestns {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctestns {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x09,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestns {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctestns {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x09,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestns {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestns {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x09,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestns {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestns {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x09,0x84,0x5c,0x80,0x7b] + ctestns {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctestns {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x09,0x85,0x54,0x80,0x7b] + ctestns {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctestns {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x09,0x85,0x4c,0x80,0x7b] + ctestns {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctestns {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x09,0x85,0x4c,0x80,0x7b] + ctestns {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctestns {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x09,0xf6,0xc3,0x7b] + ctestns {dfv=of} bl, 123 +# CHECK: ctestns {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x09,0xf7,0xc2,0xd2,0x04] + ctestns {dfv=of} dx, 1234 +# CHECK: ctestns {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x09,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestns {dfv=of} ecx, 123456 +# CHECK: ctestns {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x09,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestns {dfv=of} r9, 123456 +# CHECK: ctestns {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x09,0x84,0xda] + ctestns {dfv=of} dl, bl +# CHECK: ctestns {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x09,0x85,0xd0] + ctestns {dfv=of} ax, dx +# CHECK: ctestns {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x09,0x85,0xca] + ctestns {dfv=of} edx, ecx +# CHECK: ctestns {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x09,0x85,0xcf] + ctestns {dfv=of} r15, r9 +# CHECK: ctestne {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x05,0xf6,0x44,0x80,0x7b,0x7b] + ctestne {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctestne {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x05,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestne {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctestne {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x05,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestne {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestne {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x05,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestne {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestne {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x05,0x84,0x5c,0x80,0x7b] + ctestne {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctestne {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x05,0x85,0x54,0x80,0x7b] + ctestne {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctestne {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x05,0x85,0x4c,0x80,0x7b] + ctestne {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctestne {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x05,0x85,0x4c,0x80,0x7b] + ctestne {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctestne {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x05,0xf6,0xc3,0x7b] + ctestne {dfv=of} bl, 123 +# CHECK: ctestne {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x05,0xf7,0xc2,0xd2,0x04] + ctestne {dfv=of} dx, 1234 +# CHECK: ctestne {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x05,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestne {dfv=of} ecx, 123456 +# CHECK: ctestne {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x05,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestne {dfv=of} r9, 123456 +# CHECK: ctestne {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x05,0x84,0xda] + ctestne {dfv=of} dl, bl +# CHECK: ctestne {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x05,0x85,0xd0] + ctestne {dfv=of} ax, dx +# CHECK: ctestne {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x05,0x85,0xca] + ctestne {dfv=of} edx, ecx +# CHECK: ctestne {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x05,0x85,0xcf] + ctestne {dfv=of} r15, r9 +# CHECK: ctesto {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x00,0xf6,0x44,0x80,0x7b,0x7b] + ctesto {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctesto {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x00,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctesto {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctesto {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x00,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctesto {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctesto {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x00,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctesto {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctesto {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x00,0x84,0x5c,0x80,0x7b] + ctesto {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctesto {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x00,0x85,0x54,0x80,0x7b] + ctesto {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctesto {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x00,0x85,0x4c,0x80,0x7b] + ctesto {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctesto {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x00,0x85,0x4c,0x80,0x7b] + ctesto {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctesto {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x00,0xf6,0xc3,0x7b] + ctesto {dfv=of} bl, 123 +# CHECK: ctesto {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x00,0xf7,0xc2,0xd2,0x04] + ctesto {dfv=of} dx, 1234 +# CHECK: ctesto {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x00,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctesto {dfv=of} ecx, 123456 +# CHECK: ctesto {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x00,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctesto {dfv=of} r9, 123456 +# CHECK: ctesto {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x00,0x84,0xda] + ctesto {dfv=of} dl, bl +# CHECK: ctesto {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x00,0x85,0xd0] + ctesto {dfv=of} ax, dx +# CHECK: ctesto {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x00,0x85,0xca] + ctesto {dfv=of} edx, ecx +# CHECK: ctesto {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x00,0x85,0xcf] + ctesto {dfv=of} r15, r9 +# CHECK: ctests {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x08,0xf6,0x44,0x80,0x7b,0x7b] + ctests {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctests {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x08,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctests {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctests {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x08,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctests {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctests {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x08,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctests {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctests {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x08,0x84,0x5c,0x80,0x7b] + ctests {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctests {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x08,0x85,0x54,0x80,0x7b] + ctests {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctests {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x08,0x85,0x4c,0x80,0x7b] + ctests {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctests {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x08,0x85,0x4c,0x80,0x7b] + ctests {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctests {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x08,0xf6,0xc3,0x7b] + ctests {dfv=of} bl, 123 +# CHECK: ctests {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x08,0xf7,0xc2,0xd2,0x04] + ctests {dfv=of} dx, 1234 +# CHECK: ctests {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x08,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctests {dfv=of} ecx, 123456 +# CHECK: ctests {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x08,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctests {dfv=of} r9, 123456 +# CHECK: ctests {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x08,0x84,0xda] + ctests {dfv=of} dl, bl +# CHECK: ctests {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x08,0x85,0xd0] + ctests {dfv=of} ax, dx +# CHECK: ctests {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x08,0x85,0xca] + ctests {dfv=of} edx, ecx +# CHECK: ctests {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x08,0x85,0xcf] + ctests {dfv=of} r15, r9 +# CHECK: ctestt {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x0a,0xf6,0x44,0x80,0x7b,0x7b] + ctestt {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: ctestt {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x0a,0xf7,0x44,0x80,0x7b,0xd2,0x04] + ctestt {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: ctestt {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0a,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestt {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestt {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x0a,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + ctestt {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: ctestt {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x0a,0x84,0x5c,0x80,0x7b] + ctestt {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: ctestt {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x0a,0x85,0x54,0x80,0x7b] + ctestt {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: ctestt {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x0a,0x85,0x4c,0x80,0x7b] + ctestt {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: ctestt {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x0a,0x85,0x4c,0x80,0x7b] + ctestt {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: ctestt {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x0a,0xf6,0xc3,0x7b] + ctestt {dfv=of} bl, 123 +# CHECK: ctestt {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x0a,0xf7,0xc2,0xd2,0x04] + ctestt {dfv=of} dx, 1234 +# CHECK: ctestt {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x0a,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestt {dfv=of} ecx, 123456 +# CHECK: ctestt {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x0a,0xf7,0xc1,0x40,0xe2,0x01,0x00] + ctestt {dfv=of} r9, 123456 +# CHECK: ctestt {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x0a,0x84,0xda] + ctestt {dfv=of} dl, bl +# CHECK: ctestt {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x0a,0x85,0xd0] + ctestt {dfv=of} ax, dx +# CHECK: ctestt {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x0a,0x85,0xca] + ctestt {dfv=of} edx, ecx +# CHECK: ctestt {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x0a,0x85,0xcf] + ctestt {dfv=of} r15, r9 +# CHECK: cteste {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: encoding: [0x62,0xd4,0x44,0x04,0xf6,0x44,0x80,0x7b,0x7b] + cteste {dfv=of} byte ptr [r8 + 4*rax + 123], 123 +# CHECK: cteste {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: encoding: [0x62,0xd4,0x45,0x04,0xf7,0x44,0x80,0x7b,0xd2,0x04] + cteste {dfv=of} word ptr [r8 + 4*rax + 123], 1234 +# CHECK: cteste {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x04,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + cteste {dfv=of} qword ptr [r8 + 4*rax + 123], 123456 +# CHECK: cteste {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: encoding: [0x62,0xd4,0x44,0x04,0xf7,0x44,0x80,0x7b,0x40,0xe2,0x01,0x00] + cteste {dfv=of} dword ptr [r8 + 4*rax + 123], 123456 +# CHECK: cteste {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: encoding: [0x62,0xd4,0x44,0x04,0x84,0x5c,0x80,0x7b] + cteste {dfv=of} byte ptr [r8 + 4*rax + 123], bl +# CHECK: cteste {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: encoding: [0x62,0xd4,0x45,0x04,0x85,0x54,0x80,0x7b] + cteste {dfv=of} word ptr [r8 + 4*rax + 123], dx +# CHECK: cteste {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: encoding: [0x62,0xd4,0x44,0x04,0x85,0x4c,0x80,0x7b] + cteste {dfv=of} dword ptr [r8 + 4*rax + 123], ecx +# CHECK: cteste {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x04,0x85,0x4c,0x80,0x7b] + cteste {dfv=of} qword ptr [r8 + 4*rax + 123], r9 +# CHECK: cteste {dfv=of} bl, 123 +# CHECK: encoding: [0x62,0xf4,0x44,0x04,0xf6,0xc3,0x7b] + cteste {dfv=of} bl, 123 +# CHECK: cteste {dfv=of} dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x45,0x04,0xf7,0xc2,0xd2,0x04] + cteste {dfv=of} dx, 1234 +# CHECK: cteste {dfv=of} ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x44,0x04,0xf7,0xc1,0x40,0xe2,0x01,0x00] + cteste {dfv=of} ecx, 123456 +# CHECK: cteste {dfv=of} r9, 123456 +# CHECK: encoding: [0x62,0xd4,0xc4,0x04,0xf7,0xc1,0x40,0xe2,0x01,0x00] + cteste {dfv=of} r9, 123456 +# CHECK: cteste {dfv=of} dl, bl +# CHECK: encoding: [0x62,0xf4,0x44,0x04,0x84,0xda] + cteste {dfv=of} dl, bl +# CHECK: cteste {dfv=of} ax, dx +# CHECK: encoding: [0x62,0xf4,0x45,0x04,0x85,0xd0] + cteste {dfv=of} ax, dx +# CHECK: cteste {dfv=of} edx, ecx +# CHECK: encoding: [0x62,0xf4,0x44,0x04,0x85,0xca] + cteste {dfv=of} edx, ecx +# CHECK: cteste {dfv=of} r15, r9 +# CHECK: encoding: [0x62,0x54,0xc4,0x04,0x85,0xcf] + cteste {dfv=of} r15, r9 -- GitLab From e89b4bcf32b8f6ddce9d7e95659e9f092a55c021 Mon Sep 17 00:00:00 2001 From: Phoebe Wang Date: Tue, 12 Mar 2024 13:41:49 +0800 Subject: [PATCH 206/953] [X86] Remove SlowDivide tuning from GRTTuning (#84676) The DIV32/64 throughput was improved since Goldmont in the Atom architecture. The Alder Lake-E shows similar number too. So we shouldn't add such tunings to Gracemont and later products. Checked from Agner Fog's table and uops.info. --- llvm/lib/Target/X86/X86.td | 2 -- .../CodeGen/X86/bypass-slow-division-tune.ll | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td index a2a65ce75d6b..8367f938c0dd 100644 --- a/llvm/lib/Target/X86/X86.td +++ b/llvm/lib/Target/X86/X86.td @@ -1237,8 +1237,6 @@ def ProcessorFeatures { // Gracemont list GRTTuning = [TuningMacroFusion, TuningSlow3OpsLEA, - TuningSlowDivide32, - TuningSlowDivide64, TuningFastScalarFSQRT, TuningFastVectorFSQRT, TuningFast15ByteNOP, diff --git a/llvm/test/CodeGen/X86/bypass-slow-division-tune.ll b/llvm/test/CodeGen/X86/bypass-slow-division-tune.ll index 8369a44dcbad..afecf00113a0 100644 --- a/llvm/test/CodeGen/X86/bypass-slow-division-tune.ll +++ b/llvm/test/CodeGen/X86/bypass-slow-division-tune.ll @@ -4,6 +4,8 @@ ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mcpu=x86-64 < %s | FileCheck -check-prefixes=CHECK,REST,X64 %s ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mcpu=silvermont < %s | FileCheck -check-prefixes=CHECK,REST,SLM %s ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mcpu=skylake < %s | FileCheck -check-prefixes=CHECK,REST,SKL %s +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mcpu=goldmont < %s | FileCheck -check-prefixes=CHECK,REST,GMT %s +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mcpu=gracemont < %s | FileCheck -check-prefixes=CHECK,REST,GMT %s ; RUN: llc -profile-summary-huge-working-set-size-threshold=1 -mtriple=x86_64-unknown-linux-gnu -mcpu=skylake < %s | FileCheck -check-prefixes=HUGEWS %s ; Verify that div32 is bypassed only for Atoms. @@ -117,6 +119,13 @@ define i64 @div64(i64 %a, i64 %b) { ; SKL-NEXT: # kill: def $eax killed $eax def $rax ; SKL-NEXT: retq ; +; GMT-LABEL: div64: +; GMT: # %bb.0: # %entry +; GMT-NEXT: movq %rdi, %rax +; GMT-NEXT: cqto +; GMT-NEXT: idivq %rsi +; GMT-NEXT: retq +; ; HUGEWS-LABEL: div64: ; HUGEWS: # %bb.0: # %entry ; HUGEWS-NEXT: movq %rdi, %rax @@ -240,6 +249,13 @@ define i64 @div64_hugews(i64 %a, i64 %b) { ; SKL-NEXT: # kill: def $eax killed $eax def $rax ; SKL-NEXT: retq ; +; GMT-LABEL: div64_hugews: +; GMT: # %bb.0: +; GMT-NEXT: movq %rdi, %rax +; GMT-NEXT: cqto +; GMT-NEXT: idivq %rsi +; GMT-NEXT: retq +; ; HUGEWS-LABEL: div64_hugews: ; HUGEWS: # %bb.0: ; HUGEWS-NEXT: movq %rdi, %rax -- GitLab From f95710c76519c611868c16f92586b6d0baedad54 Mon Sep 17 00:00:00 2001 From: Slava Zakharin Date: Mon, 11 Mar 2024 23:09:44 -0700 Subject: [PATCH 207/953] [flang] Fixed compiler build on glibc 2.17 systems after 3149c93. (#84873) --- flang/include/flang/Evaluate/integer.h | 4 ++++ flang/include/flang/Evaluate/real.h | 4 ++++ flang/lib/Evaluate/fold-implementation.h | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/flang/include/flang/Evaluate/integer.h b/flang/include/flang/Evaluate/integer.h index 31768c21daae..739564570126 100644 --- a/flang/include/flang/Evaluate/integer.h +++ b/flang/include/flang/Evaluate/integer.h @@ -27,6 +27,10 @@ #include #include +// Some environments, viz. glibc 2.17, allow the macro HUGE +// to leak out of . +#undef HUGE + namespace Fortran::evaluate::value { // Implements an integer as an assembly of smaller host integer parts diff --git a/flang/include/flang/Evaluate/real.h b/flang/include/flang/Evaluate/real.h index 5266bd0ef64b..d0da9634651f 100644 --- a/flang/include/flang/Evaluate/real.h +++ b/flang/include/flang/Evaluate/real.h @@ -18,6 +18,10 @@ #include #include +// Some environments, viz. glibc 2.17, allow the macro HUGE +// to leak out of . +#undef HUGE + namespace llvm { class raw_ostream; } diff --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h index 6b3c9416724c..9dd8c3843465 100644 --- a/flang/lib/Evaluate/fold-implementation.h +++ b/flang/lib/Evaluate/fold-implementation.h @@ -39,6 +39,10 @@ #include #include +// Some environments, viz. glibc 2.17, allow the macro HUGE +// to leak out of . +#undef HUGE + namespace Fortran::evaluate { // Utilities -- GitLab From 1d900e298449d43547312364751f730b7a0d07d1 Mon Sep 17 00:00:00 2001 From: "Dhruv Chawla (work)" Date: Tue, 12 Mar 2024 11:57:07 +0530 Subject: [PATCH 208/953] [AArch64][GlobalISel] Avoid generating inserts for undefs when selecting G_BUILD_VECTOR (#84452) It is safe to ignore undef values when selecting G_BUILD_VECTOR as undef values choose random registers for copying values from. --- .../GISel/AArch64InstructionSelector.cpp | 33 +- .../GlobalISel/select-build-vector.mir | 6 +- .../select-shufflevec-undef-mask-elt.mir | 18 +- llvm/test/CodeGen/AArch64/aarch64-bif-gen.ll | 1 - llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll | 1 - llvm/test/CodeGen/AArch64/abs.ll | 6 - llvm/test/CodeGen/AArch64/arm64-dup.ll | 6 +- llvm/test/CodeGen/AArch64/arm64-neon-copy.ll | 45 +-- llvm/test/CodeGen/AArch64/bitcast.ll | 2 - llvm/test/CodeGen/AArch64/bswap.ll | 1 - llvm/test/CodeGen/AArch64/fabs.ll | 26 +- llvm/test/CodeGen/AArch64/faddsub.ll | 62 ++-- llvm/test/CodeGen/AArch64/fcmp.ll | 286 ++++++++---------- llvm/test/CodeGen/AArch64/fcopysign.ll | 4 - llvm/test/CodeGen/AArch64/fcvt.ll | 182 +++++------ llvm/test/CodeGen/AArch64/fdiv.ll | 31 +- llvm/test/CodeGen/AArch64/fexplog.ll | 10 - llvm/test/CodeGen/AArch64/fminimummaximum.ll | 118 ++++---- llvm/test/CodeGen/AArch64/fminmax.ll | 118 ++++---- llvm/test/CodeGen/AArch64/fmla.ll | 164 +++++----- llvm/test/CodeGen/AArch64/fmul.ll | 31 +- llvm/test/CodeGen/AArch64/fneg.ll | 26 +- llvm/test/CodeGen/AArch64/fpext.ll | 2 - llvm/test/CodeGen/AArch64/fpow.ll | 2 - llvm/test/CodeGen/AArch64/fpowi.ll | 2 - llvm/test/CodeGen/AArch64/fptoi.ll | 20 -- llvm/test/CodeGen/AArch64/fptrunc.ll | 8 - llvm/test/CodeGen/AArch64/frem.ll | 2 - llvm/test/CodeGen/AArch64/fsincos.ll | 4 - llvm/test/CodeGen/AArch64/fsqrt.ll | 18 +- llvm/test/CodeGen/AArch64/icmp.ll | 14 +- llvm/test/CodeGen/AArch64/insertextract.ll | 4 - llvm/test/CodeGen/AArch64/itofp.ll | 60 ---- llvm/test/CodeGen/AArch64/llvm.exp10.ll | 11 +- llvm/test/CodeGen/AArch64/load.ll | 4 - llvm/test/CodeGen/AArch64/sext.ll | 7 - llvm/test/CodeGen/AArch64/shift.ll | 33 -- llvm/test/CodeGen/AArch64/shufflevector.ll | 26 +- llvm/test/CodeGen/AArch64/xtn.ll | 3 - llvm/test/CodeGen/AArch64/zext.ll | 13 +- 40 files changed, 545 insertions(+), 865 deletions(-) diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp index 0f3c3cb96e6c..7a49422c064b 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -5934,13 +5934,16 @@ bool AArch64InstructionSelector::selectBuildVector(MachineInstr &I, // Keep track of the last MI we inserted. Later on, we might be able to save // a copy using it. - MachineInstr *PrevMI = nullptr; + MachineInstr *PrevMI = ScalarToVec; for (unsigned i = 2, e = DstSize / EltSize + 1; i < e; ++i) { // Note that if we don't do a subregister copy, we can end up making an // extra register. - PrevMI = &*emitLaneInsert(std::nullopt, DstVec, I.getOperand(i).getReg(), - i - 1, RB, MIB); - DstVec = PrevMI->getOperand(0).getReg(); + Register OpReg = I.getOperand(i).getReg(); + // Do not emit inserts for undefs + if (!getOpcodeDef(OpReg, MRI)) { + PrevMI = &*emitLaneInsert(std::nullopt, DstVec, OpReg, i - 1, RB, MIB); + DstVec = PrevMI->getOperand(0).getReg(); + } } // If DstTy's size in bits is less than 128, then emit a subregister copy @@ -5973,11 +5976,27 @@ bool AArch64InstructionSelector::selectBuildVector(MachineInstr &I, RegOp.setReg(Reg); RBI.constrainGenericRegister(DstReg, *RC, MRI); } else { - // We don't need a subregister copy. Save a copy by re-using the - // destination register on the final insert. - assert(PrevMI && "PrevMI was null?"); + // We either have a vector with all elements (except the first one) undef or + // at least one non-undef non-first element. In the first case, we need to + // constrain the output register ourselves as we may have generated an + // INSERT_SUBREG operation which is a generic operation for which the + // output regclass cannot be automatically chosen. + // + // In the second case, there is no need to do this as it may generate an + // instruction like INSvi32gpr where the regclass can be automatically + // chosen. + // + // Also, we save a copy by re-using the destination register on the final + // insert. PrevMI->getOperand(0).setReg(I.getOperand(0).getReg()); constrainSelectedInstRegOperands(*PrevMI, TII, TRI, RBI); + + Register DstReg = PrevMI->getOperand(0).getReg(); + if (PrevMI == ScalarToVec && DstReg.isVirtual()) { + const TargetRegisterClass *RC = + getRegClassForTypeOnBank(DstTy, *RBI.getRegBank(DstVec, MRI, TRI)); + RBI.constrainGenericRegister(DstReg, *RC, MRI); + } } I.eraseFromParent(); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-build-vector.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-build-vector.mir index 5de97256fc85..71a2bd2ddcc6 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-build-vector.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-build-vector.mir @@ -266,12 +266,8 @@ body: | ; CHECK-LABEL: name: undef_elts_different_regbanks ; CHECK: liveins: $w0 ; CHECK: %val:gpr32all = COPY $w0 - ; CHECK: %undef:gpr32 = IMPLICIT_DEF ; CHECK: [[DEF:%[0-9]+]]:fpr128 = IMPLICIT_DEF - ; CHECK: [[INSERT_SUBREG:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF]], %val, %subreg.ssub - ; CHECK: [[INSvi32gpr:%[0-9]+]]:fpr128 = INSvi32gpr [[INSERT_SUBREG]], 1, %undef - ; CHECK: [[INSvi32gpr1:%[0-9]+]]:fpr128 = INSvi32gpr [[INSvi32gpr]], 2, %undef - ; CHECK: %bv:fpr128 = INSvi32gpr [[INSvi32gpr1]], 3, %undef + ; CHECK: %bv:fpr128 = INSERT_SUBREG [[DEF]], %val, %subreg.ssub ; CHECK: $q0 = COPY %bv ; CHECK: RET_ReallyLR implicit $q0 %val:gpr(s32) = COPY $w0 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-shufflevec-undef-mask-elt.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-shufflevec-undef-mask-elt.mir index 6e01723f4993..5f280ae2e302 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-shufflevec-undef-mask-elt.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-shufflevec-undef-mask-elt.mir @@ -19,20 +19,18 @@ body: | ; CHECK: liveins: $d0 ; CHECK: [[COPY:%[0-9]+]]:fpr64 = COPY $d0 ; CHECK: [[DEF:%[0-9]+]]:gpr32 = IMPLICIT_DEF - ; CHECK: [[DEF1:%[0-9]+]]:gpr32 = IMPLICIT_DEF - ; CHECK: [[DEF2:%[0-9]+]]:fpr128 = IMPLICIT_DEF - ; CHECK: [[INSERT_SUBREG:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF2]], [[DEF]], %subreg.ssub - ; CHECK: [[INSvi32gpr:%[0-9]+]]:fpr128 = INSvi32gpr [[INSERT_SUBREG]], 1, [[DEF1]] - ; CHECK: [[COPY1:%[0-9]+]]:fpr64 = COPY [[INSvi32gpr]].dsub + ; CHECK: [[DEF1:%[0-9]+]]:fpr128 = IMPLICIT_DEF + ; CHECK: [[INSERT_SUBREG:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF1]], [[DEF]], %subreg.ssub + ; CHECK: [[COPY1:%[0-9]+]]:fpr64 = COPY [[INSERT_SUBREG]].dsub ; CHECK: [[ADRP:%[0-9]+]]:gpr64common = ADRP target-flags(aarch64-page) %const.0 ; CHECK: [[LDRDui:%[0-9]+]]:fpr64 = LDRDui [[ADRP]], target-flags(aarch64-pageoff, aarch64-nc) %const.0 + ; CHECK: [[DEF2:%[0-9]+]]:fpr128 = IMPLICIT_DEF + ; CHECK: [[INSERT_SUBREG1:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF2]], [[COPY]], %subreg.dsub ; CHECK: [[DEF3:%[0-9]+]]:fpr128 = IMPLICIT_DEF - ; CHECK: [[INSERT_SUBREG1:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF3]], [[COPY]], %subreg.dsub - ; CHECK: [[DEF4:%[0-9]+]]:fpr128 = IMPLICIT_DEF - ; CHECK: [[INSERT_SUBREG2:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF4]], [[COPY1]], %subreg.dsub + ; CHECK: [[INSERT_SUBREG2:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF3]], [[COPY1]], %subreg.dsub ; CHECK: [[INSvi64lane:%[0-9]+]]:fpr128 = INSvi64lane [[INSERT_SUBREG1]], 1, [[INSERT_SUBREG2]], 0 - ; CHECK: [[DEF5:%[0-9]+]]:fpr128 = IMPLICIT_DEF - ; CHECK: [[INSERT_SUBREG3:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF5]], [[LDRDui]], %subreg.dsub + ; CHECK: [[DEF4:%[0-9]+]]:fpr128 = IMPLICIT_DEF + ; CHECK: [[INSERT_SUBREG3:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF4]], [[LDRDui]], %subreg.dsub ; CHECK: [[TBLv16i8One:%[0-9]+]]:fpr128 = TBLv16i8One [[INSvi64lane]], [[INSERT_SUBREG3]] ; CHECK: [[COPY2:%[0-9]+]]:fpr64 = COPY [[TBLv16i8One]].dsub ; CHECK: $d0 = COPY [[COPY2]] diff --git a/llvm/test/CodeGen/AArch64/aarch64-bif-gen.ll b/llvm/test/CodeGen/AArch64/aarch64-bif-gen.ll index 273bf559554c..f47da47002fb 100644 --- a/llvm/test/CodeGen/AArch64/aarch64-bif-gen.ll +++ b/llvm/test/CodeGen/AArch64/aarch64-bif-gen.ll @@ -77,7 +77,6 @@ define <1 x i32> @test_bitf_v1i32(<1 x i32> %A, <1 x i32> %B, <1 x i32> %C) { ; CHECK-GI-NEXT: and w8, w8, w10 ; CHECK-GI-NEXT: orr w8, w9, w8 ; CHECK-GI-NEXT: fmov s0, w8 -; CHECK-GI-NEXT: mov v0.s[1], w8 ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret %neg = xor <1 x i32> %C, diff --git a/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll b/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll index a92ae39c6972..5c006508d284 100644 --- a/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll +++ b/llvm/test/CodeGen/AArch64/aarch64-bit-gen.ll @@ -79,7 +79,6 @@ define <1 x i32> @test_bit_v1i32(<1 x i32> %A, <1 x i32> %B, <1 x i32> %C) { ; CHECK-GI-NEXT: bic w8, w10, w8 ; CHECK-GI-NEXT: orr w8, w9, w8 ; CHECK-GI-NEXT: fmov s0, w8 -; CHECK-GI-NEXT: mov v0.s[1], w8 ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret %and = and <1 x i32> %C, %B diff --git a/llvm/test/CodeGen/AArch64/abs.ll b/llvm/test/CodeGen/AArch64/abs.ll index f2cad6631dc2..e00f70b94e3b 100644 --- a/llvm/test/CodeGen/AArch64/abs.ll +++ b/llvm/test/CodeGen/AArch64/abs.ll @@ -252,7 +252,6 @@ define <1 x i32> @abs_v1i32(<1 x i32> %a){ ; CHECK-GI-NEXT: add w8, w8, w9 ; CHECK-GI-NEXT: eor w8, w8, w9 ; CHECK-GI-NEXT: fmov s0, w8 -; CHECK-GI-NEXT: mov v0.s[1], w8 ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret entry: @@ -308,11 +307,6 @@ define <3 x i8> @abs_v3i8(<3 x i8> %a){ ; CHECK-GI-NEXT: mov v0.b[1], v1.b[0] ; CHECK-GI-NEXT: fmov s1, w2 ; CHECK-GI-NEXT: mov v0.b[2], v1.b[0] -; CHECK-GI-NEXT: mov v0.b[3], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[4], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[5], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[6], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[7], v0.b[0] ; CHECK-GI-NEXT: abs v0.8b, v0.8b ; CHECK-GI-NEXT: umov w0, v0.b[0] ; CHECK-GI-NEXT: umov w1, v0.b[1] diff --git a/llvm/test/CodeGen/AArch64/arm64-dup.ll b/llvm/test/CodeGen/AArch64/arm64-dup.ll index 2112944cc847..2bf5419e5483 100644 --- a/llvm/test/CodeGen/AArch64/arm64-dup.ll +++ b/llvm/test/CodeGen/AArch64/arm64-dup.ll @@ -373,11 +373,9 @@ define <4 x i16> @test_build_illegal(<4 x i32> %in) { ; ; CHECK-GI-LABEL: test_build_illegal: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: mov.h v1[1], v0[0] ; CHECK-GI-NEXT: mov s0, v0[3] -; CHECK-GI-NEXT: mov.h v1[2], v0[0] -; CHECK-GI-NEXT: mov.h v1[3], v0[0] -; CHECK-GI-NEXT: fmov d0, d1 +; CHECK-GI-NEXT: mov.h v0[3], v0[0] +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret %val = extractelement <4 x i32> %in, i32 3 %smallval = trunc i32 %val to i16 diff --git a/llvm/test/CodeGen/AArch64/arm64-neon-copy.ll b/llvm/test/CodeGen/AArch64/arm64-neon-copy.ll index cc3d80008143..d282bee81827 100644 --- a/llvm/test/CodeGen/AArch64/arm64-neon-copy.ll +++ b/llvm/test/CodeGen/AArch64/arm64-neon-copy.ll @@ -1346,7 +1346,6 @@ define <2 x i32> @scalar_to_vector.v2i32(i32 %a) { ; CHECK-GI-LABEL: scalar_to_vector.v2i32: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: fmov s0, w0 -; CHECK-GI-NEXT: mov v0.s[1], w8 ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret %b = insertelement <2 x i32> undef, i32 %a, i32 0 @@ -1354,33 +1353,19 @@ define <2 x i32> @scalar_to_vector.v2i32(i32 %a) { } define <4 x i32> @scalar_to_vector.v4i32(i32 %a) { -; CHECK-SD-LABEL: scalar_to_vector.v4i32: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: fmov s0, w0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: scalar_to_vector.v4i32: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: fmov s0, w0 -; CHECK-GI-NEXT: mov v0.s[1], w8 -; CHECK-GI-NEXT: mov v0.s[2], w8 -; CHECK-GI-NEXT: mov v0.s[3], w8 -; CHECK-GI-NEXT: ret +; CHECK-LABEL: scalar_to_vector.v4i32: +; CHECK: // %bb.0: +; CHECK-NEXT: fmov s0, w0 +; CHECK-NEXT: ret %b = insertelement <4 x i32> undef, i32 %a, i32 0 ret <4 x i32> %b } define <2 x i64> @scalar_to_vector.v2i64(i64 %a) { -; CHECK-SD-LABEL: scalar_to_vector.v2i64: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: fmov d0, x0 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: scalar_to_vector.v2i64: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: fmov d0, x0 -; CHECK-GI-NEXT: mov v0.d[1], x8 -; CHECK-GI-NEXT: ret +; CHECK-LABEL: scalar_to_vector.v2i64: +; CHECK: // %bb.0: +; CHECK-NEXT: fmov d0, x0 +; CHECK-NEXT: ret %b = insertelement <2 x i64> undef, i64 %a, i32 0 ret <2 x i64> %b } @@ -1900,14 +1885,6 @@ define <16 x i8> @test_concat_v16i8_v8i8_v16i8(<8 x i8> %x, <16 x i8> %y) #0 { ; CHECK-GI-NEXT: mov v0.b[5], v6.b[0] ; CHECK-GI-NEXT: mov v0.b[6], v7.b[0] ; CHECK-GI-NEXT: mov v0.b[7], v16.b[0] -; CHECK-GI-NEXT: mov v0.b[8], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[9], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[10], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[11], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[12], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[13], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[14], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[15], v0.b[0] ; CHECK-GI-NEXT: tbl v0.16b, { v0.16b, v1.16b }, v2.16b ; CHECK-GI-NEXT: ret entry: @@ -2123,10 +2100,6 @@ define <8 x i16> @test_concat_v8i16_v4i16_v8i16(<4 x i16> %x, <8 x i16> %y) #0 { ; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI131_0] ; CHECK-GI-NEXT: mov v0.h[2], v3.h[0] ; CHECK-GI-NEXT: mov v0.h[3], v4.h[0] -; CHECK-GI-NEXT: mov v0.h[4], v0.h[0] -; CHECK-GI-NEXT: mov v0.h[5], v0.h[0] -; CHECK-GI-NEXT: mov v0.h[6], v0.h[0] -; CHECK-GI-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NEXT: tbl v0.16b, { v0.16b, v1.16b }, v2.16b ; CHECK-GI-NEXT: ret entry: @@ -2266,8 +2239,6 @@ define <4 x i32> @test_concat_v4i32_v2i32_v4i32(<2 x i32> %x, <4 x i32> %y) #0 { ; CHECK-GI-NEXT: mov s2, v0.s[1] ; CHECK-GI-NEXT: mov v0.s[1], v2.s[0] ; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI135_0] -; CHECK-GI-NEXT: mov v0.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NEXT: tbl v0.16b, { v0.16b, v1.16b }, v2.16b ; CHECK-GI-NEXT: ret entry: diff --git a/llvm/test/CodeGen/AArch64/bitcast.ll b/llvm/test/CodeGen/AArch64/bitcast.ll index a5551285f278..bccfdb93d786 100644 --- a/llvm/test/CodeGen/AArch64/bitcast.ll +++ b/llvm/test/CodeGen/AArch64/bitcast.ll @@ -21,7 +21,6 @@ define <4 x i16> @foo1(<2 x i32> %a) { ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: mov w8, #58712 // =0xe558 ; CHECK-GI-NEXT: fmov s1, w8 -; CHECK-GI-NEXT: mov v1.s[1], w8 ; CHECK-GI-NEXT: zip1 v0.2s, v1.2s, v0.2s ; CHECK-GI-NEXT: rev32 v0.4h, v0.4h ; CHECK-GI-NEXT: ret @@ -42,7 +41,6 @@ define <4 x i16> @foo2(<2 x i32> %a) { ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: mov w8, #712 // =0x2c8 ; CHECK-GI-NEXT: fmov s1, w8 -; CHECK-GI-NEXT: mov v1.s[1], w8 ; CHECK-GI-NEXT: zip1 v0.2s, v1.2s, v0.2s ; CHECK-GI-NEXT: rev32 v0.4h, v0.4h ; CHECK-GI-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/bswap.ll b/llvm/test/CodeGen/AArch64/bswap.ll index 9b065accce91..f4221accfcbc 100644 --- a/llvm/test/CodeGen/AArch64/bswap.ll +++ b/llvm/test/CodeGen/AArch64/bswap.ll @@ -137,7 +137,6 @@ define <1 x i32> @bswap_v1i32(<1 x i32> %a){ ; CHECK-GI-NEXT: fmov w8, s0 ; CHECK-GI-NEXT: rev w8, w8 ; CHECK-GI-NEXT: fmov s0, w8 -; CHECK-GI-NEXT: mov v0.s[1], w8 ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret entry: diff --git a/llvm/test/CodeGen/AArch64/fabs.ll b/llvm/test/CodeGen/AArch64/fabs.ll index 7c13b49246d2..de108b0bc2b7 100644 --- a/llvm/test/CodeGen/AArch64/fabs.ll +++ b/llvm/test/CodeGen/AArch64/fabs.ll @@ -160,21 +160,20 @@ define <7 x half> @fabs_v7f16(<7 x half> %a) { ; ; CHECK-GI-NOFP16-LABEL: fabs_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] -; CHECK-GI-NOFP16-NEXT: mov v1.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: fabs v2.4s, v3.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v2.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[6] +; CHECK-GI-NOFP16-NEXT: fabs v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v4.h[0] +; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h ; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[2] ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: fabs v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NOFP16-NEXT: fabs v1.4s, v2.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v3.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v1.4h, v1.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v4.h[0] @@ -183,7 +182,6 @@ define <7 x half> @fabs_v7f16(<7 x half> %a) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: fabs_v7f16: diff --git a/llvm/test/CodeGen/AArch64/faddsub.ll b/llvm/test/CodeGen/AArch64/faddsub.ll index f8970dc9e8d5..6913a62fb266 100644 --- a/llvm/test/CodeGen/AArch64/faddsub.ll +++ b/llvm/test/CodeGen/AArch64/faddsub.ll @@ -186,26 +186,24 @@ define <7 x half> @fadd_v7f16(<7 x half> %a, <7 x half> %b) { ; ; CHECK-GI-NOFP16-LABEL: fadd_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] -; CHECK-GI-NOFP16-NEXT: mov h4, v1.h[4] -; CHECK-GI-NOFP16-NEXT: mov h5, v1.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v6.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v7.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v1.4h +; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h5, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h6, v1.h[4] +; CHECK-GI-NOFP16-NEXT: mov h7, v1.h[5] ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[6] -; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NOFP16-NEXT: fadd v2.4s, v2.4s, v3.4s +; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[6] ; CHECK-GI-NOFP16-NEXT: mov v4.h[1], v5.h[0] -; CHECK-GI-NOFP16-NEXT: fadd v3.4s, v6.4s, v7.4s -; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[2], v1.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v3.4s -; CHECK-GI-NOFP16-NEXT: mov v2.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[3], v0.h[0] +; CHECK-GI-NOFP16-NEXT: mov v6.h[1], v7.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v2.4s +; CHECK-GI-NOFP16-NEXT: mov v4.h[2], v3.h[0] +; CHECK-GI-NOFP16-NEXT: mov v6.h[2], v1.h[0] ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov h5, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v4.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v4.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v6.4h ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-NOFP16-NEXT: fadd v1.4s, v2.4s, v3.4s @@ -217,7 +215,6 @@ define <7 x half> @fadd_v7f16(<7 x half> %a, <7 x half> %b) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: fadd_v7f16: @@ -538,26 +535,24 @@ define <7 x half> @fsub_v7f16(<7 x half> %a, <7 x half> %b) { ; ; CHECK-GI-NOFP16-LABEL: fsub_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] -; CHECK-GI-NOFP16-NEXT: mov h4, v1.h[4] -; CHECK-GI-NOFP16-NEXT: mov h5, v1.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v6.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v7.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v1.4h +; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h5, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h6, v1.h[4] +; CHECK-GI-NOFP16-NEXT: mov h7, v1.h[5] ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[6] -; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NOFP16-NEXT: fsub v2.4s, v2.4s, v3.4s +; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[6] ; CHECK-GI-NOFP16-NEXT: mov v4.h[1], v5.h[0] -; CHECK-GI-NOFP16-NEXT: fsub v3.4s, v6.4s, v7.4s -; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[2], v1.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v3.4s -; CHECK-GI-NOFP16-NEXT: mov v2.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[3], v0.h[0] +; CHECK-GI-NOFP16-NEXT: mov v6.h[1], v7.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v2.4s +; CHECK-GI-NOFP16-NEXT: mov v4.h[2], v3.h[0] +; CHECK-GI-NOFP16-NEXT: mov v6.h[2], v1.h[0] ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov h5, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v4.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v4.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v6.4h ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-NOFP16-NEXT: fsub v1.4s, v2.4s, v3.4s @@ -569,7 +564,6 @@ define <7 x half> @fsub_v7f16(<7 x half> %a, <7 x half> %b) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: fsub_v7f16: diff --git a/llvm/test/CodeGen/AArch64/fcmp.ll b/llvm/test/CodeGen/AArch64/fcmp.ll index 0f02784aaf32..2d0b5574cdd7 100644 --- a/llvm/test/CodeGen/AArch64/fcmp.ll +++ b/llvm/test/CodeGen/AArch64/fcmp.ll @@ -262,31 +262,28 @@ define <3 x i32> @v3f64_i32(<3 x double> %a, <3 x double> %b, <3 x i32> %d, <3 x ; ; CHECK-GI-LABEL: v3f64_i32: ; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: mov w8, #31 // =0x1f -; CHECK-GI-NEXT: fcmp d2, d5 ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 ; CHECK-GI-NEXT: // kill: def $d3 killed $d3 def $q3 +; CHECK-GI-NEXT: mov w8, #31 // =0x1f ; CHECK-GI-NEXT: // kill: def $d4 killed $d4 def $q4 -; CHECK-GI-NEXT: fmov s16, w8 +; CHECK-GI-NEXT: fcmp d2, d5 ; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] ; CHECK-GI-NEXT: mov v3.d[1], v4.d[0] +; CHECK-GI-NEXT: fmov s1, w8 ; CHECK-GI-NEXT: cset w9, mi -; CHECK-GI-NEXT: mov v16.s[1], w8 -; CHECK-GI-NEXT: fmov d1, x9 +; CHECK-GI-NEXT: mov v1.s[1], w8 +; CHECK-GI-NEXT: fmov d2, x9 ; CHECK-GI-NEXT: fcmgt v0.2d, v3.2d, v0.2d -; CHECK-GI-NEXT: mov v1.d[1], x8 -; CHECK-GI-NEXT: mov v16.s[2], w8 +; CHECK-GI-NEXT: mov v1.s[2], w8 ; CHECK-GI-NEXT: mov w8, #-1 // =0xffffffff +; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v2.4s ; CHECK-GI-NEXT: fmov s2, w8 -; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s ; CHECK-GI-NEXT: mov v2.s[1], w8 -; CHECK-GI-NEXT: mov v16.s[3], w8 +; CHECK-GI-NEXT: neg v3.4s, v1.4s +; CHECK-GI-NEXT: ushl v0.4s, v0.4s, v1.4s ; CHECK-GI-NEXT: mov v2.s[2], w8 -; CHECK-GI-NEXT: neg v1.4s, v16.4s -; CHECK-GI-NEXT: ushl v0.4s, v0.4s, v16.4s -; CHECK-GI-NEXT: mov v2.s[3], w8 -; CHECK-GI-NEXT: sshl v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: sshl v0.4s, v0.4s, v3.4s ; CHECK-GI-NEXT: eor v1.16b, v0.16b, v2.16b ; CHECK-GI-NEXT: and v0.16b, v6.16b, v0.16b ; CHECK-GI-NEXT: and v1.16b, v7.16b, v1.16b @@ -349,15 +346,13 @@ define <3 x float> @v3f32_float(<3 x float> %a, <3 x float> %b, <3 x float> %d, ; CHECK-GI-NEXT: mov v4.s[1], w8 ; CHECK-GI-NEXT: mov v4.s[2], w8 ; CHECK-GI-NEXT: mov w8, #-1 // =0xffffffff -; CHECK-GI-NEXT: fmov s5, w8 -; CHECK-GI-NEXT: mov v5.s[1], w8 -; CHECK-GI-NEXT: mov v4.s[3], w8 -; CHECK-GI-NEXT: mov v5.s[2], w8 -; CHECK-GI-NEXT: neg v1.4s, v4.4s +; CHECK-GI-NEXT: fmov s1, w8 +; CHECK-GI-NEXT: mov v1.s[1], w8 +; CHECK-GI-NEXT: neg v5.4s, v4.4s ; CHECK-GI-NEXT: ushl v0.4s, v0.4s, v4.4s -; CHECK-GI-NEXT: mov v5.s[3], w8 -; CHECK-GI-NEXT: sshl v0.4s, v0.4s, v1.4s -; CHECK-GI-NEXT: eor v1.16b, v0.16b, v5.16b +; CHECK-GI-NEXT: mov v1.s[2], w8 +; CHECK-GI-NEXT: sshl v0.4s, v0.4s, v5.4s +; CHECK-GI-NEXT: eor v1.16b, v0.16b, v1.16b ; CHECK-GI-NEXT: and v0.16b, v2.16b, v0.16b ; CHECK-GI-NEXT: and v1.16b, v3.16b, v1.16b ; CHECK-GI-NEXT: orr v0.16b, v0.16b, v1.16b @@ -429,15 +424,13 @@ define <3 x i32> @v3f32_i32(<3 x float> %a, <3 x float> %b, <3 x i32> %d, <3 x i ; CHECK-GI-NEXT: mov v4.s[1], w8 ; CHECK-GI-NEXT: mov v4.s[2], w8 ; CHECK-GI-NEXT: mov w8, #-1 // =0xffffffff -; CHECK-GI-NEXT: fmov s5, w8 -; CHECK-GI-NEXT: mov v5.s[1], w8 -; CHECK-GI-NEXT: mov v4.s[3], w8 -; CHECK-GI-NEXT: mov v5.s[2], w8 -; CHECK-GI-NEXT: neg v1.4s, v4.4s +; CHECK-GI-NEXT: fmov s1, w8 +; CHECK-GI-NEXT: mov v1.s[1], w8 +; CHECK-GI-NEXT: neg v5.4s, v4.4s ; CHECK-GI-NEXT: ushl v0.4s, v0.4s, v4.4s -; CHECK-GI-NEXT: mov v5.s[3], w8 -; CHECK-GI-NEXT: sshl v0.4s, v0.4s, v1.4s -; CHECK-GI-NEXT: eor v1.16b, v0.16b, v5.16b +; CHECK-GI-NEXT: mov v1.s[2], w8 +; CHECK-GI-NEXT: sshl v0.4s, v0.4s, v5.4s +; CHECK-GI-NEXT: eor v1.16b, v0.16b, v1.16b ; CHECK-GI-NEXT: and v0.16b, v2.16b, v0.16b ; CHECK-GI-NEXT: and v1.16b, v3.16b, v1.16b ; CHECK-GI-NEXT: orr v0.16b, v0.16b, v1.16b @@ -554,44 +547,40 @@ define <7 x half> @v7f16_half(<7 x half> %a, <7 x half> %b, <7 x half> %d, <7 x ; CHECK-GI-NOFP16-NEXT: mov w8, #15 // =0xf ; CHECK-GI-NOFP16-NEXT: mov h6, v0.h[4] ; CHECK-GI-NOFP16-NEXT: mov h7, v0.h[5] -; CHECK-GI-NOFP16-NEXT: fmov s5, w8 +; CHECK-GI-NOFP16-NEXT: fmov s4, w8 ; CHECK-GI-NOFP16-NEXT: mov h16, v1.h[4] ; CHECK-GI-NOFP16-NEXT: mov w8, #65535 // =0xffff ; CHECK-GI-NOFP16-NEXT: mov h17, v1.h[5] ; CHECK-GI-NOFP16-NEXT: mov h18, v0.h[6] ; CHECK-GI-NOFP16-NEXT: mov h19, v1.h[6] +; CHECK-GI-NOFP16-NEXT: fcvtl v0.4s, v0.4h ; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: mov v4.16b, v5.16b +; CHECK-GI-NOFP16-NEXT: mov v5.16b, v4.16b ; CHECK-GI-NOFP16-NEXT: mov v6.h[1], v7.h[0] ; CHECK-GI-NOFP16-NEXT: fmov s7, w8 ; CHECK-GI-NOFP16-NEXT: mov v16.h[1], v17.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[1], v5.h[0] +; CHECK-GI-NOFP16-NEXT: mov v5.h[1], v4.h[0] ; CHECK-GI-NOFP16-NEXT: mov v17.16b, v7.16b +; CHECK-GI-NOFP16-NEXT: fcmgt v0.4s, v1.4s, v0.4s ; CHECK-GI-NOFP16-NEXT: mov v6.h[2], v18.h[0] ; CHECK-GI-NOFP16-NEXT: mov v17.h[1], v7.h[0] ; CHECK-GI-NOFP16-NEXT: mov v16.h[2], v19.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[2], v5.h[0] -; CHECK-GI-NOFP16-NEXT: mov v6.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v17.h[2], v7.h[0] -; CHECK-GI-NOFP16-NEXT: mov v16.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtl v0.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: mov v4.h[3], v5.h[0] +; CHECK-GI-NOFP16-NEXT: mov v5.h[2], v4.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtl v6.4s, v6.4h -; CHECK-GI-NOFP16-NEXT: mov v17.h[3], v7.h[0] +; CHECK-GI-NOFP16-NEXT: mov v17.h[2], v7.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtl v16.4s, v16.4h -; CHECK-GI-NOFP16-NEXT: fcmgt v0.4s, v1.4s, v0.4s -; CHECK-GI-NOFP16-NEXT: mov v4.h[4], v5.h[0] -; CHECK-GI-NOFP16-NEXT: mov v17.h[4], v7.h[0] +; CHECK-GI-NOFP16-NEXT: mov v5.h[3], v4.h[0] +; CHECK-GI-NOFP16-NEXT: mov v17.h[3], v7.h[0] ; CHECK-GI-NOFP16-NEXT: fcmgt v1.4s, v16.4s, v6.4s -; CHECK-GI-NOFP16-NEXT: mov v4.h[5], v5.h[0] +; CHECK-GI-NOFP16-NEXT: mov v5.h[4], v4.h[0] +; CHECK-GI-NOFP16-NEXT: mov v17.h[4], v7.h[0] +; CHECK-GI-NOFP16-NEXT: uzp1 v0.8h, v0.8h, v1.8h +; CHECK-GI-NOFP16-NEXT: mov v5.h[5], v4.h[0] ; CHECK-GI-NOFP16-NEXT: mov v17.h[5], v7.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[6], v5.h[0] +; CHECK-GI-NOFP16-NEXT: mov v5.h[6], v4.h[0] ; CHECK-GI-NOFP16-NEXT: mov v17.h[6], v7.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[7], v0.h[0] -; CHECK-GI-NOFP16-NEXT: uzp1 v0.8h, v0.8h, v1.8h -; CHECK-GI-NOFP16-NEXT: neg v1.8h, v4.8h -; CHECK-GI-NOFP16-NEXT: ushl v0.8h, v0.8h, v4.8h -; CHECK-GI-NOFP16-NEXT: mov v17.h[7], v0.h[0] +; CHECK-GI-NOFP16-NEXT: neg v1.8h, v5.8h +; CHECK-GI-NOFP16-NEXT: ushl v0.8h, v0.8h, v5.8h ; CHECK-GI-NOFP16-NEXT: sshl v0.8h, v0.8h, v1.8h ; CHECK-GI-NOFP16-NEXT: eor v1.16b, v0.16b, v17.16b ; CHECK-GI-NOFP16-NEXT: and v0.16b, v2.16b, v0.16b @@ -602,6 +591,7 @@ define <7 x half> @v7f16_half(<7 x half> %a, <7 x half> %b, <7 x half> %d, <7 x ; CHECK-GI-FP16-LABEL: v7f16_half: ; CHECK-GI-FP16: // %bb.0: // %entry ; CHECK-GI-FP16-NEXT: mov w8, #15 // =0xf +; CHECK-GI-FP16-NEXT: fcmgt v0.8h, v1.8h, v0.8h ; CHECK-GI-FP16-NEXT: fmov s4, w8 ; CHECK-GI-FP16-NEXT: mov w8, #65535 // =0xffff ; CHECK-GI-FP16-NEXT: fmov s6, w8 @@ -619,11 +609,8 @@ define <7 x half> @v7f16_half(<7 x half> %a, <7 x half> %b, <7 x half> %d, <7 x ; CHECK-GI-FP16-NEXT: mov v7.h[5], v6.h[0] ; CHECK-GI-FP16-NEXT: mov v5.h[6], v4.h[0] ; CHECK-GI-FP16-NEXT: mov v7.h[6], v6.h[0] -; CHECK-GI-FP16-NEXT: mov v5.h[7], v0.h[0] -; CHECK-GI-FP16-NEXT: fcmgt v0.8h, v1.8h, v0.8h ; CHECK-GI-FP16-NEXT: neg v1.8h, v5.8h ; CHECK-GI-FP16-NEXT: ushl v0.8h, v0.8h, v5.8h -; CHECK-GI-FP16-NEXT: mov v7.h[7], v0.h[0] ; CHECK-GI-FP16-NEXT: sshl v0.8h, v0.8h, v1.8h ; CHECK-GI-FP16-NEXT: eor v1.16b, v0.16b, v7.16b ; CHECK-GI-FP16-NEXT: and v0.16b, v2.16b, v0.16b @@ -1054,69 +1041,63 @@ define <7 x i32> @v7f16_i32(<7 x half> %a, <7 x half> %b, <7 x i32> %d, <7 x i32 ; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] ; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] ; CHECK-GI-NOFP16-NEXT: mov w8, #31 // =0x1f -; CHECK-GI-NOFP16-NEXT: mov h5, v1.h[4] -; CHECK-GI-NOFP16-NEXT: mov h4, v1.h[5] -; CHECK-GI-NOFP16-NEXT: ldr s16, [sp, #32] +; CHECK-GI-NOFP16-NEXT: mov h4, v1.h[4] +; CHECK-GI-NOFP16-NEXT: mov h5, v1.h[5] +; CHECK-GI-NOFP16-NEXT: ldr s17, [sp, #32] ; CHECK-GI-NOFP16-NEXT: mov h6, v0.h[6] ; CHECK-GI-NOFP16-NEXT: mov h7, v1.h[6] -; CHECK-GI-NOFP16-NEXT: ldr s18, [sp, #40] -; CHECK-GI-NOFP16-NEXT: fmov s17, w4 +; CHECK-GI-NOFP16-NEXT: fmov s16, w0 +; CHECK-GI-NOFP16-NEXT: fcvtl v0.4s, v0.4h ; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v1.4h ; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] -; CHECK-GI-NOFP16-NEXT: mov v5.h[1], v4.h[0] -; CHECK-GI-NOFP16-NEXT: fmov s4, w8 -; CHECK-GI-NOFP16-NEXT: mov v17.s[1], w5 -; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v6.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.s[1], w8 -; CHECK-GI-NOFP16-NEXT: mov v5.h[2], v7.h[0] -; CHECK-GI-NOFP16-NEXT: ldr s7, [sp] -; CHECK-GI-NOFP16-NEXT: mov v17.s[2], w6 -; CHECK-GI-NOFP16-NEXT: fmov w9, s7 -; CHECK-GI-NOFP16-NEXT: fmov s7, w7 -; CHECK-GI-NOFP16-NEXT: mov v2.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.s[2], w8 -; CHECK-GI-NOFP16-NEXT: mov w8, #-1 // =0xffffffff -; CHECK-GI-NOFP16-NEXT: mov v5.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: fmov s3, w8 -; CHECK-GI-NOFP16-NEXT: fcvtl v0.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: mov v7.s[1], w9 -; CHECK-GI-NOFP16-NEXT: fcvtl v6.4s, v2.4h +; CHECK-GI-NOFP16-NEXT: mov v4.h[1], v5.h[0] +; CHECK-GI-NOFP16-NEXT: ldr s5, [sp] +; CHECK-GI-NOFP16-NEXT: mov v16.s[1], w1 ; CHECK-GI-NOFP16-NEXT: mov v3.s[1], w8 -; CHECK-GI-NOFP16-NEXT: ldr s2, [sp, #24] -; CHECK-GI-NOFP16-NEXT: fcvtl v5.4s, v5.4h -; CHECK-GI-NOFP16-NEXT: mov v4.s[3], w8 +; CHECK-GI-NOFP16-NEXT: fmov w9, s5 +; CHECK-GI-NOFP16-NEXT: fmov s5, w7 +; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v6.h[0] +; CHECK-GI-NOFP16-NEXT: ldr s6, [sp, #8] ; CHECK-GI-NOFP16-NEXT: fcmgt v0.4s, v1.4s, v0.4s -; CHECK-GI-NOFP16-NEXT: mov v2.s[1], v16.s[0] -; CHECK-GI-NOFP16-NEXT: ldr s16, [sp, #8] +; CHECK-GI-NOFP16-NEXT: mov v4.h[2], v7.h[0] +; CHECK-GI-NOFP16-NEXT: ldr s7, [sp, #24] +; CHECK-GI-NOFP16-NEXT: mov v16.s[2], w2 +; CHECK-GI-NOFP16-NEXT: mov v5.s[1], w9 +; CHECK-GI-NOFP16-NEXT: fmov w9, s6 +; CHECK-GI-NOFP16-NEXT: ldr s6, [sp, #16] ; CHECK-GI-NOFP16-NEXT: mov v3.s[2], w8 -; CHECK-GI-NOFP16-NEXT: fmov w8, s16 -; CHECK-GI-NOFP16-NEXT: fcmgt v5.4s, v5.4s, v6.4s -; CHECK-GI-NOFP16-NEXT: fmov s6, w0 -; CHECK-GI-NOFP16-NEXT: neg v19.4s, v4.4s -; CHECK-GI-NOFP16-NEXT: mov v2.s[2], v18.s[0] -; CHECK-GI-NOFP16-NEXT: mov v7.s[2], w8 -; CHECK-GI-NOFP16-NEXT: mov v17.s[3], w8 -; CHECK-GI-NOFP16-NEXT: mov v6.s[1], w1 -; CHECK-GI-NOFP16-NEXT: mov v3.s[3], w8 -; CHECK-GI-NOFP16-NEXT: ushl v4.4s, v5.4s, v4.4s -; CHECK-GI-NOFP16-NEXT: ldr s5, [sp, #16] -; CHECK-GI-NOFP16-NEXT: mov v2.s[3], v0.s[0] -; CHECK-GI-NOFP16-NEXT: fmov w8, s5 -; CHECK-GI-NOFP16-NEXT: mov v6.s[2], w2 -; CHECK-GI-NOFP16-NEXT: sshl v4.4s, v4.4s, v19.4s -; CHECK-GI-NOFP16-NEXT: mov v7.s[3], w8 -; CHECK-GI-NOFP16-NEXT: eor v1.16b, v4.16b, v3.16b -; CHECK-GI-NOFP16-NEXT: and v3.16b, v17.16b, v4.16b -; CHECK-GI-NOFP16-NEXT: mov v6.s[3], w3 -; CHECK-GI-NOFP16-NEXT: and v1.16b, v2.16b, v1.16b -; CHECK-GI-NOFP16-NEXT: bsl v0.16b, v6.16b, v7.16b -; CHECK-GI-NOFP16-NEXT: orr v1.16b, v3.16b, v1.16b +; CHECK-GI-NOFP16-NEXT: mov w8, #-1 // =0xffffffff +; CHECK-GI-NOFP16-NEXT: mov v7.s[1], v17.s[0] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h +; CHECK-GI-NOFP16-NEXT: ldr s17, [sp, #40] +; CHECK-GI-NOFP16-NEXT: fcvtl v4.4s, v4.4h +; CHECK-GI-NOFP16-NEXT: mov v16.s[3], w3 +; CHECK-GI-NOFP16-NEXT: mov v5.s[2], w9 +; CHECK-GI-NOFP16-NEXT: neg v18.4s, v3.4s +; CHECK-GI-NOFP16-NEXT: mov v7.s[2], v17.s[0] +; CHECK-GI-NOFP16-NEXT: fcmgt v2.4s, v4.4s, v2.4s +; CHECK-GI-NOFP16-NEXT: fmov s4, w8 +; CHECK-GI-NOFP16-NEXT: mov v4.s[1], w8 +; CHECK-GI-NOFP16-NEXT: ushl v2.4s, v2.4s, v3.4s +; CHECK-GI-NOFP16-NEXT: fmov s3, w4 +; CHECK-GI-NOFP16-NEXT: mov v3.s[1], w5 +; CHECK-GI-NOFP16-NEXT: mov v4.s[2], w8 +; CHECK-GI-NOFP16-NEXT: sshl v2.4s, v2.4s, v18.4s +; CHECK-GI-NOFP16-NEXT: fmov w8, s6 +; CHECK-GI-NOFP16-NEXT: mov v3.s[2], w6 +; CHECK-GI-NOFP16-NEXT: eor v1.16b, v2.16b, v4.16b +; CHECK-GI-NOFP16-NEXT: mov v5.s[3], w8 +; CHECK-GI-NOFP16-NEXT: and v1.16b, v7.16b, v1.16b +; CHECK-GI-NOFP16-NEXT: and v2.16b, v3.16b, v2.16b +; CHECK-GI-NOFP16-NEXT: bsl v0.16b, v16.16b, v5.16b +; CHECK-GI-NOFP16-NEXT: orr v1.16b, v2.16b, v1.16b ; CHECK-GI-NOFP16-NEXT: mov s2, v0.s[1] ; CHECK-GI-NOFP16-NEXT: mov s3, v0.s[2] ; CHECK-GI-NOFP16-NEXT: mov s4, v0.s[3] +; CHECK-GI-NOFP16-NEXT: fmov w0, s0 ; CHECK-GI-NOFP16-NEXT: mov s5, v1.s[1] ; CHECK-GI-NOFP16-NEXT: mov s6, v1.s[2] -; CHECK-GI-NOFP16-NEXT: fmov w0, s0 ; CHECK-GI-NOFP16-NEXT: fmov w4, s1 ; CHECK-GI-NOFP16-NEXT: fmov w1, s2 ; CHECK-GI-NOFP16-NEXT: fmov w2, s3 @@ -1127,65 +1108,60 @@ define <7 x i32> @v7f16_i32(<7 x half> %a, <7 x half> %b, <7 x i32> %d, <7 x i32 ; ; CHECK-GI-FP16-LABEL: v7f16_i32: ; CHECK-GI-FP16: // %bb.0: // %entry -; CHECK-GI-FP16-NEXT: fcmgt v5.8h, v1.8h, v0.8h -; CHECK-GI-FP16-NEXT: mov w10, #31 // =0x1f -; CHECK-GI-FP16-NEXT: ldr s6, [sp] -; CHECK-GI-FP16-NEXT: fmov s2, w10 -; CHECK-GI-FP16-NEXT: ldr s1, [sp, #24] -; CHECK-GI-FP16-NEXT: ldr s7, [sp, #32] -; CHECK-GI-FP16-NEXT: fmov s16, w0 -; CHECK-GI-FP16-NEXT: ldr s17, [sp, #40] -; CHECK-GI-FP16-NEXT: mov v1.s[1], v7.s[0] -; CHECK-GI-FP16-NEXT: ldr s7, [sp, #8] -; CHECK-GI-FP16-NEXT: umov w8, v5.h[4] -; CHECK-GI-FP16-NEXT: umov w9, v5.h[5] -; CHECK-GI-FP16-NEXT: umov w11, v5.h[0] -; CHECK-GI-FP16-NEXT: umov w12, v5.h[1] -; CHECK-GI-FP16-NEXT: mov v2.s[1], w10 -; CHECK-GI-FP16-NEXT: mov v16.s[1], w1 -; CHECK-GI-FP16-NEXT: mov v1.s[2], v17.s[0] -; CHECK-GI-FP16-NEXT: fmov s3, w8 -; CHECK-GI-FP16-NEXT: umov w8, v5.h[6] -; CHECK-GI-FP16-NEXT: fmov s0, w11 -; CHECK-GI-FP16-NEXT: mov v2.s[2], w10 -; CHECK-GI-FP16-NEXT: umov w10, v5.h[3] -; CHECK-GI-FP16-NEXT: mov v16.s[2], w2 -; CHECK-GI-FP16-NEXT: mov v3.s[1], w9 -; CHECK-GI-FP16-NEXT: umov w9, v5.h[2] -; CHECK-GI-FP16-NEXT: mov v0.s[1], w12 -; CHECK-GI-FP16-NEXT: fmov s5, w4 -; CHECK-GI-FP16-NEXT: mov v16.s[3], w3 +; CHECK-GI-FP16-NEXT: fcmgt v1.8h, v1.8h, v0.8h +; CHECK-GI-FP16-NEXT: mov w12, #31 // =0x1f +; CHECK-GI-FP16-NEXT: ldr s4, [sp] +; CHECK-GI-FP16-NEXT: fmov s2, w12 +; CHECK-GI-FP16-NEXT: fmov s6, w0 +; CHECK-GI-FP16-NEXT: ldr s5, [sp, #8] +; CHECK-GI-FP16-NEXT: ldr s7, [sp, #24] +; CHECK-GI-FP16-NEXT: ldr s16, [sp, #32] +; CHECK-GI-FP16-NEXT: umov w9, v1.h[4] +; CHECK-GI-FP16-NEXT: umov w8, v1.h[0] +; CHECK-GI-FP16-NEXT: umov w11, v1.h[5] +; CHECK-GI-FP16-NEXT: umov w10, v1.h[1] +; CHECK-GI-FP16-NEXT: mov v2.s[1], w12 +; CHECK-GI-FP16-NEXT: umov w13, v1.h[2] +; CHECK-GI-FP16-NEXT: mov v6.s[1], w1 +; CHECK-GI-FP16-NEXT: mov v7.s[1], v16.s[0] +; CHECK-GI-FP16-NEXT: ldr s16, [sp, #40] +; CHECK-GI-FP16-NEXT: fmov s3, w9 +; CHECK-GI-FP16-NEXT: fmov s0, w8 +; CHECK-GI-FP16-NEXT: umov w8, v1.h[6] +; CHECK-GI-FP16-NEXT: mov v2.s[2], w12 +; CHECK-GI-FP16-NEXT: umov w9, v1.h[3] +; CHECK-GI-FP16-NEXT: mov v6.s[2], w2 +; CHECK-GI-FP16-NEXT: mov v7.s[2], v16.s[0] +; CHECK-GI-FP16-NEXT: mov v3.s[1], w11 +; CHECK-GI-FP16-NEXT: mov v0.s[1], w10 +; CHECK-GI-FP16-NEXT: mov w10, #-1 // =0xffffffff +; CHECK-GI-FP16-NEXT: fmov s1, w10 +; CHECK-GI-FP16-NEXT: neg v17.4s, v2.4s +; CHECK-GI-FP16-NEXT: mov v6.s[3], w3 ; CHECK-GI-FP16-NEXT: mov v3.s[2], w8 -; CHECK-GI-FP16-NEXT: mov w8, #-1 // =0xffffffff -; CHECK-GI-FP16-NEXT: mov v0.s[2], w9 -; CHECK-GI-FP16-NEXT: fmov s4, w8 -; CHECK-GI-FP16-NEXT: mov v2.s[3], w8 -; CHECK-GI-FP16-NEXT: mov v5.s[1], w5 -; CHECK-GI-FP16-NEXT: fmov w9, s6 -; CHECK-GI-FP16-NEXT: fmov s6, w7 +; CHECK-GI-FP16-NEXT: fmov w8, s4 +; CHECK-GI-FP16-NEXT: fmov s4, w7 +; CHECK-GI-FP16-NEXT: mov v0.s[2], w13 +; CHECK-GI-FP16-NEXT: mov v1.s[1], w10 ; CHECK-GI-FP16-NEXT: mov v4.s[1], w8 -; CHECK-GI-FP16-NEXT: mov v3.s[3], w8 -; CHECK-GI-FP16-NEXT: mov v0.s[3], w10 -; CHECK-GI-FP16-NEXT: mov v6.s[1], w9 -; CHECK-GI-FP16-NEXT: neg v18.4s, v2.4s -; CHECK-GI-FP16-NEXT: mov v5.s[2], w6 -; CHECK-GI-FP16-NEXT: mov v4.s[2], w8 -; CHECK-GI-FP16-NEXT: fmov w8, s7 +; CHECK-GI-FP16-NEXT: fmov w8, s5 +; CHECK-GI-FP16-NEXT: ldr s5, [sp, #16] ; CHECK-GI-FP16-NEXT: ushl v2.4s, v3.4s, v2.4s -; CHECK-GI-FP16-NEXT: ldr s3, [sp, #16] +; CHECK-GI-FP16-NEXT: fmov s3, w4 +; CHECK-GI-FP16-NEXT: mov v0.s[3], w9 +; CHECK-GI-FP16-NEXT: mov v1.s[2], w10 +; CHECK-GI-FP16-NEXT: mov v3.s[1], w5 +; CHECK-GI-FP16-NEXT: mov v4.s[2], w8 +; CHECK-GI-FP16-NEXT: sshl v2.4s, v2.4s, v17.4s +; CHECK-GI-FP16-NEXT: fmov w8, s5 ; CHECK-GI-FP16-NEXT: shl v0.4s, v0.4s, #31 -; CHECK-GI-FP16-NEXT: mov v6.s[2], w8 -; CHECK-GI-FP16-NEXT: sshl v2.4s, v2.4s, v18.4s -; CHECK-GI-FP16-NEXT: mov v5.s[3], w8 +; CHECK-GI-FP16-NEXT: eor v1.16b, v2.16b, v1.16b +; CHECK-GI-FP16-NEXT: mov v3.s[2], w6 ; CHECK-GI-FP16-NEXT: mov v4.s[3], w8 -; CHECK-GI-FP16-NEXT: fmov w8, s3 -; CHECK-GI-FP16-NEXT: mov v1.s[3], v0.s[0] ; CHECK-GI-FP16-NEXT: sshr v0.4s, v0.4s, #31 -; CHECK-GI-FP16-NEXT: mov v6.s[3], w8 -; CHECK-GI-FP16-NEXT: eor v3.16b, v2.16b, v4.16b -; CHECK-GI-FP16-NEXT: and v2.16b, v5.16b, v2.16b -; CHECK-GI-FP16-NEXT: and v1.16b, v1.16b, v3.16b -; CHECK-GI-FP16-NEXT: bsl v0.16b, v16.16b, v6.16b +; CHECK-GI-FP16-NEXT: and v1.16b, v7.16b, v1.16b +; CHECK-GI-FP16-NEXT: and v2.16b, v3.16b, v2.16b +; CHECK-GI-FP16-NEXT: bsl v0.16b, v6.16b, v4.16b ; CHECK-GI-FP16-NEXT: orr v1.16b, v2.16b, v1.16b ; CHECK-GI-FP16-NEXT: mov s2, v0.s[1] ; CHECK-GI-FP16-NEXT: mov s3, v0.s[2] diff --git a/llvm/test/CodeGen/AArch64/fcopysign.ll b/llvm/test/CodeGen/AArch64/fcopysign.ll index 78fd38ca9f26..84376107679d 100644 --- a/llvm/test/CodeGen/AArch64/fcopysign.ll +++ b/llvm/test/CodeGen/AArch64/fcopysign.ll @@ -162,8 +162,6 @@ define <3 x float> @copysign_v3f32(<3 x float> %a, <3 x float> %b) { ; CHECK-GI-NEXT: mov v3.s[1], w8 ; CHECK-GI-NEXT: mov v2.s[2], w9 ; CHECK-GI-NEXT: mov v3.s[2], w8 -; CHECK-GI-NEXT: mov v2.s[3], w8 -; CHECK-GI-NEXT: mov v3.s[3], w8 ; CHECK-GI-NEXT: and v0.16b, v0.16b, v2.16b ; CHECK-GI-NEXT: and v1.16b, v1.16b, v3.16b ; CHECK-GI-NEXT: orr v0.16b, v0.16b, v1.16b @@ -223,8 +221,6 @@ define <7 x half> @copysign_v7f16(<7 x half> %a, <7 x half> %b) { ; CHECK-GI-NEXT: mov v5.h[5], v3.h[0] ; CHECK-GI-NEXT: mov v4.h[6], v2.h[0] ; CHECK-GI-NEXT: mov v5.h[6], v3.h[0] -; CHECK-GI-NEXT: mov v4.h[7], v0.h[0] -; CHECK-GI-NEXT: mov v5.h[7], v0.h[0] ; CHECK-GI-NEXT: and v0.16b, v0.16b, v4.16b ; CHECK-GI-NEXT: and v1.16b, v1.16b, v5.16b ; CHECK-GI-NEXT: orr v0.16b, v0.16b, v1.16b diff --git a/llvm/test/CodeGen/AArch64/fcvt.ll b/llvm/test/CodeGen/AArch64/fcvt.ll index 3b8a22a052b8..1c761ea08302 100644 --- a/llvm/test/CodeGen/AArch64/fcvt.ll +++ b/llvm/test/CodeGen/AArch64/fcvt.ll @@ -163,21 +163,20 @@ define <7 x half> @ceil_v7f16(<7 x half> %a) { ; ; CHECK-GI-NOFP16-LABEL: ceil_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] -; CHECK-GI-NOFP16-NEXT: mov v1.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: frintp v2.4s, v3.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v2.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[6] +; CHECK-GI-NOFP16-NEXT: frintp v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v4.h[0] +; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h ; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[2] ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: frintp v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NOFP16-NEXT: frintp v1.4s, v2.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v3.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v1.4h, v1.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v4.h[0] @@ -186,7 +185,6 @@ define <7 x half> @ceil_v7f16(<7 x half> %a) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: ceil_v7f16: @@ -470,21 +468,20 @@ define <7 x half> @floor_v7f16(<7 x half> %a) { ; ; CHECK-GI-NOFP16-LABEL: floor_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] -; CHECK-GI-NOFP16-NEXT: mov v1.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: frintm v2.4s, v3.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v2.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[6] +; CHECK-GI-NOFP16-NEXT: frintm v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v4.h[0] +; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h ; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[2] ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: frintm v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NOFP16-NEXT: frintm v1.4s, v2.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v3.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v1.4h, v1.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v4.h[0] @@ -493,7 +490,6 @@ define <7 x half> @floor_v7f16(<7 x half> %a) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: floor_v7f16: @@ -777,21 +773,20 @@ define <7 x half> @nearbyint_v7f16(<7 x half> %a) { ; ; CHECK-GI-NOFP16-LABEL: nearbyint_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] -; CHECK-GI-NOFP16-NEXT: mov v1.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: frinti v2.4s, v3.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v2.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[6] +; CHECK-GI-NOFP16-NEXT: frinti v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v4.h[0] +; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h ; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[2] ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: frinti v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NOFP16-NEXT: frinti v1.4s, v2.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v3.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v1.4h, v1.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v4.h[0] @@ -800,7 +795,6 @@ define <7 x half> @nearbyint_v7f16(<7 x half> %a) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: nearbyint_v7f16: @@ -1084,21 +1078,20 @@ define <7 x half> @roundeven_v7f16(<7 x half> %a) { ; ; CHECK-GI-NOFP16-LABEL: roundeven_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] -; CHECK-GI-NOFP16-NEXT: mov v1.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: frintn v2.4s, v3.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v2.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[6] +; CHECK-GI-NOFP16-NEXT: frintn v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v4.h[0] +; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h ; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[2] ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: frintn v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NOFP16-NEXT: frintn v1.4s, v2.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v3.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v1.4h, v1.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v4.h[0] @@ -1107,7 +1100,6 @@ define <7 x half> @roundeven_v7f16(<7 x half> %a) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: roundeven_v7f16: @@ -1391,21 +1383,20 @@ define <7 x half> @rint_v7f16(<7 x half> %a) { ; ; CHECK-GI-NOFP16-LABEL: rint_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] -; CHECK-GI-NOFP16-NEXT: mov v1.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: frintx v2.4s, v3.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v2.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[6] +; CHECK-GI-NOFP16-NEXT: frintx v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v4.h[0] +; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h ; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[2] ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: frintx v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NOFP16-NEXT: frintx v1.4s, v2.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v3.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v1.4h, v1.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v4.h[0] @@ -1414,7 +1405,6 @@ define <7 x half> @rint_v7f16(<7 x half> %a) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: rint_v7f16: @@ -1698,21 +1688,20 @@ define <7 x half> @round_v7f16(<7 x half> %a) { ; ; CHECK-GI-NOFP16-LABEL: round_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] -; CHECK-GI-NOFP16-NEXT: mov v1.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: frinta v2.4s, v3.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v2.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[6] +; CHECK-GI-NOFP16-NEXT: frinta v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v4.h[0] +; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h ; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[2] ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: frinta v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NOFP16-NEXT: frinta v1.4s, v2.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v3.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v1.4h, v1.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v4.h[0] @@ -1721,7 +1710,6 @@ define <7 x half> @round_v7f16(<7 x half> %a) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: round_v7f16: @@ -2005,21 +1993,20 @@ define <7 x half> @trunc_v7f16(<7 x half> %a) { ; ; CHECK-GI-NOFP16-LABEL: trunc_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] -; CHECK-GI-NOFP16-NEXT: mov v1.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: frintz v2.4s, v3.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v2.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[6] +; CHECK-GI-NOFP16-NEXT: frintz v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v4.h[0] +; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h ; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[2] ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: frintz v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NOFP16-NEXT: frintz v1.4s, v2.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v3.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v1.4h, v1.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v4.h[0] @@ -2028,7 +2015,6 @@ define <7 x half> @trunc_v7f16(<7 x half> %a) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: trunc_v7f16: diff --git a/llvm/test/CodeGen/AArch64/fdiv.ll b/llvm/test/CodeGen/AArch64/fdiv.ll index e73124fbb595..d73a5dc73eef 100644 --- a/llvm/test/CodeGen/AArch64/fdiv.ll +++ b/llvm/test/CodeGen/AArch64/fdiv.ll @@ -186,25 +186,23 @@ define <7 x half> @fdiv_v7f16(<7 x half> %a, <7 x half> %b) { ; ; CHECK-GI-NOFP16-LABEL: fdiv_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] -; CHECK-GI-NOFP16-NEXT: mov h4, v1.h[4] -; CHECK-GI-NOFP16-NEXT: mov h5, v1.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v6.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v7.4s, v1.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v1.4h +; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h5, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h6, v1.h[4] +; CHECK-GI-NOFP16-NEXT: mov h7, v1.h[5] ; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[6] -; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NOFP16-NEXT: fdiv v2.4s, v2.4s, v3.4s ; CHECK-GI-NOFP16-NEXT: mov v4.h[1], v5.h[0] -; CHECK-GI-NOFP16-NEXT: fdiv v3.4s, v6.4s, v7.4s -; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[2], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v2.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v2.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v4.4h -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v3.4s -; CHECK-GI-NOFP16-NEXT: fdiv v1.4s, v1.4s, v2.4s +; CHECK-GI-NOFP16-NEXT: mov v6.h[1], v7.h[0] +; CHECK-GI-NOFP16-NEXT: mov v4.h[2], v0.h[0] +; CHECK-GI-NOFP16-NEXT: mov v6.h[2], v1.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v4.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v6.4h +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v2.4s +; CHECK-GI-NOFP16-NEXT: fdiv v1.4s, v1.4s, v3.4s ; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[2] ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[3] @@ -217,7 +215,6 @@ define <7 x half> @fdiv_v7f16(<7 x half> %a, <7 x half> %b) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: fdiv_v7f16: diff --git a/llvm/test/CodeGen/AArch64/fexplog.ll b/llvm/test/CodeGen/AArch64/fexplog.ll index e3c0ced79f07..519a2978d860 100644 --- a/llvm/test/CodeGen/AArch64/fexplog.ll +++ b/llvm/test/CodeGen/AArch64/fexplog.ll @@ -332,7 +332,6 @@ define <3 x float> @exp_v3f32(<3 x float> %a) { ; CHECK-GI-NEXT: ldp d9, d8, [sp, #32] // 16-byte Folded Reload ; CHECK-GI-NEXT: mov v1.s[1], v2.s[0] ; CHECK-GI-NEXT: mov v1.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v1.s[3], v0.s[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #64 ; CHECK-GI-NEXT: ret @@ -703,7 +702,6 @@ define <7 x half> @exp_v7f16(<7 x half> %a) { ; CHECK-GI-NEXT: mov v1.h[4], v3.h[0] ; CHECK-GI-NEXT: mov v1.h[5], v2.h[0] ; CHECK-GI-NEXT: mov v1.h[6], v0.h[0] -; CHECK-GI-NEXT: mov v1.h[7], v0.h[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #160 ; CHECK-GI-NEXT: ret @@ -1591,7 +1589,6 @@ define <3 x float> @exp2_v3f32(<3 x float> %a) { ; CHECK-GI-NEXT: ldp d9, d8, [sp, #32] // 16-byte Folded Reload ; CHECK-GI-NEXT: mov v1.s[1], v2.s[0] ; CHECK-GI-NEXT: mov v1.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v1.s[3], v0.s[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #64 ; CHECK-GI-NEXT: ret @@ -1962,7 +1959,6 @@ define <7 x half> @exp2_v7f16(<7 x half> %a) { ; CHECK-GI-NEXT: mov v1.h[4], v3.h[0] ; CHECK-GI-NEXT: mov v1.h[5], v2.h[0] ; CHECK-GI-NEXT: mov v1.h[6], v0.h[0] -; CHECK-GI-NEXT: mov v1.h[7], v0.h[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #160 ; CHECK-GI-NEXT: ret @@ -2850,7 +2846,6 @@ define <3 x float> @log_v3f32(<3 x float> %a) { ; CHECK-GI-NEXT: ldp d9, d8, [sp, #32] // 16-byte Folded Reload ; CHECK-GI-NEXT: mov v1.s[1], v2.s[0] ; CHECK-GI-NEXT: mov v1.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v1.s[3], v0.s[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #64 ; CHECK-GI-NEXT: ret @@ -3221,7 +3216,6 @@ define <7 x half> @log_v7f16(<7 x half> %a) { ; CHECK-GI-NEXT: mov v1.h[4], v3.h[0] ; CHECK-GI-NEXT: mov v1.h[5], v2.h[0] ; CHECK-GI-NEXT: mov v1.h[6], v0.h[0] -; CHECK-GI-NEXT: mov v1.h[7], v0.h[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #160 ; CHECK-GI-NEXT: ret @@ -4109,7 +4103,6 @@ define <3 x float> @log2_v3f32(<3 x float> %a) { ; CHECK-GI-NEXT: ldp d9, d8, [sp, #32] // 16-byte Folded Reload ; CHECK-GI-NEXT: mov v1.s[1], v2.s[0] ; CHECK-GI-NEXT: mov v1.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v1.s[3], v0.s[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #64 ; CHECK-GI-NEXT: ret @@ -4480,7 +4473,6 @@ define <7 x half> @log2_v7f16(<7 x half> %a) { ; CHECK-GI-NEXT: mov v1.h[4], v3.h[0] ; CHECK-GI-NEXT: mov v1.h[5], v2.h[0] ; CHECK-GI-NEXT: mov v1.h[6], v0.h[0] -; CHECK-GI-NEXT: mov v1.h[7], v0.h[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #160 ; CHECK-GI-NEXT: ret @@ -5368,7 +5360,6 @@ define <3 x float> @log10_v3f32(<3 x float> %a) { ; CHECK-GI-NEXT: ldp d9, d8, [sp, #32] // 16-byte Folded Reload ; CHECK-GI-NEXT: mov v1.s[1], v2.s[0] ; CHECK-GI-NEXT: mov v1.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v1.s[3], v0.s[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #64 ; CHECK-GI-NEXT: ret @@ -5739,7 +5730,6 @@ define <7 x half> @log10_v7f16(<7 x half> %a) { ; CHECK-GI-NEXT: mov v1.h[4], v3.h[0] ; CHECK-GI-NEXT: mov v1.h[5], v2.h[0] ; CHECK-GI-NEXT: mov v1.h[6], v0.h[0] -; CHECK-GI-NEXT: mov v1.h[7], v0.h[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #160 ; CHECK-GI-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/fminimummaximum.ll b/llvm/test/CodeGen/AArch64/fminimummaximum.ll index f0e946c13998..357d91960624 100644 --- a/llvm/test/CodeGen/AArch64/fminimummaximum.ll +++ b/llvm/test/CodeGen/AArch64/fminimummaximum.ll @@ -334,41 +334,39 @@ define <7 x float> @min_v7f32(<7 x float> %a, <7 x float> %b) { ; ; CHECK-GI-LABEL: min_v7f32: ; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: ldr s16, [sp] ; CHECK-GI-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-GI-NEXT: // kill: def $s7 killed $s7 def $q7 ; CHECK-GI-NEXT: // kill: def $s1 killed $s1 def $q1 -; CHECK-GI-NEXT: ldr s16, [sp] -; CHECK-GI-NEXT: ldr s17, [sp, #24] +; CHECK-GI-NEXT: ldr s17, [sp, #32] ; CHECK-GI-NEXT: // kill: def $s4 killed $s4 def $q4 -; CHECK-GI-NEXT: // kill: def $s7 killed $s7 def $q7 ; CHECK-GI-NEXT: // kill: def $s2 killed $s2 def $q2 ; CHECK-GI-NEXT: // kill: def $s5 killed $s5 def $q5 -; CHECK-GI-NEXT: // kill: def $s6 killed $s6 def $q6 ; CHECK-GI-NEXT: // kill: def $s3 killed $s3 def $q3 -; CHECK-GI-NEXT: ldr s18, [sp, #32] +; CHECK-GI-NEXT: // kill: def $s6 killed $s6 def $q6 ; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] -; CHECK-GI-NEXT: mov v4.s[1], v5.s[0] ; CHECK-GI-NEXT: ldr s1, [sp, #8] +; CHECK-GI-NEXT: mov v4.s[1], v5.s[0] ; CHECK-GI-NEXT: mov v7.s[1], v16.s[0] -; CHECK-GI-NEXT: mov v17.s[1], v18.s[0] -; CHECK-GI-NEXT: ldr s5, [sp, #40] +; CHECK-GI-NEXT: ldr s16, [sp, #24] +; CHECK-GI-NEXT: mov v16.s[1], v17.s[0] ; CHECK-GI-NEXT: mov v0.s[2], v2.s[0] +; CHECK-GI-NEXT: ldr s2, [sp, #40] ; CHECK-GI-NEXT: mov v4.s[2], v6.s[0] ; CHECK-GI-NEXT: mov v7.s[2], v1.s[0] -; CHECK-GI-NEXT: mov v17.s[2], v5.s[0] ; CHECK-GI-NEXT: ldr s1, [sp, #16] +; CHECK-GI-NEXT: mov v16.s[2], v2.s[0] ; CHECK-GI-NEXT: mov v0.s[3], v3.s[0] ; CHECK-GI-NEXT: mov v7.s[3], v1.s[0] -; CHECK-GI-NEXT: mov v4.s[3], v0.s[0] -; CHECK-GI-NEXT: mov v17.s[3], v0.s[0] +; CHECK-GI-NEXT: fmin v4.4s, v4.4s, v16.4s ; CHECK-GI-NEXT: fmin v0.4s, v0.4s, v7.4s -; CHECK-GI-NEXT: fmin v4.4s, v4.4s, v17.4s +; CHECK-GI-NEXT: mov s5, v4.s[1] +; CHECK-GI-NEXT: mov s6, v4.s[2] +; CHECK-GI-NEXT: // kill: def $s4 killed $s4 killed $q4 ; CHECK-GI-NEXT: mov s1, v0.s[1] ; CHECK-GI-NEXT: mov s2, v0.s[2] ; CHECK-GI-NEXT: mov s3, v0.s[3] ; CHECK-GI-NEXT: // kill: def $s0 killed $s0 killed $q0 -; CHECK-GI-NEXT: mov s5, v4.s[1] -; CHECK-GI-NEXT: mov s6, v4.s[2] -; CHECK-GI-NEXT: // kill: def $s4 killed $s4 killed $q4 ; CHECK-GI-NEXT: ret entry: %c = call <7 x float> @llvm.minimum.v7f32(<7 x float> %a, <7 x float> %b) @@ -415,41 +413,39 @@ define <7 x float> @max_v7f32(<7 x float> %a, <7 x float> %b) { ; ; CHECK-GI-LABEL: max_v7f32: ; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: ldr s16, [sp] ; CHECK-GI-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-GI-NEXT: // kill: def $s7 killed $s7 def $q7 ; CHECK-GI-NEXT: // kill: def $s1 killed $s1 def $q1 -; CHECK-GI-NEXT: ldr s16, [sp] -; CHECK-GI-NEXT: ldr s17, [sp, #24] +; CHECK-GI-NEXT: ldr s17, [sp, #32] ; CHECK-GI-NEXT: // kill: def $s4 killed $s4 def $q4 -; CHECK-GI-NEXT: // kill: def $s7 killed $s7 def $q7 ; CHECK-GI-NEXT: // kill: def $s2 killed $s2 def $q2 ; CHECK-GI-NEXT: // kill: def $s5 killed $s5 def $q5 -; CHECK-GI-NEXT: // kill: def $s6 killed $s6 def $q6 ; CHECK-GI-NEXT: // kill: def $s3 killed $s3 def $q3 -; CHECK-GI-NEXT: ldr s18, [sp, #32] +; CHECK-GI-NEXT: // kill: def $s6 killed $s6 def $q6 ; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] -; CHECK-GI-NEXT: mov v4.s[1], v5.s[0] ; CHECK-GI-NEXT: ldr s1, [sp, #8] +; CHECK-GI-NEXT: mov v4.s[1], v5.s[0] ; CHECK-GI-NEXT: mov v7.s[1], v16.s[0] -; CHECK-GI-NEXT: mov v17.s[1], v18.s[0] -; CHECK-GI-NEXT: ldr s5, [sp, #40] +; CHECK-GI-NEXT: ldr s16, [sp, #24] +; CHECK-GI-NEXT: mov v16.s[1], v17.s[0] ; CHECK-GI-NEXT: mov v0.s[2], v2.s[0] +; CHECK-GI-NEXT: ldr s2, [sp, #40] ; CHECK-GI-NEXT: mov v4.s[2], v6.s[0] ; CHECK-GI-NEXT: mov v7.s[2], v1.s[0] -; CHECK-GI-NEXT: mov v17.s[2], v5.s[0] ; CHECK-GI-NEXT: ldr s1, [sp, #16] +; CHECK-GI-NEXT: mov v16.s[2], v2.s[0] ; CHECK-GI-NEXT: mov v0.s[3], v3.s[0] ; CHECK-GI-NEXT: mov v7.s[3], v1.s[0] -; CHECK-GI-NEXT: mov v4.s[3], v0.s[0] -; CHECK-GI-NEXT: mov v17.s[3], v0.s[0] +; CHECK-GI-NEXT: fmax v4.4s, v4.4s, v16.4s ; CHECK-GI-NEXT: fmax v0.4s, v0.4s, v7.4s -; CHECK-GI-NEXT: fmax v4.4s, v4.4s, v17.4s +; CHECK-GI-NEXT: mov s5, v4.s[1] +; CHECK-GI-NEXT: mov s6, v4.s[2] +; CHECK-GI-NEXT: // kill: def $s4 killed $s4 killed $q4 ; CHECK-GI-NEXT: mov s1, v0.s[1] ; CHECK-GI-NEXT: mov s2, v0.s[2] ; CHECK-GI-NEXT: mov s3, v0.s[3] ; CHECK-GI-NEXT: // kill: def $s0 killed $s0 killed $q0 -; CHECK-GI-NEXT: mov s5, v4.s[1] -; CHECK-GI-NEXT: mov s6, v4.s[2] -; CHECK-GI-NEXT: // kill: def $s4 killed $s4 killed $q4 ; CHECK-GI-NEXT: ret entry: %c = call <7 x float> @llvm.maximum.v7f32(<7 x float> %a, <7 x float> %b) @@ -666,26 +662,24 @@ define <7 x half> @min_v7f16(<7 x half> %a, <7 x half> %b) { ; ; CHECK-NOFP16-GI-LABEL: min_v7f16: ; CHECK-NOFP16-GI: // %bb.0: // %entry -; CHECK-NOFP16-GI-NEXT: mov h2, v0.h[4] -; CHECK-NOFP16-GI-NEXT: mov h3, v0.h[5] -; CHECK-NOFP16-GI-NEXT: mov h4, v1.h[4] -; CHECK-NOFP16-GI-NEXT: mov h5, v1.h[5] -; CHECK-NOFP16-GI-NEXT: fcvtl v6.4s, v0.4h -; CHECK-NOFP16-GI-NEXT: fcvtl v7.4s, v1.4h -; CHECK-NOFP16-GI-NEXT: mov h0, v0.h[6] +; CHECK-NOFP16-GI-NEXT: fcvtl v2.4s, v0.4h +; CHECK-NOFP16-GI-NEXT: fcvtl v3.4s, v1.4h +; CHECK-NOFP16-GI-NEXT: mov h4, v0.h[4] +; CHECK-NOFP16-GI-NEXT: mov h5, v0.h[5] +; CHECK-NOFP16-GI-NEXT: mov h6, v1.h[4] +; CHECK-NOFP16-GI-NEXT: mov h7, v1.h[5] ; CHECK-NOFP16-GI-NEXT: mov h1, v1.h[6] -; CHECK-NOFP16-GI-NEXT: mov v2.h[1], v3.h[0] +; CHECK-NOFP16-GI-NEXT: fmin v2.4s, v2.4s, v3.4s +; CHECK-NOFP16-GI-NEXT: mov h3, v0.h[6] ; CHECK-NOFP16-GI-NEXT: mov v4.h[1], v5.h[0] -; CHECK-NOFP16-GI-NEXT: fmin v3.4s, v6.4s, v7.4s -; CHECK-NOFP16-GI-NEXT: mov v2.h[2], v0.h[0] -; CHECK-NOFP16-GI-NEXT: mov v4.h[2], v1.h[0] -; CHECK-NOFP16-GI-NEXT: fcvtn v0.4h, v3.4s -; CHECK-NOFP16-GI-NEXT: mov v2.h[3], v0.h[0] -; CHECK-NOFP16-GI-NEXT: mov v4.h[3], v0.h[0] +; CHECK-NOFP16-GI-NEXT: mov v6.h[1], v7.h[0] +; CHECK-NOFP16-GI-NEXT: fcvtn v0.4h, v2.4s +; CHECK-NOFP16-GI-NEXT: mov v4.h[2], v3.h[0] +; CHECK-NOFP16-GI-NEXT: mov v6.h[2], v1.h[0] ; CHECK-NOFP16-GI-NEXT: mov h1, v0.h[1] ; CHECK-NOFP16-GI-NEXT: mov h5, v0.h[3] -; CHECK-NOFP16-GI-NEXT: fcvtl v2.4s, v2.4h -; CHECK-NOFP16-GI-NEXT: fcvtl v3.4s, v4.4h +; CHECK-NOFP16-GI-NEXT: fcvtl v2.4s, v4.4h +; CHECK-NOFP16-GI-NEXT: fcvtl v3.4s, v6.4h ; CHECK-NOFP16-GI-NEXT: mov h4, v0.h[2] ; CHECK-NOFP16-GI-NEXT: mov v0.h[1], v1.h[0] ; CHECK-NOFP16-GI-NEXT: fmin v1.4s, v2.4s, v3.4s @@ -697,7 +691,6 @@ define <7 x half> @min_v7f16(<7 x half> %a, <7 x half> %b) { ; CHECK-NOFP16-GI-NEXT: mov h1, v1.h[2] ; CHECK-NOFP16-GI-NEXT: mov v0.h[5], v2.h[0] ; CHECK-NOFP16-GI-NEXT: mov v0.h[6], v1.h[0] -; CHECK-NOFP16-GI-NEXT: mov v0.h[7], v0.h[0] ; CHECK-NOFP16-GI-NEXT: ret ; ; CHECK-FP16-GI-LABEL: min_v7f16: @@ -775,26 +768,24 @@ define <7 x half> @max_v7f16(<7 x half> %a, <7 x half> %b) { ; ; CHECK-NOFP16-GI-LABEL: max_v7f16: ; CHECK-NOFP16-GI: // %bb.0: // %entry -; CHECK-NOFP16-GI-NEXT: mov h2, v0.h[4] -; CHECK-NOFP16-GI-NEXT: mov h3, v0.h[5] -; CHECK-NOFP16-GI-NEXT: mov h4, v1.h[4] -; CHECK-NOFP16-GI-NEXT: mov h5, v1.h[5] -; CHECK-NOFP16-GI-NEXT: fcvtl v6.4s, v0.4h -; CHECK-NOFP16-GI-NEXT: fcvtl v7.4s, v1.4h -; CHECK-NOFP16-GI-NEXT: mov h0, v0.h[6] +; CHECK-NOFP16-GI-NEXT: fcvtl v2.4s, v0.4h +; CHECK-NOFP16-GI-NEXT: fcvtl v3.4s, v1.4h +; CHECK-NOFP16-GI-NEXT: mov h4, v0.h[4] +; CHECK-NOFP16-GI-NEXT: mov h5, v0.h[5] +; CHECK-NOFP16-GI-NEXT: mov h6, v1.h[4] +; CHECK-NOFP16-GI-NEXT: mov h7, v1.h[5] ; CHECK-NOFP16-GI-NEXT: mov h1, v1.h[6] -; CHECK-NOFP16-GI-NEXT: mov v2.h[1], v3.h[0] +; CHECK-NOFP16-GI-NEXT: fmax v2.4s, v2.4s, v3.4s +; CHECK-NOFP16-GI-NEXT: mov h3, v0.h[6] ; CHECK-NOFP16-GI-NEXT: mov v4.h[1], v5.h[0] -; CHECK-NOFP16-GI-NEXT: fmax v3.4s, v6.4s, v7.4s -; CHECK-NOFP16-GI-NEXT: mov v2.h[2], v0.h[0] -; CHECK-NOFP16-GI-NEXT: mov v4.h[2], v1.h[0] -; CHECK-NOFP16-GI-NEXT: fcvtn v0.4h, v3.4s -; CHECK-NOFP16-GI-NEXT: mov v2.h[3], v0.h[0] -; CHECK-NOFP16-GI-NEXT: mov v4.h[3], v0.h[0] +; CHECK-NOFP16-GI-NEXT: mov v6.h[1], v7.h[0] +; CHECK-NOFP16-GI-NEXT: fcvtn v0.4h, v2.4s +; CHECK-NOFP16-GI-NEXT: mov v4.h[2], v3.h[0] +; CHECK-NOFP16-GI-NEXT: mov v6.h[2], v1.h[0] ; CHECK-NOFP16-GI-NEXT: mov h1, v0.h[1] ; CHECK-NOFP16-GI-NEXT: mov h5, v0.h[3] -; CHECK-NOFP16-GI-NEXT: fcvtl v2.4s, v2.4h -; CHECK-NOFP16-GI-NEXT: fcvtl v3.4s, v4.4h +; CHECK-NOFP16-GI-NEXT: fcvtl v2.4s, v4.4h +; CHECK-NOFP16-GI-NEXT: fcvtl v3.4s, v6.4h ; CHECK-NOFP16-GI-NEXT: mov h4, v0.h[2] ; CHECK-NOFP16-GI-NEXT: mov v0.h[1], v1.h[0] ; CHECK-NOFP16-GI-NEXT: fmax v1.4s, v2.4s, v3.4s @@ -806,7 +797,6 @@ define <7 x half> @max_v7f16(<7 x half> %a, <7 x half> %b) { ; CHECK-NOFP16-GI-NEXT: mov h1, v1.h[2] ; CHECK-NOFP16-GI-NEXT: mov v0.h[5], v2.h[0] ; CHECK-NOFP16-GI-NEXT: mov v0.h[6], v1.h[0] -; CHECK-NOFP16-GI-NEXT: mov v0.h[7], v0.h[0] ; CHECK-NOFP16-GI-NEXT: ret ; ; CHECK-FP16-GI-LABEL: max_v7f16: diff --git a/llvm/test/CodeGen/AArch64/fminmax.ll b/llvm/test/CodeGen/AArch64/fminmax.ll index cdf9973b49f4..61199f82615b 100644 --- a/llvm/test/CodeGen/AArch64/fminmax.ll +++ b/llvm/test/CodeGen/AArch64/fminmax.ll @@ -334,41 +334,39 @@ define <7 x float> @min_v7f32(<7 x float> %a, <7 x float> %b) { ; ; CHECK-GI-LABEL: min_v7f32: ; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: ldr s16, [sp] ; CHECK-GI-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-GI-NEXT: // kill: def $s7 killed $s7 def $q7 ; CHECK-GI-NEXT: // kill: def $s1 killed $s1 def $q1 -; CHECK-GI-NEXT: ldr s16, [sp] -; CHECK-GI-NEXT: ldr s17, [sp, #24] +; CHECK-GI-NEXT: ldr s17, [sp, #32] ; CHECK-GI-NEXT: // kill: def $s4 killed $s4 def $q4 -; CHECK-GI-NEXT: // kill: def $s7 killed $s7 def $q7 ; CHECK-GI-NEXT: // kill: def $s2 killed $s2 def $q2 ; CHECK-GI-NEXT: // kill: def $s5 killed $s5 def $q5 -; CHECK-GI-NEXT: // kill: def $s6 killed $s6 def $q6 ; CHECK-GI-NEXT: // kill: def $s3 killed $s3 def $q3 -; CHECK-GI-NEXT: ldr s18, [sp, #32] +; CHECK-GI-NEXT: // kill: def $s6 killed $s6 def $q6 ; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] -; CHECK-GI-NEXT: mov v4.s[1], v5.s[0] ; CHECK-GI-NEXT: ldr s1, [sp, #8] +; CHECK-GI-NEXT: mov v4.s[1], v5.s[0] ; CHECK-GI-NEXT: mov v7.s[1], v16.s[0] -; CHECK-GI-NEXT: mov v17.s[1], v18.s[0] -; CHECK-GI-NEXT: ldr s5, [sp, #40] +; CHECK-GI-NEXT: ldr s16, [sp, #24] +; CHECK-GI-NEXT: mov v16.s[1], v17.s[0] ; CHECK-GI-NEXT: mov v0.s[2], v2.s[0] +; CHECK-GI-NEXT: ldr s2, [sp, #40] ; CHECK-GI-NEXT: mov v4.s[2], v6.s[0] ; CHECK-GI-NEXT: mov v7.s[2], v1.s[0] -; CHECK-GI-NEXT: mov v17.s[2], v5.s[0] ; CHECK-GI-NEXT: ldr s1, [sp, #16] +; CHECK-GI-NEXT: mov v16.s[2], v2.s[0] ; CHECK-GI-NEXT: mov v0.s[3], v3.s[0] ; CHECK-GI-NEXT: mov v7.s[3], v1.s[0] -; CHECK-GI-NEXT: mov v4.s[3], v0.s[0] -; CHECK-GI-NEXT: mov v17.s[3], v0.s[0] +; CHECK-GI-NEXT: fminnm v4.4s, v4.4s, v16.4s ; CHECK-GI-NEXT: fminnm v0.4s, v0.4s, v7.4s -; CHECK-GI-NEXT: fminnm v4.4s, v4.4s, v17.4s +; CHECK-GI-NEXT: mov s5, v4.s[1] +; CHECK-GI-NEXT: mov s6, v4.s[2] +; CHECK-GI-NEXT: // kill: def $s4 killed $s4 killed $q4 ; CHECK-GI-NEXT: mov s1, v0.s[1] ; CHECK-GI-NEXT: mov s2, v0.s[2] ; CHECK-GI-NEXT: mov s3, v0.s[3] ; CHECK-GI-NEXT: // kill: def $s0 killed $s0 killed $q0 -; CHECK-GI-NEXT: mov s5, v4.s[1] -; CHECK-GI-NEXT: mov s6, v4.s[2] -; CHECK-GI-NEXT: // kill: def $s4 killed $s4 killed $q4 ; CHECK-GI-NEXT: ret entry: %c = call <7 x float> @llvm.minnum.v7f32(<7 x float> %a, <7 x float> %b) @@ -415,41 +413,39 @@ define <7 x float> @max_v7f32(<7 x float> %a, <7 x float> %b) { ; ; CHECK-GI-LABEL: max_v7f32: ; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: ldr s16, [sp] ; CHECK-GI-NEXT: // kill: def $s0 killed $s0 def $q0 +; CHECK-GI-NEXT: // kill: def $s7 killed $s7 def $q7 ; CHECK-GI-NEXT: // kill: def $s1 killed $s1 def $q1 -; CHECK-GI-NEXT: ldr s16, [sp] -; CHECK-GI-NEXT: ldr s17, [sp, #24] +; CHECK-GI-NEXT: ldr s17, [sp, #32] ; CHECK-GI-NEXT: // kill: def $s4 killed $s4 def $q4 -; CHECK-GI-NEXT: // kill: def $s7 killed $s7 def $q7 ; CHECK-GI-NEXT: // kill: def $s2 killed $s2 def $q2 ; CHECK-GI-NEXT: // kill: def $s5 killed $s5 def $q5 -; CHECK-GI-NEXT: // kill: def $s6 killed $s6 def $q6 ; CHECK-GI-NEXT: // kill: def $s3 killed $s3 def $q3 -; CHECK-GI-NEXT: ldr s18, [sp, #32] +; CHECK-GI-NEXT: // kill: def $s6 killed $s6 def $q6 ; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] -; CHECK-GI-NEXT: mov v4.s[1], v5.s[0] ; CHECK-GI-NEXT: ldr s1, [sp, #8] +; CHECK-GI-NEXT: mov v4.s[1], v5.s[0] ; CHECK-GI-NEXT: mov v7.s[1], v16.s[0] -; CHECK-GI-NEXT: mov v17.s[1], v18.s[0] -; CHECK-GI-NEXT: ldr s5, [sp, #40] +; CHECK-GI-NEXT: ldr s16, [sp, #24] +; CHECK-GI-NEXT: mov v16.s[1], v17.s[0] ; CHECK-GI-NEXT: mov v0.s[2], v2.s[0] +; CHECK-GI-NEXT: ldr s2, [sp, #40] ; CHECK-GI-NEXT: mov v4.s[2], v6.s[0] ; CHECK-GI-NEXT: mov v7.s[2], v1.s[0] -; CHECK-GI-NEXT: mov v17.s[2], v5.s[0] ; CHECK-GI-NEXT: ldr s1, [sp, #16] +; CHECK-GI-NEXT: mov v16.s[2], v2.s[0] ; CHECK-GI-NEXT: mov v0.s[3], v3.s[0] ; CHECK-GI-NEXT: mov v7.s[3], v1.s[0] -; CHECK-GI-NEXT: mov v4.s[3], v0.s[0] -; CHECK-GI-NEXT: mov v17.s[3], v0.s[0] +; CHECK-GI-NEXT: fmaxnm v4.4s, v4.4s, v16.4s ; CHECK-GI-NEXT: fmaxnm v0.4s, v0.4s, v7.4s -; CHECK-GI-NEXT: fmaxnm v4.4s, v4.4s, v17.4s +; CHECK-GI-NEXT: mov s5, v4.s[1] +; CHECK-GI-NEXT: mov s6, v4.s[2] +; CHECK-GI-NEXT: // kill: def $s4 killed $s4 killed $q4 ; CHECK-GI-NEXT: mov s1, v0.s[1] ; CHECK-GI-NEXT: mov s2, v0.s[2] ; CHECK-GI-NEXT: mov s3, v0.s[3] ; CHECK-GI-NEXT: // kill: def $s0 killed $s0 killed $q0 -; CHECK-GI-NEXT: mov s5, v4.s[1] -; CHECK-GI-NEXT: mov s6, v4.s[2] -; CHECK-GI-NEXT: // kill: def $s4 killed $s4 killed $q4 ; CHECK-GI-NEXT: ret entry: %c = call <7 x float> @llvm.maxnum.v7f32(<7 x float> %a, <7 x float> %b) @@ -666,26 +662,24 @@ define <7 x half> @min_v7f16(<7 x half> %a, <7 x half> %b) { ; ; CHECK-NOFP16-GI-LABEL: min_v7f16: ; CHECK-NOFP16-GI: // %bb.0: // %entry -; CHECK-NOFP16-GI-NEXT: mov h2, v0.h[4] -; CHECK-NOFP16-GI-NEXT: mov h3, v0.h[5] -; CHECK-NOFP16-GI-NEXT: mov h4, v1.h[4] -; CHECK-NOFP16-GI-NEXT: mov h5, v1.h[5] -; CHECK-NOFP16-GI-NEXT: fcvtl v6.4s, v0.4h -; CHECK-NOFP16-GI-NEXT: fcvtl v7.4s, v1.4h -; CHECK-NOFP16-GI-NEXT: mov h0, v0.h[6] +; CHECK-NOFP16-GI-NEXT: fcvtl v2.4s, v0.4h +; CHECK-NOFP16-GI-NEXT: fcvtl v3.4s, v1.4h +; CHECK-NOFP16-GI-NEXT: mov h4, v0.h[4] +; CHECK-NOFP16-GI-NEXT: mov h5, v0.h[5] +; CHECK-NOFP16-GI-NEXT: mov h6, v1.h[4] +; CHECK-NOFP16-GI-NEXT: mov h7, v1.h[5] ; CHECK-NOFP16-GI-NEXT: mov h1, v1.h[6] -; CHECK-NOFP16-GI-NEXT: mov v2.h[1], v3.h[0] +; CHECK-NOFP16-GI-NEXT: fminnm v2.4s, v2.4s, v3.4s +; CHECK-NOFP16-GI-NEXT: mov h3, v0.h[6] ; CHECK-NOFP16-GI-NEXT: mov v4.h[1], v5.h[0] -; CHECK-NOFP16-GI-NEXT: fminnm v3.4s, v6.4s, v7.4s -; CHECK-NOFP16-GI-NEXT: mov v2.h[2], v0.h[0] -; CHECK-NOFP16-GI-NEXT: mov v4.h[2], v1.h[0] -; CHECK-NOFP16-GI-NEXT: fcvtn v0.4h, v3.4s -; CHECK-NOFP16-GI-NEXT: mov v2.h[3], v0.h[0] -; CHECK-NOFP16-GI-NEXT: mov v4.h[3], v0.h[0] +; CHECK-NOFP16-GI-NEXT: mov v6.h[1], v7.h[0] +; CHECK-NOFP16-GI-NEXT: fcvtn v0.4h, v2.4s +; CHECK-NOFP16-GI-NEXT: mov v4.h[2], v3.h[0] +; CHECK-NOFP16-GI-NEXT: mov v6.h[2], v1.h[0] ; CHECK-NOFP16-GI-NEXT: mov h1, v0.h[1] ; CHECK-NOFP16-GI-NEXT: mov h5, v0.h[3] -; CHECK-NOFP16-GI-NEXT: fcvtl v2.4s, v2.4h -; CHECK-NOFP16-GI-NEXT: fcvtl v3.4s, v4.4h +; CHECK-NOFP16-GI-NEXT: fcvtl v2.4s, v4.4h +; CHECK-NOFP16-GI-NEXT: fcvtl v3.4s, v6.4h ; CHECK-NOFP16-GI-NEXT: mov h4, v0.h[2] ; CHECK-NOFP16-GI-NEXT: mov v0.h[1], v1.h[0] ; CHECK-NOFP16-GI-NEXT: fminnm v1.4s, v2.4s, v3.4s @@ -697,7 +691,6 @@ define <7 x half> @min_v7f16(<7 x half> %a, <7 x half> %b) { ; CHECK-NOFP16-GI-NEXT: mov h1, v1.h[2] ; CHECK-NOFP16-GI-NEXT: mov v0.h[5], v2.h[0] ; CHECK-NOFP16-GI-NEXT: mov v0.h[6], v1.h[0] -; CHECK-NOFP16-GI-NEXT: mov v0.h[7], v0.h[0] ; CHECK-NOFP16-GI-NEXT: ret ; ; CHECK-FP16-GI-LABEL: min_v7f16: @@ -775,26 +768,24 @@ define <7 x half> @max_v7f16(<7 x half> %a, <7 x half> %b) { ; ; CHECK-NOFP16-GI-LABEL: max_v7f16: ; CHECK-NOFP16-GI: // %bb.0: // %entry -; CHECK-NOFP16-GI-NEXT: mov h2, v0.h[4] -; CHECK-NOFP16-GI-NEXT: mov h3, v0.h[5] -; CHECK-NOFP16-GI-NEXT: mov h4, v1.h[4] -; CHECK-NOFP16-GI-NEXT: mov h5, v1.h[5] -; CHECK-NOFP16-GI-NEXT: fcvtl v6.4s, v0.4h -; CHECK-NOFP16-GI-NEXT: fcvtl v7.4s, v1.4h -; CHECK-NOFP16-GI-NEXT: mov h0, v0.h[6] +; CHECK-NOFP16-GI-NEXT: fcvtl v2.4s, v0.4h +; CHECK-NOFP16-GI-NEXT: fcvtl v3.4s, v1.4h +; CHECK-NOFP16-GI-NEXT: mov h4, v0.h[4] +; CHECK-NOFP16-GI-NEXT: mov h5, v0.h[5] +; CHECK-NOFP16-GI-NEXT: mov h6, v1.h[4] +; CHECK-NOFP16-GI-NEXT: mov h7, v1.h[5] ; CHECK-NOFP16-GI-NEXT: mov h1, v1.h[6] -; CHECK-NOFP16-GI-NEXT: mov v2.h[1], v3.h[0] +; CHECK-NOFP16-GI-NEXT: fmaxnm v2.4s, v2.4s, v3.4s +; CHECK-NOFP16-GI-NEXT: mov h3, v0.h[6] ; CHECK-NOFP16-GI-NEXT: mov v4.h[1], v5.h[0] -; CHECK-NOFP16-GI-NEXT: fmaxnm v3.4s, v6.4s, v7.4s -; CHECK-NOFP16-GI-NEXT: mov v2.h[2], v0.h[0] -; CHECK-NOFP16-GI-NEXT: mov v4.h[2], v1.h[0] -; CHECK-NOFP16-GI-NEXT: fcvtn v0.4h, v3.4s -; CHECK-NOFP16-GI-NEXT: mov v2.h[3], v0.h[0] -; CHECK-NOFP16-GI-NEXT: mov v4.h[3], v0.h[0] +; CHECK-NOFP16-GI-NEXT: mov v6.h[1], v7.h[0] +; CHECK-NOFP16-GI-NEXT: fcvtn v0.4h, v2.4s +; CHECK-NOFP16-GI-NEXT: mov v4.h[2], v3.h[0] +; CHECK-NOFP16-GI-NEXT: mov v6.h[2], v1.h[0] ; CHECK-NOFP16-GI-NEXT: mov h1, v0.h[1] ; CHECK-NOFP16-GI-NEXT: mov h5, v0.h[3] -; CHECK-NOFP16-GI-NEXT: fcvtl v2.4s, v2.4h -; CHECK-NOFP16-GI-NEXT: fcvtl v3.4s, v4.4h +; CHECK-NOFP16-GI-NEXT: fcvtl v2.4s, v4.4h +; CHECK-NOFP16-GI-NEXT: fcvtl v3.4s, v6.4h ; CHECK-NOFP16-GI-NEXT: mov h4, v0.h[2] ; CHECK-NOFP16-GI-NEXT: mov v0.h[1], v1.h[0] ; CHECK-NOFP16-GI-NEXT: fmaxnm v1.4s, v2.4s, v3.4s @@ -806,7 +797,6 @@ define <7 x half> @max_v7f16(<7 x half> %a, <7 x half> %b) { ; CHECK-NOFP16-GI-NEXT: mov h1, v1.h[2] ; CHECK-NOFP16-GI-NEXT: mov v0.h[5], v2.h[0] ; CHECK-NOFP16-GI-NEXT: mov v0.h[6], v1.h[0] -; CHECK-NOFP16-GI-NEXT: mov v0.h[7], v0.h[0] ; CHECK-NOFP16-GI-NEXT: ret ; ; CHECK-FP16-GI-LABEL: max_v7f16: diff --git a/llvm/test/CodeGen/AArch64/fmla.ll b/llvm/test/CodeGen/AArch64/fmla.ll index 336c9705f399..4b019b57d968 100644 --- a/llvm/test/CodeGen/AArch64/fmla.ll +++ b/llvm/test/CodeGen/AArch64/fmla.ll @@ -254,35 +254,32 @@ define <7 x half> @fma_v7f16(<7 x half> %a, <7 x half> %b, <7 x half> %c) { ; ; CHECK-GI-NOFP16-LABEL: fma_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h6, v0.h[5] -; CHECK-GI-NOFP16-NEXT: mov h4, v1.h[4] -; CHECK-GI-NOFP16-NEXT: mov h7, v1.h[5] -; CHECK-GI-NOFP16-NEXT: mov h5, v2.h[4] -; CHECK-GI-NOFP16-NEXT: mov h16, v2.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v17.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v18.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v19.4s, v2.4h -; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] +; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v4.4s, v1.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v5.4s, v2.4h +; CHECK-GI-NOFP16-NEXT: mov h6, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h7, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h16, v1.h[4] +; CHECK-GI-NOFP16-NEXT: mov h17, v1.h[5] +; CHECK-GI-NOFP16-NEXT: mov h18, v2.h[4] +; CHECK-GI-NOFP16-NEXT: mov h19, v2.h[5] ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[6] ; CHECK-GI-NOFP16-NEXT: mov h2, v2.h[6] -; CHECK-GI-NOFP16-NEXT: mov v3.h[1], v6.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[1], v7.h[0] -; CHECK-GI-NOFP16-NEXT: mov v5.h[1], v16.h[0] -; CHECK-GI-NOFP16-NEXT: fmla v19.4s, v18.4s, v17.4s -; CHECK-GI-NOFP16-NEXT: mov v3.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[2], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v5.h[2], v2.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v19.4s -; CHECK-GI-NOFP16-NEXT: mov v3.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v5.h[3], v0.h[0] +; CHECK-GI-NOFP16-NEXT: fmla v5.4s, v4.4s, v3.4s +; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[6] +; CHECK-GI-NOFP16-NEXT: mov v6.h[1], v7.h[0] +; CHECK-GI-NOFP16-NEXT: mov v16.h[1], v17.h[0] +; CHECK-GI-NOFP16-NEXT: mov v18.h[1], v19.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v5.4s +; CHECK-GI-NOFP16-NEXT: mov v6.h[2], v3.h[0] +; CHECK-GI-NOFP16-NEXT: mov v16.h[2], v1.h[0] +; CHECK-GI-NOFP16-NEXT: mov v18.h[2], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] -; CHECK-GI-NOFP16-NEXT: mov h6, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v3.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v4.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v4.4s, v5.4h ; CHECK-GI-NOFP16-NEXT: mov h5, v0.h[2] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v6.4h +; CHECK-GI-NOFP16-NEXT: mov h6, v0.h[3] +; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v16.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v4.4s, v18.4h ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-NOFP16-NEXT: fmla v4.4s, v3.4s, v2.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v5.h[0] @@ -293,7 +290,6 @@ define <7 x half> @fma_v7f16(<7 x half> %a, <7 x half> %b, <7 x half> %c) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: fma_v7f16: @@ -866,43 +862,40 @@ define <7 x half> @fmuladd_v7f16(<7 x half> %a, <7 x half> %b, <7 x half> %c) { ; ; CHECK-GI-NOFP16-LABEL: fmuladd_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[5] -; CHECK-GI-NOFP16-NEXT: mov h5, v1.h[4] -; CHECK-GI-NOFP16-NEXT: mov h6, v1.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v7.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v16.4s, v1.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v4.4s, v1.4h +; CHECK-GI-NOFP16-NEXT: mov h5, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h6, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h7, v1.h[4] +; CHECK-GI-NOFP16-NEXT: mov h16, v1.h[5] ; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[6] -; CHECK-GI-NOFP16-NEXT: mov v3.h[1], v4.h[0] -; CHECK-GI-NOFP16-NEXT: mov v5.h[1], v6.h[0] -; CHECK-GI-NOFP16-NEXT: fmul v4.4s, v7.4s, v16.4s -; CHECK-GI-NOFP16-NEXT: fcvtl v6.4s, v2.4h -; CHECK-GI-NOFP16-NEXT: mov v3.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v5.h[2], v1.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v4.4s -; CHECK-GI-NOFP16-NEXT: mov h1, v2.h[4] +; CHECK-GI-NOFP16-NEXT: fmul v3.4s, v3.4s, v4.4s ; CHECK-GI-NOFP16-NEXT: mov h4, v2.h[5] -; CHECK-GI-NOFP16-NEXT: mov h2, v2.h[6] -; CHECK-GI-NOFP16-NEXT: mov v3.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v5.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtl v0.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: mov v1.h[1], v4.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v3.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v4.4s, v5.4h -; CHECK-GI-NOFP16-NEXT: fadd v0.4s, v0.4s, v6.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[2], v2.h[0] -; CHECK-GI-NOFP16-NEXT: fmul v2.4s, v3.4s, v4.4s +; CHECK-GI-NOFP16-NEXT: mov v5.h[1], v6.h[0] +; CHECK-GI-NOFP16-NEXT: mov v7.h[1], v16.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v3.4h, v3.4s +; CHECK-GI-NOFP16-NEXT: mov v5.h[2], v0.h[0] +; CHECK-GI-NOFP16-NEXT: mov v7.h[2], v1.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v2.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v0.4s, v3.4h +; CHECK-GI-NOFP16-NEXT: mov h3, v2.h[4] +; CHECK-GI-NOFP16-NEXT: fcvtl v5.4s, v5.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v6.4s, v7.4h +; CHECK-GI-NOFP16-NEXT: fadd v0.4s, v0.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov h1, v2.h[6] +; CHECK-GI-NOFP16-NEXT: mov v3.h[1], v4.h[0] +; CHECK-GI-NOFP16-NEXT: fmul v2.4s, v5.4s, v6.4s ; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v0.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[3], v0.h[0] +; CHECK-GI-NOFP16-NEXT: mov v3.h[2], v1.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v2.4h, v2.4s -; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[1] +; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v3.4h ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[2] -; CHECK-GI-NOFP16-NEXT: mov h5, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v1.4h ; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h -; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v3.h[0] -; CHECK-GI-NOFP16-NEXT: fadd v1.4s, v2.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov h5, v0.h[3] +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NOFP16-NEXT: fadd v1.4s, v2.4s, v3.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v4.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v1.4h, v1.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v5.h[0] @@ -911,7 +904,6 @@ define <7 x half> @fmuladd_v7f16(<7 x half> %a, <7 x half> %b, <7 x half> %c) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: fmuladd_v7f16: @@ -1368,43 +1360,40 @@ define <7 x half> @fmul_v7f16(<7 x half> %a, <7 x half> %b, <7 x half> %c) { ; ; CHECK-GI-NOFP16-LABEL: fmul_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[5] -; CHECK-GI-NOFP16-NEXT: mov h5, v1.h[4] -; CHECK-GI-NOFP16-NEXT: mov h6, v1.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v7.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v16.4s, v1.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v4.4s, v1.4h +; CHECK-GI-NOFP16-NEXT: mov h5, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h6, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h7, v1.h[4] +; CHECK-GI-NOFP16-NEXT: mov h16, v1.h[5] ; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[6] -; CHECK-GI-NOFP16-NEXT: mov v3.h[1], v4.h[0] -; CHECK-GI-NOFP16-NEXT: mov v5.h[1], v6.h[0] -; CHECK-GI-NOFP16-NEXT: fmul v4.4s, v7.4s, v16.4s -; CHECK-GI-NOFP16-NEXT: fcvtl v6.4s, v2.4h -; CHECK-GI-NOFP16-NEXT: mov v3.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v5.h[2], v1.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v4.4s -; CHECK-GI-NOFP16-NEXT: mov h1, v2.h[4] +; CHECK-GI-NOFP16-NEXT: fmul v3.4s, v3.4s, v4.4s ; CHECK-GI-NOFP16-NEXT: mov h4, v2.h[5] -; CHECK-GI-NOFP16-NEXT: mov h2, v2.h[6] -; CHECK-GI-NOFP16-NEXT: mov v3.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v5.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtl v0.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: mov v1.h[1], v4.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v3.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v4.4s, v5.4h -; CHECK-GI-NOFP16-NEXT: fadd v0.4s, v0.4s, v6.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[2], v2.h[0] -; CHECK-GI-NOFP16-NEXT: fmul v2.4s, v3.4s, v4.4s +; CHECK-GI-NOFP16-NEXT: mov v5.h[1], v6.h[0] +; CHECK-GI-NOFP16-NEXT: mov v7.h[1], v16.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v3.4h, v3.4s +; CHECK-GI-NOFP16-NEXT: mov v5.h[2], v0.h[0] +; CHECK-GI-NOFP16-NEXT: mov v7.h[2], v1.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v2.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v0.4s, v3.4h +; CHECK-GI-NOFP16-NEXT: mov h3, v2.h[4] +; CHECK-GI-NOFP16-NEXT: fcvtl v5.4s, v5.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v6.4s, v7.4h +; CHECK-GI-NOFP16-NEXT: fadd v0.4s, v0.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov h1, v2.h[6] +; CHECK-GI-NOFP16-NEXT: mov v3.h[1], v4.h[0] +; CHECK-GI-NOFP16-NEXT: fmul v2.4s, v5.4s, v6.4s ; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v0.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[3], v0.h[0] +; CHECK-GI-NOFP16-NEXT: mov v3.h[2], v1.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v2.4h, v2.4s -; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[1] +; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v3.4h ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[2] -; CHECK-GI-NOFP16-NEXT: mov h5, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v1.4h ; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h -; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v3.h[0] -; CHECK-GI-NOFP16-NEXT: fadd v1.4s, v2.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov h5, v0.h[3] +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NOFP16-NEXT: fadd v1.4s, v2.4s, v3.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v4.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v1.4h, v1.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v5.h[0] @@ -1413,7 +1402,6 @@ define <7 x half> @fmul_v7f16(<7 x half> %a, <7 x half> %b, <7 x half> %c) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: fmul_v7f16: diff --git a/llvm/test/CodeGen/AArch64/fmul.ll b/llvm/test/CodeGen/AArch64/fmul.ll index 1f49601a1827..1f41f2385c33 100644 --- a/llvm/test/CodeGen/AArch64/fmul.ll +++ b/llvm/test/CodeGen/AArch64/fmul.ll @@ -186,26 +186,24 @@ define <7 x half> @fmul_v7f16(<7 x half> %a, <7 x half> %b) { ; ; CHECK-GI-NOFP16-LABEL: fmul_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] -; CHECK-GI-NOFP16-NEXT: mov h4, v1.h[4] -; CHECK-GI-NOFP16-NEXT: mov h5, v1.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v6.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v7.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v1.4h +; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h5, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h6, v1.h[4] +; CHECK-GI-NOFP16-NEXT: mov h7, v1.h[5] ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[6] -; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NOFP16-NEXT: fmul v2.4s, v2.4s, v3.4s +; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[6] ; CHECK-GI-NOFP16-NEXT: mov v4.h[1], v5.h[0] -; CHECK-GI-NOFP16-NEXT: fmul v3.4s, v6.4s, v7.4s -; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[2], v1.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v3.4s -; CHECK-GI-NOFP16-NEXT: mov v2.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v4.h[3], v0.h[0] +; CHECK-GI-NOFP16-NEXT: mov v6.h[1], v7.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v2.4s +; CHECK-GI-NOFP16-NEXT: mov v4.h[2], v3.h[0] +; CHECK-GI-NOFP16-NEXT: mov v6.h[2], v1.h[0] ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov h5, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v4.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v4.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v6.4h ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-NOFP16-NEXT: fmul v1.4s, v2.4s, v3.4s @@ -217,7 +215,6 @@ define <7 x half> @fmul_v7f16(<7 x half> %a, <7 x half> %b) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: fmul_v7f16: diff --git a/llvm/test/CodeGen/AArch64/fneg.ll b/llvm/test/CodeGen/AArch64/fneg.ll index d5010cf36084..cc0f7d2fd607 100644 --- a/llvm/test/CodeGen/AArch64/fneg.ll +++ b/llvm/test/CodeGen/AArch64/fneg.ll @@ -161,21 +161,20 @@ define <7 x half> @fabs_v7f16(<7 x half> %a) { ; ; CHECK-GI-NOFP16-LABEL: fabs_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v0.4h -; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] -; CHECK-GI-NOFP16-NEXT: mov v1.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: fneg v2.4s, v3.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v2.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] +; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[6] +; CHECK-GI-NOFP16-NEXT: fneg v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v4.h[0] +; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h ; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[2] ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[3] -; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: fneg v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NOFP16-NEXT: fneg v1.4s, v2.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v3.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v1.4h, v1.4s ; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v4.h[0] @@ -184,7 +183,6 @@ define <7 x half> @fabs_v7f16(<7 x half> %a) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: fabs_v7f16: diff --git a/llvm/test/CodeGen/AArch64/fpext.ll b/llvm/test/CodeGen/AArch64/fpext.ll index 86f7322f7c4e..24a2451df484 100644 --- a/llvm/test/CodeGen/AArch64/fpext.ll +++ b/llvm/test/CodeGen/AArch64/fpext.ll @@ -168,8 +168,6 @@ define <2 x float> @fpext_v2f16_v2f32(<2 x half> %a) { ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-NEXT: mov h1, v0.h[1] ; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NEXT: fcvtl v0.4s, v0.4h ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/fpow.ll b/llvm/test/CodeGen/AArch64/fpow.ll index 1dd5450c271c..c2ad1aafd65f 100644 --- a/llvm/test/CodeGen/AArch64/fpow.ll +++ b/llvm/test/CodeGen/AArch64/fpow.ll @@ -395,7 +395,6 @@ define <3 x float> @pow_v3f32(<3 x float> %a, <3 x float> %b) { ; CHECK-GI-NEXT: ldp d11, d10, [sp, #32] // 16-byte Folded Reload ; CHECK-GI-NEXT: mov v1.s[1], v2.s[0] ; CHECK-GI-NEXT: mov v1.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v1.s[3], v0.s[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #80 ; CHECK-GI-NEXT: ret @@ -856,7 +855,6 @@ define <7 x half> @pow_v7f16(<7 x half> %a, <7 x half> %b) { ; CHECK-GI-NEXT: ldr q2, [sp, #80] // 16-byte Folded Reload ; CHECK-GI-NEXT: mov v1.h[5], v2.h[0] ; CHECK-GI-NEXT: mov v1.h[6], v0.h[0] -; CHECK-GI-NEXT: mov v1.h[7], v0.h[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #176 ; CHECK-GI-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/fpowi.ll b/llvm/test/CodeGen/AArch64/fpowi.ll index b496c7d15eef..5dbcaa4a5fda 100644 --- a/llvm/test/CodeGen/AArch64/fpowi.ll +++ b/llvm/test/CodeGen/AArch64/fpowi.ll @@ -370,7 +370,6 @@ define <3 x float> @powi_v3f32(<3 x float> %a, i32 %b) { ; CHECK-GI-NEXT: ldp d9, d8, [sp, #32] // 16-byte Folded Reload ; CHECK-GI-NEXT: mov v1.s[1], v2.s[0] ; CHECK-GI-NEXT: mov v1.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v1.s[3], v0.s[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #64 ; CHECK-GI-NEXT: ret @@ -787,7 +786,6 @@ define <7 x half> @powi_v7f16(<7 x half> %a, i32 %b) { ; CHECK-GI-NEXT: mov v1.h[4], v3.h[0] ; CHECK-GI-NEXT: mov v1.h[5], v2.h[0] ; CHECK-GI-NEXT: mov v1.h[6], v0.h[0] -; CHECK-GI-NEXT: mov v1.h[7], v0.h[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #160 ; CHECK-GI-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/fptoi.ll b/llvm/test/CodeGen/AArch64/fptoi.ll index facb89671056..67190e8596c4 100644 --- a/llvm/test/CodeGen/AArch64/fptoi.ll +++ b/llvm/test/CodeGen/AArch64/fptoi.ll @@ -2708,7 +2708,6 @@ define <3 x i16> @fptos_v3f32_v3i16(<3 x float> %a) { ; CHECK-GI-NEXT: mov s2, v0.s[2] ; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-NEXT: mov v0.h[2], v2.h[0] -; CHECK-GI-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret entry: @@ -2730,7 +2729,6 @@ define <3 x i16> @fptou_v3f32_v3i16(<3 x float> %a) { ; CHECK-GI-NEXT: mov s2, v0.s[2] ; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-NEXT: mov v0.h[2], v2.h[0] -; CHECK-GI-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret entry: @@ -3243,8 +3241,6 @@ define <2 x i64> @fptos_v2f16_v2i64(<2 x half> %a) { ; CHECK-GI-NOFP16-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtl v0.4s, v0.4h ; CHECK-GI-NOFP16-NEXT: fcvtl v0.2d, v0.2s ; CHECK-GI-NOFP16-NEXT: fcvtzs v0.2d, v0.2d @@ -3292,8 +3288,6 @@ define <2 x i64> @fptou_v2f16_v2i64(<2 x half> %a) { ; CHECK-GI-NOFP16-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtl v0.4s, v0.4h ; CHECK-GI-NOFP16-NEXT: fcvtl v0.2d, v0.2s ; CHECK-GI-NOFP16-NEXT: fcvtzu v0.2d, v0.2d @@ -4996,8 +4990,6 @@ define <2 x i32> @fptos_v2f16_v2i32(<2 x half> %a) { ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-NEXT: mov h1, v0.h[1] ; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NEXT: fcvtl v0.4s, v0.4h ; CHECK-GI-NEXT: fcvtzs v0.2s, v0.2s ; CHECK-GI-NEXT: ret @@ -5019,8 +5011,6 @@ define <2 x i32> @fptou_v2f16_v2i32(<2 x half> %a) { ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-NEXT: mov h1, v0.h[1] ; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NEXT: fcvtl v0.4s, v0.4h ; CHECK-GI-NEXT: fcvtzu v0.2s, v0.2s ; CHECK-GI-NEXT: ret @@ -5276,8 +5266,6 @@ define <2 x i16> @fptos_v2f16_v2i16(<2 x half> %a) { ; CHECK-GI-NOFP16-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtl v0.4s, v0.4h ; CHECK-GI-NOFP16-NEXT: fcvtzs v0.2s, v0.2s ; CHECK-GI-NOFP16-NEXT: ret @@ -5306,8 +5294,6 @@ define <2 x i16> @fptou_v2f16_v2i16(<2 x half> %a) { ; CHECK-GI-NOFP16-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtl v0.4s, v0.4h ; CHECK-GI-NOFP16-NEXT: fcvtzu v0.2s, v0.2s ; CHECK-GI-NOFP16-NEXT: ret @@ -5344,7 +5330,6 @@ define <3 x i16> @fptos_v3f16_v3i16(<3 x half> %a) { ; CHECK-GI-NOFP16-NEXT: mov s2, v0.s[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v2.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NOFP16-NEXT: ret ; @@ -5378,7 +5363,6 @@ define <3 x i16> @fptou_v3f16_v3i16(<3 x half> %a) { ; CHECK-GI-NOFP16-NEXT: mov s2, v0.s[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v2.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NOFP16-NEXT: ret ; @@ -5756,8 +5740,6 @@ define <2 x i8> @fptos_v2f16_v2i8(<2 x half> %a) { ; CHECK-GI-NOFP16-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtl v0.4s, v0.4h ; CHECK-GI-NOFP16-NEXT: fcvtzs v0.2s, v0.2s ; CHECK-GI-NOFP16-NEXT: ret @@ -5786,8 +5768,6 @@ define <2 x i8> @fptou_v2f16_v2i8(<2 x half> %a) { ; CHECK-GI-NOFP16-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: fcvtl v0.4s, v0.4h ; CHECK-GI-NOFP16-NEXT: fcvtzu v0.2s, v0.2s ; CHECK-GI-NOFP16-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/fptrunc.ll b/llvm/test/CodeGen/AArch64/fptrunc.ll index 3efc98ab5fd5..9d0672d1c95e 100644 --- a/llvm/test/CodeGen/AArch64/fptrunc.ll +++ b/llvm/test/CodeGen/AArch64/fptrunc.ll @@ -63,7 +63,6 @@ define <3 x float> @fptrunc_v3f64_v3f32(<3 x double> %a) { ; CHECK-GI-NEXT: mov s1, v0.s[1] ; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] ; CHECK-GI-NEXT: mov v0.s[2], v2.s[0] -; CHECK-GI-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NEXT: ret entry: %c = fptrunc <3 x double> %a to <3 x float> @@ -94,8 +93,6 @@ define <2 x half> @fptrunc_v2f64_v2f16(<2 x double> %a) { ; CHECK-GI-NEXT: fcvt h0, d0 ; CHECK-GI-NEXT: fcvt h1, d1 ; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret entry: @@ -121,7 +118,6 @@ define <3 x half> @fptrunc_v3f64_v3f16(<3 x double> %a) { ; CHECK-GI-NEXT: fcvt h2, d2 ; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-NEXT: mov v0.h[2], v2.h[0] -; CHECK-GI-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret entry: @@ -167,13 +163,9 @@ define <2 x half> @fptrunc_v2f32_v2f16(<2 x float> %a) { ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-NEXT: mov s1, v0.s[1] ; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] -; CHECK-GI-NEXT: mov v0.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NEXT: fcvtn v0.4h, v0.4s ; CHECK-GI-NEXT: mov h1, v0.h[1] ; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret entry: diff --git a/llvm/test/CodeGen/AArch64/frem.ll b/llvm/test/CodeGen/AArch64/frem.ll index 03caf0a33eb4..1a10fd2f1cdc 100644 --- a/llvm/test/CodeGen/AArch64/frem.ll +++ b/llvm/test/CodeGen/AArch64/frem.ll @@ -397,7 +397,6 @@ define <3 x float> @frem_v3f32(<3 x float> %a, <3 x float> %b) { ; CHECK-GI-NEXT: ldp d11, d10, [sp, #32] // 16-byte Folded Reload ; CHECK-GI-NEXT: mov v1.s[1], v2.s[0] ; CHECK-GI-NEXT: mov v1.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v1.s[3], v0.s[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #80 ; CHECK-GI-NEXT: ret @@ -858,7 +857,6 @@ define <7 x half> @frem_v7f16(<7 x half> %a, <7 x half> %b) { ; CHECK-GI-NEXT: ldr q2, [sp, #80] // 16-byte Folded Reload ; CHECK-GI-NEXT: mov v1.h[5], v2.h[0] ; CHECK-GI-NEXT: mov v1.h[6], v0.h[0] -; CHECK-GI-NEXT: mov v1.h[7], v0.h[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #176 ; CHECK-GI-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/fsincos.ll b/llvm/test/CodeGen/AArch64/fsincos.ll index 2c76d969d6ef..2ab1610edcc7 100644 --- a/llvm/test/CodeGen/AArch64/fsincos.ll +++ b/llvm/test/CodeGen/AArch64/fsincos.ll @@ -332,7 +332,6 @@ define <3 x float> @sin_v3f32(<3 x float> %a) { ; CHECK-GI-NEXT: ldp d9, d8, [sp, #32] // 16-byte Folded Reload ; CHECK-GI-NEXT: mov v1.s[1], v2.s[0] ; CHECK-GI-NEXT: mov v1.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v1.s[3], v0.s[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #64 ; CHECK-GI-NEXT: ret @@ -703,7 +702,6 @@ define <7 x half> @sin_v7f16(<7 x half> %a) { ; CHECK-GI-NEXT: mov v1.h[4], v3.h[0] ; CHECK-GI-NEXT: mov v1.h[5], v2.h[0] ; CHECK-GI-NEXT: mov v1.h[6], v0.h[0] -; CHECK-GI-NEXT: mov v1.h[7], v0.h[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #160 ; CHECK-GI-NEXT: ret @@ -1591,7 +1589,6 @@ define <3 x float> @cos_v3f32(<3 x float> %a) { ; CHECK-GI-NEXT: ldp d9, d8, [sp, #32] // 16-byte Folded Reload ; CHECK-GI-NEXT: mov v1.s[1], v2.s[0] ; CHECK-GI-NEXT: mov v1.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v1.s[3], v0.s[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #64 ; CHECK-GI-NEXT: ret @@ -1962,7 +1959,6 @@ define <7 x half> @cos_v7f16(<7 x half> %a) { ; CHECK-GI-NEXT: mov v1.h[4], v3.h[0] ; CHECK-GI-NEXT: mov v1.h[5], v2.h[0] ; CHECK-GI-NEXT: mov v1.h[6], v0.h[0] -; CHECK-GI-NEXT: mov v1.h[7], v0.h[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: add sp, sp, #160 ; CHECK-GI-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/fsqrt.ll b/llvm/test/CodeGen/AArch64/fsqrt.ll index 683544a69ebe..4b48bcc5508d 100644 --- a/llvm/test/CodeGen/AArch64/fsqrt.ll +++ b/llvm/test/CodeGen/AArch64/fsqrt.ll @@ -195,17 +195,16 @@ define <7 x half> @sqrt_v7f16(<7 x half> %a) { ; ; CHECK-GI-NOFP16-LABEL: sqrt_v7f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry -; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[4] -; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[5] -; CHECK-GI-NOFP16-NEXT: fcvtl v3.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v0.4h +; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[4] +; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[5] ; CHECK-GI-NOFP16-NEXT: mov h0, v0.h[6] -; CHECK-GI-NOFP16-NEXT: mov v1.h[1], v2.h[0] -; CHECK-GI-NOFP16-NEXT: fsqrt v2.4s, v3.4s -; CHECK-GI-NOFP16-NEXT: mov v1.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v1.h[3], v0.h[0] -; CHECK-GI-NOFP16-NEXT: fcvtl v1.4s, v1.4h -; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v2.4s ; CHECK-GI-NOFP16-NEXT: fsqrt v1.4s, v1.4s +; CHECK-GI-NOFP16-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NOFP16-NEXT: mov v2.h[2], v0.h[0] +; CHECK-GI-NOFP16-NEXT: fcvtl v2.4s, v2.4h +; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v1.4s +; CHECK-GI-NOFP16-NEXT: fsqrt v1.4s, v2.4s ; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov h3, v0.h[2] ; CHECK-GI-NOFP16-NEXT: mov h4, v0.h[3] @@ -218,7 +217,6 @@ define <7 x half> @sqrt_v7f16(<7 x half> %a) { ; CHECK-GI-NOFP16-NEXT: mov h1, v1.h[2] ; CHECK-GI-NOFP16-NEXT: mov v0.h[5], v2.h[0] ; CHECK-GI-NOFP16-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NOFP16-NEXT: ret ; ; CHECK-GI-FP16-LABEL: sqrt_v7f16: diff --git a/llvm/test/CodeGen/AArch64/icmp.ll b/llvm/test/CodeGen/AArch64/icmp.ll index 2e8c93a00a0d..e7352fe03d01 100644 --- a/llvm/test/CodeGen/AArch64/icmp.ll +++ b/llvm/test/CodeGen/AArch64/icmp.ll @@ -177,15 +177,13 @@ define <3 x i32> @v3i32_i32(<3 x i32> %a, <3 x i32> %b, <3 x i32> %d, <3 x i32> ; CHECK-GI-NEXT: mov v4.s[1], w8 ; CHECK-GI-NEXT: mov v4.s[2], w8 ; CHECK-GI-NEXT: mov w8, #-1 // =0xffffffff -; CHECK-GI-NEXT: fmov s5, w8 -; CHECK-GI-NEXT: mov v5.s[1], w8 -; CHECK-GI-NEXT: mov v4.s[3], w8 -; CHECK-GI-NEXT: mov v5.s[2], w8 -; CHECK-GI-NEXT: neg v1.4s, v4.4s +; CHECK-GI-NEXT: fmov s1, w8 +; CHECK-GI-NEXT: mov v1.s[1], w8 +; CHECK-GI-NEXT: neg v5.4s, v4.4s ; CHECK-GI-NEXT: ushl v0.4s, v0.4s, v4.4s -; CHECK-GI-NEXT: mov v5.s[3], w8 -; CHECK-GI-NEXT: sshl v0.4s, v0.4s, v1.4s -; CHECK-GI-NEXT: eor v1.16b, v0.16b, v5.16b +; CHECK-GI-NEXT: mov v1.s[2], w8 +; CHECK-GI-NEXT: sshl v0.4s, v0.4s, v5.4s +; CHECK-GI-NEXT: eor v1.16b, v0.16b, v1.16b ; CHECK-GI-NEXT: and v0.16b, v2.16b, v0.16b ; CHECK-GI-NEXT: and v1.16b, v3.16b, v1.16b ; CHECK-GI-NEXT: orr v0.16b, v0.16b, v1.16b diff --git a/llvm/test/CodeGen/AArch64/insertextract.ll b/llvm/test/CodeGen/AArch64/insertextract.ll index b0df5cb3d837..5c2dd761bdc0 100644 --- a/llvm/test/CodeGen/AArch64/insertextract.ll +++ b/llvm/test/CodeGen/AArch64/insertextract.ll @@ -233,7 +233,6 @@ define <3 x float> @insert_v3f32_0(<3 x float> %a, float %b, i32 %c) { ; CHECK-GI-NEXT: mov s0, v0.s[2] ; CHECK-GI-NEXT: mov v1.s[1], v2.s[0] ; CHECK-GI-NEXT: mov v1.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v1.s[3], v0.s[0] ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: ret entry: @@ -254,7 +253,6 @@ define <3 x float> @insert_v3f32_2(<3 x float> %a, float %b, i32 %c) { ; CHECK-GI-NEXT: // kill: def $s1 killed $s1 def $q1 ; CHECK-GI-NEXT: mov v0.s[1], v2.s[0] ; CHECK-GI-NEXT: mov v0.s[2], v1.s[0] -; CHECK-GI-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NEXT: ret entry: %d = insertelement <3 x float> %a, float %b, i32 2 @@ -766,7 +764,6 @@ define <3 x i32> @insert_v3i32_0(<3 x i32> %a, i32 %b, i32 %c) { ; CHECK-GI-NEXT: mov v0.s[1], w8 ; CHECK-GI-NEXT: fmov w8, s2 ; CHECK-GI-NEXT: mov v0.s[2], w8 -; CHECK-GI-NEXT: mov v0.s[3], w8 ; CHECK-GI-NEXT: ret entry: %d = insertelement <3 x i32> %a, i32 %b, i32 0 @@ -785,7 +782,6 @@ define <3 x i32> @insert_v3i32_2(<3 x i32> %a, i32 %b, i32 %c) { ; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] ; CHECK-GI-NEXT: fmov s1, w0 ; CHECK-GI-NEXT: mov v0.s[2], v1.s[0] -; CHECK-GI-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NEXT: ret entry: %d = insertelement <3 x i32> %a, i32 %b, i32 2 diff --git a/llvm/test/CodeGen/AArch64/itofp.ll b/llvm/test/CodeGen/AArch64/itofp.ll index 708bb43887f8..2164c2aad201 100644 --- a/llvm/test/CodeGen/AArch64/itofp.ll +++ b/llvm/test/CodeGen/AArch64/itofp.ll @@ -2605,7 +2605,6 @@ define <3 x float> @stofp_v3i64_v3f32(<3 x i64> %a) { ; CHECK-GI-NEXT: mov s2, v0.s[1] ; CHECK-GI-NEXT: mov v0.s[1], v2.s[0] ; CHECK-GI-NEXT: mov v0.s[2], v1.s[0] -; CHECK-GI-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NEXT: ret entry: %c = sitofp <3 x i64> %a to <3 x float> @@ -2638,7 +2637,6 @@ define <3 x float> @utofp_v3i64_v3f32(<3 x i64> %a) { ; CHECK-GI-NEXT: mov s2, v0.s[1] ; CHECK-GI-NEXT: mov v0.s[1], v2.s[0] ; CHECK-GI-NEXT: mov v0.s[2], v1.s[0] -; CHECK-GI-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NEXT: ret entry: %c = uitofp <3 x i64> %a to <3 x float> @@ -3754,13 +3752,9 @@ define <2 x half> @stofp_v2i64_v2f16(<2 x i64> %a) { ; CHECK-GI-NOFP16-NEXT: fcvtn v0.2s, v0.2d ; CHECK-GI-NOFP16-NEXT: mov s1, v0.s[1] ; CHECK-GI-NOFP16-NEXT: mov v0.s[1], v1.s[0] -; CHECK-GI-NOFP16-NEXT: mov v0.s[2], v0.s[0] -; CHECK-GI-NOFP16-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v0.4s ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NOFP16-NEXT: ret ; @@ -3771,8 +3765,6 @@ define <2 x half> @stofp_v2i64_v2f16(<2 x i64> %a) { ; CHECK-GI-FP16-NEXT: fcvt h0, d0 ; CHECK-GI-FP16-NEXT: fcvt h1, d1 ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-FP16-NEXT: ret entry: @@ -3809,13 +3801,9 @@ define <2 x half> @utofp_v2i64_v2f16(<2 x i64> %a) { ; CHECK-GI-NOFP16-NEXT: fcvtn v0.2s, v0.2d ; CHECK-GI-NOFP16-NEXT: mov s1, v0.s[1] ; CHECK-GI-NOFP16-NEXT: mov v0.s[1], v1.s[0] -; CHECK-GI-NOFP16-NEXT: mov v0.s[2], v0.s[0] -; CHECK-GI-NOFP16-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v0.4s ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NOFP16-NEXT: ret ; @@ -3826,8 +3814,6 @@ define <2 x half> @utofp_v2i64_v2f16(<2 x i64> %a) { ; CHECK-GI-FP16-NEXT: fcvt h0, d0 ; CHECK-GI-FP16-NEXT: fcvt h1, d1 ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-FP16-NEXT: ret entry: @@ -3876,7 +3862,6 @@ define <3 x half> @stofp_v3i64_v3f16(<3 x i64> %a) { ; CHECK-GI-FP16-NEXT: fcvt h1, d1 ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-FP16-NEXT: mov v0.h[2], v2.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-FP16-NEXT: ret entry: @@ -3925,7 +3910,6 @@ define <3 x half> @utofp_v3i64_v3f16(<3 x i64> %a) { ; CHECK-GI-FP16-NEXT: fcvt h1, d1 ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-FP16-NEXT: mov v0.h[2], v2.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-FP16-NEXT: ret entry: @@ -4756,13 +4740,9 @@ define <2 x half> @stofp_v2i32_v2f16(<2 x i32> %a) { ; CHECK-GI-NEXT: scvtf v0.2s, v0.2s ; CHECK-GI-NEXT: mov s1, v0.s[1] ; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] -; CHECK-GI-NEXT: mov v0.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NEXT: fcvtn v0.4h, v0.4s ; CHECK-GI-NEXT: mov h1, v0.h[1] ; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret entry: @@ -4783,13 +4763,9 @@ define <2 x half> @utofp_v2i32_v2f16(<2 x i32> %a) { ; CHECK-GI-NEXT: ucvtf v0.2s, v0.2s ; CHECK-GI-NEXT: mov s1, v0.s[1] ; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] -; CHECK-GI-NEXT: mov v0.s[2], v0.s[0] -; CHECK-GI-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NEXT: fcvtn v0.4h, v0.4s ; CHECK-GI-NEXT: mov h1, v0.h[1] ; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret entry: @@ -4997,13 +4973,9 @@ define <2 x half> @stofp_v2i16_v2f16(<2 x i16> %a) { ; CHECK-GI-NOFP16-NEXT: scvtf v0.2s, v0.2s ; CHECK-GI-NOFP16-NEXT: mov s1, v0.s[1] ; CHECK-GI-NOFP16-NEXT: mov v0.s[1], v1.s[0] -; CHECK-GI-NOFP16-NEXT: mov v0.s[2], v0.s[0] -; CHECK-GI-NOFP16-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v0.4s ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NOFP16-NEXT: ret ; @@ -5012,13 +4984,9 @@ define <2 x half> @stofp_v2i16_v2f16(<2 x i16> %a) { ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-FP16-NEXT: mov s1, v0.s[1] ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: scvtf v0.4h, v0.4h ; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-FP16-NEXT: ret entry: @@ -5048,13 +5016,9 @@ define <2 x half> @utofp_v2i16_v2f16(<2 x i16> %a) { ; CHECK-GI-NOFP16-NEXT: ucvtf v0.2s, v0.2s ; CHECK-GI-NOFP16-NEXT: mov s1, v0.s[1] ; CHECK-GI-NOFP16-NEXT: mov v0.s[1], v1.s[0] -; CHECK-GI-NOFP16-NEXT: mov v0.s[2], v0.s[0] -; CHECK-GI-NOFP16-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v0.4s ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NOFP16-NEXT: ret ; @@ -5063,13 +5027,9 @@ define <2 x half> @utofp_v2i16_v2f16(<2 x i16> %a) { ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-FP16-NEXT: mov s1, v0.s[1] ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: ucvtf v0.4h, v0.4h ; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-FP16-NEXT: ret entry: @@ -5551,13 +5511,9 @@ define <2 x half> @stofp_v2i8_v2f16(<2 x i8> %a) { ; CHECK-GI-NOFP16-NEXT: scvtf v0.2s, v0.2s ; CHECK-GI-NOFP16-NEXT: mov s1, v0.s[1] ; CHECK-GI-NOFP16-NEXT: mov v0.s[1], v1.s[0] -; CHECK-GI-NOFP16-NEXT: mov v0.s[2], v0.s[0] -; CHECK-GI-NOFP16-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v0.4s ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NOFP16-NEXT: ret ; @@ -5566,19 +5522,13 @@ define <2 x half> @stofp_v2i8_v2f16(<2 x i8> %a) { ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-FP16-NEXT: mov s1, v0.s[1] ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-GI-FP16-NEXT: sshr v0.4h, v0.4h, #8 ; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: scvtf v0.4h, v0.4h ; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-FP16-NEXT: ret entry: @@ -5622,13 +5572,9 @@ define <2 x half> @utofp_v2i8_v2f16(<2 x i8> %a) { ; CHECK-GI-NOFP16-NEXT: ucvtf v0.2s, v0.2s ; CHECK-GI-NOFP16-NEXT: mov s1, v0.s[1] ; CHECK-GI-NOFP16-NEXT: mov v0.s[1], v1.s[0] -; CHECK-GI-NOFP16-NEXT: mov v0.s[2], v0.s[0] -; CHECK-GI-NOFP16-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v0.4s ; CHECK-GI-NOFP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NOFP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NOFP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NOFP16-NEXT: ret ; @@ -5638,13 +5584,9 @@ define <2 x half> @utofp_v2i8_v2f16(<2 x i8> %a) { ; CHECK-GI-FP16-NEXT: and v0.8b, v0.8b, v1.8b ; CHECK-GI-FP16-NEXT: mov s1, v0.s[1] ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: ucvtf v0.4h, v0.4h ; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-FP16-NEXT: ret entry: @@ -5694,7 +5636,6 @@ define <3 x half> @stofp_v3i8_v3f16(<3 x i8> %a) { ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-FP16-NEXT: fmov s1, w2 ; CHECK-GI-FP16-NEXT: mov v0.h[2], v1.h[0] -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-GI-FP16-NEXT: sshr v0.4h, v0.4h, #8 ; CHECK-GI-FP16-NEXT: scvtf v0.4h, v0.4h @@ -5744,7 +5685,6 @@ define <3 x half> @utofp_v3i8_v3f16(<3 x i8> %a) { ; CHECK-GI-FP16-NEXT: fmov s1, w2 ; CHECK-GI-FP16-NEXT: mov v0.h[2], v1.h[0] ; CHECK-GI-FP16-NEXT: movi d1, #0xff00ff00ff00ff -; CHECK-GI-FP16-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-FP16-NEXT: and v0.8b, v0.8b, v1.8b ; CHECK-GI-FP16-NEXT: ucvtf v0.4h, v0.4h ; CHECK-GI-FP16-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/llvm.exp10.ll b/llvm/test/CodeGen/AArch64/llvm.exp10.ll index 70df88ba9f89..56f4272c4363 100644 --- a/llvm/test/CodeGen/AArch64/llvm.exp10.ll +++ b/llvm/test/CodeGen/AArch64/llvm.exp10.ll @@ -109,14 +109,11 @@ define <2 x half> @exp10_v2f16(<2 x half> %x) { ; GISEL-NEXT: str q0, [sp] // 16-byte Folded Spill ; GISEL-NEXT: fmov s0, s1 ; GISEL-NEXT: bl exp10f -; GISEL-NEXT: fcvt h0, s0 -; GISEL-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; GISEL-NEXT: fcvt h1, s0 +; GISEL-NEXT: ldr q0, [sp] // 16-byte Folded Reload ; GISEL-NEXT: ldr x30, [sp, #24] // 8-byte Folded Reload ; GISEL-NEXT: ldr d8, [sp, #16] // 8-byte Folded Reload -; GISEL-NEXT: mov v1.h[1], v0.h[0] -; GISEL-NEXT: mov v1.h[2], v0.h[0] -; GISEL-NEXT: mov v1.h[3], v0.h[0] -; GISEL-NEXT: mov v0.16b, v1.16b +; GISEL-NEXT: mov v0.h[1], v1.h[0] ; GISEL-NEXT: // kill: def $d0 killed $d0 killed $q0 ; GISEL-NEXT: add sp, sp, #32 ; GISEL-NEXT: ret @@ -196,7 +193,6 @@ define <3 x half> @exp10_v3f16(<3 x half> %x) { ; GISEL-NEXT: ldr x30, [sp, #48] // 8-byte Folded Reload ; GISEL-NEXT: mov v1.h[1], v2.h[0] ; GISEL-NEXT: mov v1.h[2], v0.h[0] -; GISEL-NEXT: mov v1.h[3], v0.h[0] ; GISEL-NEXT: mov v0.16b, v1.16b ; GISEL-NEXT: // kill: def $d0 killed $d0 killed $q0 ; GISEL-NEXT: add sp, sp, #64 @@ -440,7 +436,6 @@ define <3 x float> @exp10_v3f32(<3 x float> %x) { ; GISEL-NEXT: ldp d9, d8, [sp, #32] // 16-byte Folded Reload ; GISEL-NEXT: mov v1.s[1], v2.s[0] ; GISEL-NEXT: mov v1.s[2], v0.s[0] -; GISEL-NEXT: mov v1.s[3], v0.s[0] ; GISEL-NEXT: mov v0.16b, v1.16b ; GISEL-NEXT: add sp, sp, #64 ; GISEL-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/load.ll b/llvm/test/CodeGen/AArch64/load.ll index 7f4540d915ab..39143e5c53ff 100644 --- a/llvm/test/CodeGen/AArch64/load.ll +++ b/llvm/test/CodeGen/AArch64/load.ll @@ -245,7 +245,6 @@ define <7 x i8> @load_v7i8(ptr %ptr){ ; CHECK-GI-NEXT: mov v0.b[5], v1.b[0] ; CHECK-GI-NEXT: ldr b1, [x0, #6] ; CHECK-GI-NEXT: mov v0.b[6], v1.b[0] -; CHECK-GI-NEXT: mov v0.b[7], v0.b[0] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret %a = load <7 x i8>, ptr %ptr @@ -265,7 +264,6 @@ define <3 x i16> @load_v3i16(ptr %ptr){ ; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-NEXT: ldr h1, [x0, #4] ; CHECK-GI-NEXT: mov v0.h[2], v1.h[0] -; CHECK-GI-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret %a = load <3 x i16>, ptr %ptr @@ -293,7 +291,6 @@ define <7 x i16> @load_v7i16(ptr %ptr){ ; CHECK-GI-NEXT: mov v0.h[5], v1.h[0] ; CHECK-GI-NEXT: ldr h1, [x0, #12] ; CHECK-GI-NEXT: mov v0.h[6], v1.h[0] -; CHECK-GI-NEXT: mov v0.h[7], v0.h[0] ; CHECK-GI-NEXT: ret %a = load <7 x i16>, ptr %ptr ret <7 x i16> %a @@ -311,7 +308,6 @@ define <3 x i32> @load_v3i32(ptr %ptr){ ; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] ; CHECK-GI-NEXT: ldr s1, [x0, #8] ; CHECK-GI-NEXT: mov v0.s[2], v1.s[0] -; CHECK-GI-NEXT: mov v0.s[3], v0.s[0] ; CHECK-GI-NEXT: ret %a = load <3 x i32>, ptr %ptr ret <3 x i32> %a diff --git a/llvm/test/CodeGen/AArch64/sext.ll b/llvm/test/CodeGen/AArch64/sext.ll index f319721e0f2f..61f04fbf0484 100644 --- a/llvm/test/CodeGen/AArch64/sext.ll +++ b/llvm/test/CodeGen/AArch64/sext.ll @@ -222,7 +222,6 @@ define <3 x i16> @sext_v3i8_v3i16(<3 x i8> %a) { ; CHECK-GI-NEXT: fmov s0, w0 ; CHECK-GI-NEXT: mov v0.s[1], w1 ; CHECK-GI-NEXT: mov v0.s[2], w2 -; CHECK-GI-NEXT: mov v0.s[3], w8 ; CHECK-GI-NEXT: xtn v0.4h, v0.4s ; CHECK-GI-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-GI-NEXT: sshr v0.4h, v0.4h, #8 @@ -252,8 +251,6 @@ define <3 x i32> @sext_v3i8_v3i32(<3 x i8> %a) { ; CHECK-GI-NEXT: mov v0.s[1], w8 ; CHECK-GI-NEXT: mov v1.s[2], w2 ; CHECK-GI-NEXT: mov v0.s[2], w8 -; CHECK-GI-NEXT: mov v1.s[3], w8 -; CHECK-GI-NEXT: mov v0.s[3], w8 ; CHECK-GI-NEXT: neg v2.4s, v0.4s ; CHECK-GI-NEXT: ushl v0.4s, v1.4s, v0.4s ; CHECK-GI-NEXT: sshl v0.4s, v0.4s, v2.4s @@ -315,7 +312,6 @@ define <3 x i32> @sext_v3i16_v3i32(<3 x i16> %a) { ; CHECK-GI-NEXT: smov w8, v0.h[2] ; CHECK-GI-NEXT: mov v1.s[1], w9 ; CHECK-GI-NEXT: mov v1.s[2], w8 -; CHECK-GI-NEXT: mov v1.s[3], w8 ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: ret entry: @@ -390,7 +386,6 @@ define <3 x i16> @sext_v3i10_v3i16(<3 x i10> %a) { ; CHECK-GI-NEXT: fmov s0, w0 ; CHECK-GI-NEXT: mov v0.s[1], w1 ; CHECK-GI-NEXT: mov v0.s[2], w2 -; CHECK-GI-NEXT: mov v0.s[3], w8 ; CHECK-GI-NEXT: xtn v0.4h, v0.4s ; CHECK-GI-NEXT: shl v0.4h, v0.4h, #6 ; CHECK-GI-NEXT: sshr v0.4h, v0.4h, #6 @@ -420,8 +415,6 @@ define <3 x i32> @sext_v3i10_v3i32(<3 x i10> %a) { ; CHECK-GI-NEXT: mov v0.s[1], w8 ; CHECK-GI-NEXT: mov v1.s[2], w2 ; CHECK-GI-NEXT: mov v0.s[2], w8 -; CHECK-GI-NEXT: mov v1.s[3], w8 -; CHECK-GI-NEXT: mov v0.s[3], w8 ; CHECK-GI-NEXT: neg v2.4s, v0.4s ; CHECK-GI-NEXT: ushl v0.4s, v1.4s, v0.4s ; CHECK-GI-NEXT: sshl v0.4s, v0.4s, v2.4s diff --git a/llvm/test/CodeGen/AArch64/shift.ll b/llvm/test/CodeGen/AArch64/shift.ll index ccc06f2e1058..5287839ee7b7 100644 --- a/llvm/test/CodeGen/AArch64/shift.ll +++ b/llvm/test/CodeGen/AArch64/shift.ll @@ -594,7 +594,6 @@ define <1 x i32> @shl_v1i32(<1 x i32> %0, <1 x i32> %1){ ; CHECK-GI-NEXT: fmov w9, s1 ; CHECK-GI-NEXT: lsl w8, w8, w9 ; CHECK-GI-NEXT: fmov s0, w8 -; CHECK-GI-NEXT: mov v0.s[1], w8 ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret %3 = shl <1 x i32> %0, %1 @@ -697,7 +696,6 @@ define <1 x i32> @ashr_v1i32(<1 x i32> %0, <1 x i32> %1){ ; CHECK-GI-NEXT: fmov w9, s1 ; CHECK-GI-NEXT: asr w8, w8, w9 ; CHECK-GI-NEXT: fmov s0, w8 -; CHECK-GI-NEXT: mov v0.s[1], w8 ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret %3 = ashr <1 x i32> %0, %1 @@ -790,7 +788,6 @@ define <1 x i32> @lshr_v1i32(<1 x i32> %0, <1 x i32> %1){ ; CHECK-GI-NEXT: fmov w9, s1 ; CHECK-GI-NEXT: lsr w8, w8, w9 ; CHECK-GI-NEXT: fmov s0, w8 -; CHECK-GI-NEXT: mov v0.s[1], w8 ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret %3 = lshr <1 x i32> %0, %1 @@ -851,16 +848,6 @@ define <3 x i8> @shl_v3i8(<3 x i8> %0, <3 x i8> %1){ ; CHECK-GI-NEXT: fmov s3, w5 ; CHECK-GI-NEXT: mov v0.b[2], v1.b[0] ; CHECK-GI-NEXT: mov v2.b[2], v3.b[0] -; CHECK-GI-NEXT: mov v0.b[3], v0.b[0] -; CHECK-GI-NEXT: mov v2.b[3], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[4], v0.b[0] -; CHECK-GI-NEXT: mov v2.b[4], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[5], v0.b[0] -; CHECK-GI-NEXT: mov v2.b[5], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[6], v0.b[0] -; CHECK-GI-NEXT: mov v2.b[6], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[7], v0.b[0] -; CHECK-GI-NEXT: mov v2.b[7], v0.b[0] ; CHECK-GI-NEXT: ushl v0.8b, v0.8b, v2.8b ; CHECK-GI-NEXT: umov w0, v0.b[0] ; CHECK-GI-NEXT: umov w1, v0.b[1] @@ -937,16 +924,6 @@ define <3 x i8> @ashr_v3i8(<3 x i8> %0, <3 x i8> %1){ ; CHECK-GI-NEXT: mov v0.b[2], v2.b[0] ; CHECK-GI-NEXT: fmov s2, w2 ; CHECK-GI-NEXT: mov v1.b[2], v2.b[0] -; CHECK-GI-NEXT: mov v0.b[3], v0.b[0] -; CHECK-GI-NEXT: mov v1.b[3], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[4], v0.b[0] -; CHECK-GI-NEXT: mov v1.b[4], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[5], v0.b[0] -; CHECK-GI-NEXT: mov v1.b[5], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[6], v0.b[0] -; CHECK-GI-NEXT: mov v1.b[6], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[7], v0.b[0] -; CHECK-GI-NEXT: mov v1.b[7], v0.b[0] ; CHECK-GI-NEXT: neg v0.8b, v0.8b ; CHECK-GI-NEXT: sshl v0.8b, v1.8b, v0.8b ; CHECK-GI-NEXT: umov w0, v0.b[0] @@ -1027,16 +1004,6 @@ define <3 x i8> @lshr_v3i8(<3 x i8> %0, <3 x i8> %1){ ; CHECK-GI-NEXT: mov v0.b[2], v2.b[0] ; CHECK-GI-NEXT: fmov s2, w2 ; CHECK-GI-NEXT: mov v1.b[2], v2.b[0] -; CHECK-GI-NEXT: mov v0.b[3], v0.b[0] -; CHECK-GI-NEXT: mov v1.b[3], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[4], v0.b[0] -; CHECK-GI-NEXT: mov v1.b[4], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[5], v0.b[0] -; CHECK-GI-NEXT: mov v1.b[5], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[6], v0.b[0] -; CHECK-GI-NEXT: mov v1.b[6], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[7], v0.b[0] -; CHECK-GI-NEXT: mov v1.b[7], v0.b[0] ; CHECK-GI-NEXT: neg v0.8b, v0.8b ; CHECK-GI-NEXT: ushl v0.8b, v1.8b, v0.8b ; CHECK-GI-NEXT: umov w0, v0.b[0] diff --git a/llvm/test/CodeGen/AArch64/shufflevector.ll b/llvm/test/CodeGen/AArch64/shufflevector.ll index b408bc1c3897..d79f3ae11167 100644 --- a/llvm/test/CodeGen/AArch64/shufflevector.ll +++ b/llvm/test/CodeGen/AArch64/shufflevector.ll @@ -210,8 +210,8 @@ define i32 @shufflevector_v4i8(<4 x i8> %a, <4 x i8> %b){ ; CHECK-GI-LABEL: shufflevector_v4i8: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-GI-NEXT: mov h2, v0.h[1] ; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: mov h2, v0.h[1] ; CHECK-GI-NEXT: mov h3, v1.h[1] ; CHECK-GI-NEXT: adrp x8, .LCPI15_0 ; CHECK-GI-NEXT: mov h4, v0.h[2] @@ -224,14 +224,6 @@ define i32 @shufflevector_v4i8(<4 x i8> %a, <4 x i8> %b){ ; CHECK-GI-NEXT: mov v1.b[2], v2.b[0] ; CHECK-GI-NEXT: mov v0.b[3], v5.b[0] ; CHECK-GI-NEXT: mov v1.b[3], v6.b[0] -; CHECK-GI-NEXT: mov v0.b[4], v0.b[0] -; CHECK-GI-NEXT: mov v1.b[4], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[5], v0.b[0] -; CHECK-GI-NEXT: mov v1.b[5], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[6], v0.b[0] -; CHECK-GI-NEXT: mov v1.b[6], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[7], v0.b[0] -; CHECK-GI-NEXT: mov v1.b[7], v0.b[0] ; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] ; CHECK-GI-NEXT: ldr d1, [x8, :lo12:.LCPI15_0] ; CHECK-GI-NEXT: tbl v0.16b, { v0.16b }, v1.16b @@ -287,16 +279,12 @@ define i32 @shufflevector_v2i16(<2 x i16> %a, <2 x i16> %b){ ; CHECK-GI-LABEL: shufflevector_v2i16: ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-GI-NEXT: mov s2, v0.s[1] ; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: mov s2, v0.s[1] ; CHECK-GI-NEXT: mov s3, v1.s[1] ; CHECK-GI-NEXT: adrp x8, .LCPI17_0 ; CHECK-GI-NEXT: mov v0.h[1], v2.h[0] ; CHECK-GI-NEXT: mov v1.h[1], v3.h[0] -; CHECK-GI-NEXT: mov v0.h[2], v0.h[0] -; CHECK-GI-NEXT: mov v1.h[2], v0.h[0] -; CHECK-GI-NEXT: mov v0.h[3], v0.h[0] -; CHECK-GI-NEXT: mov v1.h[3], v0.h[0] ; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] ; CHECK-GI-NEXT: ldr d1, [x8, :lo12:.LCPI17_0] ; CHECK-GI-NEXT: tbl v0.16b, { v0.16b }, v1.16b @@ -516,16 +504,6 @@ define <3 x i8> @shufflevector_v3i8(<3 x i8> %a, <3 x i8> %b) { ; CHECK-GI-NEXT: mov v0.b[2], v1.b[0] ; CHECK-GI-NEXT: ldr d1, [x8, :lo12:.LCPI30_0] ; CHECK-GI-NEXT: mov v2.b[2], v3.b[0] -; CHECK-GI-NEXT: mov v0.b[3], v0.b[0] -; CHECK-GI-NEXT: mov v2.b[3], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[4], v0.b[0] -; CHECK-GI-NEXT: mov v2.b[4], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[5], v0.b[0] -; CHECK-GI-NEXT: mov v2.b[5], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[6], v0.b[0] -; CHECK-GI-NEXT: mov v2.b[6], v0.b[0] -; CHECK-GI-NEXT: mov v0.b[7], v0.b[0] -; CHECK-GI-NEXT: mov v2.b[7], v0.b[0] ; CHECK-GI-NEXT: mov v0.d[1], v2.d[0] ; CHECK-GI-NEXT: tbl v0.16b, { v0.16b }, v1.16b ; CHECK-GI-NEXT: mov b1, v0.b[1] diff --git a/llvm/test/CodeGen/AArch64/xtn.ll b/llvm/test/CodeGen/AArch64/xtn.ll index 21982fadbe80..3c86f4bf9eb2 100644 --- a/llvm/test/CodeGen/AArch64/xtn.ll +++ b/llvm/test/CodeGen/AArch64/xtn.ll @@ -298,7 +298,6 @@ define <3 x i16> @xtn_v3i32_v3i16(<3 x i32> %a) { ; CHECK-GI-NEXT: mov s2, v0.s[2] ; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-NEXT: mov v0.h[2], v2.h[0] -; CHECK-GI-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret entry: @@ -327,7 +326,6 @@ define <3 x i16> @xtn_v3i64_v3i16(<3 x i64> %a) { ; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-NEXT: fmov s1, w8 ; CHECK-GI-NEXT: mov v0.h[2], v1.h[0] -; CHECK-GI-NEXT: mov v0.h[3], v0.h[0] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret entry: @@ -353,7 +351,6 @@ define <3 x i32> @xtn_v3i64_v3i32(<3 x i64> %a) { ; CHECK-GI-NEXT: fmov x8, d2 ; CHECK-GI-NEXT: mov v0.s[1], w9 ; CHECK-GI-NEXT: mov v0.s[2], w8 -; CHECK-GI-NEXT: mov v0.s[3], w8 ; CHECK-GI-NEXT: ret entry: %arg1 = trunc <3 x i64> %a to <3 x i32> diff --git a/llvm/test/CodeGen/AArch64/zext.ll b/llvm/test/CodeGen/AArch64/zext.ll index e513340f5b18..54b29be2132c 100644 --- a/llvm/test/CodeGen/AArch64/zext.ll +++ b/llvm/test/CodeGen/AArch64/zext.ll @@ -249,10 +249,8 @@ define <3 x i16> @zext_v3i8_v3i16(<3 x i8> %a) { ; CHECK-GI-NEXT: mov v2.16b, v1.16b ; CHECK-GI-NEXT: mov v0.s[2], w2 ; CHECK-GI-NEXT: mov v2.h[1], v1.h[0] -; CHECK-GI-NEXT: mov v0.s[3], w8 -; CHECK-GI-NEXT: mov v2.h[2], v1.h[0] ; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: mov v2.h[3], v0.h[0] +; CHECK-GI-NEXT: mov v2.h[2], v1.h[0] ; CHECK-GI-NEXT: and v0.8b, v0.8b, v2.8b ; CHECK-GI-NEXT: ret entry: @@ -280,8 +278,6 @@ define <3 x i32> @zext_v3i8_v3i32(<3 x i8> %a) { ; CHECK-GI-NEXT: mov v1.s[1], w8 ; CHECK-GI-NEXT: mov v0.s[2], w2 ; CHECK-GI-NEXT: mov v1.s[2], w8 -; CHECK-GI-NEXT: mov v0.s[3], w8 -; CHECK-GI-NEXT: mov v1.s[3], w8 ; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b ; CHECK-GI-NEXT: ret entry: @@ -341,7 +337,6 @@ define <3 x i32> @zext_v3i16_v3i32(<3 x i16> %a) { ; CHECK-GI-NEXT: umov w8, v0.h[2] ; CHECK-GI-NEXT: mov v1.s[1], w9 ; CHECK-GI-NEXT: mov v1.s[2], w8 -; CHECK-GI-NEXT: mov v1.s[3], w8 ; CHECK-GI-NEXT: mov v0.16b, v1.16b ; CHECK-GI-NEXT: ret entry: @@ -420,10 +415,8 @@ define <3 x i16> @zext_v3i10_v3i16(<3 x i10> %a) { ; CHECK-GI-NEXT: mov v2.16b, v1.16b ; CHECK-GI-NEXT: mov v0.s[2], w2 ; CHECK-GI-NEXT: mov v2.h[1], v1.h[0] -; CHECK-GI-NEXT: mov v0.s[3], w8 -; CHECK-GI-NEXT: mov v2.h[2], v1.h[0] ; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: mov v2.h[3], v0.h[0] +; CHECK-GI-NEXT: mov v2.h[2], v1.h[0] ; CHECK-GI-NEXT: and v0.8b, v0.8b, v2.8b ; CHECK-GI-NEXT: ret entry: @@ -451,8 +444,6 @@ define <3 x i32> @zext_v3i10_v3i32(<3 x i10> %a) { ; CHECK-GI-NEXT: mov v1.s[1], w8 ; CHECK-GI-NEXT: mov v0.s[2], w2 ; CHECK-GI-NEXT: mov v1.s[2], w8 -; CHECK-GI-NEXT: mov v0.s[3], w8 -; CHECK-GI-NEXT: mov v1.s[3], w8 ; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b ; CHECK-GI-NEXT: ret entry: -- GitLab From 1dd104db59d145d516a5e9cbb081ed01262961ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 12 Mar 2024 07:47:48 +0100 Subject: [PATCH 209/953] [clang][Interp] Implement _Complex Not unary operators This only happens in C as far as I can tell. The complex varialbe will have undergone a conversion to bool in C++ before reaching the unary operator. --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 11 +++++++++++ clang/test/AST/Interp/complex.c | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 0dd645990d1d..da4a8f88f139 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -3182,6 +3182,17 @@ bool ByteCodeExprGen::VisitComplexUnaryOperator( case UO_AddrOf: return this->delegate(SubExpr); + case UO_LNot: + if (!this->visit(SubExpr)) + return false; + if (!this->emitComplexBoolCast(SubExpr)) + return false; + if (!this->emitInvBool(E)) + return false; + if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool) + return this->emitCast(PT_Bool, ET, E); + return true; + case UO_Real: return this->emitComplexReal(SubExpr); diff --git a/clang/test/AST/Interp/complex.c b/clang/test/AST/Interp/complex.c index c9c2efb59745..b5f30b87baa7 100644 --- a/clang/test/AST/Interp/complex.c +++ b/clang/test/AST/Interp/complex.c @@ -14,3 +14,8 @@ void blah() { _Static_assert((0.0 + 0.0j) == (0.0 + 0.0j), ""); _Static_assert((0.0 + 0.0j) != (0.0 + 0.0j), ""); // both-error {{static assertion}} \ // both-note {{evaluates to}} + +const _Complex float FC = {0.0f, 0.0f}; +_Static_assert(!FC, ""); +const _Complex float FI = {0, 0}; +_Static_assert(!FI, ""); -- GitLab From 103469b5f7467d5df15799c2d8ad150729bc33bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 12 Mar 2024 08:50:51 +0100 Subject: [PATCH 210/953] [clang][Interp] Implement more easy _Complex unary operators --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 25 ++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index da4a8f88f139..86304a54473c 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -3138,16 +3138,17 @@ bool ByteCodeExprGen::VisitComplexUnaryOperator( return this->discard(SubExpr); std::optional ResT = classify(E); + auto prepareResult = [=]() -> bool { + if (!ResT && !Initializing) { + std::optional LocalIndex = + allocateLocal(SubExpr, /*IsExtended=*/false); + if (!LocalIndex) + return false; + return this->emitGetPtrLocal(*LocalIndex, E); + } - // Prepare storage for result. - if (!ResT && !Initializing) { - std::optional LocalIndex = - allocateLocal(SubExpr, /*IsExtended=*/false); - if (!LocalIndex) - return false; - if (!this->emitGetPtrLocal(*LocalIndex, E)) - return false; - } + return true; + }; // The offset of the temporary, if we created one. unsigned SubExprOffset = ~0u; @@ -3167,6 +3168,8 @@ bool ByteCodeExprGen::VisitComplexUnaryOperator( switch (E->getOpcode()) { case UO_Minus: + if (!prepareResult()) + return false; if (!createTemp()) return false; for (unsigned I = 0; I != 2; ++I) { @@ -3179,7 +3182,9 @@ bool ByteCodeExprGen::VisitComplexUnaryOperator( } break; - case UO_AddrOf: + case UO_Plus: // +x + case UO_AddrOf: // &x + case UO_Deref: // *x return this->delegate(SubExpr); case UO_LNot: -- GitLab From 85f6669de59b2bb75c6848afa79de63be988721c Mon Sep 17 00:00:00 2001 From: jeanPerier Date: Tue, 12 Mar 2024 09:04:25 +0100 Subject: [PATCH 211/953] [flang] implement sizeof lowering for polymorphic entities (#84498) For non polymorphic entities, semantics knows the type size and rewrite sizeof to `"cst element size" * size(x)`. Lowering has to deal with the polymorphic case where the type size must be retrieved from the descriptor (note that the lowering implementation would work with any entity, polymorphic on not, it is just not used for the non polymorphic cases). --- .../flang/Optimizer/Builder/IntrinsicCall.h | 1 + flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 18 +++++++++++++++ flang/test/Lower/Intrinsics/sizeof.f90 | 23 +++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 flang/test/Lower/Intrinsics/sizeof.f90 diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h index 7cb99d61a686..ca15b4bc34b2 100644 --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -338,6 +338,7 @@ struct IntrinsicLibrary { mlir::Value genSign(mlir::Type, llvm::ArrayRef); mlir::Value genSind(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genSize(mlir::Type, llvm::ArrayRef); + fir::ExtendedValue genSizeOf(mlir::Type, llvm::ArrayRef); mlir::Value genSpacing(mlir::Type resultType, llvm::ArrayRef args); fir::ExtendedValue genSpread(mlir::Type, llvm::ArrayRef); diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index 2f7ace658e47..ca5ab6fcea34 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -567,6 +567,10 @@ static constexpr IntrinsicHandler handlers[]{ {"dim", asAddr, handleDynamicOptional}, {"kind", asValue}}}, /*isElemental=*/false}, + {"sizeof", + &I::genSizeOf, + {{{"a", asBox}}}, + /*isElemental=*/false}, {"sleep", &I::genSleep, {{{"seconds", asValue}}}, /*isElemental=*/false}, {"spacing", &I::genSpacing}, {"spread", @@ -5946,6 +5950,20 @@ IntrinsicLibrary::genSize(mlir::Type resultType, .getResults()[0]; } +// SIZEOF +fir::ExtendedValue +IntrinsicLibrary::genSizeOf(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 1); + mlir::Value box = fir::getBase(args[0]); + mlir::Value eleSize = builder.create(loc, resultType, box); + if (!fir::isArray(args[0])) + return eleSize; + mlir::Value arraySize = builder.createConvert( + loc, resultType, fir::runtime::genSize(builder, loc, box)); + return builder.create(loc, eleSize, arraySize); +} + // TAND mlir::Value IntrinsicLibrary::genTand(mlir::Type resultType, llvm::ArrayRef args) { diff --git a/flang/test/Lower/Intrinsics/sizeof.f90 b/flang/test/Lower/Intrinsics/sizeof.f90 new file mode 100644 index 000000000000..959ca1692b51 --- /dev/null +++ b/flang/test/Lower/Intrinsics/sizeof.f90 @@ -0,0 +1,23 @@ +! Test SIZEOF lowering for polymorphic entities. +! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s + +integer(8) function test1(x) + class(*) :: x + test1 = sizeof(x) +end function +! CHECK-LABEL: func.func @_QPtest1( +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtest1Ex"} : (!fir.class) -> (!fir.class, !fir.class) +! CHECK: %[[VAL_4:.*]] = fir.box_elesize %[[VAL_3]]#1 : (!fir.class) -> i64 +! CHECK: hlfir.assign %[[VAL_4]] to %{{.*}} : i64, !fir.ref + +integer(8) function test2(x) + class(*) :: x(:, :) + test2 = sizeof(x) +end function +! CHECK-LABEL: func.func @_QPtest2( +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtest2Ex"} : (!fir.class>) -> (!fir.class>, !fir.class>) +! CHECK: %[[VAL_4:.*]] = fir.box_elesize %[[VAL_3]]#1 : (!fir.class>) -> i64 +! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_3]]#1 : (!fir.class>) -> !fir.box +! CHECK: %[[VAL_9:.*]] = fir.call @_FortranASize(%[[VAL_7]], %{{.*}}, %{{.*}}) fastmath : (!fir.box, !fir.ref, i32) -> i64 +! CHECK: %[[VAL_10:.*]] = arith.muli %[[VAL_4]], %[[VAL_9]] : i64 +! CHECK: hlfir.assign %[[VAL_10]] to %{{.*}} : i64, !fir.ref -- GitLab From 8e0f4b943fee13afc970ca8277a8e76b9da63b96 Mon Sep 17 00:00:00 2001 From: Adrian Kuegel Date: Tue, 12 Mar 2024 09:12:44 +0100 Subject: [PATCH 212/953] [NVPTX] Add support for atomic add for f16 type (#84295) atom.add.noftz.f16 is supported since SM 7.0 --- llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp | 3 + llvm/lib/Target/NVPTX/NVPTXIntrinsics.td | 15 +++ llvm/test/CodeGen/NVPTX/atomics-sm70.ll | 121 ++++++++++++++++++++ llvm/test/CodeGen/NVPTX/atomics.ll | 7 ++ 4 files changed, 146 insertions(+) create mode 100644 llvm/test/CodeGen/NVPTX/atomics-sm70.ll diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp index c979c03dc1b8..c411c8ef9528 100644 --- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp @@ -6100,6 +6100,9 @@ NVPTXTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const { if (AI->isFloatingPointOperation()) { if (AI->getOperation() == AtomicRMWInst::BinOp::FAdd) { + if (Ty->isHalfTy() && STI.getSmVersion() >= 70 && + STI.getPTXVersion() >= 63) + return AtomicExpansionKind::None; if (Ty->isFloatTy()) return AtomicExpansionKind::None; if (Ty->isDoubleTy() && STI.hasAtomAddF64()) diff --git a/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td b/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td index 477789a164ea..869b13369e87 100644 --- a/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td +++ b/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td @@ -1630,6 +1630,13 @@ defm INT_PTX_ATOM_ADD_GEN_64 : F_ATOMIC_2; +defm INT_PTX_ATOM_ADD_G_F16 : F_ATOMIC_2, hasPTX<63>]>; +defm INT_PTX_ATOM_ADD_S_F16 : F_ATOMIC_2, hasPTX<63>]>; +defm INT_PTX_ATOM_ADD_GEN_F16 : F_ATOMIC_2, hasPTX<63>]>; + defm INT_PTX_ATOM_ADD_G_F32 : F_ATOMIC_2; defm INT_PTX_ATOM_ADD_S_F32 : F_ATOMIC_2 Preds> { let AddedComplexity = 1 in { + def : ATOM23_impl; def : ATOM23_impl; @@ -2017,6 +2027,9 @@ multiclass ATOM2P_impl; def : ATOM23_impl; @@ -2136,6 +2149,8 @@ multiclass ATOM2_add_impl { defm _s32 : ATOM2S_impl; defm _u32 : ATOM2S_impl; defm _u64 : ATOM2S_impl; + defm _f16 : ATOM2S_impl, hasPTX<63>]>; defm _f32 : ATOM2S_impl; defm _f64 : ATOM2S_impl; +; CHECK-NEXT: .reg .b32 %r<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [test_param_0]; +; CHECK-NEXT: ld.param.b16 %rs1, [test_param_3]; +; CHECK-NEXT: atom.add.noftz.f16 %rs2, [%r1], %rs1; +; CHECK-NEXT: ld.param.u32 %r2, [test_param_1]; +; CHECK-NEXT: atom.global.add.noftz.f16 %rs3, [%r2], %rs1; +; CHECK-NEXT: ld.param.u32 %r3, [test_param_2]; +; CHECK-NEXT: atom.shared.add.noftz.f16 %rs4, [%r3], %rs1; +; CHECK-NEXT: ret; +; +; CHECK64-LABEL: test( +; CHECK64: { +; CHECK64-NEXT: .reg .b16 %rs<5>; +; CHECK64-NEXT: .reg .b64 %rd<4>; +; CHECK64-EMPTY: +; CHECK64-NEXT: // %bb.0: +; CHECK64-NEXT: ld.param.u64 %rd1, [test_param_0]; +; CHECK64-NEXT: ld.param.b16 %rs1, [test_param_3]; +; CHECK64-NEXT: atom.add.noftz.f16 %rs2, [%rd1], %rs1; +; CHECK64-NEXT: ld.param.u64 %rd2, [test_param_1]; +; CHECK64-NEXT: atom.global.add.noftz.f16 %rs3, [%rd2], %rs1; +; CHECK64-NEXT: ld.param.u64 %rd3, [test_param_2]; +; CHECK64-NEXT: atom.shared.add.noftz.f16 %rs4, [%rd3], %rs1; +; CHECK64-NEXT: ret; +; +; CHECKPTX62-LABEL: test( +; CHECKPTX62: { +; CHECKPTX62-NEXT: .reg .pred %p<4>; +; CHECKPTX62-NEXT: .reg .b16 %rs<14>; +; CHECKPTX62-NEXT: .reg .b32 %r<49>; +; CHECKPTX62-EMPTY: +; CHECKPTX62-NEXT: // %bb.0: +; CHECKPTX62-NEXT: ld.param.b16 %rs1, [test_param_3]; +; CHECKPTX62-NEXT: ld.param.u32 %r20, [test_param_2]; +; CHECKPTX62-NEXT: ld.param.u32 %r19, [test_param_1]; +; CHECKPTX62-NEXT: ld.param.u32 %r21, [test_param_0]; +; CHECKPTX62-NEXT: and.b32 %r1, %r21, -4; +; CHECKPTX62-NEXT: and.b32 %r22, %r21, 3; +; CHECKPTX62-NEXT: shl.b32 %r2, %r22, 3; +; CHECKPTX62-NEXT: mov.b32 %r23, 65535; +; CHECKPTX62-NEXT: shl.b32 %r24, %r23, %r2; +; CHECKPTX62-NEXT: not.b32 %r3, %r24; +; CHECKPTX62-NEXT: ld.u32 %r46, [%r1]; +; CHECKPTX62-NEXT: $L__BB0_1: // %atomicrmw.start +; CHECKPTX62-NEXT: // =>This Inner Loop Header: Depth=1 +; CHECKPTX62-NEXT: shr.u32 %r25, %r46, %r2; +; CHECKPTX62-NEXT: cvt.u16.u32 %rs2, %r25; +; CHECKPTX62-NEXT: add.rn.f16 %rs4, %rs2, %rs1; +; CHECKPTX62-NEXT: cvt.u32.u16 %r26, %rs4; +; CHECKPTX62-NEXT: shl.b32 %r27, %r26, %r2; +; CHECKPTX62-NEXT: and.b32 %r28, %r46, %r3; +; CHECKPTX62-NEXT: or.b32 %r29, %r28, %r27; +; CHECKPTX62-NEXT: atom.cas.b32 %r6, [%r1], %r46, %r29; +; CHECKPTX62-NEXT: setp.ne.s32 %p1, %r6, %r46; +; CHECKPTX62-NEXT: mov.u32 %r46, %r6; +; CHECKPTX62-NEXT: @%p1 bra $L__BB0_1; +; CHECKPTX62-NEXT: // %bb.2: // %atomicrmw.end +; CHECKPTX62-NEXT: and.b32 %r7, %r19, -4; +; CHECKPTX62-NEXT: shl.b32 %r30, %r19, 3; +; CHECKPTX62-NEXT: and.b32 %r8, %r30, 24; +; CHECKPTX62-NEXT: shl.b32 %r32, %r23, %r8; +; CHECKPTX62-NEXT: not.b32 %r9, %r32; +; CHECKPTX62-NEXT: ld.global.u32 %r47, [%r7]; +; CHECKPTX62-NEXT: $L__BB0_3: // %atomicrmw.start9 +; CHECKPTX62-NEXT: // =>This Inner Loop Header: Depth=1 +; CHECKPTX62-NEXT: shr.u32 %r33, %r47, %r8; +; CHECKPTX62-NEXT: cvt.u16.u32 %rs6, %r33; +; CHECKPTX62-NEXT: add.rn.f16 %rs8, %rs6, %rs1; +; CHECKPTX62-NEXT: cvt.u32.u16 %r34, %rs8; +; CHECKPTX62-NEXT: shl.b32 %r35, %r34, %r8; +; CHECKPTX62-NEXT: and.b32 %r36, %r47, %r9; +; CHECKPTX62-NEXT: or.b32 %r37, %r36, %r35; +; CHECKPTX62-NEXT: atom.global.cas.b32 %r12, [%r7], %r47, %r37; +; CHECKPTX62-NEXT: setp.ne.s32 %p2, %r12, %r47; +; CHECKPTX62-NEXT: mov.u32 %r47, %r12; +; CHECKPTX62-NEXT: @%p2 bra $L__BB0_3; +; CHECKPTX62-NEXT: // %bb.4: // %atomicrmw.end8 +; CHECKPTX62-NEXT: and.b32 %r13, %r20, -4; +; CHECKPTX62-NEXT: shl.b32 %r38, %r20, 3; +; CHECKPTX62-NEXT: and.b32 %r14, %r38, 24; +; CHECKPTX62-NEXT: shl.b32 %r40, %r23, %r14; +; CHECKPTX62-NEXT: not.b32 %r15, %r40; +; CHECKPTX62-NEXT: ld.shared.u32 %r48, [%r13]; +; CHECKPTX62-NEXT: $L__BB0_5: // %atomicrmw.start27 +; CHECKPTX62-NEXT: // =>This Inner Loop Header: Depth=1 +; CHECKPTX62-NEXT: shr.u32 %r41, %r48, %r14; +; CHECKPTX62-NEXT: cvt.u16.u32 %rs10, %r41; +; CHECKPTX62-NEXT: add.rn.f16 %rs12, %rs10, %rs1; +; CHECKPTX62-NEXT: cvt.u32.u16 %r42, %rs12; +; CHECKPTX62-NEXT: shl.b32 %r43, %r42, %r14; +; CHECKPTX62-NEXT: and.b32 %r44, %r48, %r15; +; CHECKPTX62-NEXT: or.b32 %r45, %r44, %r43; +; CHECKPTX62-NEXT: atom.shared.cas.b32 %r18, [%r13], %r48, %r45; +; CHECKPTX62-NEXT: setp.ne.s32 %p3, %r18, %r48; +; CHECKPTX62-NEXT: mov.u32 %r48, %r18; +; CHECKPTX62-NEXT: @%p3 bra $L__BB0_5; +; CHECKPTX62-NEXT: // %bb.6: // %atomicrmw.end26 +; CHECKPTX62-NEXT: ret; + %r1 = atomicrmw fadd ptr %dp0, half %val seq_cst + %r2 = atomicrmw fadd ptr addrspace(1) %dp1, half %val seq_cst + %ret = atomicrmw fadd ptr addrspace(3) %dp3, half %val seq_cst + ret void +} + +attributes #1 = { argmemonly nounwind } diff --git a/llvm/test/CodeGen/NVPTX/atomics.ll b/llvm/test/CodeGen/NVPTX/atomics.ll index e99d0fd05e34..6f2b5dcf47f1 100644 --- a/llvm/test/CodeGen/NVPTX/atomics.ll +++ b/llvm/test/CodeGen/NVPTX/atomics.ll @@ -175,6 +175,13 @@ define float @atomicrmw_add_f32_generic(ptr %addr, float %val) { ret float %ret } +; CHECK-LABEL: atomicrmw_add_f16_generic +define half @atomicrmw_add_f16_generic(ptr %addr, half %val) { +; CHECK: atom.cas + %ret = atomicrmw fadd ptr %addr, half %val seq_cst + ret half %ret +} + ; CHECK-LABEL: atomicrmw_add_f32_addrspace1 define float @atomicrmw_add_f32_addrspace1(ptr addrspace(1) %addr, float %val) { ; CHECK: atom.global.add.f32 -- GitLab From 36dece001325bbf00129c48ddb3c83668b0ac36e Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Tue, 12 Mar 2024 08:20:08 +0000 Subject: [PATCH 213/953] [AMDGPU] Add missing GFX10 buffer format d16 hi instructions (#84809) --- llvm/lib/Target/AMDGPU/BUFInstructions.td | 5 ++--- llvm/test/MC/AMDGPU/gfx10_asm_mubuf.s | 6 ++++++ llvm/test/MC/Disassembler/AMDGPU/gfx10_mubuf.txt | 6 ++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/BUFInstructions.td b/llvm/lib/Target/AMDGPU/BUFInstructions.td index a1bbe170ee29..c7091028b3b5 100644 --- a/llvm/lib/Target/AMDGPU/BUFInstructions.td +++ b/llvm/lib/Target/AMDGPU/BUFInstructions.td @@ -2691,9 +2691,8 @@ defm BUFFER_LOAD_SBYTE_D16 : MUBUF_Real_AllAddr_gfx10<0x022>; defm BUFFER_LOAD_SBYTE_D16_HI : MUBUF_Real_AllAddr_gfx10<0x023>; defm BUFFER_LOAD_SHORT_D16 : MUBUF_Real_AllAddr_gfx10<0x024>; defm BUFFER_LOAD_SHORT_D16_HI : MUBUF_Real_AllAddr_gfx10<0x025>; -// FIXME-GFX10: Add following instructions: -//defm BUFFER_LOAD_FORMAT_D16_HI_X : MUBUF_Real_AllAddr_gfx10<0x026>; -//defm BUFFER_STORE_FORMAT_D16_HI_X : MUBUF_Real_AllAddr_gfx10<0x027>; +defm BUFFER_LOAD_FORMAT_D16_HI_X : MUBUF_Real_AllAddr_gfx10<0x026>; +defm BUFFER_STORE_FORMAT_D16_HI_X : MUBUF_Real_AllAddr_gfx10<0x027>; defm BUFFER_LOAD_FORMAT_D16_X : MUBUF_Real_AllAddr_gfx10<0x080>; defm BUFFER_LOAD_FORMAT_D16_XY : MUBUF_Real_AllAddr_gfx10<0x081>; defm BUFFER_LOAD_FORMAT_D16_XYZ : MUBUF_Real_AllAddr_gfx10<0x082>; diff --git a/llvm/test/MC/AMDGPU/gfx10_asm_mubuf.s b/llvm/test/MC/AMDGPU/gfx10_asm_mubuf.s index aacdfcb4e871..b77f8e0a3192 100644 --- a/llvm/test/MC/AMDGPU/gfx10_asm_mubuf.s +++ b/llvm/test/MC/AMDGPU/gfx10_asm_mubuf.s @@ -17,6 +17,9 @@ buffer_load_format_d16_xyz v[1:2], off, s[4:7], s1 buffer_load_format_d16_xyzw v[1:2], off, s[4:7], s1 // GFX10: encoding: [0x00,0x00,0x0c,0xe2,0x00,0x01,0x01,0x01] +buffer_load_format_d16_hi_x v1, off, s[4:7], s1 +// GFX10: encoding: [0x00,0x00,0x98,0xe0,0x00,0x01,0x01,0x01] + buffer_load_format_x v5, off, s[8:11], s3 offset:4095 // GFX10: encoding: [0xff,0x0f,0x00,0xe0,0x00,0x05,0x02,0x03] @@ -245,6 +248,9 @@ buffer_store_format_d16_xyz v[1:2], off, s[4:7], s1 buffer_store_format_d16_xyzw v[1:2], off, s[4:7], s1 // GFX10: encoding: [0x00,0x00,0x1c,0xe2,0x00,0x01,0x01,0x01] +buffer_store_format_d16_hi_x v1, off, s[4:7], s1 +// GFX10: encoding: [0x00,0x00,0x9c,0xe0,0x00,0x01,0x01,0x01] + buffer_store_format_x v1, off, s[12:15], s4 offset:4095 // GFX10: encoding: [0xff,0x0f,0x10,0xe0,0x00,0x01,0x03,0x04] diff --git a/llvm/test/MC/Disassembler/AMDGPU/gfx10_mubuf.txt b/llvm/test/MC/Disassembler/AMDGPU/gfx10_mubuf.txt index b0731be4484c..849c89e37011 100644 --- a/llvm/test/MC/Disassembler/AMDGPU/gfx10_mubuf.txt +++ b/llvm/test/MC/Disassembler/AMDGPU/gfx10_mubuf.txt @@ -1328,6 +1328,9 @@ # GFX10: buffer_load_format_d16_xyzw v[1:2], off, s[4:7], s1 ; encoding: [0x00,0x00,0x0c,0xe2,0x00,0x01,0x01,0x01] 0x00,0x00,0x0c,0xe2,0x00,0x01,0x01,0x01 +# GFX10: buffer_load_format_d16_hi_x v1, off, s[4:7], s1 ; encoding: [0x00,0x00,0x98,0xe0,0x00,0x01,0x01,0x01] +0x00,0x00,0x98,0xe0,0x00,0x01,0x01,0x01 + # GFX10: buffer_load_format_x v255, off, s[8:11], s3 offset:4095 ; encoding: [0xff,0x0f,0x00,0xe0,0x00,0xff,0x02,0x03] 0xff,0x0f,0x00,0xe0,0x00,0xff,0x02,0x03 @@ -2039,6 +2042,9 @@ # GFX10: buffer_store_format_d16_xyzw v[1:2], off, s[4:7], s1 ; encoding: [0x00,0x00,0x1c,0xe2,0x00,0x01,0x01,0x01] 0x00,0x00,0x1c,0xe2,0x00,0x01,0x01,0x01 +# GFX10: buffer_store_format_d16_hi_x v1, off, s[4:7], s1 ; encoding: [0x00,0x00,0x9c,0xe0,0x00,0x01,0x01,0x01] +0x00,0x00,0x9c,0xe0,0x00,0x01,0x01,0x01 + # GFX10: buffer_store_format_x v1, off, s[12:15], -1 offset:4095 ; encoding: [0xff,0x0f,0x10,0xe0,0x00,0x01,0x03,0xc1] 0xff,0x0f,0x10,0xe0,0x00,0x01,0x03,0xc1 -- GitLab From 6bbe8a296ee91754d423c59c35727eaa624f7140 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Tue, 12 Mar 2024 01:24:21 -0700 Subject: [PATCH 214/953] [llvm-exegesis] Add thread IDs to subprocess memory names (#84451) This patch adds the thread ID to the subprocess memory shared memory names. This avoids conflicts for downstream consumers that might want to consume llvm-exegesis across multiple threads, which would otherwise run into conflicts due to the same PID running multiple instances. --- .../llvm-exegesis/lib/BenchmarkRunner.cpp | 9 +++--- .../llvm-exegesis/lib/SubprocessMemory.cpp | 28 +++++++++++++------ .../llvm-exegesis/lib/SubprocessMemory.h | 5 +++- .../X86/SubprocessMemoryTest.cpp | 5 +++- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp index 5c9848f3c688..4e97d188d172 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -301,6 +301,7 @@ private: if (AddMemDefError) return AddMemDefError; + long ParentTID = SubprocessMemory::getCurrentTID(); pid_t ParentOrChildPID = fork(); if (ParentOrChildPID == -1) { @@ -314,7 +315,7 @@ private: // Unregister handlers, signal handling is now handled through ptrace in // the host process. sys::unregisterHandlers(); - prepareAndRunBenchmark(PipeFiles[0], Key); + prepareAndRunBenchmark(PipeFiles[0], Key, ParentTID); // The child process terminates in the above function, so we should never // get to this point. llvm_unreachable("Child process didn't exit when expected."); @@ -415,8 +416,8 @@ private: setrlimit(RLIMIT_CORE, &rlim); } - [[noreturn]] void prepareAndRunBenchmark(int Pipe, - const BenchmarkKey &Key) const { + [[noreturn]] void prepareAndRunBenchmark(int Pipe, const BenchmarkKey &Key, + long ParentTID) const { // Disable core dumps in the child process as otherwise everytime we // encounter an execution failure like a segmentation fault, we will create // a core dump. We report the information directly rather than require the @@ -473,7 +474,7 @@ private: Expected AuxMemFDOrError = SubprocessMemory::setupAuxiliaryMemoryInSubprocess( - Key.MemoryValues, ParentPID, CounterFileDescriptor); + Key.MemoryValues, ParentPID, ParentTID, CounterFileDescriptor); if (!AuxMemFDOrError) exit(ChildProcessExitCodeE::AuxiliaryMemorySetupFailed); diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp index a49fa077257d..11ad72a914c4 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp @@ -9,11 +9,13 @@ #include "SubprocessMemory.h" #include "Error.h" #include "llvm/Support/Error.h" +#include "llvm/Support/FormatVariadic.h" #include #ifdef __linux__ #include #include +#include #include #endif @@ -22,12 +24,21 @@ namespace exegesis { #if defined(__linux__) && !defined(__ANDROID__) +long SubprocessMemory::getCurrentTID() { + // We're using the raw syscall here rather than the gettid() function provided + // by most libcs for compatibility as gettid() was only added to glibc in + // version 2.30. + return syscall(SYS_gettid); +} + Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessID) { // Add the PID to the shared memory name so that if we're running multiple // processes at the same time, they won't interfere with each other. // This comes up particularly often when running the exegesis tests with - // llvm-lit - std::string AuxiliaryMemoryName = "/auxmem" + std::to_string(ProcessID); + // llvm-lit. Additionally add the TID so that downstream consumers + // using multiple threads don't run into conflicts. + std::string AuxiliaryMemoryName = + formatv("/{0}auxmem{1}", getCurrentTID(), ProcessID); int AuxiliaryMemoryFD = shm_open(AuxiliaryMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryFD == -1) @@ -47,8 +58,8 @@ Error SubprocessMemory::addMemoryDefinition( pid_t ProcessPID) { SharedMemoryNames.reserve(MemoryDefinitions.size()); for (auto &[Name, MemVal] : MemoryDefinitions) { - std::string SharedMemoryName = "/" + std::to_string(ProcessPID) + "memdef" + - std::to_string(MemVal.Index); + std::string SharedMemoryName = + formatv("/{0}t{1}memdef{2}", ProcessPID, getCurrentTID(), MemVal.Index); SharedMemoryNames.push_back(SharedMemoryName); int SharedMemoryFD = shm_open(SharedMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); @@ -82,8 +93,9 @@ Error SubprocessMemory::addMemoryDefinition( Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, int CounterFileDescriptor) { - std::string AuxiliaryMemoryName = "/auxmem" + std::to_string(ParentPID); + pid_t ParentPID, long ParentTID, int CounterFileDescriptor) { + std::string AuxiliaryMemoryName = + formatv("/{0}auxmem{1}", ParentTID, ParentPID); int AuxiliaryMemoryFileDescriptor = shm_open(AuxiliaryMemoryName.c_str(), O_RDWR, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryFileDescriptor == -1) @@ -97,8 +109,8 @@ Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( return make_error("Mapping auxiliary memory failed"); AuxiliaryMemoryMapping[0] = CounterFileDescriptor; for (auto &[Name, MemVal] : MemoryDefinitions) { - std::string MemoryValueName = "/" + std::to_string(ParentPID) + "memdef" + - std::to_string(MemVal.Index); + std::string MemoryValueName = + formatv("/{0}t{1}memdef{2}", ParentPID, ParentTID, MemVal.Index); AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] = shm_open(MemoryValueName.c_str(), O_RDWR, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] == -1) diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h index e20b50cdc811..572d1085d9cf 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h @@ -35,6 +35,9 @@ public: static constexpr const size_t AuxiliaryMemoryOffset = 1; static constexpr const size_t AuxiliaryMemorySize = 4096; + // Gets the thread ID for the calling thread. + static long getCurrentTID(); + Error initializeSubprocessMemory(pid_t ProcessID); // The following function sets up memory definitions. It creates shared @@ -54,7 +57,7 @@ public: // section. static Expected setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, int CounterFileDescriptor); + pid_t ParentPID, long ParentTID, int CounterFileDescriptor); ~SubprocessMemory(); diff --git a/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp index c07ec188a602..7c23e7b7e9c5 100644 --- a/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #endif // __linux__ @@ -49,7 +50,9 @@ protected: std::string getSharedMemoryName(const unsigned TestNumber, const unsigned DefinitionNumber) { - return "/" + std::to_string(getSharedMemoryNumber(TestNumber)) + "memdef" + + long CurrentTID = syscall(SYS_gettid); + return "/" + std::to_string(getSharedMemoryNumber(TestNumber)) + "t" + + std::to_string(CurrentTID) + "memdef" + std::to_string(DefinitionNumber); } -- GitLab From aefad27096bba513f06162fac2763089578f3de4 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 12 Mar 2024 08:51:45 +0000 Subject: [PATCH 215/953] Revert "[llvm-exegesis] Add thread IDs to subprocess memory names (#84451)" This reverts commit 6bbe8a296ee91754d423c59c35727eaa624f7140. This breaks building LLVM on macOS, failing with llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp:146:33: error: out-of-line definition of 'setupAuxiliaryMemoryInSubprocess' does not match any declaration in 'llvm::exegesis::SubprocessMemory' Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( --- .../llvm-exegesis/lib/BenchmarkRunner.cpp | 9 +++--- .../llvm-exegesis/lib/SubprocessMemory.cpp | 28 ++++++------------- .../llvm-exegesis/lib/SubprocessMemory.h | 5 +--- .../X86/SubprocessMemoryTest.cpp | 5 +--- 4 files changed, 14 insertions(+), 33 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp index 4e97d188d172..5c9848f3c688 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -301,7 +301,6 @@ private: if (AddMemDefError) return AddMemDefError; - long ParentTID = SubprocessMemory::getCurrentTID(); pid_t ParentOrChildPID = fork(); if (ParentOrChildPID == -1) { @@ -315,7 +314,7 @@ private: // Unregister handlers, signal handling is now handled through ptrace in // the host process. sys::unregisterHandlers(); - prepareAndRunBenchmark(PipeFiles[0], Key, ParentTID); + prepareAndRunBenchmark(PipeFiles[0], Key); // The child process terminates in the above function, so we should never // get to this point. llvm_unreachable("Child process didn't exit when expected."); @@ -416,8 +415,8 @@ private: setrlimit(RLIMIT_CORE, &rlim); } - [[noreturn]] void prepareAndRunBenchmark(int Pipe, const BenchmarkKey &Key, - long ParentTID) const { + [[noreturn]] void prepareAndRunBenchmark(int Pipe, + const BenchmarkKey &Key) const { // Disable core dumps in the child process as otherwise everytime we // encounter an execution failure like a segmentation fault, we will create // a core dump. We report the information directly rather than require the @@ -474,7 +473,7 @@ private: Expected AuxMemFDOrError = SubprocessMemory::setupAuxiliaryMemoryInSubprocess( - Key.MemoryValues, ParentPID, ParentTID, CounterFileDescriptor); + Key.MemoryValues, ParentPID, CounterFileDescriptor); if (!AuxMemFDOrError) exit(ChildProcessExitCodeE::AuxiliaryMemorySetupFailed); diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp index 11ad72a914c4..a49fa077257d 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp @@ -9,13 +9,11 @@ #include "SubprocessMemory.h" #include "Error.h" #include "llvm/Support/Error.h" -#include "llvm/Support/FormatVariadic.h" #include #ifdef __linux__ #include #include -#include #include #endif @@ -24,21 +22,12 @@ namespace exegesis { #if defined(__linux__) && !defined(__ANDROID__) -long SubprocessMemory::getCurrentTID() { - // We're using the raw syscall here rather than the gettid() function provided - // by most libcs for compatibility as gettid() was only added to glibc in - // version 2.30. - return syscall(SYS_gettid); -} - Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessID) { // Add the PID to the shared memory name so that if we're running multiple // processes at the same time, they won't interfere with each other. // This comes up particularly often when running the exegesis tests with - // llvm-lit. Additionally add the TID so that downstream consumers - // using multiple threads don't run into conflicts. - std::string AuxiliaryMemoryName = - formatv("/{0}auxmem{1}", getCurrentTID(), ProcessID); + // llvm-lit + std::string AuxiliaryMemoryName = "/auxmem" + std::to_string(ProcessID); int AuxiliaryMemoryFD = shm_open(AuxiliaryMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryFD == -1) @@ -58,8 +47,8 @@ Error SubprocessMemory::addMemoryDefinition( pid_t ProcessPID) { SharedMemoryNames.reserve(MemoryDefinitions.size()); for (auto &[Name, MemVal] : MemoryDefinitions) { - std::string SharedMemoryName = - formatv("/{0}t{1}memdef{2}", ProcessPID, getCurrentTID(), MemVal.Index); + std::string SharedMemoryName = "/" + std::to_string(ProcessPID) + "memdef" + + std::to_string(MemVal.Index); SharedMemoryNames.push_back(SharedMemoryName); int SharedMemoryFD = shm_open(SharedMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); @@ -93,9 +82,8 @@ Error SubprocessMemory::addMemoryDefinition( Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, long ParentTID, int CounterFileDescriptor) { - std::string AuxiliaryMemoryName = - formatv("/{0}auxmem{1}", ParentTID, ParentPID); + pid_t ParentPID, int CounterFileDescriptor) { + std::string AuxiliaryMemoryName = "/auxmem" + std::to_string(ParentPID); int AuxiliaryMemoryFileDescriptor = shm_open(AuxiliaryMemoryName.c_str(), O_RDWR, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryFileDescriptor == -1) @@ -109,8 +97,8 @@ Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( return make_error("Mapping auxiliary memory failed"); AuxiliaryMemoryMapping[0] = CounterFileDescriptor; for (auto &[Name, MemVal] : MemoryDefinitions) { - std::string MemoryValueName = - formatv("/{0}t{1}memdef{2}", ParentPID, ParentTID, MemVal.Index); + std::string MemoryValueName = "/" + std::to_string(ParentPID) + "memdef" + + std::to_string(MemVal.Index); AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] = shm_open(MemoryValueName.c_str(), O_RDWR, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] == -1) diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h index 572d1085d9cf..e20b50cdc811 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h @@ -35,9 +35,6 @@ public: static constexpr const size_t AuxiliaryMemoryOffset = 1; static constexpr const size_t AuxiliaryMemorySize = 4096; - // Gets the thread ID for the calling thread. - static long getCurrentTID(); - Error initializeSubprocessMemory(pid_t ProcessID); // The following function sets up memory definitions. It creates shared @@ -57,7 +54,7 @@ public: // section. static Expected setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, long ParentTID, int CounterFileDescriptor); + pid_t ParentPID, int CounterFileDescriptor); ~SubprocessMemory(); diff --git a/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp index 7c23e7b7e9c5..c07ec188a602 100644 --- a/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #endif // __linux__ @@ -50,9 +49,7 @@ protected: std::string getSharedMemoryName(const unsigned TestNumber, const unsigned DefinitionNumber) { - long CurrentTID = syscall(SYS_gettid); - return "/" + std::to_string(getSharedMemoryNumber(TestNumber)) + "t" + - std::to_string(CurrentTID) + "memdef" + + return "/" + std::to_string(getSharedMemoryNumber(TestNumber)) + "memdef" + std::to_string(DefinitionNumber); } -- GitLab From b274b23665dec30f3ae4fb83ccca8b77e6d3ada3 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 12 Mar 2024 08:55:03 +0000 Subject: [PATCH 216/953] [ValueTracking] Treat phi as underlying obj when not decomposing further (#84339) At the moment, getUnderlyingObjects simply continues for phis that do not refer to the same underlying object in loops, without adding them to the list of underlying objects, effectively ignoring those phis. Instead of ignoring those phis, add them to the list of underlying objects. This fixes a miscompile where LoopAccessAnalysis fails to identify a memory dependence, because no underlying objects can be found for a set of memory accesses. Fixes https://github.com/llvm/llvm-project/issues/82665. PR: https://github.com/llvm/llvm-project/pull/84339 --- llvm/lib/Analysis/ValueTracking.cpp | 2 ++ .../underlying-object-loop-varying-phi.ll | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index d7f60d85b452..371ad41ee965 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -6131,6 +6131,8 @@ void llvm::getUnderlyingObjects(const Value *V, if (!LI || !LI->isLoopHeader(PN->getParent()) || isSameUnderlyingObjectInLoop(PN, LI)) append_range(Worklist, PN->incoming_values()); + else + Objects.push_back(P); continue; } diff --git a/llvm/test/Analysis/LoopAccessAnalysis/underlying-object-loop-varying-phi.ll b/llvm/test/Analysis/LoopAccessAnalysis/underlying-object-loop-varying-phi.ll index 1a5a6ac08d40..106dc8c13a49 100644 --- a/llvm/test/Analysis/LoopAccessAnalysis/underlying-object-loop-varying-phi.ll +++ b/llvm/test/Analysis/LoopAccessAnalysis/underlying-object-loop-varying-phi.ll @@ -7,8 +7,13 @@ target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" define void @indirect_ptr_recurrences_read_write(ptr %A, ptr %B) { ; CHECK-LABEL: 'indirect_ptr_recurrences_read_write' ; CHECK-NEXT: loop: -; CHECK-NEXT: Memory dependences are safe +; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop +; CHECK-NEXT: Unsafe indirect dependence. ; CHECK-NEXT: Dependences: +; CHECK-NEXT: IndidrectUnsafe: +; CHECK-NEXT: %l = load i32, ptr %ptr.recur, align 4, !tbaa !4 -> +; CHECK-NEXT: store i32 %xor, ptr %ptr.recur, align 4, !tbaa !4 +; CHECK-EMPTY: ; CHECK-NEXT: Run-time memory checks: ; CHECK-NEXT: Grouped accesses: ; CHECK-EMPTY: -- GitLab From 939f038296e601abd9143955f1b347aee1e99c06 Mon Sep 17 00:00:00 2001 From: jeanPerier Date: Tue, 12 Mar 2024 10:29:19 +0100 Subject: [PATCH 217/953] [flang] lower vector subscripted polymorphic designators (#84778) A mold argument need to be added to the hlfir.element_addr and set in lowering so that when the hlfir.element_addr need to be turned into an hlfir.elemental operation because the designator must be turned into a value, the mold can be set on the hlfir.elemental to later allocate the temporary according the the dynamic type. This situation happens whenever the vector subscripted polymorphic designator does not appear as an assignment left-hand side, or as an IO-input item. I initially thought retrieving the mold would be tricky if the dynamic type of the designator was set by a part-ref of the right of the vector subscripts ("array(vector)%polymorphic_comp"), but this turned out to be impossible because: 1. A derived type component can be polymorphic only if it has the POINTER or ALLOCATABLE attribute (F2023 C708). 2. Vector-subscripted part are ranked and F2023 C919 prohibits any part-ref on the right of the rank part to have the POINTER or ALLOCATABLE attribute. => If a vector subscripted designator is polymorphic, the vector subscripted part is the rightmost part, and the mold is the base of the vector subscripted part. This makes the retrieval of the mold easy in lowering. The mold argument is always set to be the base of the vector subscripted part when lowering the vector subscripted part, and it is removed at the end of the designator lowering if the designator is not polymorphic. This way there is no need to find back the mold from the inside of the hlfir.element_addr body. --- .../include/flang/Optimizer/HLFIR/HLFIROps.td | 13 +++-- flang/lib/Lower/ConvertExprToHLFIR.cpp | 27 +++++----- flang/lib/Optimizer/Builder/HLFIRTools.cpp | 6 +-- flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp | 50 ++++++++++--------- flang/test/HLFIR/element-addr.fir | 42 ++++++++++++++++ .../Lower/HLFIR/vector-subscript-as-value.f90 | 36 ++++++++++++- 6 files changed, 132 insertions(+), 42 deletions(-) diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td index c82eae154d31..743a6c98ec1a 100644 --- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td +++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td @@ -1358,7 +1358,9 @@ def hlfir_YieldOp : hlfir_Op<"yield", [Terminator, ParentOneOf<["RegionAssignOp" let assemblyFormat = "$entity attr-dict `:` type($entity) custom($cleanup)"; } -def hlfir_ElementalAddrOp : hlfir_Op<"elemental_addr", [Terminator, HasParent<"RegionAssignOp">, RecursiveMemoryEffects, RecursivelySpeculatable, hlfir_ElementalOpInterface]> { +def hlfir_ElementalAddrOp : hlfir_Op<"elemental_addr", [Terminator, HasParent<"RegionAssignOp">, + RecursiveMemoryEffects, RecursivelySpeculatable, hlfir_ElementalOpInterface, + AttrSizedOperandSegments]> { let summary = "Yield the address of a vector subscripted variable inside an hlfir.region_assign"; let description = [{ Special terminator node for the left-hand side region of an hlfir.region_assign @@ -1398,6 +1400,7 @@ def hlfir_ElementalAddrOp : hlfir_Op<"elemental_addr", [Terminator, HasParent<"R let arguments = (ins fir_ShapeType:$shape, + Optional:$mold, Variadic:$typeparams, OptionalAttr:$unordered ); @@ -1406,11 +1409,15 @@ def hlfir_ElementalAddrOp : hlfir_Op<"elemental_addr", [Terminator, HasParent<"R MaxSizedRegion<1>:$cleanup); let builders = [ - OpBuilder<(ins "mlir::Value":$shape, CArg<"bool", "false">:$isUnordered)> + OpBuilder<(ins "mlir::Value":$shape, + CArg<"mlir::Value", "{}">:$mold, + CArg<"mlir::ValueRange", "{}">:$typeparams, + CArg<"bool", "false">:$isUnordered)> ]; let assemblyFormat = [{ - $shape (`typeparams` $typeparams^)? (`unordered` $unordered^)? + $shape (`mold` $mold^)? (`typeparams` $typeparams^)? + (`unordered` $unordered^)? attr-dict `:` type(operands) $body custom($cleanup)}]; diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp index 731c5072c45c..c5bfbdf6b8c1 100644 --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -761,9 +761,17 @@ private: // of the whole designator (not the ones of the vector subscripted part). // These are not yet known and will be added when finalizing the designator // lowering. - auto elementalAddrOp = - builder.create(loc, shape, - /*isUnordered=*/true); + // The resulting designator may be polymorphic, in which case the resulting + // type is the base of the vector subscripted part because + // allocatable/pointer components cannot be referenced after a vector + // subscripted part. Set the mold to the current base. It will be erased if + // the resulting designator is not polymorphic. + assert(partInfo.base.has_value() && + "vector subscripted part must have a base"); + mlir::Value mold = *partInfo.base; + auto elementalAddrOp = builder.create( + loc, shape, mold, mlir::ValueRange{}, + /*isUnordered=*/true); setVectorSubscriptElementAddrOp(elementalAddrOp); builder.setInsertionPointToEnd(&elementalAddrOp.getBody().front()); mlir::Region::BlockArgListType indices = elementalAddrOp.getIndices(); @@ -804,15 +812,8 @@ private: hlfir::EntityWithAttributes elementAddr) { fir::FirOpBuilder &builder = getBuilder(); builder.setInsertionPointToEnd(&elementalAddrOp.getBody().front()); - // For polymorphic entities, it will be needed to add a mold on the - // hlfir.elemental so that we are able to create temporary storage - // for it using the dynamic type. It seems that a reference to the mold - // entity can be created by evaluating the hlfir.elemental_addr - // for a single index. The evaluation should be legal as long as - // the hlfir.elemental_addr has no side effects, otherwise, - // it is not clear how to get the mold reference. - if (elementAddr.isPolymorphic()) - TODO(loc, "vector subscripted polymorphic entity in HLFIR"); + if (!elementAddr.isPolymorphic()) + elementalAddrOp.getMoldMutable().clear(); builder.create(loc, elementAddr); builder.setInsertionPointAfter(elementalAddrOp); } @@ -929,6 +930,8 @@ HlfirDesignatorBuilder::convertVectorSubscriptedExprToElementalAddr( hlfir::genLengthParameters(loc, builder, elementAddrEntity, lengths); if (!lengths.empty()) elementalAddrOp.getTypeparamsMutable().assign(lengths); + if (!elementAddrEntity.isPolymorphic()) + elementalAddrOp.getMoldMutable().clear(); // Create the hlfir.yield terminator inside the hlfir.elemental_body. builder.setInsertionPointToEnd(&elementalAddrOp.getBody().front()); builder.create(loc, elementAddrEntity); diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp index 0e0b14e8d690..c7a550814e1d 100644 --- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp +++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp @@ -1036,9 +1036,9 @@ hlfir::cloneToElementalOp(mlir::Location loc, fir::FirOpBuilder &builder, return hlfir::loadTrivialScalar(l, b, newAddr); }; mlir::Type elementType = scalarAddress.getFortranElementType(); - return hlfir::genElementalOp(loc, builder, elementType, - elementalAddrOp.getShape(), typeParams, - genKernel, !elementalAddrOp.isOrdered()); + return hlfir::genElementalOp( + loc, builder, elementType, elementalAddrOp.getShape(), typeParams, + genKernel, !elementalAddrOp.isOrdered(), elementalAddrOp.getMold()); } bool hlfir::elementalOpMustProduceTemp(hlfir::ElementalOp elemental) { diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp index 3568fe202caf..8bad4e445082 100644 --- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp +++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp @@ -1406,33 +1406,45 @@ void hlfir::AsExprOp::getEffects( // ElementalOp //===----------------------------------------------------------------------===// -void hlfir::ElementalOp::build(mlir::OpBuilder &builder, - mlir::OperationState &odsState, - mlir::Type resultType, mlir::Value shape, - mlir::Value mold, mlir::ValueRange typeparams, - bool isUnordered) { +/// Common builder for ElementalOp and ElementalAddrOp to add the arguments and +/// create the elemental body. Result and clean-up body must be handled in +/// specific builders. +template +static void buildElemental(mlir::OpBuilder &builder, + mlir::OperationState &odsState, mlir::Value shape, + mlir::Value mold, mlir::ValueRange typeparams, + bool isUnordered) { odsState.addOperands(shape); if (mold) odsState.addOperands(mold); odsState.addOperands(typeparams); - odsState.addTypes(resultType); odsState.addAttribute( - getOperandSegmentSizesAttrName(odsState.name), + Op::getOperandSegmentSizesAttrName(odsState.name), builder.getDenseI32ArrayAttr({/*shape=*/1, (mold ? 1 : 0), static_cast(typeparams.size())})); if (isUnordered) - odsState.addAttribute(getUnorderedAttrName(odsState.name), + odsState.addAttribute(Op::getUnorderedAttrName(odsState.name), isUnordered ? builder.getUnitAttr() : nullptr); mlir::Region *bodyRegion = odsState.addRegion(); bodyRegion->push_back(new mlir::Block{}); - if (auto exprType = resultType.dyn_cast()) { - unsigned dim = exprType.getRank(); + if (auto shapeType = shape.getType().dyn_cast()) { + unsigned dim = shapeType.getRank(); mlir::Type indexType = builder.getIndexType(); for (unsigned d = 0; d < dim; ++d) bodyRegion->front().addArgument(indexType, odsState.location); } } +void hlfir::ElementalOp::build(mlir::OpBuilder &builder, + mlir::OperationState &odsState, + mlir::Type resultType, mlir::Value shape, + mlir::Value mold, mlir::ValueRange typeparams, + bool isUnordered) { + odsState.addTypes(resultType); + buildElemental(builder, odsState, shape, mold, typeparams, + isUnordered); +} + mlir::Value hlfir::ElementalOp::getElementEntity() { return mlir::cast(getBody()->back()).getElementValue(); } @@ -1681,19 +1693,11 @@ static void printYieldOpCleanup(mlir::OpAsmPrinter &p, YieldOp yieldOp, void hlfir::ElementalAddrOp::build(mlir::OpBuilder &builder, mlir::OperationState &odsState, - mlir::Value shape, bool isUnordered) { - odsState.addOperands(shape); - if (isUnordered) - odsState.addAttribute(getUnorderedAttrName(odsState.name), - isUnordered ? builder.getUnitAttr() : nullptr); - mlir::Region *bodyRegion = odsState.addRegion(); - bodyRegion->push_back(new mlir::Block{}); - if (auto shapeType = shape.getType().dyn_cast()) { - unsigned dim = shapeType.getRank(); - mlir::Type indexType = builder.getIndexType(); - for (unsigned d = 0; d < dim; ++d) - bodyRegion->front().addArgument(indexType, odsState.location); - } + mlir::Value shape, mlir::Value mold, + mlir::ValueRange typeparams, + bool isUnordered) { + buildElemental(builder, odsState, shape, mold, + typeparams, isUnordered); // Push cleanUp region. odsState.addRegion(); } diff --git a/flang/test/HLFIR/element-addr.fir b/flang/test/HLFIR/element-addr.fir index 73946f8b40e3..c3c48edd9b56 100644 --- a/flang/test/HLFIR/element-addr.fir +++ b/flang/test/HLFIR/element-addr.fir @@ -114,3 +114,45 @@ func.func @unordered() { // CHECK: } // CHECK: return // CHECK: } + +// "X(VECTOR) = Y" with polymorphic X and Y and user defined assignment. +func.func @test_mold(%x: !fir.class>>, %y: !fir.class>>, %vector: !fir.box>) { + hlfir.region_assign { + hlfir.yield %y : !fir.class>> + } to { + %c0 = arith.constant 0 : index + %0:3 = fir.box_dims %vector, %c0 : (!fir.box>, index) -> (index, index, index) + %1 = fir.shape %0#1 : (index) -> !fir.shape<1> + hlfir.elemental_addr %1 mold %x unordered : !fir.shape<1>, !fir.class>> { + ^bb0(%arg3: index): + %2 = hlfir.designate %vector (%arg3) : (!fir.box>, index) -> !fir.ref + %3 = fir.load %2 : !fir.ref + %4 = hlfir.designate %x (%3) : (!fir.class>>, i64) -> !fir.class> + hlfir.yield %4 : !fir.class> + } + } user_defined_assign (%arg3: !fir.class>) to (%arg4: !fir.class>) { + fir.call @user_def_assign(%arg4, %arg3) : (!fir.class>, !fir.class>) -> () + } + return +} +func.func private @user_def_assign(!fir.class>, !fir.class>) +// CHECK-LABEL: func.func @test_mold( +// CHECK-SAME: %[[VAL_0:[^:]*]]: !fir.class>>, +// CHECK-SAME: %[[VAL_1:.*]]: !fir.class>>, +// CHECK-SAME: %[[VAL_2:.*]]: !fir.box>) { +// CHECK: hlfir.region_assign { +// CHECK: hlfir.yield %[[VAL_1]] : !fir.class>> +// CHECK: } to { +// CHECK: %[[VAL_3:.*]] = arith.constant 0 : index +// CHECK: %[[VAL_4:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_3]] : (!fir.box>, index) -> (index, index, index) +// CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]]#1 : (index) -> !fir.shape<1> +// CHECK: hlfir.elemental_addr %[[VAL_5]] mold %[[VAL_0]] unordered : !fir.shape<1>, !fir.class>> { +// CHECK: ^bb0(%[[VAL_6:.*]]: index): +// CHECK: %[[VAL_7:.*]] = hlfir.designate %[[VAL_2]] (%[[VAL_6]]) : (!fir.box>, index) -> !fir.ref +// CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_7]] : !fir.ref +// CHECK: %[[VAL_9:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_8]]) : (!fir.class>>, i64) -> !fir.class> +// CHECK: hlfir.yield %[[VAL_9]] : !fir.class> +// CHECK: } +// CHECK: } user_defined_assign (%[[VAL_10:.*]]: !fir.class>) to (%[[VAL_11:.*]]: !fir.class>) { +// CHECK: fir.call @user_def_assign(%[[VAL_11]], %[[VAL_10]]) : (!fir.class>, !fir.class>) -> () +// CHECK: } diff --git a/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 b/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 index 2f463cfaa8b0..d4026a37720f 100644 --- a/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 +++ b/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 @@ -1,6 +1,6 @@ ! Test lowering of vector subscript designators outside of the ! assignment left-and side and input IO context. -! RUN: bbc -emit-hlfir -o - -I nw %s 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -o - -I nw %s --polymorphic-type 2>&1 | FileCheck %s subroutine foo(x, y) integer :: x(100) @@ -182,3 +182,37 @@ end subroutine ! CHECK: %[[VAL_27:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_26]]) substr %[[VAL_15]], %[[VAL_16]] typeparams %[[VAL_22]] : (!fir.box>>, i64, index, index, index) -> !fir.boxchar<1> ! CHECK: hlfir.yield_element %[[VAL_27]] : !fir.boxchar<1> ! CHECK: } + +subroutine test_passing_subscripted_poly(x, vector) + interface + subroutine do_something(x) + class(*) :: x(:) + end subroutine + end interface + class(*) :: x(:, :) + integer(8) :: vector(:) + call do_something(x(314, vector)) +end subroutine +! CHECK-LABEL: func.func @_QPtest_passing_subscripted_poly( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.class> +! CHECK-SAME: %[[VAL_1:.*]]: !fir.box> +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest_passing_subscripted_polyEvector"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest_passing_subscripted_polyEx"} : (!fir.class>) -> (!fir.class>, !fir.class>) +! CHECK: %[[VAL_4:.*]] = arith.constant 314 : index +! CHECK: %[[VAL_5:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_6:.*]]:3 = fir.box_dims %[[VAL_2]]#0, %[[VAL_5]] : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[VAL_8:.*]] = hlfir.elemental %[[VAL_7]] mold %[[VAL_3]]#0 unordered : (!fir.shape<1>, !fir.class>) -> !hlfir.expr { +! CHECK: ^bb0(%[[VAL_9:.*]]: index): +! CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_2]]#0 (%[[VAL_9]]) : (!fir.box>, index) -> !fir.ref +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_10]] : !fir.ref +! CHECK: %[[VAL_12:.*]] = hlfir.designate %[[VAL_3]]#0 (%[[VAL_4]], %[[VAL_11]]) : (!fir.class>, index, i64) -> !fir.class +! CHECK: hlfir.yield_element %[[VAL_12]] : !fir.class +! CHECK: } +! CHECK: %[[VAL_13:.*]]:3 = hlfir.associate %[[VAL_8]](%[[VAL_7]]) {adapt.valuebyref} : (!hlfir.expr, !fir.shape<1>) -> (!fir.class>>, !fir.class>>, i1) +! CHECK: %[[VAL_14:.*]] = fir.rebox %[[VAL_13]]#0 : (!fir.class>>) -> !fir.class> +! CHECK: fir.call @_QPdo_something(%[[VAL_14]]) fastmath : (!fir.class>) -> () +! CHECK: hlfir.end_associate %[[VAL_13]]#0, %[[VAL_13]]#2 : !fir.class>>, i1 +! CHECK: hlfir.destroy %[[VAL_8]] : !hlfir.expr +! CHECK: return +! CHECK: } -- GitLab From 9d16e79aac09e68c46b89cbbad9fe7edd915b8c3 Mon Sep 17 00:00:00 2001 From: Dani Date: Tue, 12 Mar 2024 10:33:16 +0100 Subject: [PATCH 218/953] [AArch64] Fix COMPILER_RT_HAS_AUXV for builtins. (#84816) COMPILER_RT_HAS_AUXV is used now in builtins so the test need to be in the builtin-config-ix.cmake too. --- compiler-rt/cmake/builtin-config-ix.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler-rt/cmake/builtin-config-ix.cmake b/compiler-rt/cmake/builtin-config-ix.cmake index d10222b7530a..33c97b1ac28a 100644 --- a/compiler-rt/cmake/builtin-config-ix.cmake +++ b/compiler-rt/cmake/builtin-config-ix.cmake @@ -1,4 +1,5 @@ include(BuiltinTests) +include(CheckIncludeFiles) include(CheckCSourceCompiles) # Make all the tests only check the compiler @@ -43,6 +44,8 @@ void foo(void) __arm_streaming_compatible { } ") +check_include_files("sys/auxv.h" COMPILER_RT_HAS_AUXV) + if(ANDROID) set(OS_NAME "Android") else() -- GitLab From 368db5683bb9f8c619a8a6d3d15522429ef615c6 Mon Sep 17 00:00:00 2001 From: Luke Weiler <163067703+lwmaia@users.noreply.github.com> Date: Tue, 12 Mar 2024 02:38:36 -0700 Subject: [PATCH 219/953] [lldb] Fix build break on windows (#84863) This is a one line fix for a Windows specific (I believe) build break. The build failure looks like this: `D:\a\_work\1\s\lldb\source\Symbol\Symtab.cpp(128): error C2440: '': cannot convert from 'lldb_private::ConstString' to 'llvm::StringRef' D:\a\_work\1\s\lldb\source\Symbol\Symtab.cpp(128): note: 'llvm::StringRef::StringRef': ambiguous call to overloaded function D:\a\_work\1\s\llvm\include\llvm/ADT/StringRef.h(840): note: could be 'llvm::StringRef::StringRef(llvm::StringRef &&)' D:\a\_work\1\s\llvm\include\llvm/ADT/StringRef.h(104): note: or 'llvm::StringRef::StringRef(std::string_view)' D:\a\_work\1\s\lldb\source\Symbol\Symtab.cpp(128): note: while trying to match the argument list '(lldb_private::ConstString)' D:\a\_work\1\s\lldb\source\Symbol\Symtab.cpp(128): error C2672: 'std::multimap,std::allocator>>::emplace': no matching overloaded function found C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.37.32822\include\map(557): note: could be 'std::_Tree_iterator>>> std::multimap,std::allocator>>::emplace(_Valty &&...)' ` The StringRef constructor here is intended to take a ConstString object, which I assume is implicitly converted to a std::string_view by compilers other than Visual Studio's. To fix the VS build I made the StringRef initialization more explicit, as you can see in the diff. --- lldb/source/Symbol/Symtab.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp index c63bbe94fece..5b5bf5c3f6f8 100644 --- a/lldb/source/Symbol/Symtab.cpp +++ b/lldb/source/Symbol/Symtab.cpp @@ -125,7 +125,7 @@ void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order, std::multimap name_map; for (const Symbol &symbol : m_symbols) - name_map.emplace(llvm::StringRef(symbol.GetName()), &symbol); + name_map.emplace(symbol.GetName().GetStringRef(), &symbol); for (const auto &name_to_symbol : name_map) { const Symbol *symbol = name_to_symbol.second; -- GitLab From a3b52509d522442915a51d8aabcec1df49e95b23 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Tue, 12 Mar 2024 10:39:37 +0100 Subject: [PATCH 220/953] [InstSimpliy] Use range attribute to simplify comparisons (#84627) Use the new range attribute from https://github.com/llvm/llvm-project/pull/84617 to simplify comparisons where both sides have range information. --- llvm/include/llvm/IR/Attributes.h | 5 + llvm/include/llvm/IR/Function.h | 3 + llvm/include/llvm/IR/InstrTypes.h | 12 ++ llvm/lib/Analysis/InstructionSimplify.cpp | 38 +++-- llvm/lib/IR/Function.cpp | 4 + .../test/Transforms/InstCombine/icmp-range.ll | 144 +++++++++++++++++- 6 files changed, 187 insertions(+), 19 deletions(-) diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h index 0c2a02514ba0..7dd8a329029a 100644 --- a/llvm/include/llvm/IR/Attributes.h +++ b/llvm/include/llvm/IR/Attributes.h @@ -848,6 +848,11 @@ public: return getAttributeAtIndex(FunctionIndex, Kind); } + /// Return the attribute for the given attribute kind for the return value. + Attribute getRetAttr(Attribute::AttrKind Kind) const { + return getAttributeAtIndex(ReturnIndex, Kind); + } + /// Return the alignment of the return value. MaybeAlign getRetAlignment() const; diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index cb87a4498032..d96d506a9b05 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -430,6 +430,9 @@ public: /// Return the attribute for the given attribute kind. Attribute getFnAttribute(StringRef Kind) const; + /// Return the attribute for the given attribute kind for the return value. + Attribute getRetAttribute(Attribute::AttrKind Kind) const; + /// For a string attribute \p Kind, parse attribute as an integer. /// /// \returns \p Default if attribute is not present. diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h index 0e81d3b391a0..fed21b992e3d 100644 --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -1909,6 +1909,18 @@ public: /// Determine whether the return value has the given attribute. bool hasRetAttr(StringRef Kind) const { return hasRetAttrImpl(Kind); } + /// Return the attribute for the given attribute kind for the return value. + Attribute getRetAttr(Attribute::AttrKind Kind) const { + Attribute RetAttr = Attrs.getRetAttr(Kind); + if (RetAttr.isValid()) + return RetAttr; + + // Look at the callee, if available. + if (const Function *F = getCalledFunction()) + return F->getAttributes().getRetAttr(Kind); + return Attribute(); + } + /// Determine whether the argument or parameter has the given attribute. bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const; diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 8c48174b9f52..ce651783caf1 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3729,6 +3729,26 @@ static Value *simplifyICmpWithIntrinsicOnLHS(CmpInst::Predicate Pred, } } +/// Helper method to get range from metadata or attribute. +static std::optional getRange(Value *V, + const InstrInfoQuery &IIQ) { + if (Instruction *I = dyn_cast(V)) + if (MDNode *MD = IIQ.getMetadata(I, LLVMContext::MD_range)) + return getConstantRangeFromMetadata(*MD); + + Attribute Range; + if (const Argument *A = dyn_cast(V)) { + Range = A->getAttribute(llvm::Attribute::Range); + } else if (const CallBase *CB = dyn_cast(V)) { + Range = CB->getRetAttr(llvm::Attribute::Range); + } + + if (Range.isValid()) + return Range.getRange(); + + return std::nullopt; +} + /// Given operands for an ICmpInst, see if we can fold the result. /// If not, this returns null. static Value *simplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, @@ -3776,24 +3796,14 @@ static Value *simplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, // If both operands have range metadata, use the metadata // to simplify the comparison. - if (isa(RHS) && isa(LHS)) { - auto RHS_Instr = cast(RHS); - auto LHS_Instr = cast(LHS); - - if (Q.IIQ.getMetadata(RHS_Instr, LLVMContext::MD_range) && - Q.IIQ.getMetadata(LHS_Instr, LLVMContext::MD_range)) { - auto RHS_CR = getConstantRangeFromMetadata( - *RHS_Instr->getMetadata(LLVMContext::MD_range)); - auto LHS_CR = getConstantRangeFromMetadata( - *LHS_Instr->getMetadata(LLVMContext::MD_range)); - - if (LHS_CR.icmp(Pred, RHS_CR)) + if (std::optional RhsCr = getRange(RHS, Q.IIQ)) + if (std::optional LhsCr = getRange(LHS, Q.IIQ)) { + if (LhsCr->icmp(Pred, *RhsCr)) return ConstantInt::getTrue(ITy); - if (LHS_CR.icmp(CmpInst::getInversePredicate(Pred), RHS_CR)) + if (LhsCr->icmp(CmpInst::getInversePredicate(Pred), *RhsCr)) return ConstantInt::getFalse(ITy); } - } // Compare of cast, for example (zext X) != 0 -> X != 0 if (isa(LHS) && (isa(RHS) || isa(RHS))) { diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index 056e4f31981a..d22e1c123111 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -700,6 +700,10 @@ Attribute Function::getFnAttribute(StringRef Kind) const { return AttributeSets.getFnAttr(Kind); } +Attribute Function::getRetAttribute(Attribute::AttrKind Kind) const { + return AttributeSets.getRetAttr(Kind); +} + uint64_t Function::getFnAttributeAsParsedInteger(StringRef Name, uint64_t Default) const { Attribute A = getFnAttribute(Name); diff --git a/llvm/test/Transforms/InstCombine/icmp-range.ll b/llvm/test/Transforms/InstCombine/icmp-range.ll index 77bb5fdb6bfd..9ed2f2a4860c 100644 --- a/llvm/test/Transforms/InstCombine/icmp-range.ll +++ b/llvm/test/Transforms/InstCombine/icmp-range.ll @@ -149,6 +149,16 @@ define i1 @test_two_ranges(ptr nocapture readonly %arg1, ptr nocapture readonly ret i1 %rval } +; Values' ranges overlap each other, so it can not be simplified. +define i1 @test_two_attribute_ranges(i32 range(i32 5, 10) %arg1, i32 range(i32 8, 16) %arg2) { +; CHECK-LABEL: @test_two_attribute_ranges( +; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[ARG1:%.*]], [[ARG2:%.*]] +; CHECK-NEXT: ret i1 [[RVAL]] +; + %rval = icmp ult i32 %arg2, %arg1 + ret i1 %rval +} + ; Values' ranges do not overlap each other, so it can simplified to false. define i1 @test_two_ranges2(ptr nocapture readonly %arg1, ptr nocapture readonly %arg2) { ; CHECK-LABEL: @test_two_ranges2( @@ -160,6 +170,35 @@ define i1 @test_two_ranges2(ptr nocapture readonly %arg1, ptr nocapture readonly ret i1 %rval } +; Values' ranges do not overlap each other, so it can simplified to false. +define i1 @test_two_argument_ranges(i32 range(i32 1, 6) %arg1, i32 range(i32 8, 16) %arg2) { +; CHECK-LABEL: @test_two_argument_ranges( +; CHECK-NEXT: ret i1 false +; + %rval = icmp ult i32 %arg2, %arg1 + ret i1 %rval +} + +; Values' ranges do not overlap each other, so it can simplified to false. +define i1 @test_one_range_and_one_argument_range(ptr nocapture readonly %arg1, i32 range(i32 8, 16) %arg2) { +; CHECK-LABEL: @test_one_range_and_one_argument_range( +; CHECK-NEXT: ret i1 false +; + %val1 = load i32, ptr %arg1, !range !0 + %rval = icmp ult i32 %arg2, %val1 + ret i1 %rval +} + +; Values' ranges do not overlap each other, so it can simplified to false. +define i1 @test_one_argument_range_and_one_range(i32 range(i32 1, 6) %arg1, ptr nocapture readonly %arg2) { +; CHECK-LABEL: @test_one_argument_range_and_one_range( +; CHECK-NEXT: ret i1 false +; + %val1 = load i32, ptr %arg2, !range !6 + %rval = icmp ult i32 %val1, %arg1 + ret i1 %rval +} + ; Values' ranges do not overlap each other, so it can simplified to true. define i1 @test_two_ranges3(ptr nocapture readonly %arg1, ptr nocapture readonly %arg2) { ; CHECK-LABEL: @test_two_ranges3( @@ -186,8 +225,8 @@ define <2 x i1> @test_two_ranges_vec(ptr nocapture readonly %arg1, ptr nocapture } ; Values' ranges do not overlap each other, so it can simplified to false. -define <2 x i1> @test_two_ranges_vec_true(ptr nocapture readonly %arg1, ptr nocapture readonly %arg2) { -; CHECK-LABEL: @test_two_ranges_vec_true( +define <2 x i1> @test_two_ranges_vec_false(ptr nocapture readonly %arg1, ptr nocapture readonly %arg2) { +; CHECK-LABEL: @test_two_ranges_vec_false( ; CHECK-NEXT: ret <2 x i1> zeroinitializer ; %val1 = load <2 x i32>, ptr %arg1, !range !0 @@ -196,9 +235,9 @@ define <2 x i1> @test_two_ranges_vec_true(ptr nocapture readonly %arg1, ptr noca ret <2 x i1> %rval } -; Values' ranges do not overlap each other, so it can simplified to false. -define <2 x i1> @test_two_ranges_vec_false(ptr nocapture readonly %arg1, ptr nocapture readonly %arg2) { -; CHECK-LABEL: @test_two_ranges_vec_false( +; Values' ranges do not overlap each other, so it can simplified to true. +define <2 x i1> @test_two_ranges_vec_true(ptr nocapture readonly %arg1, ptr nocapture readonly %arg2) { +; CHECK-LABEL: @test_two_ranges_vec_true( ; CHECK-NEXT: ret <2 x i1> ; %val1 = load <2 x i32>, ptr %arg1, !range !0 @@ -207,6 +246,101 @@ define <2 x i1> @test_two_ranges_vec_false(ptr nocapture readonly %arg1, ptr noc ret <2 x i1> %rval } +; Values' ranges overlap each other, so it can not be simplified. +define <2 x i1> @test_two_argument_ranges_vec(<2 x i32> range(i32 5, 10) %arg1, <2 x i32> range(i32 8, 16) %arg2) { +; CHECK-LABEL: @test_two_argument_ranges_vec( +; CHECK-NEXT: [[RVAL:%.*]] = icmp ult <2 x i32> [[VAL2:%.*]], [[VAL1:%.*]] +; CHECK-NEXT: ret <2 x i1> [[RVAL]] +; + %rval = icmp ult <2 x i32> %arg2, %arg1 + ret <2 x i1> %rval +} + +; Values' ranges do not overlap each other, so it can simplified to false. +define <2 x i1> @test_two_argument_ranges_vec_false(<2 x i32> range(i32 1, 6) %arg1, <2 x i32> range(i32 8, 16) %arg2) { +; CHECK-LABEL: @test_two_argument_ranges_vec_false( +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %rval = icmp ult <2 x i32> %arg2, %arg1 + ret <2 x i1> %rval +} + +; Values' ranges do not overlap each other, so it can simplified to true. +define <2 x i1> @test_two_argument_ranges_vec_true(<2 x i32> range(i32 1, 6) %arg1, <2 x i32> range(i32 8, 16) %arg2) { +; CHECK-LABEL: @test_two_argument_ranges_vec_true( +; CHECK-NEXT: ret <2 x i1> +; + %rval = icmp ugt <2 x i32> %arg2, %arg1 + ret <2 x i1> %rval +} + +declare i32 @create_range1() +declare range(i32 8, 16) i32 @create_range2() +declare range(i32 1, 6) i32 @create_range3() + +; Values' ranges overlap each other, so it can not be simplified. +define i1 @test_two_return_attribute_ranges_not_simplified() { +; CHECK-LABEL: @test_two_return_attribute_ranges_not_simplified( +; CHECK-NEXT: [[ARG2:%.*]] = call range(i32 5, 10) i32 @create_range1() +; CHECK-NEXT: [[ARG1:%.*]] = call i32 @create_range2() +; CHECK-NEXT: [[RVAL:%.*]] = icmp ult i32 [[ARG1]], [[ARG2]] +; CHECK-NEXT: ret i1 [[RVAL]] +; + %val1 = call range(i32 5, 10) i32 @create_range1() + %val2 = call i32 @create_range2() + %rval = icmp ult i32 %val2, %val1 + ret i1 %rval +} + +; Values' ranges do not overlap each other, so it can simplified to false. +define i1 @test_two_return_attribute_ranges_one_in_call() { +; CHECK-LABEL: @test_two_return_attribute_ranges_one_in_call( +; CHECK-NEXT: [[VAL1:%.*]] = call range(i32 1, 6) i32 @create_range1() +; CHECK-NEXT: [[ARG1:%.*]] = call i32 @create_range2() +; CHECK-NEXT: ret i1 false +; + %val1 = call range(i32 1, 6) i32 @create_range1() + %val2 = call i32 @create_range2() + %rval = icmp ult i32 %val2, %val1 + ret i1 %rval +} + +; Values' ranges do not overlap each other, so it can simplified to false. +define i1 @test_two_return_attribute_ranges() { +; CHECK-LABEL: @test_two_return_attribute_ranges( +; CHECK-NEXT: [[VAL1:%.*]] = call i32 @create_range3() +; CHECK-NEXT: [[ARG1:%.*]] = call i32 @create_range2() +; CHECK-NEXT: ret i1 false +; + %val1 = call i32 @create_range3() + %val2 = call i32 @create_range2() + %rval = icmp ult i32 %val2, %val1 + ret i1 %rval +} + +; Values' ranges do not overlap each other, so it can simplified to false. +define i1 @test_one_return_argument_and_one_argument_range(i32 range(i32 8, 16) %arg1) { +; CHECK-LABEL: @test_one_return_argument_and_one_argument_range( +; CHECK-NEXT: [[VAL1:%.*]] = call i32 @create_range3() +; CHECK-NEXT: ret i1 false +; + %val1 = call i32 @create_range3() + %rval = icmp ult i32 %arg1, %val1 + ret i1 %rval +} + +; Values' ranges do not overlap each other, so it can simplified to false. +define i1 @test_one_range_and_one_return_argument(ptr nocapture readonly %arg1) { +; CHECK-LABEL: @test_one_range_and_one_return_argument( +; CHECK-NEXT: [[VAL1:%.*]] = call i32 @create_range3() +; CHECK-NEXT: ret i1 false +; + %val1 = call i32 @create_range3() + %val2 = load i32, ptr %arg1, !range !6 + %rval = icmp ult i32 %val2, %val1 + ret i1 %rval +} + define i1 @ugt_zext(i1 %b, i8 %x) { ; CHECK-LABEL: @ugt_zext( ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 -- GitLab From bba4a1daff6ee09941f1369a4e56b4af95efdc5c Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 12 Mar 2024 09:47:42 +0000 Subject: [PATCH 221/953] [ArgPromotion] Remove incorrect TranspBlocks set for loads. (#84835) The TranspBlocks set was used to cache aliasing decision for all processed loads in the parent loop. This is incorrect, because each load can access a different location, which means one load not being modified in a block doesn't translate to another load not being modified in the same block. All loads access the same underlying object, so we could perhaps use a location without size for all loads and retain the cache, but that would mean we loose precision. For now, just drop the cache. Fixes https://github.com/llvm/llvm-project/issues/84807 PR: https://github.com/llvm/llvm-project/pull/84835 --- llvm/lib/Transforms/IPO/ArgumentPromotion.cpp | 6 +----- ...aliasing-and-non-aliasing-loads-with-clobber.ll | 14 +++++++------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp index e89ec353487e..3aa8ea3f5147 100644 --- a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -653,10 +653,6 @@ static bool findArgParts(Argument *Arg, const DataLayout &DL, AAResults &AAR, // check to see if the pointer is guaranteed to not be modified from entry of // the function to each of the load instructions. - // Because there could be several/many load instructions, remember which - // blocks we know to be transparent to the load. - df_iterator_default_set TranspBlocks; - for (LoadInst *Load : Loads) { // Check to see if the load is invalidated from the start of the block to // the load itself. @@ -670,7 +666,7 @@ static bool findArgParts(Argument *Arg, const DataLayout &DL, AAResults &AAR, // To do this, we perform a depth first search on the inverse CFG from the // loading block. for (BasicBlock *P : predecessors(BB)) { - for (BasicBlock *TranspBB : inverse_depth_first_ext(P, TranspBlocks)) + for (BasicBlock *TranspBB : inverse_depth_first(P)) if (AAR.canBasicBlockModify(*TranspBB, Loc)) return false; } diff --git a/llvm/test/Transforms/ArgumentPromotion/aliasing-and-non-aliasing-loads-with-clobber.ll b/llvm/test/Transforms/ArgumentPromotion/aliasing-and-non-aliasing-loads-with-clobber.ll index 69385a7ea51a..1e1669b29b0d 100644 --- a/llvm/test/Transforms/ArgumentPromotion/aliasing-and-non-aliasing-loads-with-clobber.ll +++ b/llvm/test/Transforms/ArgumentPromotion/aliasing-and-non-aliasing-loads-with-clobber.ll @@ -7,17 +7,14 @@ target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80: ; Test case for https://github.com/llvm/llvm-project/issues/84807. -; FIXME: Currently the loads from @callee are moved to @caller, even though -; the store in %then may aliases to load from %q. +; Make sure the loads from @callee are not moved to @caller, as the store +; in %then may aliases to load from %q. define i32 @caller1(i1 %c) { ; CHECK-LABEL: define i32 @caller1( ; CHECK-SAME: i1 [[C:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[F_VAL:%.*]] = load i16, ptr @f, align 8 -; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr @f, i64 8 -; CHECK-NEXT: [[F_VAL1:%.*]] = load i64, ptr [[TMP0]], align 8 -; CHECK-NEXT: call void @callee1(i16 [[F_VAL]], i64 [[F_VAL1]], i1 [[C]]) +; CHECK-NEXT: call void @callee1(ptr noundef nonnull @f, i1 [[C]]) ; CHECK-NEXT: ret i32 0 ; entry: @@ -27,13 +24,16 @@ entry: define internal void @callee1(ptr nocapture noundef readonly %q, i1 %c) { ; CHECK-LABEL: define internal void @callee1( -; CHECK-SAME: i16 [[Q_0_VAL:%.*]], i64 [[Q_8_VAL:%.*]], i1 [[C:%.*]]) { +; CHECK-SAME: ptr nocapture noundef readonly [[Q:%.*]], i1 [[C:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK: then: ; CHECK-NEXT: store i16 123, ptr @f, align 8 ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: +; CHECK-NEXT: [[Q_0_VAL:%.*]] = load i16, ptr [[Q]], align 8 +; CHECK-NEXT: [[GEP_8:%.*]] = getelementptr inbounds i8, ptr [[Q]], i64 8 +; CHECK-NEXT: [[Q_8_VAL:%.*]] = load i64, ptr [[GEP_8]], align 8 ; CHECK-NEXT: call void @use(i16 [[Q_0_VAL]], i64 [[Q_8_VAL]]) ; CHECK-NEXT: ret void ; -- GitLab From 9228859c2a5aed307dc61edb4cfd6bee7b4c5949 Mon Sep 17 00:00:00 2001 From: David Stuttard Date: Tue, 12 Mar 2024 10:07:02 +0000 Subject: [PATCH 222/953] [CMake] Add tablegen job pool support (#84762) Add the ability to set the number of tablegen jobs that can run in parallel similar to the LLVM_PARALLEL_[COMPILE|LINK]_JOBS options that already exist. --- llvm/cmake/modules/HandleLLVMOptions.cmake | 24 +++++++++++++++++++++- llvm/cmake/modules/TableGen.cmake | 7 +++++++ llvm/docs/CMake.rst | 8 ++++++++ llvm/docs/GettingStarted.rst | 6 +++--- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake index eca2962cf820..745a8354f118 100644 --- a/llvm/cmake/modules/HandleLLVMOptions.cmake +++ b/llvm/cmake/modules/HandleLLVMOptions.cmake @@ -36,7 +36,7 @@ string(TOUPPER "${LLVM_ENABLE_LTO}" uppercase_LLVM_ENABLE_LTO) # The following only works with the Ninja generator in CMake >= 3.0. set(LLVM_PARALLEL_COMPILE_JOBS "" CACHE STRING "Define the maximum number of concurrent compilation jobs (Ninja only).") -if(LLVM_RAM_PER_COMPILE_JOB OR LLVM_RAM_PER_LINK_JOB) +if(LLVM_RAM_PER_COMPILE_JOB OR LLVM_RAM_PER_LINK_JOB OR LLVM_RAM_PER_TABLEGEN_JOB) cmake_host_system_information(RESULT available_physical_memory QUERY AVAILABLE_PHYSICAL_MEMORY) cmake_host_system_information(RESULT number_of_logical_cores QUERY NUMBER_OF_LOGICAL_CORES) endif() @@ -86,6 +86,28 @@ elseif(LLVM_PARALLEL_LINK_JOBS) message(WARNING "Job pooling is only available with Ninja generators.") endif() +set(LLVM_PARALLEL_TABLEGEN_JOBS "" CACHE STRING + "Define the maximum number of concurrent tablegen jobs (Ninja only).") +if(LLVM_RAM_PER_TABLEGEN_JOB) + math(EXPR jobs_with_sufficient_memory "${available_physical_memory} / ${LLVM_RAM_PER_TABLEGEN_JOB}" OUTPUT_FORMAT DECIMAL) + if (jobs_with_sufficient_memory LESS 1) + set(jobs_with_sufficient_memory 1) + endif() + if (jobs_with_sufficient_memory LESS number_of_logical_cores) + set(LLVM_PARALLEL_TABLEGEN_JOBS "${jobs_with_sufficient_memory}") + else() + set(LLVM_PARALLEL_TABLEGEN_JOBS "${number_of_logical_cores}") + endif() +endif() +if(LLVM_PARALLEL_TABLEGEN_JOBS) + if(NOT CMAKE_GENERATOR MATCHES "Ninja") + message(WARNING "Job pooling is only available with Ninja generators.") + else() + set_property(GLOBAL APPEND PROPERTY JOB_POOLS tablegen_job_pool=${LLVM_PARALLEL_TABLEGEN_JOBS}) + # Job pool for tablegen is set on the add_custom_command + endif() +endif() + if( LLVM_ENABLE_ASSERTIONS ) # MSVC doesn't like _DEBUG on release builds. See PR 4379. if( NOT MSVC ) diff --git a/llvm/cmake/modules/TableGen.cmake b/llvm/cmake/modules/TableGen.cmake index 1d18fdde2bb9..df91598c404f 100644 --- a/llvm/cmake/modules/TableGen.cmake +++ b/llvm/cmake/modules/TableGen.cmake @@ -125,6 +125,12 @@ function(tablegen project ofn) set(tablegen_exe ${${project}_TABLEGEN_EXE}) set(tablegen_depends ${${project}_TABLEGEN_TARGET} ${tablegen_exe}) + if(LLVM_PARALLEL_TABLEGEN_JOBS) + set(LLVM_TABLEGEN_JOB_POOL JOB_POOL tablegen_job_pool) + else() + set(LLVM_TABLEGEN_JOB_POOL "") + endif() + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn} COMMAND ${tablegen_exe} ${ARG_UNPARSED_ARGUMENTS} -I ${CMAKE_CURRENT_SOURCE_DIR} ${tblgen_includes} @@ -139,6 +145,7 @@ function(tablegen project ofn) ${local_tds} ${global_tds} ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} ${LLVM_TARGET_DEPENDS} + ${LLVM_TABLEGEN_JOB_POOL} COMMENT "Building ${ofn}..." ) diff --git a/llvm/docs/CMake.rst b/llvm/docs/CMake.rst index 1490b38feb1e..d2f66d71d39a 100644 --- a/llvm/docs/CMake.rst +++ b/llvm/docs/CMake.rst @@ -762,6 +762,9 @@ enabled sub-projects. Nearly all of these variable names begin with **LLVM_PARALLEL_LINK_JOBS**:STRING Define the maximum number of concurrent link jobs. +**LLVM_PARALLEL_TABLEGEN_JOBS**:STRING + Define the maximum number of concurrent tablegen jobs. + **LLVM_RAM_PER_COMPILE_JOB**:STRING Calculates the amount of Ninja compile jobs according to available resources. Value has to be in MB, overwrites LLVM_PARALLEL_COMPILE_JOBS. Compile jobs @@ -775,6 +778,11 @@ enabled sub-projects. Nearly all of these variable names begin with to be sure its not terminated in your memory restricted environment. On ELF platforms also consider ``LLVM_USE_SPLIT_DWARF`` in Debug build. +**LLVM_RAM_PER_TABLEGEN_JOB**:STRING + Calculates the amount of Ninja tablegen jobs according to available resources. + Value has to be in MB, overwrites LLVM_PARALLEL_TABLEGEN_JOBS. Tablegen jobs + will be between one and amount of logical cores. + **LLVM_PROFDATA_FILE**:PATH Path to a profdata file to pass into clang's -fprofile-instr-use flag. This can only be specified if you're building with clang. diff --git a/llvm/docs/GettingStarted.rst b/llvm/docs/GettingStarted.rst index 7634199babba..705f6427d9ed 100644 --- a/llvm/docs/GettingStarted.rst +++ b/llvm/docs/GettingStarted.rst @@ -90,11 +90,11 @@ Getting the Source Code and Building LLVM is installed on your system. This can dramatically speed up link times if the default linker is slow. - * ``-DLLVM_PARALLEL_{COMPILE,LINK}_JOBS=N`` --- Limit the number of - compile/link jobs running in parallel at the same time. This is + * ``-DLLVM_PARALLEL_{COMPILE,LINK,TABLEGEN}_JOBS=N`` --- Limit the number of + compile/link/tablegen jobs running in parallel at the same time. This is especially important for linking since linking can use lots of memory. If you run into memory issues building LLVM, try setting this to limit the - maximum number of compile/link jobs running at the same time. + maximum number of compile/link/tablegen jobs running at the same time. * ``cmake --build build [--target ]`` or the build system specified above directly. -- GitLab From ce1fd9281707c2163728085d126ff83041e1db51 Mon Sep 17 00:00:00 2001 From: Danial Klimkin Date: Tue, 12 Mar 2024 11:19:48 +0100 Subject: [PATCH 223/953] Update test past bdbad0d07bb600301cb324e87a6be37ca4af591a (#84889) --- .../data-formatter/builtin-formats/TestBuiltinFormats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/test/API/functionalities/data-formatter/builtin-formats/TestBuiltinFormats.py b/lldb/test/API/functionalities/data-formatter/builtin-formats/TestBuiltinFormats.py index 8c3bdabeaac1..4d6f44db0195 100644 --- a/lldb/test/API/functionalities/data-formatter/builtin-formats/TestBuiltinFormats.py +++ b/lldb/test/API/functionalities/data-formatter/builtin-formats/TestBuiltinFormats.py @@ -308,5 +308,5 @@ class TestCase(TestBase): @no_debug_info_test def test_instruction(self): self.assertIn( - " addq 0xa(%rdi), %r8\n", self.getFormatted("instruction", "0x0a47034c") + "= addq 0xa(%rdi), %r8\n", self.getFormatted("instruction", "0x0a47034c") ) -- GitLab From 9997e0397156ff7e01aecbd17bdeb7bfe5fb15b0 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Tue, 12 Mar 2024 10:25:58 +0000 Subject: [PATCH 224/953] [RemoveDIs] Update DIBuilder to conditionally insert DbgRecords (#84739) Have DIBuilder conditionally insert either debug intrinsics or DbgRecord depending on the module's IsNewDbgInfoFormat flag. The insertion methods now return a `DbgInstPtr` (a `PointerUnion`). Add a unittest for both modes (I couldn't find an existing test testing insertion behaviours specifically). This patch changes the existing assumption that DbgRecords are only ever inserted if there's an instruction to insert-before because clang currently inserts debug intrinsics while CodeGening (like any other instruction) meaning it'll try inserting to the end of a block without a terminator. We already have machinery in place to maintain the DbgRecords when a terminator is removed - these become "trailing DbgRecords" which are re-attached when a new instruction is inserted. All I've done is allow this state to occur while inserting DbgRecords too, i.e., it's not only removing terminators that causes this valid transient state, but inserting DbgRecords into incomplete blocks too. The C API will be updated in follow up patches. --- Note: this doesn't mean clang is emitting DbgRecords yet, because the modules it creates are still always in the old debug mode. That will come in a future patch. --- llvm/include/llvm/IR/DIBuilder.h | 73 +++++---- llvm/lib/IR/BasicBlock.cpp | 13 +- llvm/lib/IR/DIBuilder.cpp | 131 ++++++++++----- llvm/lib/IR/DebugInfo.cpp | 89 +++++----- llvm/lib/IR/Instruction.cpp | 3 +- llvm/lib/Transforms/Scalar/SROA.cpp | 47 +++--- llvm/lib/Transforms/Utils/Local.cpp | 12 +- .../Utils/PromoteMemoryToRegister.cpp | 25 ++- llvm/unittests/IR/IRBuilderTest.cpp | 152 +++++++++++++++--- 9 files changed, 358 insertions(+), 187 deletions(-) diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index edec161b3971..94af17af8160 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -38,6 +38,9 @@ namespace llvm { class Module; class Value; class DbgAssignIntrinsic; + class DbgRecord; + + using DbgInstPtr = PointerUnion; class DIBuilder { Module &M; @@ -90,13 +93,17 @@ namespace llvm { void trackIfUnresolved(MDNode *N); /// Internal helper for insertDeclare. - Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, - DIExpression *Expr, const DILocation *DL, - BasicBlock *InsertBB, Instruction *InsertBefore); + DbgInstPtr insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, + BasicBlock *InsertBB, Instruction *InsertBefore); /// Internal helper for insertLabel. - Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL, - BasicBlock *InsertBB, Instruction *InsertBefore); + DbgInstPtr insertLabel(DILabel *LabelInfo, const DILocation *DL, + BasicBlock *InsertBB, Instruction *InsertBefore); + + /// Internal helper. Track metadata if untracked and insert \p DPV. + void insertDPValue(DPValue *DPV, BasicBlock *InsertBB, + Instruction *InsertBefore, bool InsertAtHead = false); /// Internal helper with common code used by insertDbg{Value,Addr}Intrinsic. Instruction *insertDbgIntrinsic(llvm::Function *Intrinsic, llvm::Value *Val, @@ -106,10 +113,11 @@ namespace llvm { Instruction *InsertBefore); /// Internal helper for insertDbgValueIntrinsic. - Instruction * - insertDbgValueIntrinsic(llvm::Value *Val, DILocalVariable *VarInfo, - DIExpression *Expr, const DILocation *DL, - BasicBlock *InsertBB, Instruction *InsertBefore); + DbgInstPtr insertDbgValueIntrinsic(llvm::Value *Val, + DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, + BasicBlock *InsertBB, + Instruction *InsertBefore); public: /// Construct a builder for a module. @@ -921,9 +929,9 @@ namespace llvm { /// \param Expr A complex location expression. /// \param DL Debug info location. /// \param InsertAtEnd Location for the new intrinsic. - Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, - DIExpression *Expr, const DILocation *DL, - BasicBlock *InsertAtEnd); + DbgInstPtr insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, + BasicBlock *InsertAtEnd); /// Insert a new llvm.dbg.assign intrinsic call. /// \param LinkedInstr Instruction with a DIAssignID to link with the new @@ -939,11 +947,10 @@ namespace llvm { /// \param DL Debug info location, usually: (line: 0, /// column: 0, scope: var-decl-scope). See /// getDebugValueLoc. - DbgAssignIntrinsic *insertDbgAssign(Instruction *LinkedInstr, Value *Val, - DILocalVariable *SrcVar, - DIExpression *ValExpr, Value *Addr, - DIExpression *AddrExpr, - const DILocation *DL); + DbgInstPtr insertDbgAssign(Instruction *LinkedInstr, Value *Val, + DILocalVariable *SrcVar, DIExpression *ValExpr, + Value *Addr, DIExpression *AddrExpr, + const DILocation *DL); /// Insert a new llvm.dbg.declare intrinsic call. /// \param Storage llvm::Value of the variable @@ -951,23 +958,23 @@ namespace llvm { /// \param Expr A complex location expression. /// \param DL Debug info location. /// \param InsertBefore Location for the new intrinsic. - Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, - DIExpression *Expr, const DILocation *DL, - Instruction *InsertBefore); + DbgInstPtr insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, + Instruction *InsertBefore); /// Insert a new llvm.dbg.label intrinsic call. /// \param LabelInfo Label's debug info descriptor. /// \param DL Debug info location. /// \param InsertBefore Location for the new intrinsic. - Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL, - Instruction *InsertBefore); + DbgInstPtr insertLabel(DILabel *LabelInfo, const DILocation *DL, + Instruction *InsertBefore); /// Insert a new llvm.dbg.label intrinsic call. /// \param LabelInfo Label's debug info descriptor. /// \param DL Debug info location. /// \param InsertAtEnd Location for the new intrinsic. - Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL, - BasicBlock *InsertAtEnd); + DbgInstPtr insertLabel(DILabel *LabelInfo, const DILocation *DL, + BasicBlock *InsertAtEnd); /// Insert a new llvm.dbg.value intrinsic call. /// \param Val llvm::Value of the variable @@ -975,11 +982,10 @@ namespace llvm { /// \param Expr A complex location expression. /// \param DL Debug info location. /// \param InsertAtEnd Location for the new intrinsic. - Instruction *insertDbgValueIntrinsic(llvm::Value *Val, - DILocalVariable *VarInfo, - DIExpression *Expr, - const DILocation *DL, - BasicBlock *InsertAtEnd); + DbgInstPtr insertDbgValueIntrinsic(llvm::Value *Val, + DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, + BasicBlock *InsertAtEnd); /// Insert a new llvm.dbg.value intrinsic call. /// \param Val llvm::Value of the variable @@ -987,11 +993,10 @@ namespace llvm { /// \param Expr A complex location expression. /// \param DL Debug info location. /// \param InsertBefore Location for the new intrinsic. - Instruction *insertDbgValueIntrinsic(llvm::Value *Val, - DILocalVariable *VarInfo, - DIExpression *Expr, - const DILocation *DL, - Instruction *InsertBefore); + DbgInstPtr insertDbgValueIntrinsic(llvm::Value *Val, + DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, + Instruction *InsertBefore); /// Replace the vtable holder in the given type. /// diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp index c188d2f912d1..673e2f68249c 100644 --- a/llvm/lib/IR/BasicBlock.cpp +++ b/llvm/lib/IR/BasicBlock.cpp @@ -754,8 +754,6 @@ void BasicBlock::spliceDebugInfoEmptyBlock(BasicBlock::iterator Dest, // occur when a block is optimised away and the terminator has been moved // somewhere else. if (Src->empty()) { - assert(Dest != end() && - "Transferring trailing DPValues to another trailing position"); DPMarker *SrcTrailingDPValues = Src->getTrailingDPValues(); if (!SrcTrailingDPValues) return; @@ -1040,15 +1038,10 @@ void BasicBlock::insertDPValueAfter(DbgRecord *DPV, Instruction *I) { void BasicBlock::insertDPValueBefore(DbgRecord *DPV, InstListType::iterator Where) { - // We should never directly insert at the end of the block, new DPValues - // shouldn't be generated at times when there's no terminator. - assert(Where != end()); - assert(Where->getParent() == this); - if (!Where->DbgMarker) - createMarker(Where); + assert(Where == end() || Where->getParent() == this); bool InsertAtHead = Where.getHeadBit(); - createMarker(&*Where); - Where->DbgMarker->insertDPValue(DPV, InsertAtHead); + DPMarker *M = createMarker(Where); + M->insertDPValue(DPV, InsertAtHead); } DPMarker *BasicBlock::getNextMarker(Instruction *I) { diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index 62efaba02534..c0643f63c972 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -925,35 +925,47 @@ DILexicalBlock *DIBuilder::createLexicalBlock(DIScope *Scope, DIFile *File, File, Line, Col); } -Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, - DIExpression *Expr, const DILocation *DL, - Instruction *InsertBefore) { +DbgInstPtr DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, + Instruction *InsertBefore) { return insertDeclare(Storage, VarInfo, Expr, DL, InsertBefore->getParent(), InsertBefore); } -Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, - DIExpression *Expr, const DILocation *DL, - BasicBlock *InsertAtEnd) { +DbgInstPtr DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, + BasicBlock *InsertAtEnd) { // If this block already has a terminator then insert this intrinsic before // the terminator. Otherwise, put it at the end of the block. Instruction *InsertBefore = InsertAtEnd->getTerminator(); return insertDeclare(Storage, VarInfo, Expr, DL, InsertAtEnd, InsertBefore); } -DbgAssignIntrinsic * -DIBuilder::insertDbgAssign(Instruction *LinkedInstr, Value *Val, - DILocalVariable *SrcVar, DIExpression *ValExpr, - Value *Addr, DIExpression *AddrExpr, - const DILocation *DL) { +DbgInstPtr DIBuilder::insertDbgAssign(Instruction *LinkedInstr, Value *Val, + DILocalVariable *SrcVar, + DIExpression *ValExpr, Value *Addr, + DIExpression *AddrExpr, + const DILocation *DL) { + auto *Link = cast_or_null( + LinkedInstr->getMetadata(LLVMContext::MD_DIAssignID)); + assert(Link && "Linked instruction must have DIAssign metadata attached"); + + if (M.IsNewDbgInfoFormat) { + DPValue *DPV = DPValue::createDPVAssign(Val, SrcVar, ValExpr, Link, Addr, + AddrExpr, DL); + BasicBlock *InsertBB = LinkedInstr->getParent(); + // Insert after LinkedInstr. + BasicBlock::iterator NextIt = std::next(LinkedInstr->getIterator()); + Instruction *InsertBefore = NextIt == InsertBB->end() ? nullptr : &*NextIt; + insertDPValue(DPV, InsertBB, InsertBefore, true); + return DPV; + } + LLVMContext &Ctx = LinkedInstr->getContext(); Module *M = LinkedInstr->getModule(); if (!AssignFn) AssignFn = Intrinsic::getDeclaration(M, Intrinsic::dbg_assign); - auto *Link = LinkedInstr->getMetadata(LLVMContext::MD_DIAssignID); - assert(Link && "Linked instruction must have DIAssign metadata attached"); - std::array Args = { MetadataAsValue::get(Ctx, ValueAsMetadata::get(Val)), MetadataAsValue::get(Ctx, SrcVar), @@ -971,35 +983,36 @@ DIBuilder::insertDbgAssign(Instruction *LinkedInstr, Value *Val, return DVI; } -Instruction *DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL, - Instruction *InsertBefore) { +DbgInstPtr DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL, + Instruction *InsertBefore) { return insertLabel(LabelInfo, DL, InsertBefore ? InsertBefore->getParent() : nullptr, InsertBefore); } -Instruction *DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL, - BasicBlock *InsertAtEnd) { +DbgInstPtr DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL, + BasicBlock *InsertAtEnd) { return insertLabel(LabelInfo, DL, InsertAtEnd, nullptr); } -Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, - DILocalVariable *VarInfo, - DIExpression *Expr, - const DILocation *DL, - Instruction *InsertBefore) { - Instruction *DVI = insertDbgValueIntrinsic( +DbgInstPtr DIBuilder::insertDbgValueIntrinsic(Value *V, + DILocalVariable *VarInfo, + DIExpression *Expr, + const DILocation *DL, + Instruction *InsertBefore) { + DbgInstPtr DVI = insertDbgValueIntrinsic( V, VarInfo, Expr, DL, InsertBefore ? InsertBefore->getParent() : nullptr, InsertBefore); - cast(DVI)->setTailCall(); + if (DVI.is()) + cast(DVI.get())->setTailCall(); return DVI; } -Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, - DILocalVariable *VarInfo, - DIExpression *Expr, - const DILocation *DL, - BasicBlock *InsertAtEnd) { +DbgInstPtr DIBuilder::insertDbgValueIntrinsic(Value *V, + DILocalVariable *VarInfo, + DIExpression *Expr, + const DILocation *DL, + BasicBlock *InsertAtEnd) { return insertDbgValueIntrinsic(V, VarInfo, Expr, DL, InsertAtEnd, nullptr); } @@ -1023,24 +1036,37 @@ static Function *getDeclareIntrin(Module &M) { return Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); } -Instruction *DIBuilder::insertDbgValueIntrinsic( +DbgInstPtr DIBuilder::insertDbgValueIntrinsic( llvm::Value *Val, DILocalVariable *VarInfo, DIExpression *Expr, const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore) { + if (M.IsNewDbgInfoFormat) { + DPValue *DPV = DPValue::createDPValue(Val, VarInfo, Expr, DL); + insertDPValue(DPV, InsertBB, InsertBefore); + return DPV; + } + if (!ValueFn) ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); return insertDbgIntrinsic(ValueFn, Val, VarInfo, Expr, DL, InsertBB, InsertBefore); } -Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, - DIExpression *Expr, const DILocation *DL, - BasicBlock *InsertBB, - Instruction *InsertBefore) { +DbgInstPtr DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, + BasicBlock *InsertBB, + Instruction *InsertBefore) { assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.declare"); assert(DL && "Expected debug loc"); assert(DL->getScope()->getSubprogram() == VarInfo->getScope()->getSubprogram() && "Expected matching subprograms"); + + if (M.IsNewDbgInfoFormat) { + DPValue *DPV = DPValue::createDPVDeclare(Storage, VarInfo, Expr, DL); + insertDPValue(DPV, InsertBB, InsertBefore); + return DPV; + } + if (!DeclareFn) DeclareFn = getDeclareIntrin(M); @@ -1055,6 +1081,23 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, return B.CreateCall(DeclareFn, Args); } +void DIBuilder::insertDPValue(DPValue *DPV, BasicBlock *InsertBB, + Instruction *InsertBefore, bool InsertAtHead) { + assert(InsertBefore || InsertBB); + trackIfUnresolved(DPV->getVariable()); + trackIfUnresolved(DPV->getExpression()); + if (DPV->isDbgAssign()) + trackIfUnresolved(DPV->getAddressExpression()); + + BasicBlock::iterator InsertPt; + if (InsertBB && InsertBefore) + InsertPt = InsertBefore->getIterator(); + else if (InsertBB) + InsertPt = InsertBB->end(); + InsertPt.setHeadBit(InsertAtHead); + InsertBB->insertDPValueBefore(DPV, InsertPt); +} + Instruction *DIBuilder::insertDbgIntrinsic(llvm::Function *IntrinsicFn, Value *V, DILocalVariable *VarInfo, DIExpression *Expr, @@ -1081,18 +1124,28 @@ Instruction *DIBuilder::insertDbgIntrinsic(llvm::Function *IntrinsicFn, return B.CreateCall(IntrinsicFn, Args); } -Instruction *DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL, - BasicBlock *InsertBB, - Instruction *InsertBefore) { +DbgInstPtr DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL, + BasicBlock *InsertBB, + Instruction *InsertBefore) { assert(LabelInfo && "empty or invalid DILabel* passed to dbg.label"); assert(DL && "Expected debug loc"); assert(DL->getScope()->getSubprogram() == LabelInfo->getScope()->getSubprogram() && "Expected matching subprograms"); + + trackIfUnresolved(LabelInfo); + if (M.IsNewDbgInfoFormat) { + DPLabel *DPL = new DPLabel(LabelInfo, DL); + if (InsertBB && InsertBefore) + InsertBB->insertDPValueBefore(DPL, InsertBefore->getIterator()); + else if (InsertBB) + InsertBB->insertDPValueBefore(DPL, InsertBB->end()); + return DPL; + } + if (!LabelFn) LabelFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_label); - trackIfUnresolved(LabelInfo); Value *Args[] = {MetadataAsValue::get(VMContext, LabelInfo)}; IRBuilder<> B(DL->getContext()); diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 1f3ff2246a44..68fd244e2569 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -1663,43 +1663,47 @@ LLVMValueRef LLVMDIBuilderInsertDeclareBefore(LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMValueRef Instr) { - return wrap(unwrap(Builder)->insertDeclare( - unwrap(Storage), unwrap(VarInfo), - unwrap(Expr), unwrap(DL), - unwrap(Instr))); -} - -LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd( - LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, - LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMBasicBlockRef Block) { - return wrap(unwrap(Builder)->insertDeclare( - unwrap(Storage), unwrap(VarInfo), - unwrap(Expr), unwrap(DL), - unwrap(Block))); -} - -LLVMValueRef LLVMDIBuilderInsertDbgValueBefore(LLVMDIBuilderRef Builder, - LLVMValueRef Val, - LLVMMetadataRef VarInfo, - LLVMMetadataRef Expr, - LLVMMetadataRef DebugLoc, - LLVMValueRef Instr) { - return wrap(unwrap(Builder)->insertDbgValueIntrinsic( - unwrap(Val), unwrap(VarInfo), - unwrap(Expr), unwrap(DebugLoc), - unwrap(Instr))); -} - -LLVMValueRef LLVMDIBuilderInsertDbgValueAtEnd(LLVMDIBuilderRef Builder, - LLVMValueRef Val, - LLVMMetadataRef VarInfo, - LLVMMetadataRef Expr, - LLVMMetadataRef DebugLoc, - LLVMBasicBlockRef Block) { - return wrap(unwrap(Builder)->insertDbgValueIntrinsic( - unwrap(Val), unwrap(VarInfo), - unwrap(Expr), unwrap(DebugLoc), - unwrap(Block))); + DbgInstPtr DbgInst = unwrap(Builder)->insertDeclare( + unwrap(Storage), unwrap(VarInfo), + unwrap(Expr), unwrap(DL), + unwrap(Instr)); + assert(isa(DbgInst) && + "Inserted a DbgRecord into function using old debug info mode"); + return wrap(cast(DbgInst)); +} + +LLVMValueRef +LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Builder, LLVMValueRef Storage, + LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, + LLVMMetadataRef DL, LLVMBasicBlockRef Block) { + DbgInstPtr DbgInst = unwrap(Builder)->insertDeclare( + unwrap(Storage), unwrap(VarInfo), + unwrap(Expr), unwrap(DL), unwrap(Block)); + assert(isa(DbgInst) && + "Inserted a DbgRecord into function using old debug info mode"); + return wrap(cast(DbgInst)); +} + +LLVMValueRef LLVMDIBuilderInsertDbgValueBefore( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr) { + DbgInstPtr DbgInst = unwrap(Builder)->insertDbgValueIntrinsic( + unwrap(Val), unwrap(VarInfo), unwrap(Expr), + unwrap(DebugLoc), unwrap(Instr)); + assert(isa(DbgInst) && + "Inserted a DbgRecord into function using old debug info mode"); + return wrap(cast(DbgInst)); +} + +LLVMValueRef LLVMDIBuilderInsertDbgValueAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block) { + DbgInstPtr DbgInst = unwrap(Builder)->insertDbgValueIntrinsic( + unwrap(Val), unwrap(VarInfo), unwrap(Expr), + unwrap(DebugLoc), unwrap(Block)); + assert(isa(DbgInst) && + "Inserted a DbgRecord into function using old debug info mode"); + return wrap(cast(DbgInst)); } LLVMMetadataRef LLVMDIBuilderCreateAutoVariable( @@ -2115,10 +2119,15 @@ static void emitDbgAssign(AssignmentInfo Info, Value *Val, Value *Dest, LLVM_DEBUG(if (Assign) errs() << " > INSERT: " << *Assign << "\n"); return; } - auto *Assign = DIB.insertDbgAssign(&StoreLikeInst, Val, VarRec.Var, Expr, - Dest, AddrExpr, VarRec.DL); + auto Assign = DIB.insertDbgAssign(&StoreLikeInst, Val, VarRec.Var, Expr, Dest, + AddrExpr, VarRec.DL); (void)Assign; - LLVM_DEBUG(if (Assign) errs() << " > INSERT: " << *Assign << "\n"); + LLVM_DEBUG(if (!Assign.isNull()) { + if (Assign.is()) + errs() << " > INSERT: " << *Assign.get() << "\n"; + else + errs() << " > INSERT: " << *Assign.get() << "\n"; + }); } #undef DEBUG_TYPE // Silence redefinition warning (from ConstantsContext.h). diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index e863ef3eb8d6..6b8c6e0c85ed 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -166,7 +166,8 @@ void Instruction::insertBefore(BasicBlock &BB, } // If we're inserting a terminator, check if we need to flush out - // TrailingDPValues. + // TrailingDPValues. Inserting instructions at the end of an incomplete + // block is handled by the code block above. if (isTerminator()) getParent()->flushTerminatorDbgValues(); } diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp index e11b984f13bb..190fee11618b 100644 --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -324,23 +324,16 @@ static DebugVariable getAggregateVariable(DPValue *DPV) { DPV->getDebugLoc().getInlinedAt()); } -static DPValue *createLinkedAssign(DPValue *, DIBuilder &DIB, - Instruction *LinkedInstr, Value *NewValue, - DILocalVariable *Variable, - DIExpression *Expression, Value *Address, - DIExpression *AddressExpression, - const DILocation *DI) { - (void)DIB; - return DPValue::createLinkedDPVAssign(LinkedInstr, NewValue, Variable, - Expression, Address, AddressExpression, - DI); +/// Helpers for handling new and old debug info modes in migrateDebugInfo. +/// These overloads unwrap a DbgInstPtr {Instruction* | DbgRecord*} union based +/// on the \p Unused parameter type. +DPValue *UnwrapDbgInstPtr(DbgInstPtr P, DPValue *Unused) { + (void)Unused; + return static_cast(cast(P)); } -static DbgAssignIntrinsic *createLinkedAssign( - DbgAssignIntrinsic *, DIBuilder &DIB, Instruction *LinkedInstr, - Value *NewValue, DILocalVariable *Variable, DIExpression *Expression, - Value *Address, DIExpression *AddressExpression, const DILocation *DI) { - return DIB.insertDbgAssign(LinkedInstr, NewValue, Variable, Expression, - Address, AddressExpression, DI); +DbgAssignIntrinsic *UnwrapDbgInstPtr(DbgInstPtr P, DbgAssignIntrinsic *Unused) { + (void)Unused; + return static_cast(cast(P)); } /// Find linked dbg.assign and generate a new one with the correct @@ -398,7 +391,7 @@ static void migrateDebugInfo(AllocaInst *OldAlloca, bool IsSplit, DIBuilder DIB(*OldInst->getModule(), /*AllowUnresolved*/ false); assert(OldAlloca->isStaticAlloca()); - auto MigrateDbgAssign = [&](auto DbgAssign) { + auto MigrateDbgAssign = [&](auto *DbgAssign) { LLVM_DEBUG(dbgs() << " existing dbg.assign is: " << *DbgAssign << "\n"); auto *Expr = DbgAssign->getExpression(); @@ -452,10 +445,12 @@ static void migrateDebugInfo(AllocaInst *OldAlloca, bool IsSplit, } ::Value *NewValue = Value ? Value : DbgAssign->getValue(); - auto *NewAssign = createLinkedAssign( - DbgAssign, DIB, Inst, NewValue, DbgAssign->getVariable(), Expr, Dest, - DIExpression::get(Expr->getContext(), std::nullopt), - DbgAssign->getDebugLoc()); + auto *NewAssign = UnwrapDbgInstPtr( + DIB.insertDbgAssign(Inst, NewValue, DbgAssign->getVariable(), Expr, + Dest, + DIExpression::get(Expr->getContext(), std::nullopt), + DbgAssign->getDebugLoc()), + DbgAssign); // If we've updated the value but the original dbg.assign has an arglist // then kill it now - we can't use the requested new value. @@ -5031,9 +5026,11 @@ static void insertNewDbgInst(DIBuilder &DIB, DbgAssignIntrinsic *Orig, NewAddr->setMetadata(LLVMContext::MD_DIAssignID, DIAssignID::getDistinct(NewAddr->getContext())); } - auto *NewAssign = DIB.insertDbgAssign( - NewAddr, Orig->getValue(), Orig->getVariable(), NewFragmentExpr, NewAddr, - Orig->getAddressExpression(), Orig->getDebugLoc()); + Instruction *NewAssign = + DIB.insertDbgAssign(NewAddr, Orig->getValue(), Orig->getVariable(), + NewFragmentExpr, NewAddr, + Orig->getAddressExpression(), Orig->getDebugLoc()) + .get(); LLVM_DEBUG(dbgs() << "Created new assign intrinsic: " << *NewAssign << "\n"); (void)NewAssign; } @@ -5052,7 +5049,7 @@ static void insertNewDbgInst(DIBuilder &DIB, DPValue *Orig, AllocaInst *NewAddr, NewAddr->setMetadata(LLVMContext::MD_DIAssignID, DIAssignID::getDistinct(NewAddr->getContext())); } - auto *NewAssign = DPValue::createLinkedDPVAssign( + DPValue *NewAssign = DPValue::createLinkedDPVAssign( NewAddr, Orig->getValue(), Orig->getVariable(), NewFragmentExpr, NewAddr, Orig->getAddressExpression(), Orig->getDebugLoc()); LLVM_DEBUG(dbgs() << "Created new DPVAssign: " << *NewAssign << "\n"); diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index d3bb89075015..a44536e34c92 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1649,9 +1649,9 @@ static void insertDbgValueOrDPValue(DIBuilder &Builder, Value *DV, const DebugLoc &NewLoc, BasicBlock::iterator Instr) { if (!UseNewDbgInfoFormat) { - auto *DbgVal = Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, NewLoc, - (Instruction *)nullptr); - DbgVal->insertBefore(Instr); + auto DbgVal = Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, NewLoc, + (Instruction *)nullptr); + DbgVal.get()->insertBefore(Instr); } else { // RemoveDIs: if we're using the new debug-info format, allocate a // DPValue directly instead of a dbg.value intrinsic. @@ -1667,9 +1667,9 @@ static void insertDbgValueOrDPValueAfter(DIBuilder &Builder, Value *DV, const DebugLoc &NewLoc, BasicBlock::iterator Instr) { if (!UseNewDbgInfoFormat) { - auto *DbgVal = Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, NewLoc, - (Instruction *)nullptr); - DbgVal->insertAfter(&*Instr); + auto DbgVal = Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, NewLoc, + (Instruction *)nullptr); + DbgVal.get()->insertAfter(&*Instr); } else { // RemoveDIs: if we're using the new debug-info format, allocate a // DPValue directly instead of a dbg.value intrinsic. diff --git a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index 88b05aab8db4..b462803bad38 100644 --- a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -101,21 +101,20 @@ bool llvm::isAllocaPromotable(const AllocaInst *AI) { namespace { -static DPValue *createDebugValue(DIBuilder &DIB, Value *NewValue, - DILocalVariable *Variable, - DIExpression *Expression, const DILocation *DI, - DPValue *InsertBefore) { +static void createDebugValue(DIBuilder &DIB, Value *NewValue, + DILocalVariable *Variable, + DIExpression *Expression, const DILocation *DI, + DPValue *InsertBefore) { + // FIXME: Merge these two functions now that DIBuilder supports DPValues. + // We neeed the API to accept DPValues as an insert point for that to work. (void)DIB; - return DPValue::createDPValue(NewValue, Variable, Expression, DI, - *InsertBefore); + DPValue::createDPValue(NewValue, Variable, Expression, DI, *InsertBefore); } -static DbgValueInst *createDebugValue(DIBuilder &DIB, Value *NewValue, - DILocalVariable *Variable, - DIExpression *Expression, - const DILocation *DI, - Instruction *InsertBefore) { - return static_cast(DIB.insertDbgValueIntrinsic( - NewValue, Variable, Expression, DI, InsertBefore)); +static void createDebugValue(DIBuilder &DIB, Value *NewValue, + DILocalVariable *Variable, + DIExpression *Expression, const DILocation *DI, + Instruction *InsertBefore) { + DIB.insertDbgValueIntrinsic(NewValue, Variable, Expression, DI, InsertBefore); } /// Helper for updating assignment tracking debug info when promoting allocas. diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp index d15ff9dd51a4..cece65974c01 100644 --- a/llvm/unittests/IR/IRBuilderTest.cpp +++ b/llvm/unittests/IR/IRBuilderTest.cpp @@ -871,25 +871,139 @@ TEST_F(IRBuilderTest, createFunction) { } TEST_F(IRBuilderTest, DIBuilder) { - IRBuilder<> Builder(BB); - DIBuilder DIB(*M); - auto File = DIB.createFile("F.CBL", "/"); - auto CU = DIB.createCompileUnit(dwarf::DW_LANG_Cobol74, - DIB.createFile("F.CBL", "/"), "llvm-cobol74", - true, "", 0); - auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray(std::nullopt)); - auto SP = DIB.createFunction( - CU, "foo", "", File, 1, Type, 1, DINode::FlagZero, - DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized); - F->setSubprogram(SP); - AllocaInst *I = Builder.CreateAlloca(Builder.getInt8Ty()); - auto BarSP = DIB.createFunction( - CU, "bar", "", File, 1, Type, 1, DINode::FlagZero, - DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized); - auto BadScope = DIB.createLexicalBlockFile(BarSP, File, 0); - I->setDebugLoc(DILocation::get(Ctx, 2, 0, BadScope)); - DIB.finalize(); - EXPECT_TRUE(verifyModule(*M)); + auto GetLastDbgRecord = [](const Instruction *I) -> DbgRecord * { + if (I->getDbgValueRange().empty()) + return nullptr; + return &*std::prev(I->getDbgValueRange().end()); + }; + + auto ExpectOrder = [&](DbgInstPtr First, BasicBlock::iterator Second) { + if (M->IsNewDbgInfoFormat) { + EXPECT_TRUE(First.is()); + EXPECT_FALSE(Second->getDbgValueRange().empty()); + EXPECT_EQ(GetLastDbgRecord(&*Second), First.get()); + } else { + EXPECT_TRUE(First.is()); + EXPECT_EQ(&*std::prev(Second), First.get()); + } + }; + + auto RunTest = [&]() { + IRBuilder<> Builder(BB); + DIBuilder DIB(*M); + auto File = DIB.createFile("F.CBL", "/"); + auto CU = DIB.createCompileUnit(dwarf::DW_LANG_Cobol74, + DIB.createFile("F.CBL", "/"), + "llvm-cobol74", true, "", 0); + auto Type = + DIB.createSubroutineType(DIB.getOrCreateTypeArray(std::nullopt)); + auto SP = DIB.createFunction( + CU, "foo", "", File, 1, Type, 1, DINode::FlagZero, + DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized); + F->setSubprogram(SP); + AllocaInst *I = Builder.CreateAlloca(Builder.getInt8Ty()); + auto BarSP = DIB.createFunction( + CU, "bar", "", File, 1, Type, 1, DINode::FlagZero, + DISubprogram::SPFlagDefinition | DISubprogram::SPFlagOptimized); + auto BarScope = DIB.createLexicalBlockFile(BarSP, File, 0); + I->setDebugLoc(DILocation::get(Ctx, 2, 0, BarScope)); + + // Create another instruction so that there's one before the alloca we're + // inserting debug intrinsics before, to make end-checking easier. + I = Builder.CreateAlloca(Builder.getInt1Ty()); + + // Label metadata and records + // -------------------------- + DILocation *LabelLoc = DILocation::get(Ctx, 1, 0, BarScope); + DILabel *AlwaysPreserveLabel = DIB.createLabel( + BarScope, "meles_meles", File, 1, /*AlwaysPreserve*/ true); + DILabel *Label = + DIB.createLabel(BarScope, "badger", File, 1, /*AlwaysPreserve*/ false); + + { /* dbg.label | DPLabel */ + // Insert before I and check order. + ExpectOrder(DIB.insertLabel(Label, LabelLoc, I), I->getIterator()); + + // We should be able to insert at the end of the block, even if there's + // no terminator yet. Note that in RemoveDIs mode this record won't get + // inserted into the block untill another instruction is added. + DbgInstPtr LabelRecord = DIB.insertLabel(Label, LabelLoc, BB); + // Specifically do not insert a terminator, to check this works. `I` + // should have absorbed the DPLabel in the new debug info mode. + I = Builder.CreateAlloca(Builder.getInt32Ty()); + ExpectOrder(LabelRecord, I->getIterator()); + } + + // Variable metadata and records + // ----------------------------- + DILocation *VarLoc = DILocation::get(Ctx, 2, 0, BarScope); + auto *IntType = DIB.createBasicType("int", 32, dwarf::DW_ATE_signed); + DILocalVariable *VarX = + DIB.createAutoVariable(BarSP, "X", File, 2, IntType, true); + DILocalVariable *VarY = + DIB.createAutoVariable(BarSP, "Y", File, 2, IntType, true); + { /* dbg.value | DPValue::Value */ + ExpectOrder(DIB.insertDbgValueIntrinsic(I, VarX, DIB.createExpression(), + VarLoc, I), + I->getIterator()); + // Check inserting at end of the block works as with labels. + DbgInstPtr VarXValue = DIB.insertDbgValueIntrinsic( + I, VarX, DIB.createExpression(), VarLoc, BB); + I = Builder.CreateAlloca(Builder.getInt32Ty()); + ExpectOrder(VarXValue, I->getIterator()); + EXPECT_EQ(BB->getTrailingDPValues(), nullptr); + } + { /* dbg.declare | DPValue::Declare */ + ExpectOrder(DIB.insertDeclare(I, VarY, DIB.createExpression(), VarLoc, I), + I->getIterator()); + // Check inserting at end of the block works as with labels. + DbgInstPtr VarYDeclare = + DIB.insertDeclare(I, VarY, DIB.createExpression(), VarLoc, BB); + I = Builder.CreateAlloca(Builder.getInt32Ty()); + ExpectOrder(VarYDeclare, I->getIterator()); + EXPECT_EQ(BB->getTrailingDPValues(), nullptr); + } + { /* dbg.assign | DPValue::Assign */ + I = Builder.CreateAlloca(Builder.getInt32Ty()); + I->setMetadata(LLVMContext::MD_DIAssignID, DIAssignID::getDistinct(Ctx)); + // DbgAssign interface is slightly different - it always inserts after the + // linked instr. Check we can do this with no instruction to insert + // before. + DbgInstPtr VarXAssign = + DIB.insertDbgAssign(I, I, VarX, DIB.createExpression(), I, + DIB.createExpression(), VarLoc); + I = Builder.CreateAlloca(Builder.getInt32Ty()); + ExpectOrder(VarXAssign, I->getIterator()); + EXPECT_EQ(BB->getTrailingDPValues(), nullptr); + } + + Builder.CreateRet(nullptr); + DIB.finalize(); + // Check the labels are not/are added to Bar's retainedNodes array + // (AlwaysPreserve). + EXPECT_EQ(find(BarSP->getRetainedNodes(), Label), + BarSP->getRetainedNodes().end()); + EXPECT_NE(find(BarSP->getRetainedNodes(), AlwaysPreserveLabel), + BarSP->getRetainedNodes().end()); + EXPECT_NE(find(BarSP->getRetainedNodes(), VarX), + BarSP->getRetainedNodes().end()); + EXPECT_NE(find(BarSP->getRetainedNodes(), VarY), + BarSP->getRetainedNodes().end()); + EXPECT_TRUE(verifyModule(*M)); + }; + + // Test in old-debug mode. + EXPECT_FALSE(M->IsNewDbgInfoFormat); + RunTest(); + + // Test in new-debug mode. + // Reset the test then call convertToNewDbgValues to flip the flag + // on the test's Module, Function and BasicBlock. + TearDown(); + SetUp(); + M->convertToNewDbgValues(); + EXPECT_TRUE(M->IsNewDbgInfoFormat); + RunTest(); } TEST_F(IRBuilderTest, createArtificialSubprogram) { -- GitLab From 19266ca389e3fc3bce9d24c074b836d6e69873ce Mon Sep 17 00:00:00 2001 From: Marius Brehler Date: Tue, 12 Mar 2024 11:27:26 +0100 Subject: [PATCH 225/953] [mlir][EmitC] Add an `emitc.conditional` operator (#84883) This adds an `emitc.conditional` operation for the ternary conditional operator. Furthermore, this adds a converion from `arith.select` to the new op. --- mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 30 +++++++++++++++ .../Conversion/ArithToEmitC/ArithToEmitC.cpp | 28 +++++++++++++- mlir/lib/Target/Cpp/TranslateToCpp.cpp | 37 ++++++++++++++++--- .../ArithToEmitC/arith-to-emitc.mlir | 8 ++++ mlir/test/Dialect/EmitC/ops.mlir | 5 +++ mlir/test/Target/Cpp/conditional.mlir | 9 +++++ 6 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 mlir/test/Target/Cpp/conditional.mlir diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td index ac1e38a5506d..ec842f76628c 100644 --- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td +++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td @@ -908,6 +908,36 @@ def EmitC_SubOp : EmitC_BinaryOp<"sub", [CExpression]> { let hasVerifier = 1; } +def EmitC_ConditionalOp : EmitC_Op<"conditional", + [AllTypesMatch<["true_value", "false_value", "result"]>, CExpression]> { + let summary = "Conditional (ternary) operation"; + let description = [{ + With the `conditional` operation the ternary conditional operator can + be applied. + + Example: + + ```mlir + %0 = emitc.cmp gt, %arg0, %arg1 : (i32, i32) -> i1 + + %c0 = "emitc.constant"() {value = 10 : i32} : () -> i32 + %c1 = "emitc.constant"() {value = 11 : i32} : () -> i32 + + %1 = emitc.conditional %0, %c0, %c1 : i32 + ``` + ```c++ + // Code emitted for the operations above. + bool v3 = v1 > v2; + int32_t v4 = 10; + int32_t v5 = 11; + int32_t v6 = v3 ? v4 : v5; + ``` + }]; + let arguments = (ins I1:$condition, AnyType:$true_value, AnyType:$false_value); + let results = (outs AnyType:$result); + let assemblyFormat = "operands attr-dict `:` type($result)"; +} + def EmitC_UnaryMinusOp : EmitC_UnaryOp<"unary_minus", [CExpression]> { let summary = "Unary minus operation"; let description = [{ diff --git a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp index 40dce001a3b2..3532785c31b9 100644 --- a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp +++ b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp @@ -54,6 +54,31 @@ public: return success(); } }; + +class SelectOpConversion : public OpConversionPattern { +public: + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(arith::SelectOp selectOp, OpAdaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + + Type dstType = getTypeConverter()->convertType(selectOp.getType()); + if (!dstType) + return rewriter.notifyMatchFailure(selectOp, "type conversion failed"); + + if (!adaptor.getCondition().getType().isInteger(1)) + return rewriter.notifyMatchFailure( + selectOp, + "can only be converted if condition is a scalar of type i1"); + + rewriter.replaceOpWithNewOp(selectOp, dstType, + adaptor.getOperands()); + + return success(); + } +}; + } // namespace //===----------------------------------------------------------------------===// @@ -70,7 +95,8 @@ void mlir::populateArithToEmitCPatterns(TypeConverter &typeConverter, ArithOpConversion, ArithOpConversion, ArithOpConversion, - ArithOpConversion + ArithOpConversion, + SelectOpConversion >(typeConverter, ctx); // clang-format on } diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp index 3cf137c1d07c..7cbb1e9265e1 100644 --- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp +++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp @@ -96,6 +96,7 @@ static FailureOr getOperatorPrecedence(Operation *operation) { } return op->emitError("unsupported cmp predicate"); }) + .Case([&](auto op) { return 2; }) .Case([&](auto op) { return 13; }) .Case([&](auto op) { return 4; }) .Case([&](auto op) { return 15; }) @@ -446,6 +447,29 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::CmpOp cmpOp) { return printBinaryOperation(emitter, operation, binaryOperator); } +static LogicalResult printOperation(CppEmitter &emitter, + emitc::ConditionalOp conditionalOp) { + raw_ostream &os = emitter.ostream(); + + if (failed(emitter.emitAssignPrefix(*conditionalOp))) + return failure(); + + if (failed(emitter.emitOperand(conditionalOp.getCondition()))) + return failure(); + + os << " ? "; + + if (failed(emitter.emitOperand(conditionalOp.getTrueValue()))) + return failure(); + + os << " : "; + + if (failed(emitter.emitOperand(conditionalOp.getFalseValue()))) + return failure(); + + return success(); +} + static LogicalResult printOperation(CppEmitter &emitter, emitc::VerbatimOp verbatimOp) { raw_ostream &os = emitter.ostream(); @@ -1383,12 +1407,13 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) { emitc::BitwiseNotOp, emitc::BitwiseOrOp, emitc::BitwiseRightShiftOp, emitc::BitwiseXorOp, emitc::CallOp, emitc::CallOpaqueOp, emitc::CastOp, emitc::CmpOp, - emitc::ConstantOp, emitc::DeclareFuncOp, emitc::DivOp, - emitc::ExpressionOp, emitc::ForOp, emitc::FuncOp, emitc::IfOp, - emitc::IncludeOp, emitc::LogicalAndOp, emitc::LogicalNotOp, - emitc::LogicalOrOp, emitc::MulOp, emitc::RemOp, emitc::ReturnOp, - emitc::SubOp, emitc::UnaryMinusOp, emitc::UnaryPlusOp, - emitc::VariableOp, emitc::VerbatimOp>( + emitc::ConditionalOp, emitc::ConstantOp, emitc::DeclareFuncOp, + emitc::DivOp, emitc::ExpressionOp, emitc::ForOp, emitc::FuncOp, + emitc::IfOp, emitc::IncludeOp, emitc::LogicalAndOp, + emitc::LogicalNotOp, emitc::LogicalOrOp, emitc::MulOp, + emitc::RemOp, emitc::ReturnOp, emitc::SubOp, + emitc::UnaryMinusOp, emitc::UnaryPlusOp, emitc::VariableOp, + emitc::VerbatimOp>( [&](auto op) { return printOperation(*this, op); }) // Func ops. .Case( diff --git a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir index 2886810c01e9..022530ef4db8 100644 --- a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir +++ b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir @@ -34,3 +34,11 @@ func.func @arith_ops(%arg0: f32, %arg1: f32) { return } + +// ----- + +func.func @arith_select(%arg0: i1, %arg1: tensor<8xi32>, %arg2: tensor<8xi32>) -> () { + // CHECK: [[V0:[^ ]*]] = emitc.conditional %arg0, %arg1, %arg2 : tensor<8xi32> + %0 = arith.select %arg0, %arg1, %arg2 : i1, tensor<8xi32> + return +} diff --git a/mlir/test/Dialect/EmitC/ops.mlir b/mlir/test/Dialect/EmitC/ops.mlir index 122b1d9ef105..5f00a295ed74 100644 --- a/mlir/test/Dialect/EmitC/ops.mlir +++ b/mlir/test/Dialect/EmitC/ops.mlir @@ -71,6 +71,11 @@ func.func @bitwise(%arg0: i32, %arg1: i32) -> () { return } +func.func @cond(%cond: i1, %arg0: i32, %arg1: i32) -> () { + %0 = emitc.conditional %cond, %arg0, %arg1 : i32 + return +} + func.func @div_int(%arg0: i32, %arg1: i32) { %1 = "emitc.div" (%arg0, %arg1) : (i32, i32) -> i32 return diff --git a/mlir/test/Target/Cpp/conditional.mlir b/mlir/test/Target/Cpp/conditional.mlir new file mode 100644 index 000000000000..2470fbeb33ad --- /dev/null +++ b/mlir/test/Target/Cpp/conditional.mlir @@ -0,0 +1,9 @@ +// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s + +func.func @cond(%cond: i1, %arg0: i32, %arg1: i32) -> () { + %0 = emitc.conditional %cond, %arg0, %arg1 : i32 + return +} + +// CHECK-LABEL: void cond +// CHECK-NEXT: int32_t [[V3:[^ ]*]] = [[V0:[^ ]*]] ? [[V1:[^ ]*]] : [[V2:[^ ]*]]; -- GitLab From 23ffb2bdb96cf5a8eebce86b1ab21acf88979661 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Tue, 12 Mar 2024 03:30:43 -0700 Subject: [PATCH 226/953] [CMake] Enable new policy for CMAKE_MSVC_DEBUG_INFORMATION_FORMAT (#82371) --- cmake/Modules/CMakePolicy.cmake | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cmake/Modules/CMakePolicy.cmake b/cmake/Modules/CMakePolicy.cmake index 0ec32ad8637f..b5bd1e6cdffe 100644 --- a/cmake/Modules/CMakePolicy.cmake +++ b/cmake/Modules/CMakePolicy.cmake @@ -10,3 +10,16 @@ endif() if(POLICY CMP0116) cmake_policy(SET CMP0116 OLD) endif() + +# MSVC debug information format flags are selected via +# CMAKE_MSVC_DEBUG_INFORMATION_FORMAT, instead of +# embedding flags in e.g. CMAKE_CXX_FLAGS_RELEASE. +# New in CMake 3.25. +# +# Supports debug info with SCCache +# (https://github.com/mozilla/sccache?tab=readme-ov-file#usage) +# avoiding “fatal error C1041: cannot open program database; if +# multiple CL.EXE write to the same .PDB file, please use /FS" ++if(POLICY CMP0141) ++ cmake_policy(SET CMP0141 NEW) ++endif() -- GitLab From 5a100551d5652da586800c67edd4ccb3b18b10dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 12 Mar 2024 12:32:48 +0200 Subject: [PATCH 227/953] [Analysis] Treat ldexpf() as missing on MinGW (#84748) The function does exist, but it is a plain wrapper over regular ldexp(), so there's no benefit in calling it over regular ldexp(). Therefore, treat it as missing. This fixes builds of Wine for aarch64 with Clang in mingw mode, which regressed recently in 8d976c7f20fe8d92fe6f54af411594e15fac25ae. That commit unlocked transforming calls to ldexp into ldexpf, for some codepaths within Wine. Wine can use compilers in mingw mode without the regular mingw runtime libraries, which caused this to fail. (However, if the transformation to use ldexpf() would have made sense, the right fix would have been for Wine to provide a similar ldexpf->ldexp wrapper just like mingw does.) --- llvm/lib/Analysis/TargetLibraryInfo.cpp | 5 +++++ llvm/test/Transforms/InstCombine/exp2-1.ll | 1 + 2 files changed, 6 insertions(+) diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index 835268bb2d85..c8195584ade3 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -456,6 +456,11 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, TLI.setUnavailable(LibFunc_uname); TLI.setUnavailable(LibFunc_unsetenv); TLI.setUnavailable(LibFunc_utimes); + + // MinGW does have ldexpf, but it is a plain wrapper over regular ldexp. + // Therefore it's not beneficial to transform code to use it, i.e. + // just pretend that the function is not available. + TLI.setUnavailable(LibFunc_ldexpf); } // Pick just one set of new/delete variants. diff --git a/llvm/test/Transforms/InstCombine/exp2-1.ll b/llvm/test/Transforms/InstCombine/exp2-1.ll index 79aeded2fa5c..8419854d3ec6 100644 --- a/llvm/test/Transforms/InstCombine/exp2-1.ll +++ b/llvm/test/Transforms/InstCombine/exp2-1.ll @@ -4,6 +4,7 @@ ; RUN: opt < %s -passes=instcombine -S -mtriple=unknown | FileCheck %s -check-prefixes=LDEXP32 ; RUN: opt < %s -passes=instcombine -S -mtriple=msp430 | FileCheck %s -check-prefixes=LDEXP16 ; RUN: opt < %s -passes=instcombine -S -mtriple=i386-pc-win32 | FileCheck %s -check-prefixes=NOLDEXPF +; RUN: opt < %s -passes=instcombine -S -mtriple=i386-windows-gnu | FileCheck %s -check-prefixes=NOLDEXPF ; RUN: opt < %s -passes=instcombine -S -mtriple=amdgcn-unknown-unknown | FileCheck %s -check-prefixes=NOLDEXP target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" -- GitLab From 1b945e35a6a59fda436585f8fca12c82a27fc6a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 12 Mar 2024 12:35:35 +0200 Subject: [PATCH 228/953] [CMake] Fix a typo in 23ffb2bdb96cf5a8eebce86b1ab21acf88979661 --- cmake/Modules/CMakePolicy.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/Modules/CMakePolicy.cmake b/cmake/Modules/CMakePolicy.cmake index b5bd1e6cdffe..1c18c1810dae 100644 --- a/cmake/Modules/CMakePolicy.cmake +++ b/cmake/Modules/CMakePolicy.cmake @@ -20,6 +20,6 @@ endif() # (https://github.com/mozilla/sccache?tab=readme-ov-file#usage) # avoiding “fatal error C1041: cannot open program database; if # multiple CL.EXE write to the same .PDB file, please use /FS" -+if(POLICY CMP0141) -+ cmake_policy(SET CMP0141 NEW) -+endif() +if(POLICY CMP0141) + cmake_policy(SET CMP0141 NEW) +endif() -- GitLab From 3358838446428976a41390fde98fe5b04b08a132 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Tue, 12 Mar 2024 10:41:59 +0000 Subject: [PATCH 229/953] [ADT] Add APIntOps::abds signed absolute difference and rename absdiff -> abdu (#84791) When I created APIntOps::absdiff, I totally missed that we already have ISD::ABDS/ABDU nodes, and we use this term in other places/targets as well. I've added the APIntOps::abds implementation and renamed APIntOps::absdiff to APIntOps::abdu. Given that APIntOps::absdiff is so young I don't think we need to create a deprecation wrapper, but I can if anyone thinks it important. I'll do a KnownBits rename patch after this. --- llvm/include/llvm/ADT/APInt.h | 7 +- .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 4 +- llvm/unittests/ADT/APIntTest.cpp | 66 ++++++++++++++----- llvm/unittests/Support/KnownBitsTest.cpp | 4 +- 4 files changed, 59 insertions(+), 22 deletions(-) diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h index 1fc3c7b2236a..bea3e28adf30 100644 --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -2188,8 +2188,13 @@ inline const APInt &umax(const APInt &A, const APInt &B) { return A.ugt(B) ? A : B; } +/// Determine the absolute difference of two APInts considered to be signed. +inline const APInt abds(const APInt &A, const APInt &B) { + return A.sge(B) ? (A - B) : (B - A); +} + /// Determine the absolute difference of two APInts considered to be unsigned. -inline const APInt absdiff(const APInt &A, const APInt &B) { +inline const APInt abdu(const APInt &A, const APInt &B) { return A.uge(B) ? (A - B) : (B - A); } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 7a0c1c328df1..c24303592769 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -6068,9 +6068,9 @@ static std::optional FoldValue(unsigned Opcode, const APInt &C1, return (C1Ext + C2Ext + 1).extractBits(C1.getBitWidth(), 1); } case ISD::ABDS: - return APIntOps::smax(C1, C2) - APIntOps::smin(C1, C2); + return APIntOps::abds(C1, C2); case ISD::ABDU: - return APIntOps::umax(C1, C2) - APIntOps::umin(C1, C2); + return APIntOps::abdu(C1, C2); } return std::nullopt; } diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp index 24324822356b..11237d2e1602 100644 --- a/llvm/unittests/ADT/APIntTest.cpp +++ b/llvm/unittests/ADT/APIntTest.cpp @@ -2532,38 +2532,72 @@ TEST(APIntTest, clearLowBits) { EXPECT_EQ(16u, i32hi16.popcount()); } -TEST(APIntTest, AbsDiff) { - using APIntOps::absdiff; +TEST(APIntTest, abds) { + using APIntOps::abds; APInt MaxU1(1, 1, false); APInt MinU1(1, 0, false); - EXPECT_EQ(1u, absdiff(MaxU1, MinU1).getZExtValue()); - EXPECT_EQ(1u, absdiff(MinU1, MaxU1).getZExtValue()); + EXPECT_EQ(1u, abds(MaxU1, MinU1).getZExtValue()); + EXPECT_EQ(1u, abds(MinU1, MaxU1).getZExtValue()); APInt MaxU4(4, 15, false); APInt MinU4(4, 0, false); - EXPECT_EQ(15u, absdiff(MaxU4, MinU4).getZExtValue()); - EXPECT_EQ(15u, absdiff(MinU4, MaxU4).getZExtValue()); + EXPECT_EQ(1, abds(MaxU4, MinU4).getSExtValue()); + EXPECT_EQ(1, abds(MinU4, MaxU4).getSExtValue()); APInt MaxS8(8, 127, true); APInt MinS8(8, -128, true); - EXPECT_EQ(1u, absdiff(MaxS8, MinS8).getZExtValue()); - EXPECT_EQ(1u, absdiff(MinS8, MaxS8).getZExtValue()); + EXPECT_EQ(-1, abds(MaxS8, MinS8).getSExtValue()); + EXPECT_EQ(-1, abds(MinS8, MaxS8).getSExtValue()); APInt MaxU16(16, 65535, false); APInt MinU16(16, 0, false); - EXPECT_EQ(65535u, absdiff(MaxU16, MinU16).getZExtValue()); - EXPECT_EQ(65535u, absdiff(MinU16, MaxU16).getZExtValue()); + EXPECT_EQ(1, abds(MaxU16, MinU16).getSExtValue()); + EXPECT_EQ(1, abds(MinU16, MaxU16).getSExtValue()); APInt MaxS16(16, 32767, true); APInt MinS16(16, -32768, true); APInt ZeroS16(16, 0, true); - EXPECT_EQ(1u, absdiff(MaxS16, MinS16).getZExtValue()); - EXPECT_EQ(1u, absdiff(MinS16, MaxS16).getZExtValue()); - EXPECT_EQ(32768u, absdiff(ZeroS16, MinS16)); - EXPECT_EQ(32768u, absdiff(MinS16, ZeroS16)); - EXPECT_EQ(32767u, absdiff(ZeroS16, MaxS16)); - EXPECT_EQ(32767u, absdiff(MaxS16, ZeroS16)); + EXPECT_EQ(-1, abds(MaxS16, MinS16).getSExtValue()); + EXPECT_EQ(-1, abds(MinS16, MaxS16).getSExtValue()); + EXPECT_EQ(32768u, abds(ZeroS16, MinS16)); + EXPECT_EQ(32768u, abds(MinS16, ZeroS16)); + EXPECT_EQ(32767u, abds(ZeroS16, MaxS16)); + EXPECT_EQ(32767u, abds(MaxS16, ZeroS16)); +} + +TEST(APIntTest, abdu) { + using APIntOps::abdu; + + APInt MaxU1(1, 1, false); + APInt MinU1(1, 0, false); + EXPECT_EQ(1u, abdu(MaxU1, MinU1).getZExtValue()); + EXPECT_EQ(1u, abdu(MinU1, MaxU1).getZExtValue()); + + APInt MaxU4(4, 15, false); + APInt MinU4(4, 0, false); + EXPECT_EQ(15u, abdu(MaxU4, MinU4).getZExtValue()); + EXPECT_EQ(15u, abdu(MinU4, MaxU4).getZExtValue()); + + APInt MaxS8(8, 127, true); + APInt MinS8(8, -128, true); + EXPECT_EQ(1u, abdu(MaxS8, MinS8).getZExtValue()); + EXPECT_EQ(1u, abdu(MinS8, MaxS8).getZExtValue()); + + APInt MaxU16(16, 65535, false); + APInt MinU16(16, 0, false); + EXPECT_EQ(65535u, abdu(MaxU16, MinU16).getZExtValue()); + EXPECT_EQ(65535u, abdu(MinU16, MaxU16).getZExtValue()); + + APInt MaxS16(16, 32767, true); + APInt MinS16(16, -32768, true); + APInt ZeroS16(16, 0, true); + EXPECT_EQ(1u, abdu(MaxS16, MinS16).getZExtValue()); + EXPECT_EQ(1u, abdu(MinS16, MaxS16).getZExtValue()); + EXPECT_EQ(32768u, abdu(ZeroS16, MinS16)); + EXPECT_EQ(32768u, abdu(MinS16, ZeroS16)); + EXPECT_EQ(32767u, abdu(ZeroS16, MaxS16)); + EXPECT_EQ(32767u, abdu(MaxS16, ZeroS16)); } TEST(APIntTest, GCD) { diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index 7c183e9626f9..2ac25f0b2801 100644 --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -361,9 +361,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::absdiff(Known1, Known2); }, - [](const APInt &N1, const APInt &N2) { - return APIntOps::absdiff(N1, N2); - }, + [](const APInt &N1, const APInt &N2) { return APIntOps::abdu(N1, N2); }, checkCorrectnessOnlyBinary); testBinaryOpExhaustive( [](const KnownBits &Known1, const KnownBits &Known2) { -- GitLab From a7ef83f005beeb3b1c7f34d44167b5abc5b6c4e5 Mon Sep 17 00:00:00 2001 From: Dani Date: Tue, 12 Mar 2024 12:36:05 +0100 Subject: [PATCH 230/953] [AArch64][SME] Add BTI and No Exec Stack markers to sme-abi.S (#84895) Adding BTI landing pads compiler-rt is built with -mbranch-protectoin. Tabulators are changed to 2 spaces for consistency. --- compiler-rt/lib/builtins/aarch64/sme-abi.S | 34 ++++++++++++++-------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/compiler-rt/lib/builtins/aarch64/sme-abi.S b/compiler-rt/lib/builtins/aarch64/sme-abi.S index d470ecaf7aaa..4c0ff66931db 100644 --- a/compiler-rt/lib/builtins/aarch64/sme-abi.S +++ b/compiler-rt/lib/builtins/aarch64/sme-abi.S @@ -26,9 +26,10 @@ // abort(). Note that there is no need to preserve any state before the call, // because the function does not return. DEFINE_COMPILERRT_PRIVATE_FUNCTION(do_abort) -.cfi_startproc - .variant_pcs SYMBOL_NAME(do_abort) - stp x29, x30, [sp, #-32]! + .cfi_startproc + .variant_pcs SYMBOL_NAME(do_abort) + BTI_C + stp x29, x30, [sp, #-32]! cntd x0 // Store VG to a stack location that we describe with .cfi_offset str x0, [sp, #16] @@ -36,22 +37,23 @@ DEFINE_COMPILERRT_PRIVATE_FUNCTION(do_abort) .cfi_offset w30, -24 .cfi_offset w29, -32 .cfi_offset 46, -16 - bl __arm_sme_state - tbz x0, #0, 2f + bl __arm_sme_state + tbz x0, #0, 2f 1: - smstop sm + smstop sm 2: // We can't make this into a tail-call because the unwinder would // need to restore the value of VG. - bl SYMBOL_NAME(abort) -.cfi_endproc + bl SYMBOL_NAME(abort) + .cfi_endproc END_COMPILERRT_FUNCTION(do_abort) // __arm_sme_state fills the result registers based on a local // that is set as part of the compiler-rt startup code. // __aarch64_has_sme_and_tpidr2_el0 DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_sme_state) - .variant_pcs __arm_sme_state + .variant_pcs __arm_sme_state + BTI_C mov x0, xzr mov x1, xzr @@ -68,7 +70,8 @@ DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_sme_state) END_COMPILERRT_OUTLINE_FUNCTION(__arm_sme_state) DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_tpidr2_restore) - .variant_pcs __arm_tpidr2_restore + .variant_pcs __arm_tpidr2_restore + BTI_C // If TPIDR2_EL0 is nonnull, the subroutine aborts in some platform-specific // manner. mrs x14, TPIDR2_EL0 @@ -103,7 +106,8 @@ DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_tpidr2_restore) END_COMPILERRT_OUTLINE_FUNCTION(__arm_tpidr2_restore) DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_tpidr2_save) - .variant_pcs __arm_tpidr2_restore + .variant_pcs __arm_tpidr2_restore + BTI_C // If the current thread does not have access to TPIDR2_EL0, the subroutine // does nothing. adrp x14, TPIDR2_SYMBOL @@ -143,7 +147,8 @@ DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_tpidr2_save) END_COMPILERRT_OUTLINE_FUNCTION(__arm_tpidr2_save) DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_za_disable) - .variant_pcs __arm_tpidr2_restore + .variant_pcs __arm_tpidr2_restore + BTI_C // If the current thread does not have access to SME, the subroutine does // nothing. adrp x14, TPIDR2_SYMBOL @@ -174,3 +179,8 @@ DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_za_disable) 0: ret END_COMPILERRT_OUTLINE_FUNCTION(__arm_za_disable) + +NO_EXEC_STACK_DIRECTIVE + +// GNU property note for BTI and PAC +GNU_PROPERTY_BTI_PAC -- GitLab From eb319708dc5371bc560c301742abcf94cc5b3de5 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 12 Mar 2024 07:40:27 -0400 Subject: [PATCH 231/953] Add bit-precise overloads for builtin operators (#84755) We previously were not adding them to the candidate set and so use of a bit-precise integer as a class member could lead to ambiguous overload sets. Fixes https://github.com/llvm/llvm-project/issues/82998 --- clang/docs/ReleaseNotes.rst | 3 ++ clang/lib/Sema/SemaOverload.cpp | 29 ++++++++++++++++-- clang/test/SemaCXX/overload-bitint.cpp | 42 ++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 clang/test/SemaCXX/overload-bitint.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 88e552d5c461..4a08b78d78b6 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -265,6 +265,9 @@ Bug Fixes in This Version operator. Fixes (#GH83267). +- Clang now correctly generates overloads for bit-precise integer types for + builtin operators in C++. Fixes #GH82998. + Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index b0c693f078ef..f6bd85bdc646 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -8516,6 +8516,9 @@ class BuiltinCandidateTypeSet { /// candidates. TypeSet MatrixTypes; + /// The set of _BitInt types that will be used in the built-in candidates. + TypeSet BitIntTypes; + /// A flag indicating non-record types are viable candidates bool HasNonRecordTypes; @@ -8564,6 +8567,7 @@ public: } llvm::iterator_range vector_types() { return VectorTypes; } llvm::iterator_range matrix_types() { return MatrixTypes; } + llvm::iterator_range bitint_types() { return BitIntTypes; } bool containsMatrixType(QualType Ty) const { return MatrixTypes.count(Ty); } bool hasNonRecordTypes() { return HasNonRecordTypes; } @@ -8735,6 +8739,9 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, } else if (Ty->isEnumeralType()) { HasArithmeticOrEnumeralTypes = true; EnumerationTypes.insert(Ty); + } else if (Ty->isBitIntType()) { + HasArithmeticOrEnumeralTypes = true; + BitIntTypes.insert(Ty); } else if (Ty->isVectorType()) { // We treat vector types as arithmetic types in many contexts as an // extension. @@ -8913,7 +8920,7 @@ class BuiltinOperatorOverloadBuilder { SmallVectorImpl &CandidateTypes; OverloadCandidateSet &CandidateSet; - static constexpr int ArithmeticTypesCap = 24; + static constexpr int ArithmeticTypesCap = 26; SmallVector ArithmeticTypes; // Define some indices used to iterate over the arithmetic types in @@ -8955,6 +8962,20 @@ class BuiltinOperatorOverloadBuilder { (S.Context.getAuxTargetInfo() && S.Context.getAuxTargetInfo()->hasInt128Type())) ArithmeticTypes.push_back(S.Context.UnsignedInt128Ty); + + /// We add candidates for the unique, unqualified _BitInt types present in + /// the candidate type set. The candidate set already handled ensuring the + /// type is unqualified and canonical, but because we're adding from N + /// different sets, we need to do some extra work to unique things. Insert + /// the candidates into a unique set, then move from that set into the list + /// of arithmetic types. + llvm::SmallSetVector BitIntCandidates; + llvm::for_each(CandidateTypes, [&BitIntCandidates]( + BuiltinCandidateTypeSet &Candidate) { + for (QualType BitTy : Candidate.bitint_types()) + BitIntCandidates.insert(CanQualType::CreateUnsafe(BitTy)); + }); + llvm::move(BitIntCandidates, std::back_inserter(ArithmeticTypes)); LastPromotedIntegralType = ArithmeticTypes.size(); LastPromotedArithmeticType = ArithmeticTypes.size(); // End of promoted types. @@ -8975,7 +8996,11 @@ class BuiltinOperatorOverloadBuilder { // End of integral types. // FIXME: What about complex? What about half? - assert(ArithmeticTypes.size() <= ArithmeticTypesCap && + // We don't know for sure how many bit-precise candidates were involved, so + // we subtract those from the total when testing whether we're under the + // cap or not. + assert(ArithmeticTypes.size() - BitIntCandidates.size() <= + ArithmeticTypesCap && "Enough inline storage for all arithmetic types."); } diff --git a/clang/test/SemaCXX/overload-bitint.cpp b/clang/test/SemaCXX/overload-bitint.cpp new file mode 100644 index 000000000000..b834a3b01fed --- /dev/null +++ b/clang/test/SemaCXX/overload-bitint.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -std=c++20 %s -verify +// expected-no-diagnostics + +#include "Inputs/std-compare.h" + +struct S { + _BitInt(12) a; + + constexpr operator _BitInt(12)() const { return a; } +}; + +// None of these used to compile because we weren't adding _BitInt types to the +// overload set for builtin operators. See GH82998. +static_assert(S{10} < 11); +static_assert(S{10} <= 11); +static_assert(S{12} > 11); +static_assert(S{12} >= 11); +static_assert(S{10} == 10); +static_assert((S{10} <=> 10) == 0); +static_assert(S{10} != 11); +static_assert(S{10} + 0 == 10); +static_assert(S{10} - 0 == 10); +static_assert(S{10} * 1 == 10); +static_assert(S{10} / 1 == 10); +static_assert(S{10} % 1 == 0); +static_assert(S{10} << 0 == 10); +static_assert(S{10} >> 0 == 10); +static_assert((S{10} | 0) == 10); +static_assert((S{10} & 10) == 10); +static_assert((S{10} ^ 0) == 10); +static_assert(-S{10} == -10); +static_assert(+S{10} == +10); +static_assert(~S{10} == ~10); + +struct A { + _BitInt(12) a; + + bool operator==(const A&) const = default; + bool operator!=(const A&) const = default; + std::strong_ordering operator<=>(const A&) const = default; +}; + -- GitLab From 4e3310a81391fbc283d263715a68d8732e73d01d Mon Sep 17 00:00:00 2001 From: mikaoP Date: Tue, 12 Mar 2024 12:50:35 +0100 Subject: [PATCH 232/953] [clang] Fix OMPT ident flag in combined distribute parallel for pragma (#80987) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Authored-by: Raúl Peñacoba Veigas --- clang/lib/CodeGen/CGOpenMPRuntime.cpp | 3 + clang/lib/CodeGen/CGStmtOpenMP.cpp | 15 +-- clang/lib/CodeGen/CodeGenFunction.h | 2 + .../test/OpenMP/amdgcn_target_device_vla.cpp | 2 +- .../amdgpu_target_with_aligned_attribute.c | 2 +- clang/test/OpenMP/bug60602.cpp | 2 +- .../distribute_parallel_for_codegen.cpp | 64 ++++++------- ...bute_parallel_for_firstprivate_codegen.cpp | 12 +-- .../distribute_parallel_for_if_codegen.cpp | 16 ++-- ...ibute_parallel_for_lastprivate_codegen.cpp | 12 +-- ...ibute_parallel_for_num_threads_codegen.cpp | 48 +++++----- ...istribute_parallel_for_private_codegen.cpp | 12 +-- ...tribute_parallel_for_proc_bind_codegen.cpp | 6 +- ...te_parallel_for_reduction_task_codegen.cpp | 34 +++---- .../distribute_parallel_for_simd_codegen.cpp | 60 ++++++------ ...parallel_for_simd_firstprivate_codegen.cpp | 12 +-- ...istribute_parallel_for_simd_if_codegen.cpp | 68 ++++++------- ..._parallel_for_simd_lastprivate_codegen.cpp | 12 +-- ..._parallel_for_simd_num_threads_codegen.cpp | 48 +++++----- ...bute_parallel_for_simd_private_codegen.cpp | 12 +-- ...te_parallel_for_simd_proc_bind_codegen.cpp | 6 +- .../metadirective_device_arch_codegen.cpp | 2 +- clang/test/OpenMP/nvptx_SPMD_codegen.cpp | 96 +++++++++---------- ...stribute_parallel_generic_mode_codegen.cpp | 4 +- ..._teams_distribute_parallel_for_codegen.cpp | 36 +++---- ...bute_parallel_for_generic_mode_codegen.cpp | 4 +- ...s_distribute_parallel_for_simd_codegen.cpp | 16 ++-- ...vptx_target_teams_generic_loop_codegen.cpp | 36 +++---- ...eams_generic_loop_generic_mode_codegen.cpp | 8 +- clang/test/OpenMP/reduction_implicit_map.cpp | 4 +- .../target_ompx_dyn_cgroup_mem_codegen.cpp | 8 +- ..._teams_distribute_parallel_for_codegen.cpp | 30 +++--- ...stribute_parallel_for_collapse_codegen.cpp | 12 +-- ...ute_parallel_for_dist_schedule_codegen.cpp | 36 +++---- ...bute_parallel_for_firstprivate_codegen.cpp | 20 ++-- ...ams_distribute_parallel_for_if_codegen.cpp | 16 ++-- ...ibute_parallel_for_lastprivate_codegen.cpp | 12 +-- ..._distribute_parallel_for_order_codegen.cpp | 2 +- ...istribute_parallel_for_private_codegen.cpp | 20 ++-- ...tribute_parallel_for_proc_bind_codegen.cpp | 6 +- ...tribute_parallel_for_reduction_codegen.cpp | 10 +- ...te_parallel_for_reduction_task_codegen.cpp | 38 ++++---- ...stribute_parallel_for_schedule_codegen.cpp | 72 +++++++------- ...s_distribute_parallel_for_simd_codegen.cpp | 24 ++--- ...ute_parallel_for_simd_collapse_codegen.cpp | 12 +-- ...arallel_for_simd_dist_schedule_codegen.cpp | 36 +++---- ...parallel_for_simd_firstprivate_codegen.cpp | 20 ++-- ...istribute_parallel_for_simd_if_codegen.cpp | 68 ++++++------- ..._parallel_for_simd_lastprivate_codegen.cpp | 12 +-- ...bute_parallel_for_simd_private_codegen.cpp | 20 ++-- ...te_parallel_for_simd_proc_bind_codegen.cpp | 6 +- ...te_parallel_for_simd_reduction_codegen.cpp | 10 +- ...ute_parallel_for_simd_schedule_codegen.cpp | 72 +++++++------- .../target_teams_generic_loop_codegen-1.cpp | 30 +++--- .../target_teams_generic_loop_codegen.cpp | 12 +-- ...et_teams_generic_loop_collapse_codegen.cpp | 20 ++-- .../target_teams_generic_loop_if_codegen.cpp | 18 ++-- ...arget_teams_generic_loop_order_codegen.cpp | 4 +- ...get_teams_generic_loop_private_codegen.cpp | 32 +++---- ...t_teams_generic_loop_reduction_codegen.cpp | 10 +- ...s_generic_loop_uses_allocators_codegen.cpp | 4 +- .../teams_distribute_parallel_for_codegen.cpp | 28 +++--- ...stribute_parallel_for_collapse_codegen.cpp | 12 +-- ...distribute_parallel_for_copyin_codegen.cpp | 10 +- ...ute_parallel_for_dist_schedule_codegen.cpp | 36 +++---- ...bute_parallel_for_firstprivate_codegen.cpp | 10 +- ...ams_distribute_parallel_for_if_codegen.cpp | 16 ++-- ...ibute_parallel_for_lastprivate_codegen.cpp | 12 +-- ...ibute_parallel_for_num_threads_codegen.cpp | 24 ++--- ...istribute_parallel_for_private_codegen.cpp | 10 +- ...tribute_parallel_for_proc_bind_codegen.cpp | 6 +- ...tribute_parallel_for_reduction_codegen.cpp | 10 +- ...te_parallel_for_reduction_task_codegen.cpp | 38 ++++---- ...stribute_parallel_for_schedule_codegen.cpp | 72 +++++++------- ...s_distribute_parallel_for_simd_codegen.cpp | 24 ++--- ...ute_parallel_for_simd_collapse_codegen.cpp | 12 +-- ...arallel_for_simd_dist_schedule_codegen.cpp | 36 +++---- ...parallel_for_simd_firstprivate_codegen.cpp | 10 +- ...istribute_parallel_for_simd_if_codegen.cpp | 68 ++++++------- ..._parallel_for_simd_lastprivate_codegen.cpp | 12 +-- ..._parallel_for_simd_num_threads_codegen.cpp | 24 ++--- ...bute_parallel_for_simd_private_codegen.cpp | 10 +- ...te_parallel_for_simd_proc_bind_codegen.cpp | 6 +- ...te_parallel_for_simd_reduction_codegen.cpp | 10 +- ...ute_parallel_for_simd_schedule_codegen.cpp | 72 +++++++------- .../OpenMP/teams_generic_loop_codegen-1.cpp | 40 ++++---- .../OpenMP/teams_generic_loop_codegen.cpp | 24 ++--- .../teams_generic_loop_collapse_codegen.cpp | 20 ++-- .../teams_generic_loop_private_codegen.cpp | 16 ++-- .../teams_generic_loop_reduction_codegen.cpp | 16 ++-- 90 files changed, 1019 insertions(+), 1011 deletions(-) diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index a7b72df6d9f8..e8a68dbcc687 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -2647,6 +2647,9 @@ void CGOpenMPRuntime::emitDistributeStaticInit( void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind) { + assert(DKind == OMPD_distribute || DKind == OMPD_for || + DKind == OMPD_sections && + "Expected distribute, for, or sections directive kind"); if (!CGF.HaveInsertPoint()) return; // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 3fbd2e03eb61..452ce6983f6a 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -2910,10 +2910,10 @@ void CodeGenFunction::EmitOMPOuterLoop( EmitBlock(LoopExit.getBlock()); // Tell the runtime we are done. - auto &&CodeGen = [DynamicOrOrdered, &S](CodeGenFunction &CGF) { + auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) { if (!DynamicOrOrdered) CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(), - S.getDirectiveKind()); + LoopArgs.DKind); }; OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen); } @@ -3019,6 +3019,7 @@ void CodeGenFunction::EmitOMPForOuterLoop( OuterLoopArgs.Cond = S.getCond(); OuterLoopArgs.NextLB = S.getNextLowerBound(); OuterLoopArgs.NextUB = S.getNextUpperBound(); + OuterLoopArgs.DKind = LoopArgs.DKind; EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs, emitOMPLoopBodyWithStopPoint, CodeGenOrdered); } @@ -3080,6 +3081,7 @@ void CodeGenFunction::EmitOMPDistributeOuterLoop( OuterLoopArgs.NextUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()) ? S.getCombinedNextUpperBound() : S.getNextUpperBound(); + OuterLoopArgs.DKind = OMPD_distribute; EmitOMPOuterLoop(/* DynamicOrOrdered = */ false, /* IsMonotonic = */ false, S, LoopScope, OuterLoopArgs, CodeGenLoopContent, @@ -3452,15 +3454,16 @@ bool CodeGenFunction::EmitOMPWorksharingLoop( // Tell the runtime we are done. auto &&CodeGen = [&S](CodeGenFunction &CGF) { CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(), - S.getDirectiveKind()); + OMPD_for); }; OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen); } else { // Emit the outer loop, which requests its work chunk [LB..UB] from // runtime and runs the inner loop to process it. - const OMPLoopArguments LoopArguments( + OMPLoopArguments LoopArguments( LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this), IL.getAddress(*this), Chunk, EUB); + LoopArguments.DKind = OMPD_for; EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered, LoopArguments, CGDispatchBounds); } @@ -4082,7 +4085,7 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) { // Tell the runtime we are done. auto &&CodeGen = [&S](CodeGenFunction &CGF) { CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(), - S.getDirectiveKind()); + OMPD_sections); }; CGF.OMPCancelStack.emitExit(CGF, S.getDirectiveKind(), CodeGen); CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel); @@ -5782,7 +5785,7 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S, }); EmitBlock(LoopExit.getBlock()); // Tell the runtime we are done. - RT.emitForStaticFinish(*this, S.getEndLoc(), S.getDirectiveKind()); + RT.emitForStaticFinish(*this, S.getEndLoc(), OMPD_distribute); } else { // Emit the outer loop, which requests its work chunk [LB..UB] from // runtime and runs the inner loop to process it. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 6c825a302913..e8f8aa601ed0 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -3831,6 +3831,8 @@ private: Expr *NextLB = nullptr; /// Update of UB after a whole chunk has been executed Expr *NextUB = nullptr; + /// Distinguish between the for distribute and sections + OpenMPDirectiveKind DKind = llvm::omp::OMPD_unknown; OMPLoopArguments() = default; OMPLoopArguments(Address LB, Address UB, Address ST, Address IL, llvm::Value *Chunk = nullptr, Expr *EUB = nullptr, diff --git a/clang/test/OpenMP/amdgcn_target_device_vla.cpp b/clang/test/OpenMP/amdgcn_target_device_vla.cpp index de150a0fcb4a..58fef517a9e7 100644 --- a/clang/test/OpenMP/amdgcn_target_device_vla.cpp +++ b/clang/test/OpenMP/amdgcn_target_device_vla.cpp @@ -539,7 +539,7 @@ int main() { // CHECK: omp.loop.exit: // CHECK-NEXT: [[TMP34:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR_ASCAST]], align 8 // CHECK-NEXT: [[TMP35:%.*]] = load i32, ptr [[TMP34]], align 4 -// CHECK-NEXT: call void @__kmpc_distribute_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB2]] to ptr), i32 [[TMP35]]) +// CHECK-NEXT: call void @__kmpc_for_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB3]] to ptr), i32 [[TMP35]]) // CHECK-NEXT: br label [[OMP_PRECOND_END]] // CHECK: omp.precond.end: // CHECK-NEXT: ret void diff --git a/clang/test/OpenMP/amdgpu_target_with_aligned_attribute.c b/clang/test/OpenMP/amdgpu_target_with_aligned_attribute.c index dd33e8405c34..cc0cc0def48b 100644 --- a/clang/test/OpenMP/amdgpu_target_with_aligned_attribute.c +++ b/clang/test/OpenMP/amdgpu_target_with_aligned_attribute.c @@ -301,7 +301,7 @@ void write_to_aligned_array(int *a, int N) { // CHECK-AMD: omp.loop.exit: // CHECK-AMD-NEXT: [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR_ASCAST]], align 8 // CHECK-AMD-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4 -// CHECK-AMD-NEXT: call void @__kmpc_distribute_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB2]] to ptr), i32 [[TMP18]]) +// CHECK-AMD-NEXT: call void @__kmpc_for_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB3]] to ptr), i32 [[TMP18]]) // CHECK-AMD-NEXT: br label [[OMP_PRECOND_END]] // CHECK-AMD: omp.precond.end: // CHECK-AMD-NEXT: ret void diff --git a/clang/test/OpenMP/bug60602.cpp b/clang/test/OpenMP/bug60602.cpp index 3ecc70cab778..48dc341a0822 100644 --- a/clang/test/OpenMP/bug60602.cpp +++ b/clang/test/OpenMP/bug60602.cpp @@ -564,7 +564,7 @@ int kernel_within_loop(int *a, int *b, int N, int num_iters) { // CHECK: omp.loop.exit: // CHECK-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4 -// CHECK-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP23]]) +// CHECK-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP23]]) // CHECK-NEXT: br label [[OMP_PRECOND_END]] // CHECK: omp.precond.end: // CHECK-NEXT: ret void diff --git a/clang/test/OpenMP/distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_codegen.cpp index 95adefa8020f..9cb0a1553065 100644 --- a/clang/test/OpenMP/distribute_parallel_for_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_codegen.cpp @@ -1027,7 +1027,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -1266,7 +1266,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -1535,7 +1535,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -1774,7 +1774,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -2047,7 +2047,7 @@ int main() { // CHECK1: omp.dispatch.end: // CHECK1-NEXT: [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP41]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP41]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -2791,7 +2791,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: omp.precond.end: // CHECK3-NEXT: ret void @@ -3023,7 +3023,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: omp.precond.end: // CHECK3-NEXT: ret void @@ -3285,7 +3285,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: omp.precond.end: // CHECK3-NEXT: ret void @@ -3517,7 +3517,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: omp.precond.end: // CHECK3-NEXT: ret void @@ -3781,7 +3781,7 @@ int main() { // CHECK3: omp.dispatch.end: // CHECK3-NEXT: [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP41]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP41]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: omp.precond.end: // CHECK3-NEXT: ret void @@ -5108,7 +5108,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -5337,7 +5337,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -5596,7 +5596,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -5825,7 +5825,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -6088,7 +6088,7 @@ int main() { // CHECK9: omp.dispatch.end: // CHECK9-NEXT: [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -7414,12 +7414,12 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: cancel.exit: // CHECK9-NEXT: [[TMP35:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP36:%.*]] = load i32, ptr [[TMP35]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP36]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP36]]) // CHECK9-NEXT: br label [[CANCEL_CONT:%.*]] // CHECK9: omp.precond.end: // CHECK9-NEXT: br label [[CANCEL_CONT]] @@ -7650,7 +7650,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -7909,7 +7909,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -8138,7 +8138,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -8401,7 +8401,7 @@ int main() { // CHECK9: omp.dispatch.end: // CHECK9-NEXT: [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -9715,7 +9715,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -9937,7 +9937,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -10189,7 +10189,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -10411,7 +10411,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -10665,7 +10665,7 @@ int main() { // CHECK11: omp.dispatch.end: // CHECK11-NEXT: [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -11970,12 +11970,12 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: cancel.exit: // CHECK11-NEXT: [[TMP35:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP36:%.*]] = load i32, ptr [[TMP35]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP36]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP36]]) // CHECK11-NEXT: br label [[CANCEL_CONT:%.*]] // CHECK11: omp.precond.end: // CHECK11-NEXT: br label [[CANCEL_CONT]] @@ -12199,7 +12199,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -12451,7 +12451,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -12673,7 +12673,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -12927,7 +12927,7 @@ int main() { // CHECK11: omp.dispatch.end: // CHECK11-NEXT: [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void diff --git a/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp index 46c115e40e43..6084a9a6cf93 100644 --- a/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp @@ -500,7 +500,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -748,7 +748,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK3-NEXT: ret void // // @@ -1167,7 +1167,7 @@ int main() { // CHECK8: omp.loop.exit: // CHECK8-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK8-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK8-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK8-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK8-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]]) #[[ATTR4]] // CHECK8-NEXT: [[ARRAY_BEGIN12:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR4]], i32 0, i32 0 // CHECK8-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN12]], i64 2 @@ -1612,7 +1612,7 @@ int main() { // CHECK8: omp.loop.exit: // CHECK8-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK8-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK8-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK8-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK8-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]]) #[[ATTR4]] // CHECK8-NEXT: [[ARRAY_BEGIN12:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i32 0, i32 0 // CHECK8-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN12]], i64 2 @@ -2080,7 +2080,7 @@ int main() { // CHECK10: omp.loop.exit: // CHECK10-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK10-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK10-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR4]] // CHECK10-NEXT: [[ARRAY_BEGIN10:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR3]], i32 0, i32 0 // CHECK10-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN10]], i32 2 @@ -2519,7 +2519,7 @@ int main() { // CHECK10: omp.loop.exit: // CHECK10-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK10-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK10-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR4]] // CHECK10-NEXT: [[ARRAY_BEGIN10:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i32 0, i32 0 // CHECK10-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN10]], i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_if_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_if_codegen.cpp index 846e7beb5d92..d3b6654e57e2 100644 --- a/clang/test/OpenMP/distribute_parallel_for_if_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_if_codegen.cpp @@ -329,7 +329,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -472,7 +472,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -740,7 +740,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -883,7 +883,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -1040,7 +1040,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -1306,7 +1306,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -1449,7 +1449,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -1606,6 +1606,6 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // diff --git a/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp index aa981f606cc8..1f069c4070ae 100644 --- a/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp @@ -443,7 +443,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]]) // CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK1-NEXT: br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -708,7 +708,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]]) // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK3-NEXT: br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -1153,7 +1153,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK9-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK9-NEXT: br i1 [[TMP24]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -1636,7 +1636,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK9-NEXT: br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -2139,7 +2139,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -2616,7 +2616,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK11-NEXT: br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] diff --git a/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp index 5d9244268d55..b6ae783b74d0 100644 --- a/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp @@ -386,7 +386,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // CHECK1: terminate.lpad: // CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -547,7 +547,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // CHECK1: terminate.lpad: // CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -879,7 +879,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // CHECK1: terminate.lpad: // CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -1026,7 +1026,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // CHECK1: terminate.lpad: // CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -1173,7 +1173,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // CHECK1: terminate.lpad: // CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -1335,7 +1335,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // CHECK1: terminate.lpad: // CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -1638,7 +1638,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: ret void // CHECK5: terminate.lpad: // CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -1799,7 +1799,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: ret void // CHECK5: terminate.lpad: // CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -2122,7 +2122,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: ret void // CHECK5: terminate.lpad: // CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -2269,7 +2269,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: ret void // CHECK5: terminate.lpad: // CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -2416,7 +2416,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: ret void // CHECK5: terminate.lpad: // CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -2578,7 +2578,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: ret void // CHECK5: terminate.lpad: // CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -2890,7 +2890,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: ret void // CHECK9: terminate.lpad: // CHECK9-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -3051,7 +3051,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: ret void // CHECK9: terminate.lpad: // CHECK9-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -3383,7 +3383,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: ret void // CHECK9: terminate.lpad: // CHECK9-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -3530,7 +3530,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: ret void // CHECK9: terminate.lpad: // CHECK9-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -3677,7 +3677,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: ret void // CHECK9: terminate.lpad: // CHECK9-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -3839,7 +3839,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: ret void // CHECK9: terminate.lpad: // CHECK9-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -4142,7 +4142,7 @@ int main() { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK13-NEXT: ret void // CHECK13: terminate.lpad: // CHECK13-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -4303,7 +4303,7 @@ int main() { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK13-NEXT: ret void // CHECK13: terminate.lpad: // CHECK13-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -4626,7 +4626,7 @@ int main() { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK13-NEXT: ret void // CHECK13: terminate.lpad: // CHECK13-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -4773,7 +4773,7 @@ int main() { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK13-NEXT: ret void // CHECK13: terminate.lpad: // CHECK13-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -4920,7 +4920,7 @@ int main() { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK13-NEXT: ret void // CHECK13: terminate.lpad: // CHECK13-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -5082,7 +5082,7 @@ int main() { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK13-NEXT: ret void // CHECK13: terminate.lpad: // CHECK13-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } diff --git a/clang/test/OpenMP/distribute_parallel_for_private_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_private_codegen.cpp index 249609c7d831..e2b0d64093eb 100644 --- a/clang/test/OpenMP/distribute_parallel_for_private_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_private_codegen.cpp @@ -313,7 +313,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -491,7 +491,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: ret void // // @@ -795,7 +795,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK9-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR4]] // CHECK9-NEXT: [[ARRAY_BEGIN8:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN8]], i64 2 @@ -1147,7 +1147,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK9-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR4]] // CHECK9-NEXT: [[ARRAY_BEGIN8:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN8]], i64 2 @@ -1500,7 +1500,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK11-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR4]] // CHECK11-NEXT: [[ARRAY_BEGIN6:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 // CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN6]], i32 2 @@ -1846,7 +1846,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK11-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR4]] // CHECK11-NEXT: [[ARRAY_BEGIN6:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 // CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN6]], i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp index 8784611d8399..040f90b9ef78 100644 --- a/clang/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp @@ -266,7 +266,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -404,7 +404,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -583,6 +583,6 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // diff --git a/clang/test/OpenMP/distribute_parallel_for_reduction_task_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_reduction_task_codegen.cpp index 7caca83c25d6..a019f09c14cb 100644 --- a/clang/test/OpenMP/distribute_parallel_for_reduction_task_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_reduction_task_codegen.cpp @@ -328,7 +328,7 @@ int main(int argc, char **argv) { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP78:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP79:%.*]] = load i32, ptr [[TMP78]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP79]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP79]]) // CHECK1-NEXT: [[TMP80:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP81:%.*]] = load i32, ptr [[TMP80]], align 4 // CHECK1-NEXT: call void @__kmpc_task_reduction_modifier_fini(ptr @[[GLOB2]], i32 [[TMP81]], i32 1) @@ -343,8 +343,8 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP87:%.*]] = load i32, ptr [[TMP86]], align 4 // CHECK1-NEXT: [[TMP88:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB4:[0-9]+]], i32 [[TMP87]], i32 2, i64 24, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l14.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) // CHECK1-NEXT: switch i32 [[TMP88]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [ -// CHECK1-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] -// CHECK1-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] +// CHECK1-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] +// CHECK1-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] // CHECK1-NEXT: ] // CHECK1: .omp.reduction.case1: // CHECK1-NEXT: [[TMP89:%.*]] = load i32, ptr [[TMP0]], align 4 @@ -536,21 +536,21 @@ int main(int argc, char **argv) { // CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]]) // CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META8:![0-9]+]]) // CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META10:![0-9]+]]) -// CHECK1-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !12 +// CHECK1-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META12:![0-9]+]] +// CHECK1-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META12]] // CHECK1-NEXT: call void [[TMP10]](ptr [[TMP11]], ptr [[DOTFIRSTPRIV_PTR_ADDR_I]]) #[[ATTR2]] -// CHECK1-NEXT: [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias !12 +// CHECK1-NEXT: [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias [[META12]] // CHECK1-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[TMP9]], i32 0, i32 1 // CHECK1-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8 // CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[TMP12]], align 8 -// CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !12 +// CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META12]] // CHECK1-NEXT: [[TMP17:%.*]] = call ptr @__kmpc_task_reduction_get_th_data(i32 [[TMP16]], ptr [[TMP15]], ptr [[TMP14]]) // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 // CHECK1-NEXT: [[TMP19:%.*]] = load ptr, ptr [[TMP18]], align 8 @@ -570,7 +570,7 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP30:%.*]] = sub i64 [[TMP28]], [[TMP29]] // CHECK1-NEXT: [[TMP31:%.*]] = add nuw i64 [[TMP30]], 1 // CHECK1-NEXT: [[TMP32:%.*]] = mul nuw i64 [[TMP31]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) -// CHECK1-NEXT: store i64 [[TMP31]], ptr @{{reduction_size[.].+[.]}}, align 8, !noalias !12 +// CHECK1-NEXT: store i64 [[TMP31]], ptr @{{reduction_size[.].+[.]}}, align 8, !noalias [[META12]] // CHECK1-NEXT: [[TMP33:%.*]] = load ptr, ptr [[TMP12]], align 8 // CHECK1-NEXT: [[TMP34:%.*]] = call ptr @__kmpc_task_reduction_get_th_data(i32 [[TMP16]], ptr [[TMP33]], ptr [[TMP20]]) // CHECK1-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 @@ -580,8 +580,8 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP39:%.*]] = ptrtoint ptr [[TMP20]] to i64 // CHECK1-NEXT: [[TMP40:%.*]] = sub i64 [[TMP38]], [[TMP39]] // CHECK1-NEXT: [[TMP41:%.*]] = getelementptr i8, ptr [[TMP34]], i64 [[TMP40]] -// CHECK1-NEXT: store ptr [[TMP4_I]], ptr [[TMP_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP41]], ptr [[TMP4_I]], align 8, !noalias !12 +// CHECK1-NEXT: store ptr [[TMP4_I]], ptr [[TMP_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr [[TMP41]], ptr [[TMP4_I]], align 8, !noalias [[META12]] // CHECK1-NEXT: ret i32 0 // // diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_codegen.cpp index e0618cb99245..77336877e2be 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_codegen.cpp @@ -1039,7 +1039,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK1-NEXT: [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0 // CHECK1-NEXT: br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1302,7 +1302,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK1-NEXT: [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0 // CHECK1-NEXT: br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1595,7 +1595,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK1-NEXT: [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0 // CHECK1-NEXT: br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1858,7 +1858,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK1-NEXT: [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0 // CHECK1-NEXT: br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2155,7 +2155,7 @@ int main() { // CHECK1: omp.dispatch.end: // CHECK1-NEXT: [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP41]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP41]]) // CHECK1-NEXT: [[TMP42:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP43:%.*]] = icmp ne i32 [[TMP42]], 0 // CHECK1-NEXT: br i1 [[TMP43]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2971,7 +2971,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK3-NEXT: [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0 // CHECK3-NEXT: br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3227,7 +3227,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK3-NEXT: [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0 // CHECK3-NEXT: br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3513,7 +3513,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK3-NEXT: [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0 // CHECK3-NEXT: br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3769,7 +3769,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK3-NEXT: [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0 // CHECK3-NEXT: br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4057,7 +4057,7 @@ int main() { // CHECK3: omp.dispatch.end: // CHECK3-NEXT: [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP41]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP41]]) // CHECK3-NEXT: [[TMP42:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP43:%.*]] = icmp ne i32 [[TMP42]], 0 // CHECK3-NEXT: br i1 [[TMP43]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5510,7 +5510,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK9-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5763,7 +5763,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK9-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6046,7 +6046,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK9-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6299,7 +6299,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK9-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6586,7 +6586,7 @@ int main() { // CHECK9: omp.dispatch.end: // CHECK9-NEXT: [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]]) // CHECK9-NEXT: [[TMP38:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP39:%.*]] = icmp ne i32 [[TMP38]], 0 // CHECK9-NEXT: br i1 [[TMP39]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7976,7 +7976,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK9-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -8229,7 +8229,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK9-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -8512,7 +8512,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK9-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -8765,7 +8765,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK9-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK9-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -9052,7 +9052,7 @@ int main() { // CHECK9: omp.dispatch.end: // CHECK9-NEXT: [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]]) // CHECK9-NEXT: [[TMP38:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP39:%.*]] = icmp ne i32 [[TMP38]], 0 // CHECK9-NEXT: br i1 [[TMP39]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -10438,7 +10438,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK11-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -10684,7 +10684,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK11-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -10960,7 +10960,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK11-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -11206,7 +11206,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK11-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -11484,7 +11484,7 @@ int main() { // CHECK11: omp.dispatch.end: // CHECK11-NEXT: [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]]) // CHECK11-NEXT: [[TMP38:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP39:%.*]] = icmp ne i32 [[TMP38]], 0 // CHECK11-NEXT: br i1 [[TMP39]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -12853,7 +12853,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK11-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -13099,7 +13099,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK11-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -13375,7 +13375,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK11-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -13621,7 +13621,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK11-NEXT: [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0 // CHECK11-NEXT: br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -13899,7 +13899,7 @@ int main() { // CHECK11: omp.dispatch.end: // CHECK11-NEXT: [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]]) // CHECK11-NEXT: [[TMP38:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP39:%.*]] = icmp ne i32 [[TMP38]], 0 // CHECK11-NEXT: br i1 [[TMP39]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp index 5c9b2aa1f47f..f47b64b1e299 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp @@ -506,7 +506,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0 // CHECK1-NEXT: br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -768,7 +768,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK3-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0 // CHECK3-NEXT: br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1237,7 +1237,7 @@ int main() { // CHECK8: omp.loop.exit: // CHECK8-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK8-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK8-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK8-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK8-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK8-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK8-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1696,7 +1696,7 @@ int main() { // CHECK8: omp.loop.exit: // CHECK8-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK8-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK8-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK8-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK8-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK8-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK8-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2178,7 +2178,7 @@ int main() { // CHECK10: omp.loop.exit: // CHECK10-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK10-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK10-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK10-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK10-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2631,7 +2631,7 @@ int main() { // CHECK10: omp.loop.exit: // CHECK10-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK10-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK10-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK10-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK10-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp index 67384abc7751..b3e964fddcf0 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp @@ -333,7 +333,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -490,7 +490,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -772,7 +772,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -929,7 +929,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1100,7 +1100,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1380,7 +1380,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1537,7 +1537,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1708,7 +1708,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1935,7 +1935,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2092,7 +2092,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2374,7 +2374,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2531,7 +2531,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2810,7 +2810,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK3-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK3-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2937,7 +2937,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK3-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK3-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3217,7 +3217,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3374,7 +3374,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3545,7 +3545,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4348,7 +4348,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4505,7 +4505,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4787,7 +4787,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4944,7 +4944,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5115,7 +5115,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5395,7 +5395,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5552,7 +5552,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5723,7 +5723,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5950,7 +5950,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6107,7 +6107,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6389,7 +6389,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6546,7 +6546,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6825,7 +6825,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6952,7 +6952,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7232,7 +7232,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7389,7 +7389,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7560,7 +7560,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp index adef55eee1cd..7656fb7bc2c5 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp @@ -453,7 +453,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]]) // CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK1-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -732,7 +732,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]]) // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK3-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1227,7 +1227,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK9-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK9-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1724,7 +1724,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK9-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2241,7 +2241,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2732,7 +2732,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK11-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp index 0a0ed699acb1..9f4fffbea63d 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp @@ -393,7 +393,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -568,7 +568,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -914,7 +914,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1075,7 +1075,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1236,7 +1236,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1412,7 +1412,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2068,7 +2068,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK5-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2243,7 +2243,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK5-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2580,7 +2580,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK5-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2741,7 +2741,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK5-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2902,7 +2902,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK5-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3078,7 +3078,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK5-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3404,7 +3404,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3579,7 +3579,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3925,7 +3925,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4086,7 +4086,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4247,7 +4247,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4423,7 +4423,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5079,7 +5079,7 @@ int main() { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK13-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK13-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5254,7 +5254,7 @@ int main() { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK13-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK13-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5591,7 +5591,7 @@ int main() { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK13-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK13-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5752,7 +5752,7 @@ int main() { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK13-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK13-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5913,7 +5913,7 @@ int main() { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK13-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK13-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6089,7 +6089,7 @@ int main() { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK13-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK13-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp index 22208e2e2c1d..61f35d8b456c 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp @@ -320,7 +320,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0 // CHECK1-NEXT: br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -512,7 +512,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0 // CHECK3-NEXT: br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -856,7 +856,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK9-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0 // CHECK9-NEXT: br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1222,7 +1222,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK9-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0 // CHECK9-NEXT: br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1589,7 +1589,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK11-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0 // CHECK11-NEXT: br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1949,7 +1949,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK11-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0 // CHECK11-NEXT: br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp index d452ac3bed48..334965f59a82 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp @@ -273,7 +273,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -425,7 +425,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -618,7 +618,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/metadirective_device_arch_codegen.cpp b/clang/test/OpenMP/metadirective_device_arch_codegen.cpp index 6150b7c07c16..eecae310d0a7 100644 --- a/clang/test/OpenMP/metadirective_device_arch_codegen.cpp +++ b/clang/test/OpenMP/metadirective_device_arch_codegen.cpp @@ -60,6 +60,6 @@ int metadirective1() { // CHECK: omp.inner.for.body: // CHECK: store atomic {{.*}} monotonic // CHECK: omp.loop.exit: -// CHECK-NEXT: call void @__kmpc_distribute_static_fini +// CHECK-NEXT: call void @__kmpc_for_static_fini // CHECK-NEXT: ret void diff --git a/clang/test/OpenMP/nvptx_SPMD_codegen.cpp b/clang/test/OpenMP/nvptx_SPMD_codegen.cpp index 1ac545499427..d47025cd1aca 100644 --- a/clang/test/OpenMP/nvptx_SPMD_codegen.cpp +++ b/clang/test/OpenMP/nvptx_SPMD_codegen.cpp @@ -573,7 +573,7 @@ int a; // CHECK-64: omp.loop.exit: // CHECK-64-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK-64-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]]) // CHECK-64-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-64-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK-64-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -680,7 +680,7 @@ int a; // CHECK-64: omp.loop.exit: // CHECK-64-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK-64-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]]) // CHECK-64-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-64-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK-64-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -873,7 +873,7 @@ int a; // CHECK-64: omp.inner.for.end: // CHECK-64-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-64: omp.loop.exit: -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-64-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-64-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK-64-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1057,7 +1057,7 @@ int a; // CHECK-64: omp.inner.for.end: // CHECK-64-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-64: omp.loop.exit: -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-64-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-64-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0 // CHECK-64-NEXT: br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2028,7 +2028,7 @@ int a; // CHECK-64: omp.inner.for.end: // CHECK-64-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-64: omp.loop.exit: -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-64-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-64-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK-64-NEXT: br i1 [[TMP12]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -2215,7 +2215,7 @@ int a; // CHECK-64: omp.inner.for.end: // CHECK-64-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-64: omp.loop.exit: -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-64-NEXT: ret void // // @@ -2385,7 +2385,7 @@ int a; // CHECK-64: omp.inner.for.end: // CHECK-64-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-64: omp.loop.exit: -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-64-NEXT: ret void // // @@ -3271,7 +3271,7 @@ int a; // CHECK-64: omp.inner.for.end: // CHECK-64-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-64: omp.loop.exit: -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-64-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-64-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0 // CHECK-64-NEXT: br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3466,7 +3466,7 @@ int a; // CHECK-64: omp.inner.for.end: // CHECK-64-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-64: omp.loop.exit: -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-64-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-64-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK-64-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3634,7 +3634,7 @@ int a; // CHECK-64: omp.inner.for.end: // CHECK-64-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-64: omp.loop.exit: -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-64-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-64-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0 // CHECK-64-NEXT: br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4595,7 +4595,7 @@ int a; // CHECK-64: omp.inner.for.end: // CHECK-64-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-64: omp.loop.exit: -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-64-NEXT: ret void // // @@ -4774,7 +4774,7 @@ int a; // CHECK-64: omp.inner.for.end: // CHECK-64-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-64: omp.loop.exit: -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-64-NEXT: ret void // // @@ -4944,7 +4944,7 @@ int a; // CHECK-64: omp.inner.for.end: // CHECK-64-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-64: omp.loop.exit: -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-64-NEXT: ret void // // @@ -5822,7 +5822,7 @@ int a; // CHECK-64: omp.inner.for.end: // CHECK-64-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-64: omp.loop.exit: -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-64-NEXT: ret void // // @@ -6001,7 +6001,7 @@ int a; // CHECK-64: omp.inner.for.end: // CHECK-64-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-64: omp.loop.exit: -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-64-NEXT: ret void // // @@ -6171,7 +6171,7 @@ int a; // CHECK-64: omp.inner.for.end: // CHECK-64-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-64: omp.loop.exit: -// CHECK-64-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-64-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-64-NEXT: ret void // // @@ -9534,7 +9534,7 @@ int a; // CHECK-32: omp.loop.exit: // CHECK-32-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK-32-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]]) // CHECK-32-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK-32-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -9637,7 +9637,7 @@ int a; // CHECK-32: omp.loop.exit: // CHECK-32-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK-32-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]]) // CHECK-32-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK-32-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -9826,7 +9826,7 @@ int a; // CHECK-32: omp.inner.for.end: // CHECK-32-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32: omp.loop.exit: -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK-32-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -10005,7 +10005,7 @@ int a; // CHECK-32: omp.inner.for.end: // CHECK-32-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32: omp.loop.exit: -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0 // CHECK-32-NEXT: br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -10955,7 +10955,7 @@ int a; // CHECK-32: omp.inner.for.end: // CHECK-32-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32: omp.loop.exit: -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK-32-NEXT: br i1 [[TMP12]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -11138,7 +11138,7 @@ int a; // CHECK-32: omp.inner.for.end: // CHECK-32-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32: omp.loop.exit: -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-NEXT: ret void // // @@ -11303,7 +11303,7 @@ int a; // CHECK-32: omp.inner.for.end: // CHECK-32-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32: omp.loop.exit: -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-NEXT: ret void // // @@ -12168,7 +12168,7 @@ int a; // CHECK-32: omp.inner.for.end: // CHECK-32-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32: omp.loop.exit: -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0 // CHECK-32-NEXT: br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -12359,7 +12359,7 @@ int a; // CHECK-32: omp.inner.for.end: // CHECK-32-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32: omp.loop.exit: -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK-32-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -12522,7 +12522,7 @@ int a; // CHECK-32: omp.inner.for.end: // CHECK-32-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32: omp.loop.exit: -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0 // CHECK-32-NEXT: br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -13462,7 +13462,7 @@ int a; // CHECK-32: omp.inner.for.end: // CHECK-32-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32: omp.loop.exit: -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-NEXT: ret void // // @@ -13637,7 +13637,7 @@ int a; // CHECK-32: omp.inner.for.end: // CHECK-32-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32: omp.loop.exit: -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-NEXT: ret void // // @@ -13802,7 +13802,7 @@ int a; // CHECK-32: omp.inner.for.end: // CHECK-32-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32: omp.loop.exit: -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-NEXT: ret void // // @@ -14659,7 +14659,7 @@ int a; // CHECK-32: omp.inner.for.end: // CHECK-32-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32: omp.loop.exit: -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-NEXT: ret void // // @@ -14834,7 +14834,7 @@ int a; // CHECK-32: omp.inner.for.end: // CHECK-32-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32: omp.loop.exit: -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-NEXT: ret void // // @@ -14999,7 +14999,7 @@ int a; // CHECK-32: omp.inner.for.end: // CHECK-32-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32: omp.loop.exit: -// CHECK-32-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-NEXT: ret void // // @@ -18346,7 +18346,7 @@ int a; // CHECK-32-EX: omp.loop.exit: // CHECK-32-EX-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK-32-EX-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]]) // CHECK-32-EX-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-EX-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK-32-EX-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -18449,7 +18449,7 @@ int a; // CHECK-32-EX: omp.loop.exit: // CHECK-32-EX-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK-32-EX-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]]) // CHECK-32-EX-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-EX-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK-32-EX-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -18638,7 +18638,7 @@ int a; // CHECK-32-EX: omp.inner.for.end: // CHECK-32-EX-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32-EX: omp.loop.exit: -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-EX-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-EX-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK-32-EX-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -18817,7 +18817,7 @@ int a; // CHECK-32-EX: omp.inner.for.end: // CHECK-32-EX-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32-EX: omp.loop.exit: -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-EX-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-EX-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0 // CHECK-32-EX-NEXT: br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -19767,7 +19767,7 @@ int a; // CHECK-32-EX: omp.inner.for.end: // CHECK-32-EX-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32-EX: omp.loop.exit: -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-EX-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-EX-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK-32-EX-NEXT: br i1 [[TMP12]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -19950,7 +19950,7 @@ int a; // CHECK-32-EX: omp.inner.for.end: // CHECK-32-EX-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32-EX: omp.loop.exit: -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-EX-NEXT: ret void // // @@ -20115,7 +20115,7 @@ int a; // CHECK-32-EX: omp.inner.for.end: // CHECK-32-EX-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32-EX: omp.loop.exit: -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-EX-NEXT: ret void // // @@ -20980,7 +20980,7 @@ int a; // CHECK-32-EX: omp.inner.for.end: // CHECK-32-EX-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32-EX: omp.loop.exit: -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-EX-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-EX-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0 // CHECK-32-EX-NEXT: br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -21171,7 +21171,7 @@ int a; // CHECK-32-EX: omp.inner.for.end: // CHECK-32-EX-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32-EX: omp.loop.exit: -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-EX-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-EX-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK-32-EX-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -21334,7 +21334,7 @@ int a; // CHECK-32-EX: omp.inner.for.end: // CHECK-32-EX-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32-EX: omp.loop.exit: -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-EX-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-32-EX-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0 // CHECK-32-EX-NEXT: br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -22274,7 +22274,7 @@ int a; // CHECK-32-EX: omp.inner.for.end: // CHECK-32-EX-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32-EX: omp.loop.exit: -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-EX-NEXT: ret void // // @@ -22449,7 +22449,7 @@ int a; // CHECK-32-EX: omp.inner.for.end: // CHECK-32-EX-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32-EX: omp.loop.exit: -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-EX-NEXT: ret void // // @@ -22614,7 +22614,7 @@ int a; // CHECK-32-EX: omp.inner.for.end: // CHECK-32-EX-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32-EX: omp.loop.exit: -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-EX-NEXT: ret void // // @@ -23471,7 +23471,7 @@ int a; // CHECK-32-EX: omp.inner.for.end: // CHECK-32-EX-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32-EX: omp.loop.exit: -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-EX-NEXT: ret void // // @@ -23646,7 +23646,7 @@ int a; // CHECK-32-EX: omp.inner.for.end: // CHECK-32-EX-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32-EX: omp.loop.exit: -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-EX-NEXT: ret void // // @@ -23811,7 +23811,7 @@ int a; // CHECK-32-EX: omp.inner.for.end: // CHECK-32-EX-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK-32-EX: omp.loop.exit: -// CHECK-32-EX-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) +// CHECK-32-EX-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]]) // CHECK-32-EX-NEXT: ret void // // diff --git a/clang/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp b/clang/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp index 7402698af3e4..986aeadaf998 100644 --- a/clang/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp +++ b/clang/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp @@ -329,7 +329,7 @@ int main(int argc, char **argv) { // CHECK4: omp.loop.exit: // CHECK4-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK4-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4 -// CHECK4-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP23]]) +// CHECK4-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP23]]) // CHECK4-NEXT: [[TMP24:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK4-NEXT: [[TMP25:%.*]] = icmp ne i32 [[TMP24]], 0 // CHECK4-NEXT: br i1 [[TMP25]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -639,7 +639,7 @@ int main(int argc, char **argv) { // CHECK5: omp.loop.exit: // CHECK5-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK5-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4 -// CHECK5-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP23]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP23]]) // CHECK5-NEXT: [[TMP24:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP25:%.*]] = icmp ne i32 [[TMP24]], 0 // CHECK5-NEXT: br i1 [[TMP25]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] diff --git a/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp index 4d6982d10616..8397b93cbeed 100644 --- a/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp +++ b/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp @@ -371,7 +371,7 @@ int bar(int n){ // CHECK1: omp.dispatch.end: // CHECK1-NEXT: [[TMP26:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4 -// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP27]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP27]]) // CHECK1-NEXT: [[TMP28:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP29:%.*]] = icmp ne i32 [[TMP28]], 0 // CHECK1-NEXT: br i1 [[TMP29]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -633,7 +633,7 @@ int bar(int n){ // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4 -// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP18]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP18]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -822,7 +822,7 @@ int bar(int n){ // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -1050,7 +1050,7 @@ int bar(int n){ // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -1360,7 +1360,7 @@ int bar(int n){ // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP27:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP28:%.*]] = load i32, ptr [[TMP27]], align 4 -// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP28]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP28]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -1625,7 +1625,7 @@ int bar(int n){ // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -1931,7 +1931,7 @@ int bar(int n){ // CHECK2: omp.dispatch.end: // CHECK2-NEXT: [[TMP26:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK2-NEXT: [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4 -// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP27]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP27]]) // CHECK2-NEXT: [[TMP28:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK2-NEXT: [[TMP29:%.*]] = icmp ne i32 [[TMP28]], 0 // CHECK2-NEXT: br i1 [[TMP29]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -2193,7 +2193,7 @@ int bar(int n){ // CHECK2: omp.loop.exit: // CHECK2-NEXT: [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK2-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4 -// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP18]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP18]]) // CHECK2-NEXT: br label [[OMP_PRECOND_END]] // CHECK2: omp.precond.end: // CHECK2-NEXT: ret void @@ -2382,7 +2382,7 @@ int bar(int n){ // CHECK2: omp.inner.for.end: // CHECK2-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK2: omp.loop.exit: -// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK2-NEXT: ret void // // @@ -2610,7 +2610,7 @@ int bar(int n){ // CHECK2: omp.inner.for.end: // CHECK2-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK2: omp.loop.exit: -// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK2-NEXT: ret void // // @@ -2915,7 +2915,7 @@ int bar(int n){ // CHECK2: omp.loop.exit: // CHECK2-NEXT: [[TMP27:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK2-NEXT: [[TMP28:%.*]] = load i32, ptr [[TMP27]], align 4 -// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP28]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP28]]) // CHECK2-NEXT: br label [[OMP_PRECOND_END]] // CHECK2: omp.precond.end: // CHECK2-NEXT: ret void @@ -3180,7 +3180,7 @@ int bar(int n){ // CHECK2: omp.loop.exit: // CHECK2-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK2-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]]) // CHECK2-NEXT: br label [[OMP_PRECOND_END]] // CHECK2: omp.precond.end: // CHECK2-NEXT: ret void @@ -3479,7 +3479,7 @@ int bar(int n){ // CHECK3: omp.dispatch.end: // CHECK3-NEXT: [[TMP26:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4 -// CHECK3-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP27]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP27]]) // CHECK3-NEXT: [[TMP28:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP29:%.*]] = icmp ne i32 [[TMP28]], 0 // CHECK3-NEXT: br i1 [[TMP29]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -3735,7 +3735,7 @@ int bar(int n){ // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4 -// CHECK3-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP18]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP18]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: omp.precond.end: // CHECK3-NEXT: ret void @@ -3918,7 +3918,7 @@ int bar(int n){ // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -4139,7 +4139,7 @@ int bar(int n){ // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -4452,7 +4452,7 @@ int bar(int n){ // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP27:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP28:%.*]] = load i32, ptr [[TMP27]], align 4 -// CHECK3-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP28]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP28]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: omp.precond.end: // CHECK3-NEXT: ret void @@ -4710,7 +4710,7 @@ int bar(int n){ // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK3-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: omp.precond.end: // CHECK3-NEXT: ret void diff --git a/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp b/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp index 045cd39b07b7..e687a537ecf1 100644 --- a/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp +++ b/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp @@ -323,7 +323,7 @@ int main(int argc, char **argv) { // CHECK1: omp.dispatch.end: // CHECK1-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 -// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP26]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP26]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -617,7 +617,7 @@ int main(int argc, char **argv) { // CHECK2: omp.dispatch.end: // CHECK2-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK2-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 -// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP26]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP26]]) // CHECK2-NEXT: br label [[OMP_PRECOND_END]] // CHECK2: omp.precond.end: // CHECK2-NEXT: ret void diff --git a/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp index 2520713da50e..9aee4bd09282 100644 --- a/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp +++ b/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp @@ -371,7 +371,7 @@ int bar(int n){ // CHECK1: omp.dispatch.end: // CHECK1-NEXT: [[TMP26:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4 -// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP27]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP27]]) // CHECK1-NEXT: [[TMP28:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP29:%.*]] = icmp ne i32 [[TMP28]], 0 // CHECK1-NEXT: br i1 [[TMP29]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -657,7 +657,7 @@ int bar(int n){ // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4 -// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP18]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP18]]) // CHECK1-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0 // CHECK1-NEXT: br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -865,7 +865,7 @@ int bar(int n){ // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK1-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1108,7 +1108,7 @@ int bar(int n){ // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0 // CHECK1-NEXT: br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1425,7 +1425,7 @@ int bar(int n){ // CHECK2: omp.dispatch.end: // CHECK2-NEXT: [[TMP26:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK2-NEXT: [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4 -// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP27]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP27]]) // CHECK2-NEXT: [[TMP28:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK2-NEXT: [[TMP29:%.*]] = icmp ne i32 [[TMP28]], 0 // CHECK2-NEXT: br i1 [[TMP29]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1705,7 +1705,7 @@ int bar(int n){ // CHECK2: omp.loop.exit: // CHECK2-NEXT: [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK2-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4 -// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP18]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP18]]) // CHECK2-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK2-NEXT: [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0 // CHECK2-NEXT: br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1907,7 +1907,7 @@ int bar(int n){ // CHECK2: omp.inner.for.end: // CHECK2-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK2: omp.loop.exit: -// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK2-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK2-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK2-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2143,7 +2143,7 @@ int bar(int n){ // CHECK2: omp.inner.for.end: // CHECK2-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK2: omp.loop.exit: -// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK2-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK2-NEXT: [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0 // CHECK2-NEXT: br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/nvptx_target_teams_generic_loop_codegen.cpp b/clang/test/OpenMP/nvptx_target_teams_generic_loop_codegen.cpp index fc83500a09f9..5226b7498e4c 100644 --- a/clang/test/OpenMP/nvptx_target_teams_generic_loop_codegen.cpp +++ b/clang/test/OpenMP/nvptx_target_teams_generic_loop_codegen.cpp @@ -219,7 +219,7 @@ int bar(int n){ // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3:[0-9]+]], i32 [[TMP41]]) +// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP41]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -276,7 +276,7 @@ int bar(int n){ // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB3]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB3:[0-9]+]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4 // CHECK1-NEXT: store i32 [[TMP9]], ptr [[DOTOMP_IV]], align 4 // CHECK1-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] @@ -432,7 +432,7 @@ int bar(int n){ // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP2]]) +// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP2]]) // CHECK1-NEXT: ret void // // @@ -637,7 +637,7 @@ int bar(int n){ // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP2]]) +// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP2]]) // CHECK1-NEXT: ret void // // @@ -904,7 +904,7 @@ int bar(int n){ // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP41:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP42:%.*]] = load i32, ptr [[TMP41]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP42]]) +// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP42]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -1208,7 +1208,7 @@ int bar(int n){ // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP42:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP43:%.*]] = load i32, ptr [[TMP42]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP43]]) +// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP43]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -1465,7 +1465,7 @@ int bar(int n){ // CHECK2: omp.loop.exit: // CHECK2-NEXT: [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK2-NEXT: [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4 -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3:[0-9]+]], i32 [[TMP41]]) +// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP41]]) // CHECK2-NEXT: br label [[OMP_PRECOND_END]] // CHECK2: omp.precond.end: // CHECK2-NEXT: ret void @@ -1522,7 +1522,7 @@ int bar(int n){ // CHECK2-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK2-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK2-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 -// CHECK2-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB3]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK2-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB3:[0-9]+]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK2-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4 // CHECK2-NEXT: store i32 [[TMP9]], ptr [[DOTOMP_IV]], align 4 // CHECK2-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] @@ -1678,7 +1678,7 @@ int bar(int n){ // CHECK2: omp.inner.for.end: // CHECK2-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK2: omp.loop.exit: -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP2]]) +// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP2]]) // CHECK2-NEXT: ret void // // @@ -1883,7 +1883,7 @@ int bar(int n){ // CHECK2: omp.inner.for.end: // CHECK2-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK2: omp.loop.exit: -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP2]]) +// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP2]]) // CHECK2-NEXT: ret void // // @@ -2149,7 +2149,7 @@ int bar(int n){ // CHECK2: omp.loop.exit: // CHECK2-NEXT: [[TMP43:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK2-NEXT: [[TMP44:%.*]] = load i32, ptr [[TMP43]], align 4 -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP44]]) +// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP44]]) // CHECK2-NEXT: br label [[OMP_PRECOND_END]] // CHECK2: omp.precond.end: // CHECK2-NEXT: ret void @@ -2449,7 +2449,7 @@ int bar(int n){ // CHECK2: omp.loop.exit: // CHECK2-NEXT: [[TMP42:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK2-NEXT: [[TMP43:%.*]] = load i32, ptr [[TMP42]], align 4 -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP43]]) +// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP43]]) // CHECK2-NEXT: br label [[OMP_PRECOND_END]] // CHECK2: omp.precond.end: // CHECK2-NEXT: ret void @@ -2704,7 +2704,7 @@ int bar(int n){ // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP38:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP39:%.*]] = load i32, ptr [[TMP38]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3:[0-9]+]], i32 [[TMP39]]) +// CHECK3-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP39]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: omp.precond.end: // CHECK3-NEXT: ret void @@ -2759,7 +2759,7 @@ int bar(int n){ // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB3]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK3-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB3:[0-9]+]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK3-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4 // CHECK3-NEXT: store i32 [[TMP9]], ptr [[DOTOMP_IV]], align 4 // CHECK3-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] @@ -2911,7 +2911,7 @@ int bar(int n){ // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP2]]) +// CHECK3-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP2]]) // CHECK3-NEXT: ret void // // @@ -3110,7 +3110,7 @@ int bar(int n){ // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP2]]) +// CHECK3-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP2]]) // CHECK3-NEXT: ret void // // @@ -3374,7 +3374,7 @@ int bar(int n){ // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP43:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP44:%.*]] = load i32, ptr [[TMP43]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP44]]) +// CHECK3-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP44]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: omp.precond.end: // CHECK3-NEXT: ret void @@ -3677,7 +3677,7 @@ int bar(int n){ // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP41]]) +// CHECK3-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP41]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: omp.precond.end: // CHECK3-NEXT: ret void diff --git a/clang/test/OpenMP/nvptx_target_teams_generic_loop_generic_mode_codegen.cpp b/clang/test/OpenMP/nvptx_target_teams_generic_loop_generic_mode_codegen.cpp index ef26c9b1003a..ca2670f0cd64 100644 --- a/clang/test/OpenMP/nvptx_target_teams_generic_loop_generic_mode_codegen.cpp +++ b/clang/test/OpenMP/nvptx_target_teams_generic_loop_generic_mode_codegen.cpp @@ -183,7 +183,7 @@ int main(int argc, char **argv) { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3:[0-9]+]], i32 [[TMP41]]) +// CHECK1-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP41]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -240,7 +240,7 @@ int main(int argc, char **argv) { // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB3]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB3:[0-9]+]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4 // CHECK1-NEXT: store i32 [[TMP9]], ptr [[DOTOMP_IV]], align 4 // CHECK1-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] @@ -433,7 +433,7 @@ int main(int argc, char **argv) { // CHECK2: omp.loop.exit: // CHECK2-NEXT: [[TMP38:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK2-NEXT: [[TMP39:%.*]] = load i32, ptr [[TMP38]], align 4 -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3:[0-9]+]], i32 [[TMP39]]) +// CHECK2-NEXT: call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP39]]) // CHECK2-NEXT: br label [[OMP_PRECOND_END]] // CHECK2: omp.precond.end: // CHECK2-NEXT: ret void @@ -488,7 +488,7 @@ int main(int argc, char **argv) { // CHECK2-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK2-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK2-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 -// CHECK2-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB3]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK2-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB3:[0-9]+]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK2-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4 // CHECK2-NEXT: store i32 [[TMP9]], ptr [[DOTOMP_IV]], align 4 // CHECK2-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] diff --git a/clang/test/OpenMP/reduction_implicit_map.cpp b/clang/test/OpenMP/reduction_implicit_map.cpp index d47c6ec7214d..7305c56289e0 100644 --- a/clang/test/OpenMP/reduction_implicit_map.cpp +++ b/clang/test/OpenMP/reduction_implicit_map.cpp @@ -1365,7 +1365,7 @@ int main() // CHECK2: omp.loop.exit: // CHECK2-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK2-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]]) // CHECK2-NEXT: [[TMP31:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0 // CHECK2-NEXT: store ptr [[OUTPUT3]], ptr [[TMP31]], align 4 // CHECK2-NEXT: [[TMP32:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 @@ -1735,7 +1735,7 @@ int main() // CHECK2: omp.loop.exit: // CHECK2-NEXT: [[TMP31:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK2-NEXT: [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4 -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP32]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP32]]) // CHECK2-NEXT: [[TMP33:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0 // CHECK2-NEXT: store ptr [[OUTPUT4]], ptr [[TMP33]], align 4 // CHECK2-NEXT: [[TMP34:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 diff --git a/clang/test/OpenMP/target_ompx_dyn_cgroup_mem_codegen.cpp b/clang/test/OpenMP/target_ompx_dyn_cgroup_mem_codegen.cpp index a8b241c17d24..e8b074a9d5f8 100644 --- a/clang/test/OpenMP/target_ompx_dyn_cgroup_mem_codegen.cpp +++ b/clang/test/OpenMP/target_ompx_dyn_cgroup_mem_codegen.cpp @@ -854,7 +854,7 @@ int bar(int n){ // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP18]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP18]]) // CHECK1-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0 // CHECK1-NEXT: br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1732,7 +1732,7 @@ int bar(int n){ // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP18]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP18]]) // CHECK3-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0 // CHECK3-NEXT: br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2145,7 +2145,7 @@ int bar(int n){ // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP18]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP18]]) // CHECK9-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0 // CHECK9-NEXT: br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2508,7 +2508,7 @@ int bar(int n){ // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP18]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP18]]) // CHECK11-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0 // CHECK11-NEXT: br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp index 9e12880be298..7e06d8c16169 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp @@ -333,12 +333,12 @@ int target_teams_fun(int *g){ // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: cancel.exit: // CHECK1-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP26]]) // CHECK1-NEXT: br label [[CANCEL_CONT:%.*]] // CHECK1: omp.precond.end: // CHECK1-NEXT: br label [[CANCEL_CONT]] @@ -559,7 +559,7 @@ int target_teams_fun(int *g){ // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -975,12 +975,12 @@ int target_teams_fun(int *g){ // CHECK2: omp.loop.exit: // CHECK2-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK2-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]]) // CHECK2-NEXT: br label [[OMP_PRECOND_END]] // CHECK2: cancel.exit: // CHECK2-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK2-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP26]]) // CHECK2-NEXT: br label [[CANCEL_CONT:%.*]] // CHECK2: omp.precond.end: // CHECK2-NEXT: br label [[CANCEL_CONT]] @@ -1201,7 +1201,7 @@ int target_teams_fun(int *g){ // CHECK2: omp.loop.exit: // CHECK2-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK2-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK2-NEXT: br label [[OMP_PRECOND_END]] // CHECK2: omp.precond.end: // CHECK2-NEXT: ret void @@ -1612,12 +1612,12 @@ int target_teams_fun(int *g){ // CHECK4: omp.loop.exit: // CHECK4-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK4-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 -// CHECK4-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]]) +// CHECK4-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]]) // CHECK4-NEXT: br label [[OMP_PRECOND_END]] // CHECK4: cancel.exit: // CHECK4-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK4-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 -// CHECK4-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]]) +// CHECK4-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP26]]) // CHECK4-NEXT: br label [[CANCEL_CONT:%.*]] // CHECK4: omp.precond.end: // CHECK4-NEXT: br label [[CANCEL_CONT]] @@ -1833,7 +1833,7 @@ int target_teams_fun(int *g){ // CHECK4: omp.loop.exit: // CHECK4-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK4-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK4-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK4-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK4-NEXT: br label [[OMP_PRECOND_END]] // CHECK4: omp.precond.end: // CHECK4-NEXT: ret void @@ -2059,12 +2059,12 @@ int target_teams_fun(int *g){ // CHECK10: omp.loop.exit: // CHECK10-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK10-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 -// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]]) +// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]]) // CHECK10-NEXT: br label [[OMP_PRECOND_END]] // CHECK10: cancel.exit: // CHECK10-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK10-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 -// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]]) +// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP26]]) // CHECK10-NEXT: br label [[CANCEL_CONT:%.*]] // CHECK10: omp.precond.end: // CHECK10-NEXT: br label [[CANCEL_CONT]] @@ -2287,7 +2287,7 @@ int target_teams_fun(int *g){ // CHECK10: omp.loop.exit: // CHECK10-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK10-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK10-NEXT: br label [[OMP_PRECOND_END]] // CHECK10: omp.precond.end: // CHECK10-NEXT: ret void @@ -2508,12 +2508,12 @@ int target_teams_fun(int *g){ // CHECK12: omp.loop.exit: // CHECK12-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK12-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 -// CHECK12-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]]) +// CHECK12-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]]) // CHECK12-NEXT: br label [[OMP_PRECOND_END]] // CHECK12: cancel.exit: // CHECK12-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK12-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 -// CHECK12-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]]) +// CHECK12-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP26]]) // CHECK12-NEXT: br label [[CANCEL_CONT:%.*]] // CHECK12: omp.precond.end: // CHECK12-NEXT: br label [[CANCEL_CONT]] @@ -2731,7 +2731,7 @@ int target_teams_fun(int *g){ // CHECK12: omp.loop.exit: // CHECK12-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK12-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK12-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK12-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK12-NEXT: br label [[OMP_PRECOND_END]] // CHECK12: omp.precond.end: // CHECK12-NEXT: ret void diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp index d13920ba956f..b812011ea4ca 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp @@ -331,7 +331,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -561,7 +561,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -1000,7 +1000,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP31:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP32]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP32]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -1224,7 +1224,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: ret void // // @@ -1664,7 +1664,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP31:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP32]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP32]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -1882,6 +1882,6 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: ret void // diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp index 517ea936a1d6..0aa75952a3c2 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp @@ -442,7 +442,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -593,7 +593,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -764,7 +764,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -1071,7 +1071,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -1217,7 +1217,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -1383,7 +1383,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -1881,7 +1881,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -2098,7 +2098,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -2354,7 +2354,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -2668,7 +2668,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: ret void // // @@ -2818,7 +2818,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: ret void // // @@ -3003,7 +3003,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: ret void // // @@ -3498,7 +3498,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -3710,7 +3710,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -3961,7 +3961,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -4270,7 +4270,7 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: ret void // // @@ -4415,7 +4415,7 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: ret void // // @@ -4595,6 +4595,6 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: ret void // diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp index 9f11929ec372..375279d96360 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp @@ -703,7 +703,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK1-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR2]] // CHECK1-NEXT: [[ARRAY_BEGIN12:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN12]], i64 2 @@ -1170,7 +1170,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK1-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]]) #[[ATTR2]] // CHECK1-NEXT: [[ARRAY_BEGIN13:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN13]], i64 2 @@ -1759,7 +1759,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK3-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR4]]) #[[ATTR2]] // CHECK3-NEXT: [[ARRAY_BEGIN10:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR2]], i32 0, i32 0 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN10]], i32 2 @@ -2220,7 +2220,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK3-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR2]] // CHECK3-NEXT: [[ARRAY_BEGIN11:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN11]], i32 2 @@ -2631,7 +2631,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: ret void // // @@ -2949,7 +2949,7 @@ int main() { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK13-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR5]] // CHECK13-NEXT: [[ARRAY_BEGIN12:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR3]], i32 0, i32 0 // CHECK13-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN12]], i64 2 @@ -3256,7 +3256,7 @@ int main() { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK13-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]]) #[[ATTR5]] // CHECK13-NEXT: [[ARRAY_BEGIN13:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i32 0, i32 0 // CHECK13-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN13]], i64 2 @@ -3663,7 +3663,7 @@ int main() { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK15-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR4]]) #[[ATTR5]] // CHECK15-NEXT: [[ARRAY_BEGIN10:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR2]], i32 0, i32 0 // CHECK15-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN10]], i32 2 @@ -3964,7 +3964,7 @@ int main() { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK15-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR5]] // CHECK15-NEXT: [[ARRAY_BEGIN11:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i32 0, i32 0 // CHECK15-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN11]], i32 2 @@ -4270,6 +4270,6 @@ int main() { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK17-NEXT: ret void // diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp index fe2088aace15..9baf13385bef 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp @@ -314,7 +314,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -457,7 +457,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -711,7 +711,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -854,7 +854,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -1016,7 +1016,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -1259,7 +1259,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -1402,7 +1402,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -1564,6 +1564,6 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp index e2181e5088cc..e54c230eea7e 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp @@ -428,7 +428,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0 // CHECK1-NEXT: br i1 [[TMP19]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -692,7 +692,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP6]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP6]]) // CHECK3-NEXT: [[TMP20:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = icmp ne i32 [[TMP20]], 0 // CHECK3-NEXT: br i1 [[TMP21]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -1144,7 +1144,7 @@ int main() { // CHECK5: omp.loop.exit: // CHECK5-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK5-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) // CHECK5-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK5-NEXT: br i1 [[TMP22]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -1628,7 +1628,7 @@ int main() { // CHECK5: omp.loop.exit: // CHECK5-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK5-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) // CHECK5-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK5-NEXT: br i1 [[TMP22]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -2138,7 +2138,7 @@ int main() { // CHECK7: omp.loop.exit: // CHECK7-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK7-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]]) +// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) // CHECK7-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK7-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK7-NEXT: br i1 [[TMP22]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -2616,7 +2616,7 @@ int main() { // CHECK7: omp.loop.exit: // CHECK7-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK7-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]]) +// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) // CHECK7-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK7-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK7-NEXT: br i1 [[TMP22]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp index 74dee0399f58..feab9cdc948b 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp @@ -195,6 +195,6 @@ void gtid_test() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp index 82f29fa1d3ef..066d926e5abc 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp @@ -534,7 +534,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]]) // CHECK1-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK1-NEXT: [[ARRAY_BEGIN7:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN7]], i64 2 @@ -842,7 +842,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK1-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK1-NEXT: [[ARRAY_BEGIN8:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN8]], i64 2 @@ -1261,7 +1261,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]]) // CHECK3-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK3-NEXT: [[ARRAY_BEGIN5:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN5]], i32 2 @@ -1563,7 +1563,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK3-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK3-NEXT: [[ARRAY_BEGIN6:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN6]], i32 2 @@ -1917,7 +1917,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: ret void // // @@ -2139,7 +2139,7 @@ int main() { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]]) // CHECK13-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5]] // CHECK13-NEXT: [[ARRAY_BEGIN7:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 // CHECK13-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN7]], i64 2 @@ -2376,7 +2376,7 @@ int main() { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK13-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5]] // CHECK13-NEXT: [[ARRAY_BEGIN8:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 // CHECK13-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN8]], i64 2 @@ -2647,7 +2647,7 @@ int main() { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]]) // CHECK15-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5]] // CHECK15-NEXT: [[ARRAY_BEGIN5:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 // CHECK15-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN5]], i32 2 @@ -2878,7 +2878,7 @@ int main() { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK15-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5]] // CHECK15-NEXT: [[ARRAY_BEGIN6:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 // CHECK15-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN6]], i32 2 @@ -3108,6 +3108,6 @@ int main() { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK17-NEXT: ret void // diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp index 6d22bc22e479..9f3e50fe20a6 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp @@ -261,7 +261,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -399,7 +399,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -578,6 +578,6 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp index bfa00ee7a0f4..1036ffd195de 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp @@ -316,7 +316,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 // CHECK1-NEXT: store ptr [[SIVAR2]], ptr [[TMP14]], align 8 // CHECK1-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l66.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -606,7 +606,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 // CHECK1-NEXT: store ptr [[T_VAR2]], ptr [[TMP14]], align 8 // CHECK1-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -891,7 +891,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[SIVAR1]], ptr [[TMP14]], align 4 // CHECK3-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l66.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -1177,7 +1177,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[T_VAR1]], ptr [[TMP14]], align 4 // CHECK3-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -1425,7 +1425,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: [[TMP15:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 // CHECK5-NEXT: store ptr [[SIVAR2]], ptr [[TMP15]], align 8 // CHECK5-NEXT: [[TMP16:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_task_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_task_codegen.cpp index fea36e882b7a..6f1cc4d308a6 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_task_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_task_codegen.cpp @@ -239,8 +239,8 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP72:%.*]] = load i32, ptr [[TMP71]], align 4 // CHECK1-NEXT: [[TMP73:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB4:[0-9]+]], i32 [[TMP72]], i32 2, i64 24, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l14.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) // CHECK1-NEXT: switch i32 [[TMP73]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [ -// CHECK1-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] -// CHECK1-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] +// CHECK1-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] +// CHECK1-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] // CHECK1-NEXT: ] // CHECK1: .omp.reduction.case1: // CHECK1-NEXT: [[TMP74:%.*]] = load i32, ptr [[TMP0]], align 4 @@ -588,7 +588,7 @@ int main(int argc, char **argv) { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP78:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP79:%.*]] = load i32, ptr [[TMP78]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP79]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP79]]) // CHECK1-NEXT: [[TMP80:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP81:%.*]] = load i32, ptr [[TMP80]], align 4 // CHECK1-NEXT: call void @__kmpc_task_reduction_modifier_fini(ptr @[[GLOB1]], i32 [[TMP81]], i32 1) @@ -603,8 +603,8 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP87:%.*]] = load i32, ptr [[TMP86]], align 4 // CHECK1-NEXT: [[TMP88:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB4]], i32 [[TMP87]], i32 2, i64 24, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l14.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) // CHECK1-NEXT: switch i32 [[TMP88]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [ -// CHECK1-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] -// CHECK1-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] +// CHECK1-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] +// CHECK1-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] // CHECK1-NEXT: ] // CHECK1: .omp.reduction.case1: // CHECK1-NEXT: [[TMP89:%.*]] = load i32, ptr [[TMP0]], align 4 @@ -796,21 +796,21 @@ int main(int argc, char **argv) { // CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]]) // CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META8:![0-9]+]]) // CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META10:![0-9]+]]) -// CHECK1-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !12 +// CHECK1-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META12:![0-9]+]] +// CHECK1-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META12]] // CHECK1-NEXT: call void [[TMP10]](ptr [[TMP11]], ptr [[DOTFIRSTPRIV_PTR_ADDR_I]]) #[[ATTR6]] -// CHECK1-NEXT: [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias !12 +// CHECK1-NEXT: [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias [[META12]] // CHECK1-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[TMP9]], i32 0, i32 1 // CHECK1-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8 // CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[TMP12]], align 8 -// CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !12 +// CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META12]] // CHECK1-NEXT: [[TMP17:%.*]] = call ptr @__kmpc_task_reduction_get_th_data(i32 [[TMP16]], ptr [[TMP15]], ptr [[TMP14]]) // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 // CHECK1-NEXT: [[TMP19:%.*]] = load ptr, ptr [[TMP18]], align 8 @@ -830,7 +830,7 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP30:%.*]] = sub i64 [[TMP28]], [[TMP29]] // CHECK1-NEXT: [[TMP31:%.*]] = add nuw i64 [[TMP30]], 1 // CHECK1-NEXT: [[TMP32:%.*]] = mul nuw i64 [[TMP31]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) -// CHECK1-NEXT: store i64 [[TMP31]], ptr @{{reduction_size[.].+[.]}}, align 8, !noalias !12 +// CHECK1-NEXT: store i64 [[TMP31]], ptr @{{reduction_size[.].+[.]}}, align 8, !noalias [[META12]] // CHECK1-NEXT: [[TMP33:%.*]] = load ptr, ptr [[TMP12]], align 8 // CHECK1-NEXT: [[TMP34:%.*]] = call ptr @__kmpc_task_reduction_get_th_data(i32 [[TMP16]], ptr [[TMP33]], ptr [[TMP20]]) // CHECK1-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 @@ -840,8 +840,8 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP39:%.*]] = ptrtoint ptr [[TMP20]] to i64 // CHECK1-NEXT: [[TMP40:%.*]] = sub i64 [[TMP38]], [[TMP39]] // CHECK1-NEXT: [[TMP41:%.*]] = getelementptr i8, ptr [[TMP34]], i64 [[TMP40]] -// CHECK1-NEXT: store ptr [[TMP4_I]], ptr [[TMP_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP41]], ptr [[TMP4_I]], align 8, !noalias !12 +// CHECK1-NEXT: store ptr [[TMP4_I]], ptr [[TMP_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr [[TMP41]], ptr [[TMP4_I]], align 8, !noalias [[META12]] // CHECK1-NEXT: ret i32 0 // // diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp index f71a5ca73437..3d031e09aa07 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp @@ -596,7 +596,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -747,7 +747,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -919,7 +919,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK1: omp.dispatch.end: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -1618,7 +1618,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -1764,7 +1764,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -1929,7 +1929,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK3-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK3: omp.dispatch.end: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -2623,7 +2623,7 @@ int main (int argc, char **argv) { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: ret void // // @@ -2774,7 +2774,7 @@ int main (int argc, char **argv) { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: ret void // // @@ -2946,7 +2946,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK5-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK5: omp.dispatch.end: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: ret void // // @@ -3645,7 +3645,7 @@ int main (int argc, char **argv) { // CHECK7: omp.inner.for.end: // CHECK7-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK7: omp.loop.exit: -// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK7-NEXT: ret void // // @@ -3791,7 +3791,7 @@ int main (int argc, char **argv) { // CHECK7: omp.inner.for.end: // CHECK7-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK7: omp.loop.exit: -// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK7-NEXT: ret void // // @@ -3956,7 +3956,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK7-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK7: omp.dispatch.end: -// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK7-NEXT: ret void // // @@ -4915,7 +4915,7 @@ int main (int argc, char **argv) { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK13-NEXT: br label [[OMP_PRECOND_END]] // CHECK13: omp.precond.end: // CHECK13-NEXT: ret void @@ -5132,7 +5132,7 @@ int main (int argc, char **argv) { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK13-NEXT: br label [[OMP_PRECOND_END]] // CHECK13: omp.precond.end: // CHECK13-NEXT: ret void @@ -5388,7 +5388,7 @@ int main (int argc, char **argv) { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK13-NEXT: br label [[OMP_PRECOND_END]] // CHECK13: omp.precond.end: // CHECK13-NEXT: ret void @@ -6248,7 +6248,7 @@ int main (int argc, char **argv) { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK13-NEXT: ret void // // @@ -6398,7 +6398,7 @@ int main (int argc, char **argv) { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK13-NEXT: ret void // // @@ -6584,7 +6584,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK13-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK13: omp.dispatch.end: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK13-NEXT: ret void // // @@ -7565,7 +7565,7 @@ int main (int argc, char **argv) { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK15-NEXT: br label [[OMP_PRECOND_END]] // CHECK15: omp.precond.end: // CHECK15-NEXT: ret void @@ -7777,7 +7777,7 @@ int main (int argc, char **argv) { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK15-NEXT: br label [[OMP_PRECOND_END]] // CHECK15: omp.precond.end: // CHECK15-NEXT: ret void @@ -8028,7 +8028,7 @@ int main (int argc, char **argv) { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK15-NEXT: br label [[OMP_PRECOND_END]] // CHECK15: omp.precond.end: // CHECK15-NEXT: ret void @@ -8873,7 +8873,7 @@ int main (int argc, char **argv) { // CHECK15: omp.inner.for.end: // CHECK15-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK15: omp.loop.exit: -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK15-NEXT: ret void // // @@ -9018,7 +9018,7 @@ int main (int argc, char **argv) { // CHECK15: omp.inner.for.end: // CHECK15-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK15: omp.loop.exit: -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK15-NEXT: ret void // // @@ -9197,7 +9197,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK15-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK15: omp.dispatch.end: -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK15-NEXT: ret void // // @@ -10169,7 +10169,7 @@ int main (int argc, char **argv) { // CHECK17: omp.loop.exit: // CHECK17-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK17-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK17-NEXT: br label [[OMP_PRECOND_END]] // CHECK17: omp.precond.end: // CHECK17-NEXT: ret void @@ -10386,7 +10386,7 @@ int main (int argc, char **argv) { // CHECK17: omp.loop.exit: // CHECK17-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK17-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK17-NEXT: br label [[OMP_PRECOND_END]] // CHECK17: omp.precond.end: // CHECK17-NEXT: ret void @@ -10642,7 +10642,7 @@ int main (int argc, char **argv) { // CHECK17: omp.loop.exit: // CHECK17-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK17-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK17-NEXT: br label [[OMP_PRECOND_END]] // CHECK17: omp.precond.end: // CHECK17-NEXT: ret void @@ -11502,7 +11502,7 @@ int main (int argc, char **argv) { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK17-NEXT: ret void // // @@ -11652,7 +11652,7 @@ int main (int argc, char **argv) { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK17-NEXT: ret void // // @@ -11838,7 +11838,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK17-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK17: omp.dispatch.end: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK17-NEXT: ret void // // @@ -12819,7 +12819,7 @@ int main (int argc, char **argv) { // CHECK19: omp.loop.exit: // CHECK19-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK19-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK19-NEXT: br label [[OMP_PRECOND_END]] // CHECK19: omp.precond.end: // CHECK19-NEXT: ret void @@ -13031,7 +13031,7 @@ int main (int argc, char **argv) { // CHECK19: omp.loop.exit: // CHECK19-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK19-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK19-NEXT: br label [[OMP_PRECOND_END]] // CHECK19: omp.precond.end: // CHECK19-NEXT: ret void @@ -13282,7 +13282,7 @@ int main (int argc, char **argv) { // CHECK19: omp.loop.exit: // CHECK19-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK19-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK19-NEXT: br label [[OMP_PRECOND_END]] // CHECK19: omp.precond.end: // CHECK19-NEXT: ret void @@ -14127,7 +14127,7 @@ int main (int argc, char **argv) { // CHECK19: omp.inner.for.end: // CHECK19-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK19: omp.loop.exit: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK19-NEXT: ret void // // @@ -14272,7 +14272,7 @@ int main (int argc, char **argv) { // CHECK19: omp.inner.for.end: // CHECK19-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK19: omp.loop.exit: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK19-NEXT: ret void // // @@ -14451,7 +14451,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK19-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK19: omp.dispatch.end: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK19-NEXT: ret void // // diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp index 5294f0d65eb6..109063c623a1 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp @@ -535,7 +535,7 @@ void test_target_teams_atomic() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP24]]) // CHECK1-NEXT: [[TMP25:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = icmp ne i32 [[TMP25]], 0 // CHECK1-NEXT: br i1 [[TMP26]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -784,7 +784,7 @@ void test_target_teams_atomic() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP22]]) // CHECK1-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK1-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1006,7 +1006,7 @@ void test_target_teams_atomic() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK1-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1465,7 +1465,7 @@ void test_target_teams_atomic() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP24]]) // CHECK3-NEXT: [[TMP25:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = icmp ne i32 [[TMP25]], 0 // CHECK3-NEXT: br i1 [[TMP26]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1709,7 +1709,7 @@ void test_target_teams_atomic() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP22]]) // CHECK3-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK3-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1927,7 +1927,7 @@ void test_target_teams_atomic() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK3-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2574,7 +2574,7 @@ void test_target_teams_atomic() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP24]]) // CHECK9-NEXT: [[TMP25:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = icmp ne i32 [[TMP25]], 0 // CHECK9-NEXT: br i1 [[TMP26]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2825,7 +2825,7 @@ void test_target_teams_atomic() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP22]]) // CHECK9-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK9-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2995,7 +2995,7 @@ void test_target_teams_atomic() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK9-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK9-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3253,7 +3253,7 @@ void test_target_teams_atomic() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP24]]) // CHECK11-NEXT: [[TMP25:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = icmp ne i32 [[TMP25]], 0 // CHECK11-NEXT: br i1 [[TMP26]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3499,7 +3499,7 @@ void test_target_teams_atomic() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP22]]) // CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3665,7 +3665,7 @@ void test_target_teams_atomic() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK11-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK11-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp index 2b4d31d14524..306ec1db2ab2 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp @@ -339,7 +339,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0 // CHECK1-NEXT: br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -585,7 +585,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0 // CHECK3-NEXT: br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1190,7 +1190,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP31:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP32]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP32]]) // CHECK9-NEXT: [[TMP33:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP34:%.*]] = icmp ne i32 [[TMP33]], 0 // CHECK9-NEXT: br i1 [[TMP34]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1440,7 +1440,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0 // CHECK9-NEXT: br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1906,7 +1906,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP31:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP32]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP32]]) // CHECK11-NEXT: [[TMP33:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP34:%.*]] = icmp ne i32 [[TMP33]], 0 // CHECK11-NEXT: br i1 [[TMP34]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2150,7 +2150,7 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0 // CHECK11-NEXT: br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp index 90fa290370b4..c265c1c616b1 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp @@ -449,7 +449,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK1-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -614,7 +614,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK1-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -799,7 +799,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK1-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1120,7 +1120,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK3-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1280,7 +1280,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK3-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1460,7 +1460,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK3-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2224,7 +2224,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK9-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2465,7 +2465,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK9-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2745,7 +2745,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK9-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3078,7 +3078,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK9-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3242,7 +3242,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK9-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3441,7 +3441,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK9-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3955,7 +3955,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK11-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4191,7 +4191,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK11-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4466,7 +4466,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK11-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4794,7 +4794,7 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK11-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4953,7 +4953,7 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK11-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5147,7 +5147,7 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK11-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp index bf79fe669d83..37c1f428ef9a 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp @@ -708,7 +708,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK1-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1189,7 +1189,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK1-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1792,7 +1792,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK3-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2267,7 +2267,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK3-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2692,7 +2692,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0 // CHECK5-NEXT: br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3798,7 +3798,7 @@ int main() { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK13-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK13-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4119,7 +4119,7 @@ int main() { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK13-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK13-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4540,7 +4540,7 @@ int main() { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK15-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK15-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK15-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4855,7 +4855,7 @@ int main() { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK15-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK15-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK15-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5175,7 +5175,7 @@ int main() { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK17-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0 // CHECK17-NEXT: br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp index 329cd788c8ba..df5dd7ba6805 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp @@ -353,7 +353,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -510,7 +510,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -778,7 +778,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -935,7 +935,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1111,7 +1111,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1368,7 +1368,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1525,7 +1525,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1701,7 +1701,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1958,7 +1958,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2115,7 +2115,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2383,7 +2383,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2540,7 +2540,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2819,7 +2819,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK3-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK3-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2946,7 +2946,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK3-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK3-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3203,7 +3203,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3360,7 +3360,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3536,7 +3536,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4386,7 +4386,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4543,7 +4543,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4811,7 +4811,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4968,7 +4968,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5144,7 +5144,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5401,7 +5401,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5558,7 +5558,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5734,7 +5734,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5991,7 +5991,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6148,7 +6148,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6416,7 +6416,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6573,7 +6573,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6852,7 +6852,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6979,7 +6979,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7236,7 +7236,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7393,7 +7393,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7569,7 +7569,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp index 903ecb865a25..3fdc0c482541 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp @@ -435,7 +435,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0 // CHECK1-NEXT: br i1 [[TMP19]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -713,7 +713,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP6]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP6]]) // CHECK3-NEXT: [[TMP20:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = icmp ne i32 [[TMP20]], 0 // CHECK3-NEXT: br i1 [[TMP21]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1179,7 +1179,7 @@ int main() { // CHECK5: omp.loop.exit: // CHECK5-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK5-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) // CHECK5-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK5-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1677,7 +1677,7 @@ int main() { // CHECK5: omp.loop.exit: // CHECK5-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK5-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) // CHECK5-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK5-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2201,7 +2201,7 @@ int main() { // CHECK7: omp.loop.exit: // CHECK7-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK7-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]]) +// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) // CHECK7-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK7-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK7-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2693,7 +2693,7 @@ int main() { // CHECK7: omp.loop.exit: // CHECK7-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK7-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]]) +// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) // CHECK7-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK7-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK7-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp index 7a211b4cd06b..bba97a750adc 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp @@ -541,7 +541,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]]) // CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0 // CHECK1-NEXT: br i1 [[TMP19]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -863,7 +863,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0 // CHECK1-NEXT: br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1296,7 +1296,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]]) // CHECK3-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0 // CHECK3-NEXT: br i1 [[TMP19]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1612,7 +1612,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK3-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0 // CHECK3-NEXT: br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1980,7 +1980,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0 // CHECK5-NEXT: br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3100,7 +3100,7 @@ int main() { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]]) // CHECK13-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0 // CHECK13-NEXT: br i1 [[TMP19]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3351,7 +3351,7 @@ int main() { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK13-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0 // CHECK13-NEXT: br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3636,7 +3636,7 @@ int main() { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]]) // CHECK15-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK15-NEXT: [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0 // CHECK15-NEXT: br i1 [[TMP19]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3881,7 +3881,7 @@ int main() { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK15-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK15-NEXT: [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0 // CHECK15-NEXT: br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4125,7 +4125,7 @@ int main() { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK17-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0 // CHECK17-NEXT: br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp index 31941b48f92d..c347743bd4fd 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp @@ -268,7 +268,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -420,7 +420,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -613,7 +613,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp index f255c3f084db..52430d51cde1 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp @@ -323,7 +323,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0 // CHECK1-NEXT: br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -627,7 +627,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0 // CHECK1-NEXT: br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -926,7 +926,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0 // CHECK3-NEXT: br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1226,7 +1226,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0 // CHECK3-NEXT: br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1488,7 +1488,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP16:%.*]] = icmp ne i32 [[TMP15]], 0 // CHECK5-NEXT: br i1 [[TMP16]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp index b41571eb415d..f7c0666d58b6 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp @@ -603,7 +603,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK1-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -768,7 +768,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK1-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -954,7 +954,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK1: omp.dispatch.end: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK1-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1695,7 +1695,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK3-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1855,7 +1855,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK3-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2034,7 +2034,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK3-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK3: omp.dispatch.end: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK3-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2770,7 +2770,7 @@ int main (int argc, char **argv) { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK5-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2935,7 +2935,7 @@ int main (int argc, char **argv) { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK5-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3121,7 +3121,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK5-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK5: omp.dispatch.end: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK5-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3862,7 +3862,7 @@ int main (int argc, char **argv) { // CHECK7: omp.inner.for.end: // CHECK7-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK7: omp.loop.exit: -// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK7-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK7-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK7-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4022,7 +4022,7 @@ int main (int argc, char **argv) { // CHECK7: omp.inner.for.end: // CHECK7-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK7: omp.loop.exit: -// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK7-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK7-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK7-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4201,7 +4201,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK7-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK7: omp.dispatch.end: -// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK7-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK7-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK7-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5592,7 +5592,7 @@ int main (int argc, char **argv) { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK13-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK13-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5833,7 +5833,7 @@ int main (int argc, char **argv) { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK13-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK13-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6113,7 +6113,7 @@ int main (int argc, char **argv) { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK13-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK13-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7040,7 +7040,7 @@ int main (int argc, char **argv) { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK13-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK13-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7204,7 +7204,7 @@ int main (int argc, char **argv) { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK13-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK13-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7404,7 +7404,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK13-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK13: omp.dispatch.end: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK13-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK13-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -8432,7 +8432,7 @@ int main (int argc, char **argv) { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK15-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK15-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK15-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -8668,7 +8668,7 @@ int main (int argc, char **argv) { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK15-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK15-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK15-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -8943,7 +8943,7 @@ int main (int argc, char **argv) { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK15-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK15-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK15-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -9855,7 +9855,7 @@ int main (int argc, char **argv) { // CHECK15: omp.inner.for.end: // CHECK15-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK15: omp.loop.exit: -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK15-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK15-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK15-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -10014,7 +10014,7 @@ int main (int argc, char **argv) { // CHECK15: omp.inner.for.end: // CHECK15-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK15: omp.loop.exit: -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK15-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK15-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK15-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -10207,7 +10207,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK15-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK15: omp.dispatch.end: -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK15-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK15-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK15-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -11226,7 +11226,7 @@ int main (int argc, char **argv) { // CHECK17: omp.loop.exit: // CHECK17-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK17-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK17-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK17-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -11467,7 +11467,7 @@ int main (int argc, char **argv) { // CHECK17: omp.loop.exit: // CHECK17-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK17-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK17-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK17-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -11747,7 +11747,7 @@ int main (int argc, char **argv) { // CHECK17: omp.loop.exit: // CHECK17-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK17-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK17-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK17-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -12674,7 +12674,7 @@ int main (int argc, char **argv) { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK17-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK17-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -12838,7 +12838,7 @@ int main (int argc, char **argv) { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK17-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK17-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -13038,7 +13038,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK17-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK17: omp.dispatch.end: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK17-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK17-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -14066,7 +14066,7 @@ int main (int argc, char **argv) { // CHECK19: omp.loop.exit: // CHECK19-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK19-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK19-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK19-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK19-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -14302,7 +14302,7 @@ int main (int argc, char **argv) { // CHECK19: omp.loop.exit: // CHECK19-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK19-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK19-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK19-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK19-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -14577,7 +14577,7 @@ int main (int argc, char **argv) { // CHECK19: omp.loop.exit: // CHECK19-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK19-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK19-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK19-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK19-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -15489,7 +15489,7 @@ int main (int argc, char **argv) { // CHECK19: omp.inner.for.end: // CHECK19-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK19: omp.loop.exit: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK19-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK19-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK19-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -15648,7 +15648,7 @@ int main (int argc, char **argv) { // CHECK19: omp.inner.for.end: // CHECK19-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK19: omp.loop.exit: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK19-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK19-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK19-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -15841,7 +15841,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK19-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK19: omp.dispatch.end: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK19-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK19-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK19-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/target_teams_generic_loop_codegen-1.cpp b/clang/test/OpenMP/target_teams_generic_loop_codegen-1.cpp index 26c9e4713f3e..190ea17e9607 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_codegen-1.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_codegen-1.cpp @@ -223,7 +223,7 @@ int target_teams_fun(int *g){ // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP23]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP23]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -280,7 +280,7 @@ int target_teams_fun(int *g){ // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK1-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]] @@ -437,7 +437,7 @@ int target_teams_fun(int *g){ // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -848,7 +848,7 @@ int target_teams_fun(int *g){ // CHECK2: omp.loop.exit: // CHECK2-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK2-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4 -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP23]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP23]]) // CHECK2-NEXT: br label [[OMP_PRECOND_END]] // CHECK2: omp.precond.end: // CHECK2-NEXT: ret void @@ -905,7 +905,7 @@ int target_teams_fun(int *g){ // CHECK2-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK2-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK2-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 -// CHECK2-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK2-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK2-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK2-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK2-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]] @@ -1062,7 +1062,7 @@ int target_teams_fun(int *g){ // CHECK2: omp.loop.exit: // CHECK2-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK2-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]]) // CHECK2-NEXT: br label [[OMP_PRECOND_END]] // CHECK2: omp.precond.end: // CHECK2-NEXT: ret void @@ -1471,7 +1471,7 @@ int target_teams_fun(int *g){ // CHECK4: omp.loop.exit: // CHECK4-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK4-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK4-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP21]]) +// CHECK4-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) // CHECK4-NEXT: br label [[OMP_PRECOND_END]] // CHECK4: omp.precond.end: // CHECK4-NEXT: ret void @@ -1526,7 +1526,7 @@ int target_teams_fun(int *g){ // CHECK4-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK4-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK4-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 -// CHECK4-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK4-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK4-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK4-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK4-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]] @@ -1680,7 +1680,7 @@ int target_teams_fun(int *g){ // CHECK4: omp.loop.exit: // CHECK4-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK4-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK4-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) +// CHECK4-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) // CHECK4-NEXT: br label [[OMP_PRECOND_END]] // CHECK4: omp.precond.end: // CHECK4-NEXT: ret void @@ -1900,7 +1900,7 @@ int target_teams_fun(int *g){ // CHECK10: omp.loop.exit: // CHECK10-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK10-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4 -// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP23]]) +// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP23]]) // CHECK10-NEXT: br label [[OMP_PRECOND_END]] // CHECK10: omp.precond.end: // CHECK10-NEXT: ret void @@ -1957,7 +1957,7 @@ int target_teams_fun(int *g){ // CHECK10-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK10-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK10-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 -// CHECK10-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK10-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK10-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK10-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK10-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]] @@ -2116,7 +2116,7 @@ int target_teams_fun(int *g){ // CHECK10: omp.loop.exit: // CHECK10-NEXT: [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK10-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 -// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]]) +// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]]) // CHECK10-NEXT: br label [[OMP_PRECOND_END]] // CHECK10: omp.precond.end: // CHECK10-NEXT: ret void @@ -2337,7 +2337,7 @@ int target_teams_fun(int *g){ // CHECK12: omp.loop.exit: // CHECK12-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK12-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK12-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP21]]) +// CHECK12-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) // CHECK12-NEXT: br label [[OMP_PRECOND_END]] // CHECK12: omp.precond.end: // CHECK12-NEXT: ret void @@ -2392,7 +2392,7 @@ int target_teams_fun(int *g){ // CHECK12-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK12-NEXT: [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK12-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4 -// CHECK12-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK12-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK12-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK12-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK12-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]] @@ -2548,7 +2548,7 @@ int target_teams_fun(int *g){ // CHECK12: omp.loop.exit: // CHECK12-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK12-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK12-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) +// CHECK12-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) // CHECK12-NEXT: br label [[OMP_PRECOND_END]] // CHECK12: omp.precond.end: // CHECK12-NEXT: ret void diff --git a/clang/test/OpenMP/target_teams_generic_loop_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_codegen.cpp index 3b1af7618794..22cf534bf0ba 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_codegen.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_codegen.cpp @@ -1312,7 +1312,7 @@ int foo() { // IR-GPU: omp.loop.exit: // IR-GPU-NEXT: [[TMP32:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR_ASCAST]], align 8 // IR-GPU-NEXT: [[TMP33:%.*]] = load i32, ptr [[TMP32]], align 4 -// IR-GPU-NEXT: call void @__kmpc_for_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB3:[0-9]+]] to ptr), i32 [[TMP33]]) +// IR-GPU-NEXT: call void @__kmpc_distribute_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB2]] to ptr), i32 [[TMP33]]) // IR-GPU-NEXT: [[TMP34:%.*]] = load i32, ptr [[DOTOMP_IS_LAST_ASCAST]], align 4 // IR-GPU-NEXT: [[TMP35:%.*]] = icmp ne i32 [[TMP34]], 0 // IR-GPU-NEXT: br i1 [[TMP35]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -1418,7 +1418,7 @@ int foo() { // IR-GPU: omp.arrayinit.done: // IR-GPU-NEXT: [[TMP4:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR_ASCAST]], align 8 // IR-GPU-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4 -// IR-GPU-NEXT: call void @__kmpc_for_static_init_4(ptr addrspacecast (ptr addrspace(1) @[[GLOB3]] to ptr), i32 [[TMP5]], i32 33, ptr [[DOTOMP_IS_LAST_ASCAST]], ptr [[DOTOMP_LB_ASCAST]], ptr [[DOTOMP_UB_ASCAST]], ptr [[DOTOMP_STRIDE_ASCAST]], i32 1, i32 1) +// IR-GPU-NEXT: call void @__kmpc_for_static_init_4(ptr addrspacecast (ptr addrspace(1) @[[GLOB3:[0-9]+]] to ptr), i32 [[TMP5]], i32 33, ptr [[DOTOMP_IS_LAST_ASCAST]], ptr [[DOTOMP_LB_ASCAST]], ptr [[DOTOMP_UB_ASCAST]], ptr [[DOTOMP_STRIDE_ASCAST]], i32 1, i32 1) // IR-GPU-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTOMP_LB_ASCAST]], align 4 // IR-GPU-NEXT: store i32 [[TMP6]], ptr [[DOTOMP_IV_ASCAST]], align 4 // IR-GPU-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] @@ -2001,7 +2001,7 @@ int foo() { // IR: omp.loop.exit: // IR-NEXT: [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // IR-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4 -// IR-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP18]]) +// IR-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP18]]) // IR-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // IR-NEXT: [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0 // IR-NEXT: br i1 [[TMP20]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -2109,7 +2109,7 @@ int foo() { // IR: omp.arrayinit.done: // IR-NEXT: [[TMP4:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // IR-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4 -// IR-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP5]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// IR-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP5]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // IR-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // IR-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP6]], 99 // IR-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -2398,7 +2398,7 @@ int foo() { // IR-PCH: omp.loop.exit: // IR-PCH-NEXT: [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // IR-PCH-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4 -// IR-PCH-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP18]]) +// IR-PCH-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP18]]) // IR-PCH-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // IR-PCH-NEXT: [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0 // IR-PCH-NEXT: br i1 [[TMP20]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -2506,7 +2506,7 @@ int foo() { // IR-PCH: omp.arrayinit.done: // IR-PCH-NEXT: [[TMP4:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // IR-PCH-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4 -// IR-PCH-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP5]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// IR-PCH-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP5]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // IR-PCH-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // IR-PCH-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP6]], 99 // IR-PCH-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] diff --git a/clang/test/OpenMP/target_teams_generic_loop_collapse_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_collapse_codegen.cpp index 6a30ef7f6eb8..82ad43373327 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_collapse_codegen.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_collapse_codegen.cpp @@ -239,7 +239,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK1-NEXT: ret void // // @@ -278,7 +278,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 56087 // CHECK1-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -473,7 +473,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK3-NEXT: ret void // // @@ -510,7 +510,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK3-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK3-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK3-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 56087 // CHECK3-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -846,7 +846,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP27:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP28:%.*]] = load i32, ptr [[TMP27]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP28]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP28]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -926,7 +926,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP13:%.*]] = load i32, ptr [[TMP12]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_init_8(ptr @[[GLOB2]], i32 [[TMP13]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1) +// CHECK9-NEXT: call void @__kmpc_for_static_init_8(ptr @[[GLOB2:[0-9]+]], i32 [[TMP13]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1) // CHECK9-NEXT: [[TMP14:%.*]] = load i64, ptr [[DOTOMP_UB]], align 8 // CHECK9-NEXT: [[TMP15:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_5]], align 8 // CHECK9-NEXT: [[CMP13:%.*]] = icmp sgt i64 [[TMP14]], [[TMP15]] @@ -1133,7 +1133,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK9-NEXT: ret void // // @@ -1510,7 +1510,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP30]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -1592,7 +1592,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP13:%.*]] = load i32, ptr [[TMP12]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_init_8(ptr @[[GLOB2]], i32 [[TMP13]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1) +// CHECK11-NEXT: call void @__kmpc_for_static_init_8(ptr @[[GLOB2:[0-9]+]], i32 [[TMP13]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1) // CHECK11-NEXT: [[TMP14:%.*]] = load i64, ptr [[DOTOMP_UB]], align 8 // CHECK11-NEXT: [[TMP15:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_5]], align 8 // CHECK11-NEXT: [[CMP15:%.*]] = icmp sgt i64 [[TMP14]], [[TMP15]] @@ -1795,7 +1795,7 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK11-NEXT: ret void // // diff --git a/clang/test/OpenMP/target_teams_generic_loop_if_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_if_codegen.cpp index c19323c35b4e..b2ff4c20db7a 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_if_codegen.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_if_codegen.cpp @@ -210,7 +210,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP1]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]]) // CHECK1-NEXT: ret void // // @@ -244,7 +244,7 @@ int main() { // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 99 // CHECK1-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -347,7 +347,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]]) // CHECK1-NEXT: ret void // // @@ -601,7 +601,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]]) // CHECK1-NEXT: ret void // // @@ -744,7 +744,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]]) // CHECK1-NEXT: ret void // // @@ -906,7 +906,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]]) // CHECK1-NEXT: ret void // // @@ -1132,7 +1132,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]]) // CHECK1-NEXT: ret void // // @@ -1275,7 +1275,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]]) // CHECK1-NEXT: ret void // // @@ -1413,7 +1413,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]]) // CHECK1-NEXT: ret void // // diff --git a/clang/test/OpenMP/target_teams_generic_loop_order_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_order_codegen.cpp index 195989692dc3..85f6a85a11bd 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_order_codegen.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_order_codegen.cpp @@ -125,7 +125,7 @@ void gtid_test() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP1]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]]) // CHECK1-NEXT: ret void // // @@ -159,7 +159,7 @@ void gtid_test() { // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 99 // CHECK1-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] diff --git a/clang/test/OpenMP/target_teams_generic_loop_private_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_private_codegen.cpp index 987c12adc6f6..7503b69b92aa 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_private_codegen.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_private_codegen.cpp @@ -420,7 +420,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP14]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP14]]) // CHECK1-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK1-NEXT: [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN2]], i64 2 @@ -481,7 +481,7 @@ int main() { // CHECK1-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) // CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1 // CHECK1-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -728,7 +728,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP14]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP14]]) // CHECK1-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK1-NEXT: [[ARRAY_BEGIN4:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN4]], i64 2 @@ -1151,7 +1151,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP12]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP12]]) // CHECK3-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK3-NEXT: [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 // CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN2]], i32 2 @@ -1210,7 +1210,7 @@ int main() { // CHECK3-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) // CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK3-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK3-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1 // CHECK3-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -1453,7 +1453,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP12]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP12]]) // CHECK3-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK3-NEXT: [[ARRAY_BEGIN4:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 // CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN4]], i32 2 @@ -1827,7 +1827,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP1]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]]) // CHECK5-NEXT: ret void // // @@ -1869,7 +1869,7 @@ int main() { // CHECK5-NEXT: store ptr [[G1]], ptr [[_TMP3]], align 8 // CHECK5-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK5-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 -// CHECK5-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK5-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK5-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK5-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1 // CHECK5-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -2015,7 +2015,7 @@ int main() { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP14]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP14]]) // CHECK13-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5:[0-9]+]] // CHECK13-NEXT: [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 // CHECK13-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN2]], i64 2 @@ -2086,7 +2086,7 @@ int main() { // CHECK13-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR4]] // CHECK13-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK13-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK13-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK13-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1 // CHECK13-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -2252,7 +2252,7 @@ int main() { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP14]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP14]]) // CHECK13-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5]] // CHECK13-NEXT: [[ARRAY_BEGIN4:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 // CHECK13-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN4]], i64 2 @@ -2527,7 +2527,7 @@ int main() { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP12]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP12]]) // CHECK15-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5:[0-9]+]] // CHECK15-NEXT: [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 // CHECK15-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN2]], i32 2 @@ -2596,7 +2596,7 @@ int main() { // CHECK15-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR4]] // CHECK15-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK15-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK15-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK15-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1 // CHECK15-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -2758,7 +2758,7 @@ int main() { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP12]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP12]]) // CHECK15-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5]] // CHECK15-NEXT: [[ARRAY_BEGIN4:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 // CHECK15-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN4]], i32 2 @@ -3018,7 +3018,7 @@ int main() { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP1]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]]) // CHECK17-NEXT: ret void // // @@ -3060,7 +3060,7 @@ int main() { // CHECK17-NEXT: store ptr [[G1]], ptr [[_TMP3]], align 8 // CHECK17-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK17-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 -// CHECK17-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK17-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK17-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK17-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1 // CHECK17-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] diff --git a/clang/test/OpenMP/target_teams_generic_loop_reduction_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_reduction_codegen.cpp index bfa00ee7a0f4..1036ffd195de 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_reduction_codegen.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_reduction_codegen.cpp @@ -316,7 +316,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 // CHECK1-NEXT: store ptr [[SIVAR2]], ptr [[TMP14]], align 8 // CHECK1-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l66.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -606,7 +606,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 // CHECK1-NEXT: store ptr [[T_VAR2]], ptr [[TMP14]], align 8 // CHECK1-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -891,7 +891,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[SIVAR1]], ptr [[TMP14]], align 4 // CHECK3-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l66.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -1177,7 +1177,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[T_VAR1]], ptr [[TMP14]], align 4 // CHECK3-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -1425,7 +1425,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: [[TMP15:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 // CHECK5-NEXT: store ptr [[SIVAR2]], ptr [[TMP15]], align 8 // CHECK5-NEXT: [[TMP16:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) diff --git a/clang/test/OpenMP/target_teams_generic_loop_uses_allocators_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_uses_allocators_codegen.cpp index f945dc9b21d4..0dc2c95641e2 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_uses_allocators_codegen.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_uses_allocators_codegen.cpp @@ -400,7 +400,7 @@ void foo() { // CHECK: omp.inner.for.end: // CHECK-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK: omp.loop.exit: -// CHECK-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3:[0-9]+]], i32 [[TMP1]]) +// CHECK-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]]) // CHECK-NEXT: ret void // // @@ -434,7 +434,7 @@ void foo() { // CHECK-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 -// CHECK-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB3]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB3:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 9 // CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp index 6dcfa4f6f2ab..a13b565cb38d 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp @@ -562,12 +562,12 @@ int main (int argc, char **argv) { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP24:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP25:%.*]] = load i32, ptr [[TMP24]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP25]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP25]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: cancel.exit: // CHECK1-NEXT: [[TMP26:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP27]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP27]]) // CHECK1-NEXT: br label [[CANCEL_CONT:%.*]] // CHECK1: omp.precond.end: // CHECK1-NEXT: br label [[CANCEL_CONT]] @@ -771,7 +771,7 @@ int main (int argc, char **argv) { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -1159,12 +1159,12 @@ int main (int argc, char **argv) { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP24:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP25:%.*]] = load i32, ptr [[TMP24]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP25]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP25]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: cancel.exit: // CHECK3-NEXT: [[TMP26:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP27]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP27]]) // CHECK3-NEXT: br label [[CANCEL_CONT:%.*]] // CHECK3: omp.precond.end: // CHECK3-NEXT: br label [[CANCEL_CONT]] @@ -1363,7 +1363,7 @@ int main (int argc, char **argv) { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: omp.precond.end: // CHECK3-NEXT: ret void @@ -1674,7 +1674,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -1980,7 +1980,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -2200,7 +2200,7 @@ int main (int argc, char **argv) { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK17-NEXT: ret void // // @@ -2413,7 +2413,7 @@ int main (int argc, char **argv) { // CHECK19: omp.inner.for.end: // CHECK19-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK19: omp.loop.exit: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK19-NEXT: ret void // // @@ -2730,7 +2730,7 @@ int main (int argc, char **argv) { // CHECK25: omp.loop.exit: // CHECK25-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK25-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK25-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK25-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK25-NEXT: br label [[OMP_PRECOND_END]] // CHECK25: omp.precond.end: // CHECK25-NEXT: ret void @@ -2973,7 +2973,7 @@ int main (int argc, char **argv) { // CHECK25: omp.inner.for.end: // CHECK25-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK25: omp.loop.exit: -// CHECK25-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK25-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK25-NEXT: ret void // // @@ -3285,7 +3285,7 @@ int main (int argc, char **argv) { // CHECK27: omp.loop.exit: // CHECK27-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK27-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK27-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK27-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK27-NEXT: br label [[OMP_PRECOND_END]] // CHECK27: omp.precond.end: // CHECK27-NEXT: ret void @@ -3523,6 +3523,6 @@ int main (int argc, char **argv) { // CHECK27: omp.inner.for.end: // CHECK27-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK27: omp.loop.exit: -// CHECK27-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK27-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK27-NEXT: ret void // diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp index 60c54f7bc0b4..64ee660b706c 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp @@ -334,7 +334,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -564,7 +564,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -991,7 +991,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -1215,7 +1215,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: ret void // // @@ -1643,7 +1643,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -1861,6 +1861,6 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: ret void // diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp index 3455597f9090..37d19f86a950 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp @@ -314,7 +314,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK1-NEXT: ret void // // @@ -537,7 +537,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK1-NEXT: ret void // // @@ -764,7 +764,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK3-NEXT: ret void // // @@ -982,7 +982,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK3-NEXT: ret void // // @@ -1168,7 +1168,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK9-NEXT: ret void // // diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp index f324d2c7ac90..eb3d2fc84568 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp @@ -451,7 +451,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -602,7 +602,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -773,7 +773,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -1080,7 +1080,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -1226,7 +1226,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -1392,7 +1392,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -1881,7 +1881,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -2092,7 +2092,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -2345,7 +2345,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -2656,7 +2656,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: ret void // // @@ -2806,7 +2806,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: ret void // // @@ -2994,7 +2994,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: ret void // // @@ -3480,7 +3480,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -3686,7 +3686,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -3934,7 +3934,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -4240,7 +4240,7 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: ret void // // @@ -4385,7 +4385,7 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: ret void // // @@ -4568,6 +4568,6 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: ret void // diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp index 24c3bc4adfef..904e6a1c1ce7 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp @@ -679,7 +679,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK1-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR2]] // CHECK1-NEXT: [[ARRAY_BEGIN12:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN12]], i64 2 @@ -1148,7 +1148,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK1-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]]) #[[ATTR2]] // CHECK1-NEXT: [[ARRAY_BEGIN13:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN13]], i64 2 @@ -1737,7 +1737,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK3-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR4]]) #[[ATTR2]] // CHECK3-NEXT: [[ARRAY_BEGIN10:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR2]], i32 0, i32 0 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN10]], i32 2 @@ -2200,7 +2200,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK3-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR2]] // CHECK3-NEXT: [[ARRAY_BEGIN11:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN11]], i32 2 @@ -2611,7 +2611,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: ret void // // diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp index 31367697db23..49ff6a5d08be 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp @@ -322,7 +322,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -465,7 +465,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -742,7 +742,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -885,7 +885,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -1052,7 +1052,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -1327,7 +1327,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -1470,7 +1470,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -1637,6 +1637,6 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp index 45197d5e296d..7b8df7367b82 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp @@ -411,7 +411,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]]) // CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK1-NEXT: br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -673,7 +673,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]]) // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK3-NEXT: br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -1115,7 +1115,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK9-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK9-NEXT: br i1 [[TMP24]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -1595,7 +1595,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK9-NEXT: br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -2095,7 +2095,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -2569,7 +2569,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK11-NEXT: br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp index c805d739cf9c..a7b1f6eb309e 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp @@ -371,7 +371,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // CHECK1: terminate.lpad: // CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -538,7 +538,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // CHECK1: terminate.lpad: // CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -887,7 +887,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // CHECK1: terminate.lpad: // CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -1034,7 +1034,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // CHECK1: terminate.lpad: // CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -1181,7 +1181,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // CHECK1: terminate.lpad: // CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -1350,7 +1350,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // CHECK1: terminate.lpad: // CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -1658,7 +1658,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: ret void // CHECK5: terminate.lpad: // CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -1825,7 +1825,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: ret void // CHECK5: terminate.lpad: // CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -2165,7 +2165,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: ret void // CHECK5: terminate.lpad: // CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -2312,7 +2312,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: ret void // CHECK5: terminate.lpad: // CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -2459,7 +2459,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: ret void // CHECK5: terminate.lpad: // CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } @@ -2628,7 +2628,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: ret void // CHECK5: terminate.lpad: // CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 } diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp index fe537dc743d4..dc430fc55787 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp @@ -496,7 +496,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]]) // CHECK1-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK1-NEXT: [[ARRAY_BEGIN7:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN7]], i64 2 @@ -804,7 +804,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK1-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK1-NEXT: [[ARRAY_BEGIN8:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN8]], i64 2 @@ -1223,7 +1223,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]]) // CHECK3-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK3-NEXT: [[ARRAY_BEGIN5:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN5]], i32 2 @@ -1525,7 +1525,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK3-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK3-NEXT: [[ARRAY_BEGIN6:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN6]], i32 2 @@ -1883,7 +1883,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: ret void // // diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp index cbd426aabb9c..386e772b7897 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp @@ -263,7 +263,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -401,7 +401,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // // @@ -580,6 +580,6 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: ret void // diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp index a003b9f203a4..7ac42579e91b 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp @@ -322,7 +322,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 // CHECK1-NEXT: store ptr [[SIVAR2]], ptr [[TMP14]], align 8 // CHECK1-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l68.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -615,7 +615,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 // CHECK1-NEXT: store ptr [[T_VAR2]], ptr [[TMP14]], align 8 // CHECK1-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -903,7 +903,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[SIVAR1]], ptr [[TMP14]], align 4 // CHECK3-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l68.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -1192,7 +1192,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[T_VAR1]], ptr [[TMP14]], align 4 // CHECK3-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -1439,7 +1439,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 // CHECK9-NEXT: store ptr [[SIVAR2]], ptr [[TMP15]], align 8 // CHECK9-NEXT: [[TMP16:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l45.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_reduction_task_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_reduction_task_codegen.cpp index b583fcad2d37..f58c848f4cae 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_reduction_task_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_reduction_task_codegen.cpp @@ -248,8 +248,8 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP72:%.*]] = load i32, ptr [[TMP71]], align 4 // CHECK1-NEXT: [[TMP73:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB4:[0-9]+]], i32 [[TMP72]], i32 2, i64 24, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l16.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) // CHECK1-NEXT: switch i32 [[TMP73]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [ -// CHECK1-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] -// CHECK1-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] +// CHECK1-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] +// CHECK1-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] // CHECK1-NEXT: ] // CHECK1: .omp.reduction.case1: // CHECK1-NEXT: [[TMP74:%.*]] = load i32, ptr [[TMP0]], align 4 @@ -597,7 +597,7 @@ int main(int argc, char **argv) { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP78:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP79:%.*]] = load i32, ptr [[TMP78]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP79]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP79]]) // CHECK1-NEXT: [[TMP80:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP81:%.*]] = load i32, ptr [[TMP80]], align 4 // CHECK1-NEXT: call void @__kmpc_task_reduction_modifier_fini(ptr @[[GLOB1]], i32 [[TMP81]], i32 1) @@ -612,8 +612,8 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP87:%.*]] = load i32, ptr [[TMP86]], align 4 // CHECK1-NEXT: [[TMP88:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB4]], i32 [[TMP87]], i32 2, i64 24, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l16.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) // CHECK1-NEXT: switch i32 [[TMP88]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [ -// CHECK1-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] -// CHECK1-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] +// CHECK1-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] +// CHECK1-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] // CHECK1-NEXT: ] // CHECK1: .omp.reduction.case1: // CHECK1-NEXT: [[TMP89:%.*]] = load i32, ptr [[TMP0]], align 4 @@ -805,21 +805,21 @@ int main(int argc, char **argv) { // CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]]) // CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META8:![0-9]+]]) // CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META10:![0-9]+]]) -// CHECK1-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !12 -// CHECK1-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !12 +// CHECK1-NEXT: store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META12:![0-9]+]] +// CHECK1-NEXT: store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META12]] // CHECK1-NEXT: call void [[TMP10]](ptr [[TMP11]], ptr [[DOTFIRSTPRIV_PTR_ADDR_I]]) #[[ATTR6]] -// CHECK1-NEXT: [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias !12 +// CHECK1-NEXT: [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias [[META12]] // CHECK1-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[TMP9]], i32 0, i32 1 // CHECK1-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8 // CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[TMP12]], align 8 -// CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !12 +// CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META12]] // CHECK1-NEXT: [[TMP17:%.*]] = call ptr @__kmpc_task_reduction_get_th_data(i32 [[TMP16]], ptr [[TMP15]], ptr [[TMP14]]) // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 // CHECK1-NEXT: [[TMP19:%.*]] = load ptr, ptr [[TMP18]], align 8 @@ -839,7 +839,7 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP30:%.*]] = sub i64 [[TMP28]], [[TMP29]] // CHECK1-NEXT: [[TMP31:%.*]] = add nuw i64 [[TMP30]], 1 // CHECK1-NEXT: [[TMP32:%.*]] = mul nuw i64 [[TMP31]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) -// CHECK1-NEXT: store i64 [[TMP31]], ptr @{{reduction_size[.].+[.]}}, align 8, !noalias !12 +// CHECK1-NEXT: store i64 [[TMP31]], ptr @{{reduction_size[.].+[.]}}, align 8, !noalias [[META12]] // CHECK1-NEXT: [[TMP33:%.*]] = load ptr, ptr [[TMP12]], align 8 // CHECK1-NEXT: [[TMP34:%.*]] = call ptr @__kmpc_task_reduction_get_th_data(i32 [[TMP16]], ptr [[TMP33]], ptr [[TMP20]]) // CHECK1-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 @@ -849,8 +849,8 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP39:%.*]] = ptrtoint ptr [[TMP20]] to i64 // CHECK1-NEXT: [[TMP40:%.*]] = sub i64 [[TMP38]], [[TMP39]] // CHECK1-NEXT: [[TMP41:%.*]] = getelementptr i8, ptr [[TMP34]], i64 [[TMP40]] -// CHECK1-NEXT: store ptr [[TMP4_I]], ptr [[TMP_I]], align 8, !noalias !12 -// CHECK1-NEXT: store ptr [[TMP41]], ptr [[TMP4_I]], align 8, !noalias !12 +// CHECK1-NEXT: store ptr [[TMP4_I]], ptr [[TMP_I]], align 8, !noalias [[META12]] +// CHECK1-NEXT: store ptr [[TMP41]], ptr [[TMP4_I]], align 8, !noalias [[META12]] // CHECK1-NEXT: ret i32 0 // // diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp index ab0e08259efe..7518179f4776 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp @@ -610,7 +610,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -761,7 +761,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -933,7 +933,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK1: omp.dispatch.end: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: ret void // // @@ -1632,7 +1632,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -1778,7 +1778,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -1943,7 +1943,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK3-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK3: omp.dispatch.end: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: ret void // // @@ -2637,7 +2637,7 @@ int main (int argc, char **argv) { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: ret void // // @@ -2788,7 +2788,7 @@ int main (int argc, char **argv) { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: ret void // // @@ -2960,7 +2960,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK5-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK5: omp.dispatch.end: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: ret void // // @@ -3659,7 +3659,7 @@ int main (int argc, char **argv) { // CHECK7: omp.inner.for.end: // CHECK7-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK7: omp.loop.exit: -// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK7-NEXT: ret void // // @@ -3805,7 +3805,7 @@ int main (int argc, char **argv) { // CHECK7: omp.inner.for.end: // CHECK7-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK7: omp.loop.exit: -// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK7-NEXT: ret void // // @@ -3970,7 +3970,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK7-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK7: omp.dispatch.end: -// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK7-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK7-NEXT: ret void // // @@ -4917,7 +4917,7 @@ int main (int argc, char **argv) { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK13-NEXT: br label [[OMP_PRECOND_END]] // CHECK13: omp.precond.end: // CHECK13-NEXT: ret void @@ -5128,7 +5128,7 @@ int main (int argc, char **argv) { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK13-NEXT: br label [[OMP_PRECOND_END]] // CHECK13: omp.precond.end: // CHECK13-NEXT: ret void @@ -5381,7 +5381,7 @@ int main (int argc, char **argv) { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK13-NEXT: br label [[OMP_PRECOND_END]] // CHECK13: omp.precond.end: // CHECK13-NEXT: ret void @@ -6226,7 +6226,7 @@ int main (int argc, char **argv) { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK13-NEXT: ret void // // @@ -6376,7 +6376,7 @@ int main (int argc, char **argv) { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK13-NEXT: ret void // // @@ -6565,7 +6565,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK13-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK13: omp.dispatch.end: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK13-NEXT: ret void // // @@ -7537,7 +7537,7 @@ int main (int argc, char **argv) { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK15-NEXT: br label [[OMP_PRECOND_END]] // CHECK15: omp.precond.end: // CHECK15-NEXT: ret void @@ -7743,7 +7743,7 @@ int main (int argc, char **argv) { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK15-NEXT: br label [[OMP_PRECOND_END]] // CHECK15: omp.precond.end: // CHECK15-NEXT: ret void @@ -7991,7 +7991,7 @@ int main (int argc, char **argv) { // CHECK15: omp.loop.exit: // CHECK15-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK15-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK15-NEXT: br label [[OMP_PRECOND_END]] // CHECK15: omp.precond.end: // CHECK15-NEXT: ret void @@ -8821,7 +8821,7 @@ int main (int argc, char **argv) { // CHECK15: omp.inner.for.end: // CHECK15-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK15: omp.loop.exit: -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK15-NEXT: ret void // // @@ -8966,7 +8966,7 @@ int main (int argc, char **argv) { // CHECK15: omp.inner.for.end: // CHECK15-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK15: omp.loop.exit: -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK15-NEXT: ret void // // @@ -9148,7 +9148,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK15-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK15: omp.dispatch.end: -// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK15-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK15-NEXT: ret void // // @@ -10111,7 +10111,7 @@ int main (int argc, char **argv) { // CHECK17: omp.loop.exit: // CHECK17-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK17-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK17-NEXT: br label [[OMP_PRECOND_END]] // CHECK17: omp.precond.end: // CHECK17-NEXT: ret void @@ -10322,7 +10322,7 @@ int main (int argc, char **argv) { // CHECK17: omp.loop.exit: // CHECK17-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK17-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK17-NEXT: br label [[OMP_PRECOND_END]] // CHECK17: omp.precond.end: // CHECK17-NEXT: ret void @@ -10575,7 +10575,7 @@ int main (int argc, char **argv) { // CHECK17: omp.loop.exit: // CHECK17-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK17-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK17-NEXT: br label [[OMP_PRECOND_END]] // CHECK17: omp.precond.end: // CHECK17-NEXT: ret void @@ -11420,7 +11420,7 @@ int main (int argc, char **argv) { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK17-NEXT: ret void // // @@ -11570,7 +11570,7 @@ int main (int argc, char **argv) { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK17-NEXT: ret void // // @@ -11759,7 +11759,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK17-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK17: omp.dispatch.end: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK17-NEXT: ret void // // @@ -12731,7 +12731,7 @@ int main (int argc, char **argv) { // CHECK19: omp.loop.exit: // CHECK19-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK19-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK19-NEXT: br label [[OMP_PRECOND_END]] // CHECK19: omp.precond.end: // CHECK19-NEXT: ret void @@ -12937,7 +12937,7 @@ int main (int argc, char **argv) { // CHECK19: omp.loop.exit: // CHECK19-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK19-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK19-NEXT: br label [[OMP_PRECOND_END]] // CHECK19: omp.precond.end: // CHECK19-NEXT: ret void @@ -13185,7 +13185,7 @@ int main (int argc, char **argv) { // CHECK19: omp.loop.exit: // CHECK19-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK19-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK19-NEXT: br label [[OMP_PRECOND_END]] // CHECK19: omp.precond.end: // CHECK19-NEXT: ret void @@ -14015,7 +14015,7 @@ int main (int argc, char **argv) { // CHECK19: omp.inner.for.end: // CHECK19-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK19: omp.loop.exit: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK19-NEXT: ret void // // @@ -14160,7 +14160,7 @@ int main (int argc, char **argv) { // CHECK19: omp.inner.for.end: // CHECK19-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK19: omp.loop.exit: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK19-NEXT: ret void // // @@ -14342,7 +14342,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK19-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK19: omp.dispatch.end: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK19-NEXT: ret void // // diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp index 96439c053ea8..854afe3b9bbc 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp @@ -583,7 +583,7 @@ int main (int argc, char **argv) { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK1-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -828,7 +828,7 @@ int main (int argc, char **argv) { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP24:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP25:%.*]] = load i32, ptr [[TMP24]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP25]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP25]]) // CHECK1-NEXT: [[TMP26:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = icmp ne i32 [[TMP26]], 0 // CHECK1-NEXT: br i1 [[TMP27]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1249,7 +1249,7 @@ int main (int argc, char **argv) { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK3-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1489,7 +1489,7 @@ int main (int argc, char **argv) { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP24:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP25:%.*]] = load i32, ptr [[TMP24]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP25]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP25]]) // CHECK3-NEXT: [[TMP26:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = icmp ne i32 [[TMP26]], 0 // CHECK3-NEXT: br i1 [[TMP27]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2126,7 +2126,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP26]]) // CHECK9-NEXT: [[TMP27:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP28:%.*]] = icmp ne i32 [[TMP27]], 0 // CHECK9-NEXT: br i1 [[TMP28]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2490,7 +2490,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP26]]) // CHECK11-NEXT: [[TMP27:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP28:%.*]] = icmp ne i32 [[TMP27]], 0 // CHECK11-NEXT: br i1 [[TMP28]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2929,7 +2929,7 @@ int main (int argc, char **argv) { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP6]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP6]]) // CHECK17-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP16:%.*]] = icmp ne i32 [[TMP15]], 0 // CHECK17-NEXT: br i1 [[TMP16]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3192,7 +3192,7 @@ int main (int argc, char **argv) { // CHECK19: omp.inner.for.end: // CHECK19-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK19: omp.loop.exit: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP6]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP6]]) // CHECK19-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK19-NEXT: [[TMP16:%.*]] = icmp ne i32 [[TMP15]], 0 // CHECK19-NEXT: br i1 [[TMP16]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3687,7 +3687,7 @@ int main (int argc, char **argv) { // CHECK25: omp.loop.exit: // CHECK25-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK25-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 -// CHECK25-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]]) +// CHECK25-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP26]]) // CHECK25-NEXT: [[TMP27:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK25-NEXT: [[TMP28:%.*]] = icmp ne i32 [[TMP27]], 0 // CHECK25-NEXT: br i1 [[TMP28]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3955,7 +3955,7 @@ int main (int argc, char **argv) { // CHECK25: omp.inner.for.end: // CHECK25-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK25: omp.loop.exit: -// CHECK25-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK25-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK25-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK25-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK25-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4314,7 +4314,7 @@ int main (int argc, char **argv) { // CHECK27: omp.loop.exit: // CHECK27-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK27-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 -// CHECK27-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]]) +// CHECK27-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP26]]) // CHECK27-NEXT: [[TMP27:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK27-NEXT: [[TMP28:%.*]] = icmp ne i32 [[TMP27]], 0 // CHECK27-NEXT: br i1 [[TMP28]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4577,7 +4577,7 @@ int main (int argc, char **argv) { // CHECK27: omp.inner.for.end: // CHECK27-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK27: omp.loop.exit: -// CHECK27-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK27-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]]) // CHECK27-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK27-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK27-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp index e68bd591519b..e7b9978dd43c 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp @@ -347,7 +347,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0 // CHECK1-NEXT: br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -593,7 +593,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0 // CHECK3-NEXT: br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1186,7 +1186,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK9-NEXT: [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0 // CHECK9-NEXT: br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1436,7 +1436,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0 // CHECK9-NEXT: br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1890,7 +1890,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]]) // CHECK11-NEXT: [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0 // CHECK11-NEXT: br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2134,7 +2134,7 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0 // CHECK11-NEXT: br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp index c2226bc9e75d..d3777e81047c 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp @@ -461,7 +461,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK1-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -626,7 +626,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK1-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -811,7 +811,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK1-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1132,7 +1132,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK3-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1292,7 +1292,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK3-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1472,7 +1472,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK3-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2227,7 +2227,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK9-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK9-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2462,7 +2462,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK9-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK9-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2739,7 +2739,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK9-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK9-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3069,7 +3069,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK9-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3233,7 +3233,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK9-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3435,7 +3435,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK9-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3940,7 +3940,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4170,7 +4170,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4442,7 +4442,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4767,7 +4767,7 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK11-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4926,7 +4926,7 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK11-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5123,7 +5123,7 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK11-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK11-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp index 4c9299e6cb9d..4f87d40e58f6 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp @@ -689,7 +689,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK1-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1172,7 +1172,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK1-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1775,7 +1775,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK3-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2252,7 +2252,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK3-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3323,7 +3323,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0 // CHECK9-NEXT: br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp index 275058b195e3..7c86b180ec67 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp @@ -326,7 +326,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -483,7 +483,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -774,7 +774,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -931,7 +931,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1112,7 +1112,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1401,7 +1401,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1558,7 +1558,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1739,7 +1739,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1966,7 +1966,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2123,7 +2123,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2414,7 +2414,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2571,7 +2571,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2855,7 +2855,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK3-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK3-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2982,7 +2982,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK3-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK3-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3271,7 +3271,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3428,7 +3428,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3609,7 +3609,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK3-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4427,7 +4427,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4584,7 +4584,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4875,7 +4875,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5032,7 +5032,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5213,7 +5213,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5502,7 +5502,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5659,7 +5659,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5840,7 +5840,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK9-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6067,7 +6067,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6224,7 +6224,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6515,7 +6515,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6672,7 +6672,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6956,7 +6956,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7083,7 +7083,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7372,7 +7372,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7529,7 +7529,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7710,7 +7710,7 @@ int main() { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK11-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp index fe2001842c26..268298c14801 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp @@ -427,7 +427,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]]) // CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK1-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -703,7 +703,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]]) // CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK3-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1195,7 +1195,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK9-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK9-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1689,7 +1689,7 @@ int main() { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK9-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2203,7 +2203,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2691,7 +2691,7 @@ int main() { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]]) // CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK11-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp index 49f57a000d3f..fa8bcf65b8fb 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp @@ -380,7 +380,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -561,7 +561,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -924,7 +924,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1085,7 +1085,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1246,7 +1246,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1429,7 +1429,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2100,7 +2100,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK5-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2281,7 +2281,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK5-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2635,7 +2635,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK5-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2796,7 +2796,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK5-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2957,7 +2957,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK5-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3140,7 +3140,7 @@ int main() { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK5-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK5-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp index 7721daf4aa32..03bee1dbb63c 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp @@ -505,7 +505,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]]) // CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0 // CHECK1-NEXT: br i1 [[TMP19]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -827,7 +827,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0 // CHECK1-NEXT: br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1260,7 +1260,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]]) // CHECK3-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0 // CHECK3-NEXT: br i1 [[TMP19]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1576,7 +1576,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]]) // CHECK3-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0 // CHECK3-NEXT: br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2700,7 +2700,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK9-NEXT: [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0 // CHECK9-NEXT: br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp index 2a3abf176929..7d35ea305f92 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp @@ -272,7 +272,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -424,7 +424,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -617,7 +617,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]]) // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0 // CHECK1-NEXT: br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp index 8745dd9710f6..2dd1db48f030 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp @@ -333,7 +333,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0 // CHECK1-NEXT: br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -640,7 +640,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0 // CHECK1-NEXT: br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -942,7 +942,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0 // CHECK3-NEXT: br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1245,7 +1245,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK3-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0 // CHECK3-NEXT: br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1704,7 +1704,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK9-NEXT: [[TMP15:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP16:%.*]] = icmp ne i32 [[TMP15]], 0 // CHECK9-NEXT: br i1 [[TMP16]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp index 0c0945a23d48..ff70e71e0126 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp @@ -627,7 +627,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK1-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -792,7 +792,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK1-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -978,7 +978,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK1: omp.dispatch.end: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK1-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK1-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1724,7 +1724,7 @@ int main (int argc, char **argv) { // CHECK2: omp.inner.for.end: // CHECK2-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK2: omp.loop.exit: -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK2-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK2-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK2-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -1889,7 +1889,7 @@ int main (int argc, char **argv) { // CHECK2: omp.inner.for.end: // CHECK2-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK2: omp.loop.exit: -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK2-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK2-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK2-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2075,7 +2075,7 @@ int main (int argc, char **argv) { // CHECK2-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK2-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK2: omp.dispatch.end: -// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK2-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK2-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK2-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK2-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2816,7 +2816,7 @@ int main (int argc, char **argv) { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK5-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -2976,7 +2976,7 @@ int main (int argc, char **argv) { // CHECK5: omp.inner.for.end: // CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK5: omp.loop.exit: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK5-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3155,7 +3155,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK5-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK5: omp.dispatch.end: -// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK5-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK5-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK5-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -3886,7 +3886,7 @@ int main (int argc, char **argv) { // CHECK6: omp.inner.for.end: // CHECK6-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK6: omp.loop.exit: -// CHECK6-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK6-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK6-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK6-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK6-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4046,7 +4046,7 @@ int main (int argc, char **argv) { // CHECK6: omp.inner.for.end: // CHECK6-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK6: omp.loop.exit: -// CHECK6-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK6-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK6-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK6-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK6-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -4225,7 +4225,7 @@ int main (int argc, char **argv) { // CHECK6-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK6-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK6: omp.dispatch.end: -// CHECK6-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK6-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK6-NEXT: [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK6-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0 // CHECK6-NEXT: br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5604,7 +5604,7 @@ int main (int argc, char **argv) { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK13-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK13-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -5839,7 +5839,7 @@ int main (int argc, char **argv) { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK13-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK13-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -6116,7 +6116,7 @@ int main (int argc, char **argv) { // CHECK13: omp.loop.exit: // CHECK13-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK13-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK13-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK13-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7028,7 +7028,7 @@ int main (int argc, char **argv) { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK13-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK13-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7192,7 +7192,7 @@ int main (int argc, char **argv) { // CHECK13: omp.inner.for.end: // CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK13: omp.loop.exit: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK13-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK13-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -7395,7 +7395,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK13-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK13: omp.dispatch.end: -// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK13-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK13-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK13-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -8415,7 +8415,7 @@ int main (int argc, char **argv) { // CHECK14: omp.loop.exit: // CHECK14-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK14-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK14-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK14-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK14-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK14-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK14-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -8650,7 +8650,7 @@ int main (int argc, char **argv) { // CHECK14: omp.loop.exit: // CHECK14-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK14-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK14-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK14-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK14-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK14-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK14-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -8927,7 +8927,7 @@ int main (int argc, char **argv) { // CHECK14: omp.loop.exit: // CHECK14-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK14-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK14-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK14-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK14-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK14-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK14-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -9839,7 +9839,7 @@ int main (int argc, char **argv) { // CHECK14: omp.inner.for.end: // CHECK14-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK14: omp.loop.exit: -// CHECK14-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK14-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK14-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK14-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK14-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -10003,7 +10003,7 @@ int main (int argc, char **argv) { // CHECK14: omp.inner.for.end: // CHECK14-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK14: omp.loop.exit: -// CHECK14-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK14-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK14-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK14-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK14-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -10206,7 +10206,7 @@ int main (int argc, char **argv) { // CHECK14-NEXT: store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4 // CHECK14-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK14: omp.dispatch.end: -// CHECK14-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK14-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK14-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK14-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK14-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -11225,7 +11225,7 @@ int main (int argc, char **argv) { // CHECK17: omp.loop.exit: // CHECK17-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK17-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK17-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK17-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -11455,7 +11455,7 @@ int main (int argc, char **argv) { // CHECK17: omp.loop.exit: // CHECK17-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK17-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK17-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK17-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -11727,7 +11727,7 @@ int main (int argc, char **argv) { // CHECK17: omp.loop.exit: // CHECK17-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK17-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK17-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK17-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -12624,7 +12624,7 @@ int main (int argc, char **argv) { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK17-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK17-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -12783,7 +12783,7 @@ int main (int argc, char **argv) { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK17-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK17-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -12979,7 +12979,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK17-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK17: omp.dispatch.end: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK17-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK17-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -13988,7 +13988,7 @@ int main (int argc, char **argv) { // CHECK19: omp.loop.exit: // CHECK19-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK19-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK19-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK19-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK19-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -14218,7 +14218,7 @@ int main (int argc, char **argv) { // CHECK19: omp.loop.exit: // CHECK19-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK19-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK19-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK19-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK19-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -14490,7 +14490,7 @@ int main (int argc, char **argv) { // CHECK19: omp.loop.exit: // CHECK19-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK19-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) // CHECK19-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK19-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0 // CHECK19-NEXT: br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -15387,7 +15387,7 @@ int main (int argc, char **argv) { // CHECK19: omp.inner.for.end: // CHECK19-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK19: omp.loop.exit: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK19-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK19-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK19-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -15546,7 +15546,7 @@ int main (int argc, char **argv) { // CHECK19: omp.inner.for.end: // CHECK19-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK19: omp.loop.exit: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]]) // CHECK19-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK19-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0 // CHECK19-NEXT: br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] @@ -15742,7 +15742,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4 // CHECK19-NEXT: br label [[OMP_DISPATCH_COND]] // CHECK19: omp.dispatch.end: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]]) // CHECK19-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK19-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0 // CHECK19-NEXT: br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]] diff --git a/clang/test/OpenMP/teams_generic_loop_codegen-1.cpp b/clang/test/OpenMP/teams_generic_loop_codegen-1.cpp index 041a28bd87e7..85a4dfea91a2 100644 --- a/clang/test/OpenMP/teams_generic_loop_codegen-1.cpp +++ b/clang/test/OpenMP/teams_generic_loop_codegen-1.cpp @@ -451,7 +451,7 @@ int main (int argc, char **argv) { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP22]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -509,7 +509,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP9]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP9]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK1-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK1-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[TMP10]], [[TMP11]] @@ -653,7 +653,7 @@ int main (int argc, char **argv) { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]]) // CHECK1-NEXT: br label [[OMP_PRECOND_END]] // CHECK1: omp.precond.end: // CHECK1-NEXT: ret void @@ -1036,7 +1036,7 @@ int main (int argc, char **argv) { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP20]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: omp.precond.end: // CHECK3-NEXT: ret void @@ -1092,7 +1092,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP9]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK3-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP9]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK3-NEXT: [[TMP10:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK3-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK3-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[TMP10]], [[TMP11]] @@ -1233,7 +1233,7 @@ int main (int argc, char **argv) { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]]) // CHECK3-NEXT: br label [[OMP_PRECOND_END]] // CHECK3: omp.precond.end: // CHECK3-NEXT: ret void @@ -1538,7 +1538,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP23]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP23]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -1599,7 +1599,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP9:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP10:%.*]] = load i32, ptr [[TMP9]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK9-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK9-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK9-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK9-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[TMP11]], [[TMP12]] @@ -1847,7 +1847,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP21]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -1906,7 +1906,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP9:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP10:%.*]] = load i32, ptr [[TMP9]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK11-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK11-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK11-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK11-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[TMP11]], [[TMP12]] @@ -2091,7 +2091,7 @@ int main (int argc, char **argv) { // CHECK17: omp.inner.for.end: // CHECK17-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK17: omp.loop.exit: -// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]]) +// CHECK17-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK17-NEXT: ret void // // @@ -2128,7 +2128,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK17-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK17-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 -// CHECK17-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK17-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK17-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK17-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 122 // CHECK17-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -2307,7 +2307,7 @@ int main (int argc, char **argv) { // CHECK19: omp.inner.for.end: // CHECK19-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK19: omp.loop.exit: -// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]]) +// CHECK19-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK19-NEXT: ret void // // @@ -2342,7 +2342,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK19-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK19-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 -// CHECK19-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK19-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK19-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK19-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 122 // CHECK19-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -2594,7 +2594,7 @@ int main (int argc, char **argv) { // CHECK25: omp.loop.exit: // CHECK25-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK25-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4 -// CHECK25-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP23]]) +// CHECK25-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP23]]) // CHECK25-NEXT: br label [[OMP_PRECOND_END]] // CHECK25: omp.precond.end: // CHECK25-NEXT: ret void @@ -2655,7 +2655,7 @@ int main (int argc, char **argv) { // CHECK25-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK25-NEXT: [[TMP9:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK25-NEXT: [[TMP10:%.*]] = load i32, ptr [[TMP9]], align 4 -// CHECK25-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK25-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK25-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK25-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK25-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[TMP11]], [[TMP12]] @@ -2865,7 +2865,7 @@ int main (int argc, char **argv) { // CHECK25: omp.inner.for.end: // CHECK25-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK25: omp.loop.exit: -// CHECK25-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]]) +// CHECK25-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK25-NEXT: ret void // // @@ -3152,7 +3152,7 @@ int main (int argc, char **argv) { // CHECK27: omp.loop.exit: // CHECK27-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK27-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4 -// CHECK27-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP21]]) +// CHECK27-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]]) // CHECK27-NEXT: br label [[OMP_PRECOND_END]] // CHECK27: omp.precond.end: // CHECK27-NEXT: ret void @@ -3211,7 +3211,7 @@ int main (int argc, char **argv) { // CHECK27-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK27-NEXT: [[TMP9:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK27-NEXT: [[TMP10:%.*]] = load i32, ptr [[TMP9]], align 4 -// CHECK27-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK27-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK27-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK27-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK27-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[TMP11]], [[TMP12]] @@ -3418,7 +3418,7 @@ int main (int argc, char **argv) { // CHECK27: omp.inner.for.end: // CHECK27-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK27: omp.loop.exit: -// CHECK27-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]]) +// CHECK27-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK27-NEXT: ret void // // diff --git a/clang/test/OpenMP/teams_generic_loop_codegen.cpp b/clang/test/OpenMP/teams_generic_loop_codegen.cpp index 2f3e70b1de58..2499fbb6811c 100644 --- a/clang/test/OpenMP/teams_generic_loop_codegen.cpp +++ b/clang/test/OpenMP/teams_generic_loop_codegen.cpp @@ -113,7 +113,7 @@ int foo() { // IR: omp.loop.exit: // IR-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // IR-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 -// IR-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP17]]) +// IR-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) // IR-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // IR-NEXT: [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0 // IR-NEXT: br i1 [[TMP19]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -129,8 +129,8 @@ int foo() { // IR-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4 // IR-NEXT: [[TMP24:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3:[0-9]+]], i32 [[TMP23]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_Z3foov.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) // IR-NEXT: switch i32 [[TMP24]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [ -// IR-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] -// IR-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] +// IR-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] +// IR-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] // IR-NEXT: ] // IR: .omp.reduction.case1: // IR-NEXT: [[TMP25:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100 @@ -221,7 +221,7 @@ int foo() { // IR: omp.arrayinit.done: // IR-NEXT: [[TMP5:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // IR-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 4 -// IR-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP6]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// IR-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP6]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // IR-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // IR-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP7]], 99 // IR-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -285,8 +285,8 @@ int foo() { // IR-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 // IR-NEXT: [[TMP25:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP24]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_Z3foov.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) // IR-NEXT: switch i32 [[TMP25]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [ -// IR-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] -// IR-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] +// IR-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] +// IR-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] // IR-NEXT: ] // IR: .omp.reduction.case1: // IR-NEXT: [[TMP26:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100 @@ -486,7 +486,7 @@ int foo() { // IR-PCH: omp.loop.exit: // IR-PCH-NEXT: [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // IR-PCH-NEXT: [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4 -// IR-PCH-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP17]]) +// IR-PCH-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]]) // IR-PCH-NEXT: [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4 // IR-PCH-NEXT: [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0 // IR-PCH-NEXT: br i1 [[TMP19]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]] @@ -502,8 +502,8 @@ int foo() { // IR-PCH-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4 // IR-PCH-NEXT: [[TMP24:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3:[0-9]+]], i32 [[TMP23]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_Z3foov.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) // IR-PCH-NEXT: switch i32 [[TMP24]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [ -// IR-PCH-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] -// IR-PCH-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] +// IR-PCH-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] +// IR-PCH-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] // IR-PCH-NEXT: ] // IR-PCH: .omp.reduction.case1: // IR-PCH-NEXT: [[TMP25:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100 @@ -594,7 +594,7 @@ int foo() { // IR-PCH: omp.arrayinit.done: // IR-PCH-NEXT: [[TMP5:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // IR-PCH-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 4 -// IR-PCH-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP6]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// IR-PCH-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP6]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // IR-PCH-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // IR-PCH-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP7]], 99 // IR-PCH-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -658,8 +658,8 @@ int foo() { // IR-PCH-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4 // IR-PCH-NEXT: [[TMP25:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP24]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_Z3foov.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) // IR-PCH-NEXT: switch i32 [[TMP25]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [ -// IR-PCH-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] -// IR-PCH-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] +// IR-PCH-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] +// IR-PCH-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] // IR-PCH-NEXT: ] // IR-PCH: .omp.reduction.case1: // IR-PCH-NEXT: [[TMP26:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100 diff --git a/clang/test/OpenMP/teams_generic_loop_collapse_codegen.cpp b/clang/test/OpenMP/teams_generic_loop_collapse_codegen.cpp index 4cf8f88b4c08..49df83c9c765 100644 --- a/clang/test/OpenMP/teams_generic_loop_collapse_codegen.cpp +++ b/clang/test/OpenMP/teams_generic_loop_collapse_codegen.cpp @@ -242,7 +242,7 @@ int main (int argc, char **argv) { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK1-NEXT: ret void // // @@ -281,7 +281,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 56087 // CHECK1-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -476,7 +476,7 @@ int main (int argc, char **argv) { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK3-NEXT: ret void // // @@ -513,7 +513,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK3-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK3-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK3-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 56087 // CHECK3-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -835,7 +835,7 @@ int main (int argc, char **argv) { // CHECK9: omp.loop.exit: // CHECK9-NEXT: [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP26]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]]) // CHECK9-NEXT: br label [[OMP_PRECOND_END]] // CHECK9: omp.precond.end: // CHECK9-NEXT: ret void @@ -917,7 +917,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK9-NEXT: [[TMP14:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP15:%.*]] = load i32, ptr [[TMP14]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_init_8(ptr @[[GLOB2]], i32 [[TMP15]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1) +// CHECK9-NEXT: call void @__kmpc_for_static_init_8(ptr @[[GLOB2:[0-9]+]], i32 [[TMP15]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1) // CHECK9-NEXT: [[TMP16:%.*]] = load i64, ptr [[DOTOMP_UB]], align 8 // CHECK9-NEXT: [[TMP17:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_5]], align 8 // CHECK9-NEXT: [[CMP13:%.*]] = icmp sgt i64 [[TMP16]], [[TMP17]] @@ -1124,7 +1124,7 @@ int main (int argc, char **argv) { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK9-NEXT: ret void // // @@ -1487,7 +1487,7 @@ int main (int argc, char **argv) { // CHECK11: omp.loop.exit: // CHECK11-NEXT: [[TMP27:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP28:%.*]] = load i32, ptr [[TMP27]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP28]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP28]]) // CHECK11-NEXT: br label [[OMP_PRECOND_END]] // CHECK11: omp.precond.end: // CHECK11-NEXT: ret void @@ -1571,7 +1571,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: store i32 0, ptr [[DOTOMP_IS_LAST]], align 4 // CHECK11-NEXT: [[TMP14:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK11-NEXT: [[TMP15:%.*]] = load i32, ptr [[TMP14]], align 4 -// CHECK11-NEXT: call void @__kmpc_for_static_init_8(ptr @[[GLOB2]], i32 [[TMP15]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1) +// CHECK11-NEXT: call void @__kmpc_for_static_init_8(ptr @[[GLOB2:[0-9]+]], i32 [[TMP15]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1) // CHECK11-NEXT: [[TMP16:%.*]] = load i64, ptr [[DOTOMP_UB]], align 8 // CHECK11-NEXT: [[TMP17:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_5]], align 8 // CHECK11-NEXT: [[CMP15:%.*]] = icmp sgt i64 [[TMP16]], [[TMP17]] @@ -1774,7 +1774,7 @@ int main (int argc, char **argv) { // CHECK11: omp.inner.for.end: // CHECK11-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK11: omp.loop.exit: -// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]]) +// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK11-NEXT: ret void // // diff --git a/clang/test/OpenMP/teams_generic_loop_private_codegen.cpp b/clang/test/OpenMP/teams_generic_loop_private_codegen.cpp index ab5cbdf1b8c9..5ef729f044e0 100644 --- a/clang/test/OpenMP/teams_generic_loop_private_codegen.cpp +++ b/clang/test/OpenMP/teams_generic_loop_private_codegen.cpp @@ -382,7 +382,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP14]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP14]]) // CHECK1-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK1-NEXT: [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN2]], i64 2 @@ -443,7 +443,7 @@ int main() { // CHECK1-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) // CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1 // CHECK1-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -690,7 +690,7 @@ int main() { // CHECK1: omp.loop.exit: // CHECK1-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP14]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP14]]) // CHECK1-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK1-NEXT: [[ARRAY_BEGIN4:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN4]], i64 2 @@ -1113,7 +1113,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP12]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP12]]) // CHECK3-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK3-NEXT: [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0 // CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN2]], i32 2 @@ -1172,7 +1172,7 @@ int main() { // CHECK3-NEXT: call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) // CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK3-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK3-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1 // CHECK3-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -1415,7 +1415,7 @@ int main() { // CHECK3: omp.loop.exit: // CHECK3-NEXT: [[TMP11:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP12]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP12]]) // CHECK3-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]] // CHECK3-NEXT: [[ARRAY_BEGIN4:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0 // CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN4]], i32 2 @@ -1793,7 +1793,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP1]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]]) // CHECK9-NEXT: ret void // // @@ -1835,7 +1835,7 @@ int main() { // CHECK9-NEXT: store ptr [[G1]], ptr [[_TMP3]], align 8 // CHECK9-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK9-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK9-NEXT: [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK9-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1 // CHECK9-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] diff --git a/clang/test/OpenMP/teams_generic_loop_reduction_codegen.cpp b/clang/test/OpenMP/teams_generic_loop_reduction_codegen.cpp index f91ee759cddf..4da49eed32ef 100644 --- a/clang/test/OpenMP/teams_generic_loop_reduction_codegen.cpp +++ b/clang/test/OpenMP/teams_generic_loop_reduction_codegen.cpp @@ -223,7 +223,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 // CHECK1-NEXT: store ptr [[SIVAR1]], ptr [[TMP14]], align 8 // CHECK1-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3:[0-9]+]], i32 [[TMP2]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l68.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -282,7 +282,7 @@ int main() { // CHECK1-NEXT: store i32 0, ptr [[SIVAR2]], align 4 // CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK1-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 -// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK1-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK1-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 1 // CHECK1-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -516,7 +516,7 @@ int main() { // CHECK1: omp.inner.for.end: // CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK1: omp.loop.exit: -// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]]) +// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 // CHECK1-NEXT: store ptr [[T_VAR1]], ptr [[TMP14]], align 8 // CHECK1-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP2]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -806,7 +806,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[SIVAR1]], ptr [[TMP12]], align 4 // CHECK3-NEXT: [[TMP13:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3:[0-9]+]], i32 [[TMP2]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l68.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -863,7 +863,7 @@ int main() { // CHECK3-NEXT: store i32 0, ptr [[SIVAR1]], align 4 // CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4 // CHECK3-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 -// CHECK3-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK3-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK3-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK3-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 1 // CHECK3-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -1095,7 +1095,7 @@ int main() { // CHECK3: omp.inner.for.end: // CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK3: omp.loop.exit: -// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]]) +// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0 // CHECK3-NEXT: store ptr [[T_VAR1]], ptr [[TMP12]], align 4 // CHECK3-NEXT: [[TMP13:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP2]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -1336,7 +1336,7 @@ int main() { // CHECK9: omp.inner.for.end: // CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]] // CHECK9: omp.loop.exit: -// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]]) +// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]]) // CHECK9-NEXT: [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0 // CHECK9-NEXT: store ptr [[SIVAR1]], ptr [[TMP14]], align 8 // CHECK9-NEXT: [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3:[0-9]+]], i32 [[TMP2]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l45.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var) @@ -1396,7 +1396,7 @@ int main() { // CHECK9-NEXT: store i32 0, ptr [[SIVAR2]], align 4 // CHECK9-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8 // CHECK9-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4 -// CHECK9-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) +// CHECK9-NEXT: call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1) // CHECK9-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4 // CHECK9-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 1 // CHECK9-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] -- GitLab From ffe41819e58365dfbe85a22556c0d9d284e746b9 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Tue, 12 Mar 2024 12:10:30 +0000 Subject: [PATCH 233/953] [Support] Add KnownBits::abds signed absolute difference and rename absdiff -> abdu (#84897) When I created KnownBits::absdiff, I totally missed that we already have ISD::ABDS/ABDU nodes, and we use this term in other places/targets as well. I've added the KnownBits::abds implementation and renamed KnownBits::absdiff to KnownBits::abdu. Followup to #84791 --- llvm/include/llvm/Support/KnownBits.h | 7 ++-- llvm/lib/Support/KnownBits.cpp | 23 +++++++++++-- llvm/lib/Target/X86/X86ISelLowering.cpp | 2 +- llvm/unittests/Support/KnownBitsTest.cpp | 44 ++++++++++++++++++++---- 4 files changed, 65 insertions(+), 11 deletions(-) diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h index 06d2c90f7b0f..73cb01e0644a 100644 --- a/llvm/include/llvm/Support/KnownBits.h +++ b/llvm/include/llvm/Support/KnownBits.h @@ -390,8 +390,11 @@ public: /// Compute known bits for smin(LHS, RHS). static KnownBits smin(const KnownBits &LHS, const KnownBits &RHS); - /// Compute known bits for absdiff(LHS, RHS). - static KnownBits absdiff(const KnownBits &LHS, const KnownBits &RHS); + /// Compute known bits for abdu(LHS, RHS). + static KnownBits abdu(const KnownBits &LHS, const KnownBits &RHS); + + /// Compute known bits for abds(LHS, RHS). + static KnownBits abds(const KnownBits &LHS, const KnownBits &RHS); /// Compute known bits for shl(LHS, RHS). /// NOTE: RHS (shift amount) bitwidth doesn't need to be the same as LHS. diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp index c33c3680825a..d72355dab6f1 100644 --- a/llvm/lib/Support/KnownBits.cpp +++ b/llvm/lib/Support/KnownBits.cpp @@ -231,8 +231,8 @@ KnownBits KnownBits::smin(const KnownBits &LHS, const KnownBits &RHS) { return Flip(umax(Flip(LHS), Flip(RHS))); } -KnownBits KnownBits::absdiff(const KnownBits &LHS, const KnownBits &RHS) { - // absdiff(LHS,RHS) = sub(umax(LHS,RHS), umin(LHS,RHS)). +KnownBits KnownBits::abdu(const KnownBits &LHS, const KnownBits &RHS) { + // abdu(LHS,RHS) = sub(umax(LHS,RHS), umin(LHS,RHS)). KnownBits UMaxValue = umax(LHS, RHS); KnownBits UMinValue = umin(LHS, RHS); KnownBits MinMaxDiff = computeForAddSub(/*Add=*/false, /*NSW=*/false, @@ -250,6 +250,25 @@ KnownBits KnownBits::absdiff(const KnownBits &LHS, const KnownBits &RHS) { return KnownAbsDiff; } +KnownBits KnownBits::abds(const KnownBits &LHS, const KnownBits &RHS) { + // abds(LHS,RHS) = sub(smax(LHS,RHS), smin(LHS,RHS)). + KnownBits SMaxValue = smax(LHS, RHS); + KnownBits SMinValue = smin(LHS, RHS); + KnownBits MinMaxDiff = computeForAddSub(/*Add=*/false, /*NSW=*/false, + /*NUW=*/false, SMaxValue, SMinValue); + + // find the common bits between sub(LHS,RHS) and sub(RHS,LHS). + KnownBits Diff0 = + computeForAddSub(/*Add=*/false, /*NSW=*/false, /*NUW=*/false, LHS, RHS); + KnownBits Diff1 = + computeForAddSub(/*Add=*/false, /*NSW=*/false, /*NUW=*/false, RHS, LHS); + KnownBits SubDiff = Diff0.intersectWith(Diff1); + + KnownBits KnownAbsDiff = MinMaxDiff.unionWith(SubDiff); + assert(!KnownAbsDiff.hasConflict() && "Bad Output"); + return KnownAbsDiff; +} + static unsigned getMaxShiftAmount(const APInt &MaxValue, unsigned BitWidth) { if (isPowerOf2_32(BitWidth)) return MaxValue.extractBitsAsZExtValue(Log2_32(BitWidth), 0); diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index a74901958ac0..b4d0421c14c0 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -36753,7 +36753,7 @@ static void computeKnownBitsForPSADBW(SDValue LHS, SDValue RHS, APInt DemandedSrcElts = APIntOps::ScaleBitMask(DemandedElts, NumSrcElts); Known = DAG.computeKnownBits(RHS, DemandedSrcElts, Depth + 1); Known2 = DAG.computeKnownBits(LHS, DemandedSrcElts, Depth + 1); - Known = KnownBits::absdiff(Known, Known2).zext(16); + Known = KnownBits::abdu(Known, Known2).zext(16); // Known = (((D0 + D1) + (D2 + D3)) + ((D4 + D5) + (D6 + D7))) Known = KnownBits::computeForAddSub(/*Add=*/true, /*NSW=*/true, /*NUW=*/true, Known, Known); diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index 2ac25f0b2801..d3177ce7e983 100644 --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -294,18 +294,18 @@ TEST(KnownBitsTest, SignBitUnknown) { EXPECT_TRUE(Known.isSignUnknown()); } -TEST(KnownBitsTest, AbsDiffSpecialCase) { - // There are 2 implementation of absdiff - both are currently needed to cover +TEST(KnownBitsTest, ABDUSpecialCase) { + // There are 2 implementations of abdu - both are currently needed to cover // extra cases. KnownBits LHS, RHS, Res; - // absdiff(LHS,RHS) = sub(umax(LHS,RHS), umin(LHS,RHS)). + // abdu(LHS,RHS) = sub(umax(LHS,RHS), umin(LHS,RHS)). // Actual: false (Inputs = 1011, 101?, Computed = 000?, Exact = 000?) LHS.One = APInt(4, 0b1011); RHS.One = APInt(4, 0b1010); LHS.Zero = APInt(4, 0b0100); RHS.Zero = APInt(4, 0b0100); - Res = KnownBits::absdiff(LHS, RHS); + Res = KnownBits::abdu(LHS, RHS); EXPECT_EQ(0b0000ul, Res.One.getZExtValue()); EXPECT_EQ(0b1110ul, Res.Zero.getZExtValue()); @@ -315,11 +315,37 @@ TEST(KnownBitsTest, AbsDiffSpecialCase) { RHS.One = APInt(4, 0b1000); LHS.Zero = APInt(4, 0b0000); RHS.Zero = APInt(4, 0b0111); - Res = KnownBits::absdiff(LHS, RHS); + Res = KnownBits::abdu(LHS, RHS); EXPECT_EQ(0b0001ul, Res.One.getZExtValue()); EXPECT_EQ(0b0000ul, Res.Zero.getZExtValue()); } +TEST(KnownBitsTest, ABDSSpecialCase) { + // There are 2 implementations of abds - both are currently needed to cover + // extra cases. + KnownBits LHS, RHS, Res; + + // abds(LHS,RHS) = sub(smax(LHS,RHS), smin(LHS,RHS)). + // Actual: false (Inputs = 1011, 10??, Computed = ????, Exact = 00??) + LHS.One = APInt(4, 0b1011); + RHS.One = APInt(4, 0b1000); + LHS.Zero = APInt(4, 0b0100); + RHS.Zero = APInt(4, 0b0100); + Res = KnownBits::abds(LHS, RHS); + EXPECT_EQ(0, Res.One.getSExtValue()); + EXPECT_EQ(-4, Res.Zero.getSExtValue()); + + // find the common bits between sub(LHS,RHS) and sub(RHS,LHS). + // Actual: false (Inputs = ???1, 1000, Computed = ???1, Exact = 0??1) + LHS.One = APInt(4, 0b0001); + RHS.One = APInt(4, 0b1000); + LHS.Zero = APInt(4, 0b0000); + RHS.Zero = APInt(4, 0b0111); + Res = KnownBits::abds(LHS, RHS); + EXPECT_EQ(1, Res.One.getSExtValue()); + EXPECT_EQ(0, Res.Zero.getSExtValue()); +} + TEST(KnownBitsTest, BinaryExhaustive) { testBinaryOpExhaustive( [](const KnownBits &Known1, const KnownBits &Known2) { @@ -359,10 +385,16 @@ TEST(KnownBitsTest, BinaryExhaustive) { [](const APInt &N1, const APInt &N2) { return APIntOps::smin(N1, N2); }); testBinaryOpExhaustive( [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::absdiff(Known1, Known2); + return KnownBits::abdu(Known1, Known2); }, [](const APInt &N1, const APInt &N2) { return APIntOps::abdu(N1, N2); }, checkCorrectnessOnlyBinary); + testBinaryOpExhaustive( + [](const KnownBits &Known1, const KnownBits &Known2) { + return KnownBits::abds(Known1, Known2); + }, + [](const APInt &N1, const APInt &N2) { return APIntOps::abds(N1, N2); }, + checkCorrectnessOnlyBinary); testBinaryOpExhaustive( [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::udiv(Known1, Known2); -- GitLab From b5a16b6d8ad51df7c14cd696f3dc1f98b6984905 Mon Sep 17 00:00:00 2001 From: Sirraide Date: Tue, 12 Mar 2024 13:42:43 +0100 Subject: [PATCH 234/953] [Clang] [Parser] Support [[omp::assume]] (#84582) This pr implements the `[[omp::assume]]` spelling for the `__attribute__((assume))` attribute. It does not change anything about how that attribute is handled by the rest of Clang. --- clang/docs/ReleaseNotes.rst | 5 +++++ clang/include/clang/Basic/Attr.td | 2 +- clang/lib/Basic/Attributes.cpp | 8 ++++++-- clang/lib/Parse/ParseDeclCXX.cpp | 4 +++- clang/test/OpenMP/attr-assume.cpp | 13 +++++++++++++ 5 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 clang/test/OpenMP/attr-assume.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 4a08b78d78b6..6c30af304d98 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -500,6 +500,11 @@ Python Binding Changes - Exposed `CXRewriter` API as `class Rewriter`. +OpenMP Support +-------------- + +- Added support for the `[[omp::assume]]` attribute. + Additional Information ====================== diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index fd7970d0451a..080340669b60 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4159,7 +4159,7 @@ def OMPDeclareVariant : InheritableAttr { } def OMPAssume : InheritableAttr { - let Spellings = [Clang<"assume">]; + let Spellings = [Clang<"assume">, CXX11<"omp", "assume">]; let Subjects = SubjectList<[Function, ObjCMethod]>; let InheritEvenIfAlreadyPresent = 1; let Documentation = [OMPAssumeDocs]; diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp index 44a4f1890d39..867d241a2cf8 100644 --- a/clang/lib/Basic/Attributes.cpp +++ b/clang/lib/Basic/Attributes.cpp @@ -47,8 +47,12 @@ int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax, // attributes. We support those, but not through the typical attribute // machinery that goes through TableGen. We support this in all OpenMP modes // so long as double square brackets are enabled. - if (LangOpts.OpenMP && ScopeName == "omp") - return (Name == "directive" || Name == "sequence") ? 1 : 0; + // + // Other OpenMP attributes (e.g. [[omp::assume]]) are handled via the + // regular attribute parsing machinery. + if (LangOpts.OpenMP && ScopeName == "omp" && + (Name == "directive" || Name == "sequence")) + return 1; int res = hasAttributeImpl(Syntax, Name, ScopeName, Target, LangOpts); if (res) diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index bdca10c4c7c0..77d2382ea6d9 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -4634,7 +4634,9 @@ bool Parser::ParseCXX11AttributeArgs( return true; } - if (ScopeName && ScopeName->isStr("omp")) { + // [[omp::directive]] and [[omp::sequence]] need special handling. + if (ScopeName && ScopeName->isStr("omp") && + (AttrName->isStr("directive") || AttrName->isStr("sequence"))) { Diag(AttrNameLoc, getLangOpts().OpenMP >= 51 ? diag::warn_omp51_compat_attributes : diag::ext_omp_attributes); diff --git a/clang/test/OpenMP/attr-assume.cpp b/clang/test/OpenMP/attr-assume.cpp new file mode 100644 index 000000000000..09c22f98d1e2 --- /dev/null +++ b/clang/test/OpenMP/attr-assume.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s +[[omp::assume(3)]] void f1(); // expected-error {{expected string literal as argument of 'assume' attribute}} +[[omp::assume(int)]] void f2(); // expected-error {{expected string literal as argument of 'assume' attribute}} +[[omp::assume(for)]] void f3(); // expected-error {{expected string literal as argument of 'assume' attribute}} +[[omp::assume("QQQQ")]] void f4(); // expected-warning {{unknown assumption string 'QQQQ'; attribute is potentially ignored}} +[[omp::assume("omp_no_openmp")]] void f5(); +[[omp::assume("omp_noopenmp")]] void f6(); // expected-warning {{unknown assumption string 'omp_noopenmp' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp'?}} +[[omp::assume("omp_no_openmp_routine")]] void f7(); // expected-warning {{unknown assumption string 'omp_no_openmp_routine' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp_routines'?}} +[[omp::assume("omp_no_openmp1")]] void f8(); // expected-warning {{unknown assumption string 'omp_no_openmp1' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp'?}} +[[omp::assume("omp_no_openmp", "omp_no_openmp")]] void f9(); // expected-error {{'assume' attribute takes one argument}} + +[[omp::assume(3)]] int g1; // expected-error {{expected string literal as argument of 'assume' attribute}} +[[omp::assume("omp_no_openmp")]] int g2; // expected-warning {{'assume' attribute only applies to functions and Objective-C methods}} -- GitLab From 80ab8234ac309418637488b97e0a62d8377b2ecf Mon Sep 17 00:00:00 2001 From: NagyDonat Date: Tue, 12 Mar 2024 13:51:12 +0100 Subject: [PATCH 235/953] [analyzer] Accept C library functions from the `std` namespace (#84469) Previously, the function `isCLibraryFunction()` and logic relying on it only accepted functions that are declared directly within a TU (i.e. not in a namespace or a class). However C++ headers like declare many C standard library functions within the namespace `std`, so this commit ensures that functions within the namespace `std` are also accepted. After this commit it will be possible to match functions like `malloc` or `free` with `CallDescription::Mode::CLibrary`. --------- Co-authored-by: Balazs Benics --- .../Core/PathSensitive/CallDescription.h | 8 +- .../StaticAnalyzer/Core/CheckerContext.cpp | 8 +- clang/unittests/StaticAnalyzer/CMakeLists.txt | 1 + .../StaticAnalyzer/IsCLibraryFunctionTest.cpp | 89 +++++++++++++++++++ .../clang/unittests/StaticAnalyzer/BUILD.gn | 1 + 5 files changed, 98 insertions(+), 9 deletions(-) create mode 100644 clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h index 3432d2648633..b4e1636130ca 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h @@ -41,12 +41,8 @@ public: /// - We also accept calls where the number of arguments or parameters is /// greater than the specified value. /// For the exact heuristics, see CheckerContext::isCLibraryFunction(). - /// Note that functions whose declaration context is not a TU (e.g. - /// methods, functions in namespaces) are not accepted as C library - /// functions. - /// FIXME: If I understand it correctly, this discards calls where C++ code - /// refers a C library function through the namespace `std::` via headers - /// like . + /// (This mode only matches functions that are declared either directly + /// within a TU or in the namespace `std`.) CLibrary, /// Matches "simple" functions that are not methods. (Static methods are diff --git a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp index d6d4cec9dd3d..1a9bff529e9b 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp @@ -87,9 +87,11 @@ bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD, if (!II) return false; - // Look through 'extern "C"' and anything similar invented in the future. - // If this function is not in TU directly, it is not a C library function. - if (!FD->getDeclContext()->getRedeclContext()->isTranslationUnit()) + // C library functions are either declared directly within a TU (the common + // case) or they are accessed through the namespace `std` (when they are used + // in C++ via headers like ). + const DeclContext *DC = FD->getDeclContext()->getRedeclContext(); + if (!(DC->isTranslationUnit() || DC->isStdNamespace())) return false; // If this function is not externally visible, it is not a C library function. diff --git a/clang/unittests/StaticAnalyzer/CMakeLists.txt b/clang/unittests/StaticAnalyzer/CMakeLists.txt index 775f0f8486b8..db56e77331b8 100644 --- a/clang/unittests/StaticAnalyzer/CMakeLists.txt +++ b/clang/unittests/StaticAnalyzer/CMakeLists.txt @@ -11,6 +11,7 @@ add_clang_unittest(StaticAnalysisTests CallEventTest.cpp ConflictingEvalCallsTest.cpp FalsePositiveRefutationBRVisitorTest.cpp + IsCLibraryFunctionTest.cpp NoStateChangeFuncVisitorTest.cpp ParamRegionTest.cpp RangeSetTest.cpp diff --git a/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp b/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp new file mode 100644 index 000000000000..19c66cc6bee1 --- /dev/null +++ b/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp @@ -0,0 +1,89 @@ +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Frontend/ASTUnit.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/Tooling/Tooling.h" +#include "gtest/gtest.h" + +#include + +using namespace clang; +using namespace ento; +using namespace ast_matchers; + +testing::AssertionResult extractFunctionDecl(StringRef Code, + const FunctionDecl *&Result) { + auto ASTUnit = tooling::buildASTFromCode(Code); + if (!ASTUnit) + return testing::AssertionFailure() << "AST construction failed"; + + ASTContext &Context = ASTUnit->getASTContext(); + if (Context.getDiagnostics().hasErrorOccurred()) + return testing::AssertionFailure() << "Compilation error"; + + auto Matches = ast_matchers::match(functionDecl().bind("fn"), Context); + if (Matches.empty()) + return testing::AssertionFailure() << "No function declaration found"; + + if (Matches.size() > 1) + return testing::AssertionFailure() + << "Multiple function declarations found"; + + Result = Matches[0].getNodeAs("fn"); + return testing::AssertionSuccess(); +} + +TEST(IsCLibraryFunctionTest, AcceptsGlobal) { + const FunctionDecl *Result; + ASSERT_TRUE(extractFunctionDecl(R"cpp(void fun();)cpp", Result)); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(Result)); +} + +TEST(IsCLibraryFunctionTest, AcceptsExternCGlobal) { + const FunctionDecl *Result; + ASSERT_TRUE( + extractFunctionDecl(R"cpp(extern "C" { void fun(); })cpp", Result)); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(Result)); +} + +TEST(IsCLibraryFunctionTest, RejectsNoInlineNoExternalLinkage) { + // Functions that are neither inlined nor externally visible cannot be C library functions. + const FunctionDecl *Result; + ASSERT_TRUE(extractFunctionDecl(R"cpp(static void fun();)cpp", Result)); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); +} + +TEST(IsCLibraryFunctionTest, RejectsAnonymousNamespace) { + const FunctionDecl *Result; + ASSERT_TRUE( + extractFunctionDecl(R"cpp(namespace { void fun(); })cpp", Result)); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); +} + +TEST(IsCLibraryFunctionTest, AcceptsStdNamespace) { + const FunctionDecl *Result; + ASSERT_TRUE( + extractFunctionDecl(R"cpp(namespace std { void fun(); })cpp", Result)); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(Result)); +} + +TEST(IsCLibraryFunctionTest, RejectsOtherNamespaces) { + const FunctionDecl *Result; + ASSERT_TRUE( + extractFunctionDecl(R"cpp(namespace stdx { void fun(); })cpp", Result)); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); +} + +TEST(IsCLibraryFunctionTest, RejectsClassStatic) { + const FunctionDecl *Result; + ASSERT_TRUE( + extractFunctionDecl(R"cpp(class A { static void fun(); };)cpp", Result)); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); +} + +TEST(IsCLibraryFunctionTest, RejectsClassMember) { + const FunctionDecl *Result; + ASSERT_TRUE(extractFunctionDecl(R"cpp(class A { void fun(); };)cpp", Result)); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); +} diff --git a/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn index 01c2b6ced336..9c240cff1816 100644 --- a/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn @@ -19,6 +19,7 @@ unittest("StaticAnalysisTests") { "CallEventTest.cpp", "ConflictingEvalCallsTest.cpp", "FalsePositiveRefutationBRVisitorTest.cpp", + "IsCLibraryFunctionTest.cpp", "NoStateChangeFuncVisitorTest.cpp", "ParamRegionTest.cpp", "RangeSetTest.cpp", -- GitLab From 0b2c24e0b33236c1dec39fe8b007b4c6aeb170b3 Mon Sep 17 00:00:00 2001 From: Zahira Ammarguellat Date: Tue, 12 Mar 2024 05:51:38 -0700 Subject: [PATCH 236/953] Fix warning message when using negative complex range options. (#84567) When `-fcx-no-limited-range` or` -fno-cx-fortran-rules` follows another complex range option on the command line, it will trigger a warning with empty message. `warning: overriding '-fcx-fortran-rules' option with '' [-Woverriding-option]` or `warning: overriding '-fcx-limited-range' option with '' [-Woverriding-option]` This patch fixes that. --- clang/lib/Driver/ToolChains/Clang.cpp | 35 ++++++++++++++++++++------- clang/test/Driver/range.c | 23 ++++++++++++++---- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index cc568b9a715b..6246a28a1306 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2687,8 +2687,8 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, } } -static StringRef EnumComplexRangeToStr(LangOptions::ComplexRangeKind Range) { - StringRef RangeStr = ""; +static StringRef EnumComplexRangeToStr(LangOptions::ComplexRangeKind Range, + StringRef Option) { switch (Range) { case LangOptions::ComplexRangeKind::CX_Limited: return "-fcx-limited-range"; @@ -2697,17 +2697,32 @@ static StringRef EnumComplexRangeToStr(LangOptions::ComplexRangeKind Range) { return "-fcx-fortran-rules"; break; default: - return RangeStr; + return Option; break; } } static void EmitComplexRangeDiag(const Driver &D, LangOptions::ComplexRangeKind Range1, - LangOptions::ComplexRangeKind Range2) { - if (Range1 != Range2 && Range1 != LangOptions::ComplexRangeKind::CX_None) - D.Diag(clang::diag::warn_drv_overriding_option) - << EnumComplexRangeToStr(Range1) << EnumComplexRangeToStr(Range2); + LangOptions::ComplexRangeKind Range2, + StringRef Option = StringRef()) { + if (Range1 != Range2 && Range1 != LangOptions::ComplexRangeKind::CX_None) { + bool NegateFortranOption = false; + bool NegateLimitedOption = false; + if (!Option.empty()) { + NegateFortranOption = + Range1 == LangOptions::ComplexRangeKind::CX_Fortran && + Option == "-fno-cx-fortran-rules"; + NegateLimitedOption = + Range1 == LangOptions::ComplexRangeKind::CX_Limited && + Option == "-fno-cx-limited-range"; + } + if (Option.empty() || + !Option.empty() && !NegateFortranOption && !NegateLimitedOption) + D.Diag(clang::diag::warn_drv_overriding_option) + << EnumComplexRangeToStr(Range1, Option) + << EnumComplexRangeToStr(Range2, Option); + } } static std::string @@ -2815,7 +2830,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, break; } case options::OPT_fno_cx_limited_range: - EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full); + EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full, + "-fno-cx-limited-range"); Range = LangOptions::ComplexRangeKind::CX_Full; break; case options::OPT_fcx_fortran_rules: { @@ -2824,7 +2840,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, break; } case options::OPT_fno_cx_fortran_rules: - EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full); + EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full, + "-fno-cx-fortran-rules"); Range = LangOptions::ComplexRangeKind::CX_Full; break; case options::OPT_ffp_model_EQ: { diff --git a/clang/test/Driver/range.c b/clang/test/Driver/range.c index 49116df2f448..2d1fd7f9f1a9 100644 --- a/clang/test/Driver/range.c +++ b/clang/test/Driver/range.c @@ -12,12 +12,23 @@ // RUN: %clang -### -target x86_64 -fcx-fortran-rules -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=FRTRN %s +// RUN: %clang -### -target x86_64 -fcx-fortran-rules -c %s 2>&1 \ +// RUN: -fno-cx-fortran-rules | FileCheck --check-prefix=FULL %s + +// RUN: %clang -### -target x86_64 -fcx-fortran-rules -fno-cx-limited-range \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN3 %s + // RUN: %clang -### -target x86_64 -fno-cx-fortran-rules -c %s 2>&1 \ // RUN: | FileCheck %s -// RUN: %clang -### -target x86_64 -fcx-limited-range \ -// RUN: -fcx-fortran-rules -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=WARN1 %s +// RUN: %clang -### -target x86_64 -fcx-limited-range -fcx-fortran-rules \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN1 %s + +// RUN: %clang -### -target x86_64 -fcx-limited-range -fno-cx-fortran-rules \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN4 %s + +// RUN: %clang -### -target x86_64 -fcx-limited-range -fno-cx-limited-range \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s // RUN: %clang -### -target x86_64 -fcx-fortran-rules \ // RUN: -fcx-limited-range -c %s 2>&1 \ @@ -32,8 +43,8 @@ // RUN: %clang -### -target x86_64 -fcx-limited-range -ffast-math -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=LMTD %s -// RUN: %clang -### -target x86_64 -ffast-math -fno-cx-limited-range -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=FULL %s +// RUN: %clang -### -target x86_64 -ffast-math -fno-cx-limited-range \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s // RUN: %clang -### -Werror -target x86_64 -fcx-limited-range -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=LMTD %s @@ -50,3 +61,5 @@ // CHECK-NOT: -complex-range=fortran // WARN1: warning: overriding '-fcx-limited-range' option with '-fcx-fortran-rules' [-Woverriding-option] // WARN2: warning: overriding '-fcx-fortran-rules' option with '-fcx-limited-range' [-Woverriding-option] +// WARN3: warning: overriding '-fcx-fortran-rules' option with '-fno-cx-limited-range' [-Woverriding-option] +// WARN4: warning: overriding '-fcx-limited-range' option with '-fno-cx-fortran-rules' [-Woverriding-option] -- GitLab From 629afd4dea1860755b4b7c05bb48538b8710c9d1 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Tue, 12 Mar 2024 07:52:48 -0500 Subject: [PATCH 237/953] [flang][Lower] Fix use-after-free with TypeRange (#84369) TypeRange is an iterator range, it does not own storage spanned by the iterators. When using TypeRange, make sure that the actual contents don't "expire" while the range is in use. This was detected by address sanitizer. --- flang/lib/Lower/IO.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp index 699897adcd0b..ac82276bcddb 100644 --- a/flang/lib/Lower/IO.cpp +++ b/flang/lib/Lower/IO.cpp @@ -242,8 +242,11 @@ static void makeNextConditionalOn(fir::FirOpBuilder &builder, // is in a fir.iterate_while loop, the result must be propagated up to the // loop scope as an extra ifOp result. (The propagation is done in genIoLoop.) mlir::TypeRange resTy; + // TypeRange does not own its contents, so make sure the the type object + // is live until the end of the function. + mlir::IntegerType boolTy = builder.getI1Type(); if (inLoop) - resTy = builder.getI1Type(); + resTy = boolTy; auto ifOp = builder.create(loc, resTy, ok, /*withElseRegion=*/inLoop); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); -- GitLab From c7f1a987a66a1ba0865ecc18adbe4dc8dbc0c788 Mon Sep 17 00:00:00 2001 From: Sven van Haastregt Date: Tue, 12 Mar 2024 12:51:30 +0000 Subject: [PATCH 238/953] [OpenCL] Elaborate about BIenqueue_kernel expansion; NFC --- clang/lib/CodeGen/CGBuiltin.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 20c357579391..93ab46507977 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -5460,7 +5460,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, } // OpenCL v2.0, s6.13.17 - Enqueue kernel function. - // It contains four different overload formats specified in Table 6.13.17.1. + // Table 6.13.17.1 specifies four overload forms of enqueue_kernel. + // The code below expands the builtin call to a call to one of the following + // functions that an OpenCL runtime library will have to provide: + // __enqueue_kernel_basic + // __enqueue_kernel_varargs + // __enqueue_kernel_basic_events + // __enqueue_kernel_events_varargs case Builtin::BIenqueue_kernel: { StringRef Name; // Generated function call name unsigned NumArgs = E->getNumArgs(); -- GitLab From 871086bf7fad42d610bfe02224662bdc71494a70 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Tue, 12 Mar 2024 07:53:57 -0500 Subject: [PATCH 239/953] [flang] Avoid passing null pointers to nonnull parameters (#84785) Certain functions in glibc have "nonnull" attributes on pointer parameters (even in cases where passing a null pointer should be handled correctly). There are a few cases of such calls in flang: memcmp and memcpy with the length parameter set to 0. Avoid passing a null pointer to these functions, since the conflict with the nonnull attribute could cause an undefined behavior. This was detected by the undefined behavior sanitizer. --- flang/include/flang/Parser/char-block.h | 7 +++++++ flang/runtime/buffer.h | 11 ++++++++--- flang/runtime/temporary-stack.cpp | 9 +++++++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/flang/include/flang/Parser/char-block.h b/flang/include/flang/Parser/char-block.h index fc5de2607b51..acd8aee98bf8 100644 --- a/flang/include/flang/Parser/char-block.h +++ b/flang/include/flang/Parser/char-block.h @@ -129,6 +129,13 @@ public: private: int Compare(const CharBlock &that) const { + // "memcmp" in glibc has "nonnull" attributes on the input pointers. + // Avoid passing null pointers, since it would result in an undefined + // behavior. + if (size() == 0) + return that.size() == 0 ? 0 : -1; + if (that.size() == 0) + return 1; std::size_t bytes{std::min(size(), that.size())}; int cmp{std::memcmp(static_cast(begin()), static_cast(that.begin()), bytes)}; diff --git a/flang/runtime/buffer.h b/flang/runtime/buffer.h index a77a5a5dda5c..93fda36f500d 100644 --- a/flang/runtime/buffer.h +++ b/flang/runtime/buffer.h @@ -148,10 +148,15 @@ private: buffer_ = reinterpret_cast(AllocateMemoryOrCrash(terminator, size_)); auto chunk{std::min(length_, oldSize - start_)}; - std::memcpy(buffer_, old + start_, chunk); + // "memcpy" in glibc has a "nonnull" attribute on the source pointer. + // Avoid passing a null pointer, since it would result in an undefined + // behavior. + if (old != nullptr) { + std::memcpy(buffer_, old + start_, chunk); + std::memcpy(buffer_ + chunk, old, length_ - chunk); + FreeMemory(old); + } start_ = 0; - std::memcpy(buffer_ + chunk, old, length_ - chunk); - FreeMemory(old); } } diff --git a/flang/runtime/temporary-stack.cpp b/flang/runtime/temporary-stack.cpp index b4d7c6064457..667b10e04dbd 100644 --- a/flang/runtime/temporary-stack.cpp +++ b/flang/runtime/temporary-stack.cpp @@ -93,8 +93,13 @@ void DescriptorStorage::resize(size_type newCapacity) { } Descriptor **newData = static_cast(AllocateMemoryOrCrash(terminator_, bytes)); - memcpy(newData, data_, capacity_ * sizeof(Descriptor *)); - FreeMemory(data_); + // "memcpy" in glibc has a "nonnull" attribute on the source pointer. + // Avoid passing a null pointer, since it would result in an undefined + // behavior. + if (data_ != nullptr) { + memcpy(newData, data_, capacity_ * sizeof(Descriptor *)); + FreeMemory(data_); + } data_ = newData; capacity_ = newCapacity; } -- GitLab From bde7a6b791872b63456cb4e50e63046728a65196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= Date: Tue, 12 Mar 2024 13:55:38 +0100 Subject: [PATCH 240/953] [clang-repl] Expose CreateExecutor() and ResetExecutor() in extended Interpreter interface (#84460) IncrementalExecutor is an implementation detail of the Interpreter. In order to test extended features properly, we must be able to setup and tear down the executor manually. --- clang/include/clang/Interpreter/Interpreter.h | 9 ++++++- clang/lib/Interpreter/Interpreter.cpp | 6 +++++ clang/unittests/Interpreter/CMakeLists.txt | 1 + .../Interpreter/InterpreterExtensionsTest.cpp | 24 +++++++++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 469ce1fd75bf..1dcba1ef9679 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -96,7 +96,6 @@ class Interpreter { // An optional parser for CUDA offloading std::unique_ptr DeviceParser; - llvm::Error CreateExecutor(); unsigned InitPTUSize = 0; // This member holds the last result of the value printing. It's a class @@ -114,6 +113,14 @@ protected: // That's useful for testing and out-of-tree clients. Interpreter(std::unique_ptr CI, llvm::Error &Err); + // Create the internal IncrementalExecutor, or re-create it after calling + // ResetExecutor(). + llvm::Error CreateExecutor(); + + // Delete the internal IncrementalExecutor. This causes a hard shutdown of the + // JIT engine. In particular, it doesn't run cleanup or destructors. + void ResetExecutor(); + // Lazily construct the RuntimeInterfaceBuilder. The provided instance will be // used for the entire lifetime of the interpreter. The default implementation // targets the in-process __clang_Interpreter runtime. Override this to use a diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index e293fefb5249..7fa52f2f15fc 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -375,6 +375,10 @@ Interpreter::Parse(llvm::StringRef Code) { llvm::Error Interpreter::CreateExecutor() { const clang::TargetInfo &TI = getCompilerInstance()->getASTContext().getTargetInfo(); + if (IncrExecutor) + return llvm::make_error("Operation failed. " + "Execution engine exists", + std::error_code()); llvm::Error Err = llvm::Error::success(); auto Executor = std::make_unique(*TSCtx, Err, TI); if (!Err) @@ -383,6 +387,8 @@ llvm::Error Interpreter::CreateExecutor() { return Err; } +void Interpreter::ResetExecutor() { IncrExecutor.reset(); } + llvm::Error Interpreter::Execute(PartialTranslationUnit &T) { assert(T.TheModule); if (!IncrExecutor) { diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt index 046d96ad0ec6..498070b43d92 100644 --- a/clang/unittests/Interpreter/CMakeLists.txt +++ b/clang/unittests/Interpreter/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS OrcJIT Support TargetParser + TestingSupport ) add_clang_unittest(ClangReplInterpreterTests diff --git a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp index 4e9f2dba210a..f1c3d65ab0a9 100644 --- a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp +++ b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp @@ -27,6 +27,30 @@ using namespace clang; namespace { +class TestCreateResetExecutor : public Interpreter { +public: + TestCreateResetExecutor(std::unique_ptr CI, + llvm::Error &Err) + : Interpreter(std::move(CI), Err) {} + + llvm::Error testCreateExecutor() { return Interpreter::CreateExecutor(); } + + void resetExecutor() { Interpreter::ResetExecutor(); } +}; + +TEST(InterpreterExtensionsTest, ExecutorCreateReset) { + clang::IncrementalCompilerBuilder CB; + llvm::Error ErrOut = llvm::Error::success(); + TestCreateResetExecutor Interp(cantFail(CB.CreateCpp()), ErrOut); + cantFail(std::move(ErrOut)); + cantFail(Interp.testCreateExecutor()); + Interp.resetExecutor(); + cantFail(Interp.testCreateExecutor()); + EXPECT_THAT_ERROR(Interp.testCreateExecutor(), + llvm::FailedWithMessage("Operation failed. " + "Execution engine exists")); +} + class RecordRuntimeIBMetrics : public Interpreter { struct NoopRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder { NoopRuntimeInterfaceBuilder(Sema &S) : S(S) {} -- GitLab From ee137e234cb70e24dbfd8903904c5d5eceda3fb0 Mon Sep 17 00:00:00 2001 From: Danial Klimkin Date: Tue, 12 Mar 2024 14:21:04 +0100 Subject: [PATCH 241/953] Update BUILD.bazel for 80ab8234ac309418637488b97e0a62d8377b2ecf (#84908) --- utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel index 095efe9babfb..9823027b766c 100644 --- a/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel @@ -396,6 +396,7 @@ cc_test( ":static_analyzer_test_headers", "//clang:analysis", "//clang:ast", + "//clang:ast_matchers", "//clang:basic", "//clang:frontend", "//clang:static_analyzer_core", -- GitLab From f03aaa3c0cca77c15adfbb4544f296bc0441f6fc Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Tue, 12 Mar 2024 21:24:37 +0800 Subject: [PATCH 242/953] [clang] Silence -Wlogical-op-parentheses in Clang.cpp (NFC) llvm-project/clang/lib/Driver/ToolChains/Clang.cpp:2721:49: error: '&&' within '||' [-Werror,-Wlogical-op-parentheses] !Option.empty() && !NegateFortranOption && !NegateLimitedOption) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~ llvm-project/clang/lib/Driver/ToolChains/Clang.cpp:2721:49: note: place parentheses around the '&&' expression to silence this warning !Option.empty() && !NegateFortranOption && !NegateLimitedOption) ^ ( ) 1 error generated. --- clang/lib/Driver/ToolChains/Clang.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 6246a28a1306..3a7a1cf99c79 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2718,7 +2718,7 @@ static void EmitComplexRangeDiag(const Driver &D, Option == "-fno-cx-limited-range"; } if (Option.empty() || - !Option.empty() && !NegateFortranOption && !NegateLimitedOption) + (!Option.empty() && !NegateFortranOption && !NegateLimitedOption)) D.Diag(clang::diag::warn_drv_overriding_option) << EnumComplexRangeToStr(Range1, Option) << EnumComplexRangeToStr(Range2, Option); -- GitLab From d96d917f38ab111adf7b1d24616a939e75141a89 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 12 Mar 2024 13:23:05 +0000 Subject: [PATCH 243/953] [Matrix] Add tests showing mis-compile with lifetime.end and fusion. Add a set of tests showing miscompiles due to multiply fusion introducing loads to dead objects after lifetime.end. --- .../multiply-fused-lifetime-ends.ll | 707 ++++++++++++++++++ 1 file changed, 707 insertions(+) create mode 100644 llvm/test/Transforms/LowerMatrixIntrinsics/multiply-fused-lifetime-ends.ll diff --git a/llvm/test/Transforms/LowerMatrixIntrinsics/multiply-fused-lifetime-ends.ll b/llvm/test/Transforms/LowerMatrixIntrinsics/multiply-fused-lifetime-ends.ll new file mode 100644 index 000000000000..ef8665b79690 --- /dev/null +++ b/llvm/test/Transforms/LowerMatrixIntrinsics/multiply-fused-lifetime-ends.ll @@ -0,0 +1,707 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes=lower-matrix-intrinsics -fuse-matrix-tile-size=2 -matrix-allow-contract -force-fuse-matrix %s -S | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + +; Tests to make sure no loads are introduced after a lifetime.end by multiply +; fusion. + +; FIXME: Currently the tests are mis-compiled, with loads being introduced after +; llvm.lifetime.end calls. + +define void @lifetime_for_first_arg_before_multiply(ptr noalias %B, ptr noalias %C) { +; CHECK-LABEL: @lifetime_for_first_arg_before_multiply( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32 +; CHECK-NEXT: call void @init(ptr [[A]]) +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A]]) +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 +; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 +; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0 +; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 +; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 +; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 +; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]] +; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]]) +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> +; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]] +; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]]) +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> +; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]] +; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]]) +; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> +; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]] +; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]]) +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C:%.*]], i64 0 +; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 +; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 +; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: ret void +; +entry: + %A = alloca <4 x double> + call void @init(ptr %A) + %a = load <4 x double>, ptr %A, align 8 + %b = load <4 x double>, ptr %B, align 8 + call void @llvm.lifetime.end(i64 -1, ptr %A) + %c = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2) + store <4 x double> %c, ptr %C, align 8 + ret void +} + +define void @lifetime_for_second_arg_before_multiply(ptr noalias %A, ptr noalias %C) { +; CHECK-LABEL: @lifetime_for_second_arg_before_multiply( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[B:%.*]] = alloca <4 x double>, align 32 +; CHECK-NEXT: call void @init(ptr [[B]]) +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[B]]) +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A:%.*]], i64 0 +; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 +; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B]], i64 0 +; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 +; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 +; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 +; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]] +; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]]) +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> +; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]] +; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]]) +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> +; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]] +; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]]) +; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> +; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]] +; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]]) +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C:%.*]], i64 0 +; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 +; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 +; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: ret void +; +entry: + %B = alloca <4 x double> + call void @init(ptr %B) + %a = load <4 x double>, ptr %A, align 8 + %b = load <4 x double>, ptr %B, align 8 + call void @llvm.lifetime.end(i64 -1, ptr %B) + %c = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2) + store <4 x double> %c, ptr %C, align 8 + ret void +} + +define void @lifetime_for_first_arg_before_multiply_load_from_offset(ptr noalias %B, ptr noalias %C) { +; CHECK-LABEL: @lifetime_for_first_arg_before_multiply_load_from_offset( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = alloca <8 x double>, align 64 +; CHECK-NEXT: call void @init(ptr [[A]]) +; CHECK-NEXT: [[GEP_8:%.*]] = getelementptr i8, ptr [[A]], i64 8 +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A]]) +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[GEP_8]], i64 0 +; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 +; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0 +; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 +; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 +; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 +; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]] +; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]]) +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> +; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]] +; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]]) +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> +; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]] +; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]]) +; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> +; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]] +; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]]) +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C:%.*]], i64 0 +; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 +; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 +; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: ret void +; +entry: + %A = alloca <8 x double> + call void @init(ptr %A) + %gep.8 = getelementptr i8, ptr %A, i64 8 + %a = load <4 x double>, ptr %gep.8, align 8 + %b = load <4 x double>, ptr %B, align 8 + call void @llvm.lifetime.end(i64 -1, ptr %A) + %c = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2) + store <4 x double> %c, ptr %C, align 8 + ret void +} + +define void @lifetime_for_first_arg_before_multiply_lifetime_does_not_dominate(ptr noalias %B, ptr noalias %C, i1 %c.0) { +; CHECK-LABEL: @lifetime_for_first_arg_before_multiply_lifetime_does_not_dominate( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32 +; CHECK-NEXT: call void @init(ptr [[A]]) +; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] +; CHECK: then: +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A]]) +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 +; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 +; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0 +; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 +; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 +; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 +; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]] +; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]]) +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> +; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]] +; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]]) +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> +; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]] +; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]]) +; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> +; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]] +; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]]) +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C1:%.*]], i64 0 +; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 +; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 +; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: ret void +; +entry: + %A = alloca <4 x double> + call void @init(ptr %A) + %a = load <4 x double>, ptr %A, align 8 + %b = load <4 x double>, ptr %B, align 8 + br i1 %c.0, label %then, label %exit + +then: + call void @llvm.lifetime.end(i64 -1, ptr %A) + br label %exit + +exit: + %m = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2) + store <4 x double> %m, ptr %C, align 8 + ret void +} + +define void @lifetime_for_second_arg_before_multiply_lifetime_does_not_dominate(ptr noalias %A, ptr noalias %C, i1 %c.0) { +; CHECK-LABEL: @lifetime_for_second_arg_before_multiply_lifetime_does_not_dominate( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[B:%.*]] = alloca <4 x double>, align 32 +; CHECK-NEXT: call void @init(ptr [[B]]) +; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] +; CHECK: then: +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[B]]) +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A:%.*]], i64 0 +; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 +; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B]], i64 0 +; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 +; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 +; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 +; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]] +; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]]) +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> +; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]] +; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]]) +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> +; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]] +; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]]) +; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> +; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]] +; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]]) +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C1:%.*]], i64 0 +; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 +; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 +; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: ret void +; +entry: + %B = alloca <4 x double> + call void @init(ptr %B) + %a = load <4 x double>, ptr %A, align 8 + %b = load <4 x double>, ptr %B, align 8 + br i1 %c.0, label %then, label %exit + +then: + call void @llvm.lifetime.end(i64 -1, ptr %B) + br label %exit + +exit: + %m = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2) + store <4 x double> %m, ptr %C, align 8 + ret void +} + +define void @lifetime_for_ptr_first_arg_before_multiply(ptr noalias %A, ptr noalias %B, ptr noalias %C, i1 %c.0) { +; CHECK-LABEL: @lifetime_for_ptr_first_arg_before_multiply( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] +; CHECK: then: +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A:%.*]]) +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 +; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 +; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0 +; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 +; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 +; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 +; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]] +; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]]) +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> +; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]] +; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]]) +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> +; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]] +; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]]) +; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> +; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]] +; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]]) +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C1:%.*]], i64 0 +; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 +; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 +; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: ret void +; +entry: + %a = load <4 x double>, ptr %A, align 8 + %b = load <4 x double>, ptr %B, align 8 + br i1 %c.0, label %then, label %exit + +then: + call void @llvm.lifetime.end(i64 -1, ptr %A) + br label %exit + +exit: + %m = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2) + store <4 x double> %m, ptr %C, align 8 + ret void +} + +define void @lifetime_for_both_ptr_args_before_multiply(ptr noalias %A, ptr noalias %B, ptr noalias %C, i1 %c.0) { +; CHECK-LABEL: @lifetime_for_both_ptr_args_before_multiply( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] +; CHECK: then: +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[B:%.*]]) +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A:%.*]]) +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 +; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 +; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B]], i64 0 +; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 +; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 +; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 +; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]] +; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]]) +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> +; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]] +; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]]) +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> +; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]] +; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]]) +; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> +; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]] +; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]]) +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C1:%.*]], i64 0 +; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 +; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 +; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: ret void +; +entry: + %a = load <4 x double>, ptr %A, align 8 + %b = load <4 x double>, ptr %B, align 8 + br i1 %c.0, label %then, label %exit + +then: + call void @llvm.lifetime.end(i64 -1, ptr %B) + call void @llvm.lifetime.end(i64 -1, ptr %A) + br label %exit + +exit: + %m = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2) + store <4 x double> %m, ptr %C, align 8 + ret void +} + +define void @lifetime_for_ptr_select_before_multiply(ptr noalias %A, ptr noalias %B, ptr noalias %C, i1 %c.0, i1 %c.1) { +; CHECK-LABEL: @lifetime_for_ptr_select_before_multiply( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P:%.*]] = select i1 [[C_0:%.*]], ptr [[A:%.*]], ptr [[B:%.*]] +; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] +; CHECK: then: +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[P]]) +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[P]], i64 0 +; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 +; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B]], i64 0 +; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 +; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 +; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 +; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]] +; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]]) +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> +; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]] +; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]]) +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> +; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]] +; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]]) +; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> +; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]] +; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]]) +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> +; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C:%.*]], i64 0 +; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 +; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 +; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: ret void +; +entry: + %P = select i1 %c.0, ptr %A, ptr %B + %a = load <4 x double>, ptr %P, align 8 + %b = load <4 x double>, ptr %B, align 8 + br i1 %c.1, label %then, label %exit + +then: + call void @llvm.lifetime.end(i64 -1, ptr %P) + br label %exit + +exit: + %m = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2) + store <4 x double> %m, ptr %C, align 8 + ret void +} + +declare void @init(ptr) +declare void @llvm.lifetime.end(i64, ptr) + +declare <4 x double> @llvm.matrix.multiply(<4 x double>, <4 x double>, i32, i32, i32) -- GitLab From ffd31c5e92da9da37cf57ca653e22db38b5af9a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= Date: Tue, 12 Mar 2024 14:47:09 +0100 Subject: [PATCH 244/953] Fix build after #84460: link LLVMTestingSupport explicitly in clang unittest This is supposed to fix the DYLIB-enabled build, i.e. https://lab.llvm.org/buildbot/#/builders/196 --- clang/unittests/Interpreter/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt index 498070b43d92..b56e1e21015d 100644 --- a/clang/unittests/Interpreter/CMakeLists.txt +++ b/clang/unittests/Interpreter/CMakeLists.txt @@ -4,7 +4,6 @@ set(LLVM_LINK_COMPONENTS OrcJIT Support TargetParser - TestingSupport ) add_clang_unittest(ClangReplInterpreterTests @@ -20,6 +19,7 @@ target_link_libraries(ClangReplInterpreterTests PUBLIC clangInterpreter clangFrontend clangSema + LLVMTestingSupport ) # Exceptions on Windows are not yet supported. -- GitLab From 9f7ed36f92c304050d401f00b013186de15130e8 Mon Sep 17 00:00:00 2001 From: Jonas Paulsson Date: Tue, 12 Mar 2024 09:53:11 -0400 Subject: [PATCH 245/953] Don't do casting of atomic FP loads/stores in FE. (#83446) The casting of FP atomic loads and stores were always done by the front-end, even though the AtomicExpandPass will do it if the target requests it (which is the default). This patch removes this casting in the front-end entirely. --- clang/lib/CodeGen/CGAtomic.cpp | 96 ++++++---- .../CodeGen/SystemZ/atomic_fp_load_store.c | 164 ++++++++++++++++++ clang/test/CodeGen/atomic.c | 3 +- clang/test/CodeGen/c11atomics-ios.c | 8 +- clang/test/OpenMP/atomic_read_codegen.c | 10 +- clang/test/OpenMP/atomic_write_codegen.c | 13 +- 6 files changed, 236 insertions(+), 58 deletions(-) create mode 100644 clang/test/CodeGen/SystemZ/atomic_fp_load_store.c diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index a8d846b4f6a5..fb03d013e8af 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -194,12 +194,14 @@ namespace { RValue convertAtomicTempToRValue(Address addr, AggValueSlot resultSlot, SourceLocation loc, bool AsValue) const; - /// Converts a rvalue to integer value. - llvm::Value *convertRValueToInt(RValue RVal) const; + llvm::Value *getScalarRValValueOrNull(RValue RVal) const; - RValue ConvertIntToValueOrAtomic(llvm::Value *IntVal, - AggValueSlot ResultSlot, - SourceLocation Loc, bool AsValue) const; + /// Converts an rvalue to integer value if needed. + llvm::Value *convertRValueToInt(RValue RVal, bool CastFP = true) const; + + RValue ConvertToValueOrAtomic(llvm::Value *IntVal, AggValueSlot ResultSlot, + SourceLocation Loc, bool AsValue, + bool CastFP = true) const; /// Copy an atomic r-value into atomic-layout memory. void emitCopyIntoMemory(RValue rvalue) const; @@ -261,7 +263,8 @@ namespace { void EmitAtomicLoadLibcall(llvm::Value *AddForLoaded, llvm::AtomicOrdering AO, bool IsVolatile); /// Emits atomic load as LLVM instruction. - llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile); + llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile, + bool CastFP = true); /// Emits atomic compare-and-exchange op as a libcall. llvm::Value *EmitAtomicCompareExchangeLibcall( llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr, @@ -1396,12 +1399,13 @@ RValue AtomicInfo::convertAtomicTempToRValue(Address addr, LVal.getBaseInfo(), TBAAAccessInfo())); } -RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal, - AggValueSlot ResultSlot, - SourceLocation Loc, - bool AsValue) const { +RValue AtomicInfo::ConvertToValueOrAtomic(llvm::Value *Val, + AggValueSlot ResultSlot, + SourceLocation Loc, bool AsValue, + bool CastFP) const { // Try not to in some easy cases. - assert(IntVal->getType()->isIntegerTy() && "Expected integer value"); + assert((Val->getType()->isIntegerTy() || Val->getType()->isIEEELikeFPTy()) && + "Expected integer or floating point value"); if (getEvaluationKind() == TEK_Scalar && (((!LVal.isBitField() || LVal.getBitFieldInfo().Size == ValueSizeInBits) && @@ -1410,13 +1414,14 @@ RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal, auto *ValTy = AsValue ? CGF.ConvertTypeForMem(ValueTy) : getAtomicAddress().getElementType(); - if (ValTy->isIntegerTy()) { - assert(IntVal->getType() == ValTy && "Different integer types."); - return RValue::get(CGF.EmitFromMemory(IntVal, ValueTy)); + if (ValTy->isIntegerTy() || (!CastFP && ValTy->isIEEELikeFPTy())) { + assert((!ValTy->isIntegerTy() || Val->getType() == ValTy) && + "Different integer types."); + return RValue::get(CGF.EmitFromMemory(Val, ValueTy)); } else if (ValTy->isPointerTy()) - return RValue::get(CGF.Builder.CreateIntToPtr(IntVal, ValTy)); - else if (llvm::CastInst::isBitCastable(IntVal->getType(), ValTy)) - return RValue::get(CGF.Builder.CreateBitCast(IntVal, ValTy)); + return RValue::get(CGF.Builder.CreateIntToPtr(Val, ValTy)); + else if (llvm::CastInst::isBitCastable(Val->getType(), ValTy)) + return RValue::get(CGF.Builder.CreateBitCast(Val, ValTy)); } // Create a temporary. This needs to be big enough to hold the @@ -1433,8 +1438,7 @@ RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal, // Slam the integer into the temporary. Address CastTemp = castToAtomicIntPointer(Temp); - CGF.Builder.CreateStore(IntVal, CastTemp) - ->setVolatile(TempIsVolatile); + CGF.Builder.CreateStore(Val, CastTemp)->setVolatile(TempIsVolatile); return convertAtomicTempToRValue(Temp, ResultSlot, Loc, AsValue); } @@ -1453,9 +1457,11 @@ void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded, } llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO, - bool IsVolatile) { + bool IsVolatile, bool CastFP) { // Okay, we're doing this natively. - Address Addr = getAtomicAddressAsAtomicIntPointer(); + Address Addr = getAtomicAddress(); + if (!(Addr.getElementType()->isIEEELikeFPTy() && !CastFP)) + Addr = castToAtomicIntPointer(Addr); llvm::LoadInst *Load = CGF.Builder.CreateLoad(Addr, "atomic-load"); Load->setAtomic(AO); @@ -1515,7 +1521,7 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc, } // Okay, we're doing this natively. - auto *Load = EmitAtomicLoadOp(AO, IsVolatile); + auto *Load = EmitAtomicLoadOp(AO, IsVolatile, /*CastFP=*/false); // If we're ignoring an aggregate return, don't do anything. if (getEvaluationKind() == TEK_Aggregate && ResultSlot.isIgnored()) @@ -1523,7 +1529,8 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc, // Okay, turn that back into the original value or atomic (for non-simple // lvalues) type. - return ConvertIntToValueOrAtomic(Load, ResultSlot, Loc, AsValue); + return ConvertToValueOrAtomic(Load, ResultSlot, Loc, AsValue, + /*CastFP=*/false); } /// Emit a load from an l-value of atomic type. Note that the r-value @@ -1586,12 +1593,18 @@ Address AtomicInfo::materializeRValue(RValue rvalue) const { return TempLV.getAddress(CGF); } -llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal) const { +llvm::Value *AtomicInfo::getScalarRValValueOrNull(RValue RVal) const { + if (RVal.isScalar() && (!hasPadding() || !LVal.isSimple())) + return RVal.getScalarVal(); + return nullptr; +} + +llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal, bool CastFP) const { // If we've got a scalar value of the right size, try to avoid going - // through memory. - if (RVal.isScalar() && (!hasPadding() || !LVal.isSimple())) { - llvm::Value *Value = RVal.getScalarVal(); - if (isa(Value->getType())) + // through memory. Floats get casted if needed by AtomicExpandPass. + if (llvm::Value *Value = getScalarRValValueOrNull(RVal)) { + if (isa(Value->getType()) || + (!CastFP && Value->getType()->isIEEELikeFPTy())) return CGF.EmitToMemory(Value, ValueTy); else { llvm::IntegerType *InputIntTy = llvm::IntegerType::get( @@ -1677,8 +1690,8 @@ std::pair AtomicInfo::EmitAtomicCompareExchange( auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success, Failure, IsWeak); return std::make_pair( - ConvertIntToValueOrAtomic(Res.first, AggValueSlot::ignored(), - SourceLocation(), /*AsValue=*/false), + ConvertToValueOrAtomic(Res.first, AggValueSlot::ignored(), + SourceLocation(), /*AsValue=*/false), Res.second); } @@ -1787,8 +1800,8 @@ void AtomicInfo::EmitAtomicUpdateOp( requiresMemSetZero(getAtomicAddress().getElementType())) { CGF.Builder.CreateStore(PHI, NewAtomicIntAddr); } - auto OldRVal = ConvertIntToValueOrAtomic(PHI, AggValueSlot::ignored(), - SourceLocation(), /*AsValue=*/false); + auto OldRVal = ConvertToValueOrAtomic(PHI, AggValueSlot::ignored(), + SourceLocation(), /*AsValue=*/false); EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, NewAtomicAddr); auto *DesiredVal = CGF.Builder.CreateLoad(NewAtomicIntAddr); // Try to write new value using cmpxchg operation. @@ -1953,13 +1966,22 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, } // Okay, we're doing this natively. - llvm::Value *intValue = atomics.convertRValueToInt(rvalue); + llvm::Value *ValToStore = + atomics.convertRValueToInt(rvalue, /*CastFP=*/false); // Do the atomic store. - Address addr = atomics.castToAtomicIntPointer(atomics.getAtomicAddress()); - intValue = Builder.CreateIntCast( - intValue, addr.getElementType(), /*isSigned=*/false); - llvm::StoreInst *store = Builder.CreateStore(intValue, addr); + Address Addr = atomics.getAtomicAddress(); + bool ShouldCastToInt = true; + if (llvm::Value *Value = atomics.getScalarRValValueOrNull(rvalue)) + if (isa(Value->getType()) || + Value->getType()->isIEEELikeFPTy()) + ShouldCastToInt = false; + if (ShouldCastToInt) { + Addr = atomics.castToAtomicIntPointer(Addr); + ValToStore = Builder.CreateIntCast(ValToStore, Addr.getElementType(), + /*isSigned=*/false); + } + llvm::StoreInst *store = Builder.CreateStore(ValToStore, Addr); if (AO == llvm::AtomicOrdering::Acquire) AO = llvm::AtomicOrdering::Monotonic; diff --git a/clang/test/CodeGen/SystemZ/atomic_fp_load_store.c b/clang/test/CodeGen/SystemZ/atomic_fp_load_store.c new file mode 100644 index 000000000000..8a4383e92a1e --- /dev/null +++ b/clang/test/CodeGen/SystemZ/atomic_fp_load_store.c @@ -0,0 +1,164 @@ +// RUN: %clang_cc1 -triple s390x-linux-gnu -O1 -emit-llvm %s -o - | FileCheck %s +// +// Test that floating point atomic stores and loads do not get casted to/from +// integer. + +#include + +_Atomic float Af; +_Atomic double Ad; +_Atomic long double Ald; + +//// Atomic stores of floating point values. +void fun0(float Arg) { +// CHECK-LABEL: @fun0 +// CHECK: store atomic float %Arg, ptr @Af seq_cst, align 4 + Af = Arg; +} + +void fun1(double Arg) { +// CHECK-LABEL: @fun1 +// CHECK: store atomic double %Arg, ptr @Ad seq_cst, align 8 + Ad = Arg; +} + +void fun2(long double Arg) { +// CHECK-LABEL: @fun2 +// CHECK: store atomic fp128 %Arg, ptr @Ald seq_cst, align 16 + Ald = Arg; +} + +void fun3(_Atomic float *Dst, float Arg) { +// CHECK-LABEL: @fun +// CHECK: store atomic float %Arg, ptr %Dst seq_cst, align 4 + *Dst = Arg; +} + +void fun4(_Atomic double *Dst, double Arg) { +// CHECK-LABEL: @fun4 +// CHECK: store atomic double %Arg, ptr %Dst seq_cst, align 8 + *Dst = Arg; +} + +void fun5(_Atomic long double *Dst, long double Arg) { +// CHECK-LABEL: @fun5 +// CHECK: store atomic fp128 %Arg, ptr %Dst seq_cst, align 16 + *Dst = Arg; +} + +//// Atomic loads of floating point values. +float fun6() { +// CHECK-LABEL: @fun6 +// CHECK: %atomic-load = load atomic float, ptr @Af seq_cst, align 4 + return Af; +} + +float fun7() { +// CHECK-LABEL: @fun7 +// CHECK: %atomic-load = load atomic double, ptr @Ad seq_cst, align 8 + return Ad; +} + +float fun8() { +// CHECK-LABEL: @fun8 +// CHECK: %atomic-load = load atomic fp128, ptr @Ald seq_cst, align 16 + return Ald; +} + +float fun9(_Atomic float *Src) { +// CHECK-LABEL: @fun9 +// CHECK: %atomic-load = load atomic float, ptr %Src seq_cst, align 4 + return *Src; +} + +double fun10(_Atomic double *Src) { +// CHECK-LABEL: @fun10 +// CHECK: %atomic-load = load atomic double, ptr %Src seq_cst, align 8 + return *Src; +} + +long double fun11(_Atomic long double *Src) { +// CHECK-LABEL: @fun11 +// CHECK: %atomic-load = load atomic fp128, ptr %Src seq_cst, align 16 + return *Src; +} + +//// Same, but with 'volatile' as well: + +_Atomic volatile float Af_vol; +_Atomic volatile double Ad_vol; +_Atomic volatile long double Ald_vol; + +//// Atomic volatile stores of floating point values. +void fun0_vol(float Arg) { +// CHECK-LABEL: @fun0_vol +// CHECK: store atomic volatile float %Arg, ptr @Af_vol seq_cst, align 4 + Af_vol = Arg; +} + +void fun1_vol(double Arg) { +// CHECK-LABEL: @fun1_vol +// CHECK: store atomic volatile double %Arg, ptr @Ad_vol seq_cst, align 8 + Ad_vol = Arg; +} + +void fun2_vol(long double Arg) { +// CHECK-LABEL: @fun2_vol +// CHECK: store atomic volatile fp128 %Arg, ptr @Ald_vol seq_cst, align 16 + Ald_vol = Arg; +} + +void fun3_vol(_Atomic volatile float *Dst, float Arg) { +// CHECK-LABEL: @fun3_vol +// CHECK: store atomic volatile float %Arg, ptr %Dst seq_cst, align 4 + *Dst = Arg; +} + +void fun4_vol(_Atomic volatile double *Dst, double Arg) { +// CHECK-LABEL: @fun4_vol +// CHECK: store atomic volatile double %Arg, ptr %Dst seq_cst, align 8 + *Dst = Arg; +} + +void fun5_vol(_Atomic volatile long double *Dst, long double Arg) { +// CHECK-LABEL: @fun5_vol +// CHECK: store atomic volatile fp128 %Arg, ptr %Dst seq_cst, align 16 + *Dst = Arg; +} + +//// Atomic volatile loads of floating point values. +float fun6_vol() { +// CHECK-LABEL: @fun6_vol +// CHECK: %atomic-load = load atomic volatile float, ptr @Af_vol seq_cst, align 4 + return Af_vol; +} + +float fun7_vol() { +// CHECK-LABEL: @fun7_vol +// CHECK: %atomic-load = load atomic volatile double, ptr @Ad_vol seq_cst, align 8 + return Ad_vol; +} + +float fun8_vol() { +// CHECK-LABEL: @fun8_vol +// CHECK: %atomic-load = load atomic volatile fp128, ptr @Ald_vol seq_cst, align 16 + return Ald_vol; +} + +float fun9_vol(_Atomic volatile float *Src) { +// CHECK-LABEL: @fun9_vol +// CHECK: %atomic-load = load atomic volatile float, ptr %Src seq_cst, align 4 + return *Src; +} + +double fun10_vol(_Atomic volatile double *Src) { +// CHECK-LABEL: @fun10_vol +// CHECK: %atomic-load = load atomic volatile double, ptr %Src seq_cst, align 8 + return *Src; +} + +long double fun11_vol(_Atomic volatile long double *Src) { +// CHECK-LABEL: @fun11_vol +// CHECK: %atomic-load = load atomic volatile fp128, ptr %Src seq_cst, align 16 + return *Src; +} diff --git a/clang/test/CodeGen/atomic.c b/clang/test/CodeGen/atomic.c index 9143bedab906..af5c056bbfe6 100644 --- a/clang/test/CodeGen/atomic.c +++ b/clang/test/CodeGen/atomic.c @@ -145,6 +145,5 @@ void force_global_uses(void) { (void)glob_int; // CHECK: load atomic i32, ptr @[[GLOB_INT]] seq_cst (void)glob_flt; - // CHECK: %[[LOCAL_FLT:.+]] = load atomic i32, ptr @[[GLOB_FLT]] seq_cst - // CHECK-NEXT: bitcast i32 %[[LOCAL_FLT]] to float + // CHECK: load atomic float, ptr @[[GLOB_FLT]] seq_cst } diff --git a/clang/test/CodeGen/c11atomics-ios.c b/clang/test/CodeGen/c11atomics-ios.c index bcb6519ab0dc..811820b67fbd 100644 --- a/clang/test/CodeGen/c11atomics-ios.c +++ b/clang/test/CodeGen/c11atomics-ios.c @@ -19,15 +19,13 @@ void testFloat(_Atomic(float) *fp) { _Atomic(float) x = 2.0f; // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[FP]] -// CHECK-NEXT: [[T2:%.*]] = load atomic i32, ptr [[T0]] seq_cst, align 4 -// CHECK-NEXT: [[T3:%.*]] = bitcast i32 [[T2]] to float -// CHECK-NEXT: store float [[T3]], ptr [[F]] +// CHECK-NEXT: [[T2:%.*]] = load atomic float, ptr [[T0]] seq_cst, align 4 +// CHECK-NEXT: store float [[T2]], ptr [[F]] float f = *fp; // CHECK-NEXT: [[T0:%.*]] = load float, ptr [[F]], align 4 // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[FP]], align 4 -// CHECK-NEXT: [[T2:%.*]] = bitcast float [[T0]] to i32 -// CHECK-NEXT: store atomic i32 [[T2]], ptr [[T1]] seq_cst, align 4 +// CHECK-NEXT: store atomic float [[T0]], ptr [[T1]] seq_cst, align 4 *fp = f; // CHECK-NEXT: ret void diff --git a/clang/test/OpenMP/atomic_read_codegen.c b/clang/test/OpenMP/atomic_read_codegen.c index b60e1686d4da..0a68c8e2c35a 100644 --- a/clang/test/OpenMP/atomic_read_codegen.c +++ b/clang/test/OpenMP/atomic_read_codegen.c @@ -128,13 +128,11 @@ int main(void) { // CHECK: store i64 #pragma omp atomic read ullv = ullx; -// CHECK: load atomic i32, ptr {{.*}} monotonic, align 4 -// CHECK: bitcast i32 {{.*}} to float +// CHECK: load atomic float, ptr {{.*}} monotonic, align 4 // CHECK: store float #pragma omp atomic read fv = fx; -// CHECK: load atomic i64, ptr {{.*}} monotonic, align 8 -// CHECK: bitcast i64 {{.*}} to double +// CHECK: load atomic double, ptr {{.*}} monotonic, align 8 // CHECK: store double #pragma omp atomic read dv = dx; @@ -194,11 +192,11 @@ int main(void) { // CHECK: store i64 #pragma omp atomic read lv = cix; -// CHECK: load atomic i32, ptr {{.*}} monotonic, align 4 +// CHECK: load atomic float, ptr {{.*}} monotonic, align 4 // CHECK: store i64 #pragma omp atomic read ulv = fx; -// CHECK: load atomic i64, ptr {{.*}} monotonic, align 8 +// CHECK: load atomic double, ptr {{.*}} monotonic, align 8 // CHECK: store i64 #pragma omp atomic read llv = dx; diff --git a/clang/test/OpenMP/atomic_write_codegen.c b/clang/test/OpenMP/atomic_write_codegen.c index 24dfbf9c0e8f..afe8737d30b0 100644 --- a/clang/test/OpenMP/atomic_write_codegen.c +++ b/clang/test/OpenMP/atomic_write_codegen.c @@ -131,13 +131,11 @@ int main(void) { #pragma omp atomic write ullx = ullv; // CHECK: load float, ptr -// CHECK: bitcast float {{.*}} to i32 -// CHECK: store atomic i32 {{.*}}, ptr {{.*}} monotonic, align 4 +// CHECK: store atomic float {{.*}}, ptr {{.*}} monotonic, align 4 #pragma omp atomic write fx = fv; // CHECK: load double, ptr -// CHECK: bitcast double {{.*}} to i64 -// CHECK: store atomic i64 {{.*}}, ptr {{.*}} monotonic, align 8 +// CHECK: store atomic double {{.*}}, ptr {{.*}} monotonic, align 8 #pragma omp atomic write dx = dv; // CHECK: [[LD:%.+]] = load x86_fp80, ptr @@ -215,11 +213,11 @@ int main(void) { #pragma omp atomic write cix = lv; // CHECK: load i64, ptr -// CHECK: store atomic i32 %{{.+}}, ptr {{.*}} monotonic, align 4 +// CHECK: store atomic float %{{.+}}, ptr {{.*}} monotonic, align 4 #pragma omp atomic write fx = ulv; // CHECK: load i64, ptr -// CHECK: store atomic i64 %{{.+}}, ptr {{.*}} monotonic, align 8 +// CHECK: store atomic double %{{.+}}, ptr {{.*}} monotonic, align 8 #pragma omp atomic write dx = llv; // CHECK: load i64, ptr @@ -491,8 +489,7 @@ int main(void) { float2x.x = ulv; // CHECK: call i32 @llvm.read_register.i32( // CHECK: sitofp i32 %{{.+}} to double -// CHECK: bitcast double %{{.+}} to i64 -// CHECK: store atomic i64 %{{.+}}, ptr @{{.+}} seq_cst, align 8 +// CHECK: store atomic double %{{.+}}, ptr @{{.+}} seq_cst, align 8 // CHECK: call{{.*}} @__kmpc_flush( #pragma omp atomic write seq_cst dv = rix; -- GitLab From afd47587039e5a93919eb962cfe3a230cc91c504 Mon Sep 17 00:00:00 2001 From: Danial Klimkin Date: Tue, 12 Mar 2024 15:01:18 +0100 Subject: [PATCH 246/953] Revert "[NVPTX] Add support for atomic add for f16 type" (#84918) Reverts llvm/llvm-project#84295 due to breakages. --- llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp | 3 - llvm/lib/Target/NVPTX/NVPTXIntrinsics.td | 15 --- llvm/test/CodeGen/NVPTX/atomics-sm70.ll | 121 -------------------- llvm/test/CodeGen/NVPTX/atomics.ll | 7 -- 4 files changed, 146 deletions(-) delete mode 100644 llvm/test/CodeGen/NVPTX/atomics-sm70.ll diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp index c411c8ef9528..c979c03dc1b8 100644 --- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp @@ -6100,9 +6100,6 @@ NVPTXTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const { if (AI->isFloatingPointOperation()) { if (AI->getOperation() == AtomicRMWInst::BinOp::FAdd) { - if (Ty->isHalfTy() && STI.getSmVersion() >= 70 && - STI.getPTXVersion() >= 63) - return AtomicExpansionKind::None; if (Ty->isFloatTy()) return AtomicExpansionKind::None; if (Ty->isDoubleTy() && STI.hasAtomAddF64()) diff --git a/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td b/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td index 869b13369e87..477789a164ea 100644 --- a/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td +++ b/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td @@ -1630,13 +1630,6 @@ defm INT_PTX_ATOM_ADD_GEN_64 : F_ATOMIC_2; -defm INT_PTX_ATOM_ADD_G_F16 : F_ATOMIC_2, hasPTX<63>]>; -defm INT_PTX_ATOM_ADD_S_F16 : F_ATOMIC_2, hasPTX<63>]>; -defm INT_PTX_ATOM_ADD_GEN_F16 : F_ATOMIC_2, hasPTX<63>]>; - defm INT_PTX_ATOM_ADD_G_F32 : F_ATOMIC_2; defm INT_PTX_ATOM_ADD_S_F32 : F_ATOMIC_2 Preds> { let AddedComplexity = 1 in { - def : ATOM23_impl; def : ATOM23_impl; @@ -2027,9 +2017,6 @@ multiclass ATOM2P_impl; def : ATOM23_impl; @@ -2149,8 +2136,6 @@ multiclass ATOM2_add_impl { defm _s32 : ATOM2S_impl; defm _u32 : ATOM2S_impl; defm _u64 : ATOM2S_impl; - defm _f16 : ATOM2S_impl, hasPTX<63>]>; defm _f32 : ATOM2S_impl; defm _f64 : ATOM2S_impl; -; CHECK-NEXT: .reg .b32 %r<4>; -; CHECK-EMPTY: -; CHECK-NEXT: // %bb.0: -; CHECK-NEXT: ld.param.u32 %r1, [test_param_0]; -; CHECK-NEXT: ld.param.b16 %rs1, [test_param_3]; -; CHECK-NEXT: atom.add.noftz.f16 %rs2, [%r1], %rs1; -; CHECK-NEXT: ld.param.u32 %r2, [test_param_1]; -; CHECK-NEXT: atom.global.add.noftz.f16 %rs3, [%r2], %rs1; -; CHECK-NEXT: ld.param.u32 %r3, [test_param_2]; -; CHECK-NEXT: atom.shared.add.noftz.f16 %rs4, [%r3], %rs1; -; CHECK-NEXT: ret; -; -; CHECK64-LABEL: test( -; CHECK64: { -; CHECK64-NEXT: .reg .b16 %rs<5>; -; CHECK64-NEXT: .reg .b64 %rd<4>; -; CHECK64-EMPTY: -; CHECK64-NEXT: // %bb.0: -; CHECK64-NEXT: ld.param.u64 %rd1, [test_param_0]; -; CHECK64-NEXT: ld.param.b16 %rs1, [test_param_3]; -; CHECK64-NEXT: atom.add.noftz.f16 %rs2, [%rd1], %rs1; -; CHECK64-NEXT: ld.param.u64 %rd2, [test_param_1]; -; CHECK64-NEXT: atom.global.add.noftz.f16 %rs3, [%rd2], %rs1; -; CHECK64-NEXT: ld.param.u64 %rd3, [test_param_2]; -; CHECK64-NEXT: atom.shared.add.noftz.f16 %rs4, [%rd3], %rs1; -; CHECK64-NEXT: ret; -; -; CHECKPTX62-LABEL: test( -; CHECKPTX62: { -; CHECKPTX62-NEXT: .reg .pred %p<4>; -; CHECKPTX62-NEXT: .reg .b16 %rs<14>; -; CHECKPTX62-NEXT: .reg .b32 %r<49>; -; CHECKPTX62-EMPTY: -; CHECKPTX62-NEXT: // %bb.0: -; CHECKPTX62-NEXT: ld.param.b16 %rs1, [test_param_3]; -; CHECKPTX62-NEXT: ld.param.u32 %r20, [test_param_2]; -; CHECKPTX62-NEXT: ld.param.u32 %r19, [test_param_1]; -; CHECKPTX62-NEXT: ld.param.u32 %r21, [test_param_0]; -; CHECKPTX62-NEXT: and.b32 %r1, %r21, -4; -; CHECKPTX62-NEXT: and.b32 %r22, %r21, 3; -; CHECKPTX62-NEXT: shl.b32 %r2, %r22, 3; -; CHECKPTX62-NEXT: mov.b32 %r23, 65535; -; CHECKPTX62-NEXT: shl.b32 %r24, %r23, %r2; -; CHECKPTX62-NEXT: not.b32 %r3, %r24; -; CHECKPTX62-NEXT: ld.u32 %r46, [%r1]; -; CHECKPTX62-NEXT: $L__BB0_1: // %atomicrmw.start -; CHECKPTX62-NEXT: // =>This Inner Loop Header: Depth=1 -; CHECKPTX62-NEXT: shr.u32 %r25, %r46, %r2; -; CHECKPTX62-NEXT: cvt.u16.u32 %rs2, %r25; -; CHECKPTX62-NEXT: add.rn.f16 %rs4, %rs2, %rs1; -; CHECKPTX62-NEXT: cvt.u32.u16 %r26, %rs4; -; CHECKPTX62-NEXT: shl.b32 %r27, %r26, %r2; -; CHECKPTX62-NEXT: and.b32 %r28, %r46, %r3; -; CHECKPTX62-NEXT: or.b32 %r29, %r28, %r27; -; CHECKPTX62-NEXT: atom.cas.b32 %r6, [%r1], %r46, %r29; -; CHECKPTX62-NEXT: setp.ne.s32 %p1, %r6, %r46; -; CHECKPTX62-NEXT: mov.u32 %r46, %r6; -; CHECKPTX62-NEXT: @%p1 bra $L__BB0_1; -; CHECKPTX62-NEXT: // %bb.2: // %atomicrmw.end -; CHECKPTX62-NEXT: and.b32 %r7, %r19, -4; -; CHECKPTX62-NEXT: shl.b32 %r30, %r19, 3; -; CHECKPTX62-NEXT: and.b32 %r8, %r30, 24; -; CHECKPTX62-NEXT: shl.b32 %r32, %r23, %r8; -; CHECKPTX62-NEXT: not.b32 %r9, %r32; -; CHECKPTX62-NEXT: ld.global.u32 %r47, [%r7]; -; CHECKPTX62-NEXT: $L__BB0_3: // %atomicrmw.start9 -; CHECKPTX62-NEXT: // =>This Inner Loop Header: Depth=1 -; CHECKPTX62-NEXT: shr.u32 %r33, %r47, %r8; -; CHECKPTX62-NEXT: cvt.u16.u32 %rs6, %r33; -; CHECKPTX62-NEXT: add.rn.f16 %rs8, %rs6, %rs1; -; CHECKPTX62-NEXT: cvt.u32.u16 %r34, %rs8; -; CHECKPTX62-NEXT: shl.b32 %r35, %r34, %r8; -; CHECKPTX62-NEXT: and.b32 %r36, %r47, %r9; -; CHECKPTX62-NEXT: or.b32 %r37, %r36, %r35; -; CHECKPTX62-NEXT: atom.global.cas.b32 %r12, [%r7], %r47, %r37; -; CHECKPTX62-NEXT: setp.ne.s32 %p2, %r12, %r47; -; CHECKPTX62-NEXT: mov.u32 %r47, %r12; -; CHECKPTX62-NEXT: @%p2 bra $L__BB0_3; -; CHECKPTX62-NEXT: // %bb.4: // %atomicrmw.end8 -; CHECKPTX62-NEXT: and.b32 %r13, %r20, -4; -; CHECKPTX62-NEXT: shl.b32 %r38, %r20, 3; -; CHECKPTX62-NEXT: and.b32 %r14, %r38, 24; -; CHECKPTX62-NEXT: shl.b32 %r40, %r23, %r14; -; CHECKPTX62-NEXT: not.b32 %r15, %r40; -; CHECKPTX62-NEXT: ld.shared.u32 %r48, [%r13]; -; CHECKPTX62-NEXT: $L__BB0_5: // %atomicrmw.start27 -; CHECKPTX62-NEXT: // =>This Inner Loop Header: Depth=1 -; CHECKPTX62-NEXT: shr.u32 %r41, %r48, %r14; -; CHECKPTX62-NEXT: cvt.u16.u32 %rs10, %r41; -; CHECKPTX62-NEXT: add.rn.f16 %rs12, %rs10, %rs1; -; CHECKPTX62-NEXT: cvt.u32.u16 %r42, %rs12; -; CHECKPTX62-NEXT: shl.b32 %r43, %r42, %r14; -; CHECKPTX62-NEXT: and.b32 %r44, %r48, %r15; -; CHECKPTX62-NEXT: or.b32 %r45, %r44, %r43; -; CHECKPTX62-NEXT: atom.shared.cas.b32 %r18, [%r13], %r48, %r45; -; CHECKPTX62-NEXT: setp.ne.s32 %p3, %r18, %r48; -; CHECKPTX62-NEXT: mov.u32 %r48, %r18; -; CHECKPTX62-NEXT: @%p3 bra $L__BB0_5; -; CHECKPTX62-NEXT: // %bb.6: // %atomicrmw.end26 -; CHECKPTX62-NEXT: ret; - %r1 = atomicrmw fadd ptr %dp0, half %val seq_cst - %r2 = atomicrmw fadd ptr addrspace(1) %dp1, half %val seq_cst - %ret = atomicrmw fadd ptr addrspace(3) %dp3, half %val seq_cst - ret void -} - -attributes #1 = { argmemonly nounwind } diff --git a/llvm/test/CodeGen/NVPTX/atomics.ll b/llvm/test/CodeGen/NVPTX/atomics.ll index 6f2b5dcf47f1..e99d0fd05e34 100644 --- a/llvm/test/CodeGen/NVPTX/atomics.ll +++ b/llvm/test/CodeGen/NVPTX/atomics.ll @@ -175,13 +175,6 @@ define float @atomicrmw_add_f32_generic(ptr %addr, float %val) { ret float %ret } -; CHECK-LABEL: atomicrmw_add_f16_generic -define half @atomicrmw_add_f16_generic(ptr %addr, half %val) { -; CHECK: atom.cas - %ret = atomicrmw fadd ptr %addr, half %val seq_cst - ret half %ret -} - ; CHECK-LABEL: atomicrmw_add_f32_addrspace1 define float @atomicrmw_add_f32_addrspace1(ptr addrspace(1) %addr, float %val) { ; CHECK: atom.global.add.f32 -- GitLab From f8fab2126ffab713f4ab4619360b6941be6d4e35 Mon Sep 17 00:00:00 2001 From: Kupa-Martin <84517188+Kupa-Martin@users.noreply.github.com> Date: Tue, 12 Mar 2024 11:21:34 -0300 Subject: [PATCH 247/953] [Clang][Sema] Fix type of enumerators in incomplete enumerations (#84068) Enumerators dont have the type of their enumeration before the closing brace. In these cases Expr::getEnumCoercedType() incorrectly returned the enumeration type. Introduced in PR #81418 Fixes #84712 --- clang/lib/AST/Expr.cpp | 13 ++++++++----- clang/test/Sema/enum-constant-type.cpp | 12 ++++++++++++ clang/test/Sema/warn-compare-enum-types-mismatch.c | 11 ++++++++++- 3 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 clang/test/Sema/enum-constant-type.cpp diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index b4de2155adce..f5ad402e3bd7 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -264,11 +264,14 @@ namespace { } QualType Expr::getEnumCoercedType(const ASTContext &Ctx) const { - if (isa(this->getType())) - return this->getType(); - else if (const auto *ECD = this->getEnumConstantDecl()) - return Ctx.getTypeDeclType(cast(ECD->getDeclContext())); - return this->getType(); + if (isa(getType())) + return getType(); + if (const auto *ECD = getEnumConstantDecl()) { + const auto *ED = cast(ECD->getDeclContext()); + if (ED->isCompleteDefinition()) + return Ctx.getTypeDeclType(ED); + } + return getType(); } SourceLocation Expr::getExprLoc() const { diff --git a/clang/test/Sema/enum-constant-type.cpp b/clang/test/Sema/enum-constant-type.cpp new file mode 100644 index 000000000000..5db3a859a395 --- /dev/null +++ b/clang/test/Sema/enum-constant-type.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -x c++ -fsyntax-only -verify %s -Wenum-compare +// expected-no-diagnostics + +enum E1 { + E11 = 0 +}; + +enum E2 { + E21 = 0, + E22 = E11, + E23 = E21 + E22 +}; diff --git a/clang/test/Sema/warn-compare-enum-types-mismatch.c b/clang/test/Sema/warn-compare-enum-types-mismatch.c index 2b72aae16b97..47dd592488e6 100644 --- a/clang/test/Sema/warn-compare-enum-types-mismatch.c +++ b/clang/test/Sema/warn-compare-enum-types-mismatch.c @@ -1,12 +1,21 @@ // RUN: %clang_cc1 -x c -fsyntax-only -verify -Wenum-compare -Wno-unused-comparison %s // RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wenum-compare -Wno-unused-comparison %s +// In C enumerators (i.e enumeration constants) have type int (until C23). In +// order to support diagnostics such as -Wenum-compare we pretend they have the +// type of their enumeration. + typedef enum EnumA { A } EnumA; enum EnumB { - B + B, + B1 = 1, + // In C++ this comparison doesnt warn as enumerators dont have the type of + // their enumeration before the closing brace. We mantain the same behavior + // in C. + B2 = A == B1 }; enum { -- GitLab From a4aac22683a44264bb3883242b1c6b711f534e8b Mon Sep 17 00:00:00 2001 From: harishch4 Date: Tue, 12 Mar 2024 20:04:35 +0530 Subject: [PATCH 248/953] [Flang][OpenMp] Fix to threadprivate not working with host-association. (#74966) This patch considers host-associated variables to generate threadprivate Ops. Fixes: #60763 #84561 --- flang/lib/Lower/HostAssociations.cpp | 14 +++++- flang/lib/Lower/OpenMP/OpenMP.cpp | 18 +++++--- .../threadprivate-host-association-2.f90 | 44 +++++++++++++++++++ .../OpenMP/threadprivate-host-association.f90 | 42 ++++++++++++++++++ 4 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 flang/test/Lower/OpenMP/threadprivate-host-association-2.f90 create mode 100644 flang/test/Lower/OpenMP/threadprivate-host-association.f90 diff --git a/flang/lib/Lower/HostAssociations.cpp b/flang/lib/Lower/HostAssociations.cpp index b9e13ccad1c9..414673b00f44 100644 --- a/flang/lib/Lower/HostAssociations.cpp +++ b/flang/lib/Lower/HostAssociations.cpp @@ -14,6 +14,7 @@ #include "flang/Lower/CallInterface.h" #include "flang/Lower/ConvertType.h" #include "flang/Lower/ConvertVariable.h" +#include "flang/Lower/OpenMP.h" #include "flang/Lower/PFTBuilder.h" #include "flang/Lower/SymbolMap.h" #include "flang/Optimizer/Builder/Character.h" @@ -542,7 +543,10 @@ void Fortran::lower::HostAssociations::addSymbolsToBind( "must be initially empty"); this->hostScope = &hostScope; for (const auto *s : symbols) - if (Fortran::lower::symbolIsGlobal(*s)) { + // GlobalOp are created for non-global threadprivate variable, + // so considering them as globals. + if (Fortran::lower::symbolIsGlobal(*s) || + (*s).test(Fortran::semantics::Symbol::Flag::OmpThreadprivate)) { // The ultimate symbol is stored here so that global symbols from the // host scope can later be searched in this set. globalSymbols.insert(&s->GetUltimate()); @@ -590,9 +594,15 @@ void Fortran::lower::HostAssociations::internalProcedureBindings( for (auto &hostVariable : pft::getScopeVariableList(*hostScope)) if ((hostVariable.isAggregateStore() && hostVariable.isGlobal()) || (hostVariable.hasSymbol() && - globalSymbols.contains(&hostVariable.getSymbol().GetUltimate()))) + globalSymbols.contains(&hostVariable.getSymbol().GetUltimate()))) { Fortran::lower::instantiateVariable(converter, hostVariable, symMap, storeMap); + // Generate threadprivate Op for host associated variables. + if (hostVariable.hasSymbol() && + hostVariable.getSymbol().test( + Fortran::semantics::Symbol::Flag::OmpThreadprivate)) + Fortran::lower::genThreadprivateOp(converter, hostVariable); + } } if (tupleSymbols.empty()) return; diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 5cff95c7d125..4f0bb80cd7fd 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -170,9 +170,10 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter, }; llvm::SetVector threadprivateSyms; - converter.collectSymbolSet( - eval, threadprivateSyms, - Fortran::semantics::Symbol::Flag::OmpThreadprivate); + converter.collectSymbolSet(eval, threadprivateSyms, + Fortran::semantics::Symbol::Flag::OmpThreadprivate, + /*collectSymbols=*/true, + /*collectHostAssociatedSymbols=*/true); std::set threadprivateSymNames; // For a COMMON block, the ThreadprivateOp is generated for itself instead of @@ -2276,8 +2277,15 @@ void Fortran::lower::genThreadprivateOp( // variable in main program, and it has implicit SAVE attribute. Take it as // with SAVE attribute, so to create GlobalOp for it to simplify the // translation to LLVM IR. - fir::GlobalOp global = globalInitialization(converter, firOpBuilder, sym, - var, currentLocation); + // Avoids performing multiple globalInitializations. + fir::GlobalOp global; + auto module = converter.getModuleOp(); + std::string globalName = converter.mangleName(sym); + if (module.lookupSymbol(globalName)) + global = module.lookupSymbol(globalName); + else + global = globalInitialization(converter, firOpBuilder, sym, var, + currentLocation); mlir::Value symValue = firOpBuilder.create( currentLocation, global.resultType(), global.getSymbol()); diff --git a/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90 b/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90 new file mode 100644 index 000000000000..b47bff5bebb0 --- /dev/null +++ b/flang/test/Lower/OpenMP/threadprivate-host-association-2.f90 @@ -0,0 +1,44 @@ +! This test checks lowering of OpenMP Threadprivate Directive. +! Test for threadprivate variable in host association. + +!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s + +!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "main"} { +!CHECK: %[[A:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"} +!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref +!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref -> !fir.ref +!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: fir.call @_QFPsub() fastmath : () -> () +!CHECK: return +!CHECK: } +!CHECK: func.func private @_QFPsub() attributes {fir.internal_proc, llvm.linkage = #llvm.linkage} { +!CHECK: %[[A:.*]] = fir.alloca i32 {bindc_name = "a", uniq_name = "_QFEa"} +!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[A_ADDR:.*]] = fir.address_of(@_QFEa) : !fir.ref +!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref -> !fir.ref +!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: omp.parallel { +!CHECK: %[[PAR_TP_A:.*]] = omp.threadprivate %[[A_ADDR]] : !fir.ref -> !fir.ref +!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] {uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %{{.*}} = fir.load %[[PAR_TP_A_DECL]]#0 : !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +!CHECK: } +!CHECK: fir.global internal @_QFEa : i32 { +!CHECK: %[[A:.*]] = fir.undefined i32 +!CHECK: fir.has_value %[[A]] : i32 +!CHECK: } + +program main + integer :: a + !$omp threadprivate(a) + call sub() +contains + subroutine sub() + !$omp parallel + print *, a + !$omp end parallel + end +end diff --git a/flang/test/Lower/OpenMP/threadprivate-host-association.f90 b/flang/test/Lower/OpenMP/threadprivate-host-association.f90 new file mode 100644 index 000000000000..98f7b51bb971 --- /dev/null +++ b/flang/test/Lower/OpenMP/threadprivate-host-association.f90 @@ -0,0 +1,42 @@ +! This test checks lowering of OpenMP Threadprivate Directive. +! Test for threadprivate variable in host association. + +!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s + +!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "main"} { +!CHECK: %[[A:.*]] = fir.address_of(@_QFEa) : !fir.ref +!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_DECL]]#1 : !fir.ref -> !fir.ref +!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: fir.call @_QFPsub() fastmath : () -> () +!CHECK: return +!CHECK: } +!CHECK: func.func private @_QFPsub() attributes {fir.internal_proc, llvm.linkage = #llvm.linkage} { +!CHECK: %[[A:.*]] = fir.address_of(@_QFEa) : !fir.ref +!CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[A]] {uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TP_A:.*]] = omp.threadprivate %[[A_DECL]]#1 : !fir.ref -> !fir.ref +!CHECK: %[[TP_A_DECL:.*]]:2 = hlfir.declare %[[TP_A]] {uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: omp.parallel { +!CHECK: %[[PAR_TP_A:.*]] = omp.threadprivate %[[A_DECL]]#1 : !fir.ref -> !fir.ref +!CHECK: %[[PAR_TP_A_DECL:.*]]:2 = hlfir.declare %[[PAR_TP_A]] {uniq_name = "_QFEa"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %{{.*}} = fir.load %[[PAR_TP_A_DECL]]#0 : !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +!CHECK: } +!CHECK: fir.global internal @_QFEa : i32 { +!CHECK: %[[A:.*]] = fir.zero_bits i32 +!CHECK: fir.has_value %[[A]] : i32 +!CHECK: } + +program main + integer, save :: a + !$omp threadprivate(a) + call sub() +contains + subroutine sub() + !$omp parallel + print *, a + !$omp end parallel + end +end -- GitLab From a3ad5faa321848376b277db369313c80d3df2152 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 12 Mar 2024 14:44:04 +0000 Subject: [PATCH 249/953] [LAA] Fix typo IndidrectUnsafe -> IndirectUnsafe. Fix type in textual analysis output. --- llvm/lib/Analysis/LoopAccessAnalysis.cpp | 2 +- .../loops-with-indirect-reads-and-writes.ll | 4 ++-- .../LoopAccessAnalysis/underlying-object-loop-varying-phi.ll | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp index dd6b88fee415..c25eede96a18 100644 --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -2260,7 +2260,7 @@ MemoryDepChecker::getInstructionsForAccess(Value *Ptr, bool isWrite) const { const char *MemoryDepChecker::Dependence::DepName[] = { "NoDep", "Unknown", - "IndidrectUnsafe", + "IndirectUnsafe", "Forward", "ForwardButPreventsForwarding", "Backward", diff --git a/llvm/test/Analysis/LoopAccessAnalysis/loops-with-indirect-reads-and-writes.ll b/llvm/test/Analysis/LoopAccessAnalysis/loops-with-indirect-reads-and-writes.ll index e643efc4bfc5..fd4f417e57b6 100644 --- a/llvm/test/Analysis/LoopAccessAnalysis/loops-with-indirect-reads-and-writes.ll +++ b/llvm/test/Analysis/LoopAccessAnalysis/loops-with-indirect-reads-and-writes.ll @@ -24,7 +24,7 @@ define void @test_indirect_read_write_loop_also_modifies_pointer_array(ptr nound ; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop ; CHECK-NEXT: Unsafe indirect dependence. ; CHECK-NEXT: Dependences: -; CHECK-NEXT: IndidrectUnsafe: +; CHECK-NEXT: IndirectUnsafe: ; CHECK-NEXT: %l.2 = load i64, ptr %l.1, align 8, !tbaa !4 -> ; CHECK-NEXT: store i64 %inc, ptr %l.1, align 8, !tbaa !4 ; CHECK-EMPTY: @@ -229,7 +229,7 @@ define void @test_indirect_read_write_loop_does_not_modify_pointer_array(ptr nou ; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop ; CHECK-NEXT: Unsafe indirect dependence. ; CHECK-NEXT: Dependences: -; CHECK-NEXT: IndidrectUnsafe: +; CHECK-NEXT: IndirectUnsafe: ; CHECK-NEXT: %l.2 = load i64, ptr %l.1, align 8, !tbaa !4 -> ; CHECK-NEXT: store i64 %inc, ptr %l.1, align 8, !tbaa !4 ; CHECK-EMPTY: diff --git a/llvm/test/Analysis/LoopAccessAnalysis/underlying-object-loop-varying-phi.ll b/llvm/test/Analysis/LoopAccessAnalysis/underlying-object-loop-varying-phi.ll index 106dc8c13a49..402081fb939f 100644 --- a/llvm/test/Analysis/LoopAccessAnalysis/underlying-object-loop-varying-phi.ll +++ b/llvm/test/Analysis/LoopAccessAnalysis/underlying-object-loop-varying-phi.ll @@ -10,7 +10,7 @@ define void @indirect_ptr_recurrences_read_write(ptr %A, ptr %B) { ; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop ; CHECK-NEXT: Unsafe indirect dependence. ; CHECK-NEXT: Dependences: -; CHECK-NEXT: IndidrectUnsafe: +; CHECK-NEXT: IndirectUnsafe: ; CHECK-NEXT: %l = load i32, ptr %ptr.recur, align 4, !tbaa !4 -> ; CHECK-NEXT: store i32 %xor, ptr %ptr.recur, align 4, !tbaa !4 ; CHECK-EMPTY: -- GitLab From 2cae13d60590c999c37828d709ff4ba58e5f261b Mon Sep 17 00:00:00 2001 From: bvlgah Date: Tue, 12 Mar 2024 22:46:18 +0800 Subject: [PATCH 250/953] [DominanceFrontierBase] Fix doc of compare()'s return value. (#81352) This is a trivial fix ( I guess it has not been noticed because of no use). Currently, the doc says the function returns `true` if two instances of `DominanceFrontierBase` matches, otherwise `false` is returned. I have checked the implementation https://github.com/llvm/llvm-project/blob/9308d6688c673606fee1625d777a52539ae72015/llvm/include/llvm/Analysis/DominanceFrontierImpl.h#L71-L94 which examines whether two dominance frontier mappings are equal, and the actual value it returns contradicts the description in the doc. --- llvm/include/llvm/Analysis/DominanceFrontier.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Analysis/DominanceFrontier.h b/llvm/include/llvm/Analysis/DominanceFrontier.h index b65cdc9cdb3c..772fdc9ddee0 100644 --- a/llvm/include/llvm/Analysis/DominanceFrontier.h +++ b/llvm/include/llvm/Analysis/DominanceFrontier.h @@ -101,8 +101,8 @@ public: /// return true; bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const; - /// compare - Return true if the other dominance frontier base matches - /// this dominance frontier base. Otherwise return false. + /// compare - Return false if the other dominance frontier base matches + /// this dominance frontier base. Otherwise return true. bool compare(DominanceFrontierBase &Other) const; /// print - Convert to human readable form -- GitLab From 0aefd702f6c5346f216d29c704c4d0e4ec7397ac Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Tue, 12 Mar 2024 10:48:50 -0400 Subject: [PATCH 251/953] [gn] port bde7a6b791872b --- llvm/utils/gn/secondary/clang/unittests/Interpreter/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/clang/unittests/Interpreter/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/Interpreter/BUILD.gn index 4107bbc12be2..c2999a67f58a 100644 --- a/llvm/utils/gn/secondary/clang/unittests/Interpreter/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/unittests/Interpreter/BUILD.gn @@ -9,6 +9,7 @@ unittest("ClangReplInterpreterTests") { "//clang/lib/Interpreter", "//llvm/lib/IR", "//llvm/lib/TargetParser", + "//llvm/lib/Testing/Support", ] sources = [ "CodeCompletionTest.cpp", -- GitLab From 15f3f446c504d1bb85282fb3bd98db6eab69829d Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Tue, 12 Mar 2024 14:53:13 +0000 Subject: [PATCH 252/953] [RemoveDIs][NFC] Rename common interface functions for DPValues->DbgRecords (#84793) As part of the effort to rename the DbgRecord classes, this patch renames the widely-used functions that operate on DbgRecords but refer to DbgValues or DPValues in their names to refer to DbgRecords instead; all such functions are defined in one of `BasicBlock.h`, `Instruction.h`, and `DebugProgramInstruction.h`. This patch explicitly does not change the names of any comments or variables, except for where they use the exact name of one of the renamed functions. The reason for this is reviewability; this patch can be trivially examined to determine that the only changes are direct string substitutions and any results from clang-format responding to the changed line lengths. Future patches will cover renaming variables and comments, and then renaming the classes themselves. --- llvm/docs/RemoveDIsDebugInfo.md | 4 +- llvm/include/llvm/IR/BasicBlock.h | 18 +-- .../include/llvm/IR/DebugProgramInstruction.h | 22 +-- llvm/include/llvm/IR/Instruction.h | 18 +-- llvm/lib/AsmParser/LLParser.cpp | 2 +- .../CodeGen/AssignmentTrackingAnalysis.cpp | 26 ++-- llvm/lib/CodeGen/CodeGenPrepare.cpp | 10 +- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 2 +- llvm/lib/CodeGen/SelectOptimize.cpp | 6 +- llvm/lib/CodeGen/SelectionDAG/FastISel.cpp | 4 +- .../SelectionDAG/SelectionDAGBuilder.cpp | 2 +- .../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 2 +- llvm/lib/IR/AsmWriter.cpp | 4 +- llvm/lib/IR/BasicBlock.cpp | 79 +++++----- llvm/lib/IR/DIBuilder.cpp | 6 +- llvm/lib/IR/DebugInfo.cpp | 10 +- llvm/lib/IR/DebugProgramInstruction.cpp | 24 ++-- llvm/lib/IR/Instruction.cpp | 22 +-- llvm/lib/IR/LLVMContextImpl.h | 8 +- llvm/lib/IR/Verifier.cpp | 6 +- llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 8 +- llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 2 +- llvm/lib/Transforms/IPO/IROutliner.cpp | 2 +- llvm/lib/Transforms/IPO/MergeFunctions.cpp | 4 +- .../InstCombine/InstructionCombining.cpp | 6 +- llvm/lib/Transforms/Scalar/ADCE.cpp | 4 +- .../Transforms/Scalar/CallSiteSplitting.cpp | 2 +- llvm/lib/Transforms/Scalar/JumpThreading.cpp | 6 +- .../Transforms/Scalar/LoopStrengthReduce.cpp | 2 +- llvm/lib/Transforms/Scalar/SROA.cpp | 4 +- .../Transforms/Scalar/SimpleLoopUnswitch.cpp | 2 +- .../Scalar/SpeculativeExecution.cpp | 6 +- llvm/lib/Transforms/Utils/BasicBlockUtils.cpp | 6 +- llvm/lib/Transforms/Utils/CloneFunction.cpp | 6 +- llvm/lib/Transforms/Utils/CodeExtractor.cpp | 6 +- llvm/lib/Transforms/Utils/InlineFunction.cpp | 6 +- llvm/lib/Transforms/Utils/Local.cpp | 24 ++-- .../Transforms/Utils/LoopRotationUtils.cpp | 10 +- .../Transforms/Utils/LoopUnrollRuntime.cpp | 2 +- llvm/lib/Transforms/Utils/LoopUtils.cpp | 4 +- .../Transforms/Utils/MemoryTaggingSupport.cpp | 2 +- llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 20 +-- llvm/lib/Transforms/Utils/ValueMapper.cpp | 2 +- .../llvm-reduce/deltas/ReduceDbgRecords.cpp | 2 +- llvm/unittests/IR/BasicBlockDbgInfoTest.cpp | 136 +++++++++--------- llvm/unittests/IR/DebugInfoTest.cpp | 26 ++-- llvm/unittests/IR/IRBuilderTest.cpp | 12 +- llvm/unittests/IR/ValueTest.cpp | 8 +- .../Transforms/Utils/DebugifyTest.cpp | 2 +- llvm/unittests/Transforms/Utils/LocalTest.cpp | 2 +- 50 files changed, 298 insertions(+), 301 deletions(-) diff --git a/llvm/docs/RemoveDIsDebugInfo.md b/llvm/docs/RemoveDIsDebugInfo.md index a0577678e20f..a9857733c70d 100644 --- a/llvm/docs/RemoveDIsDebugInfo.md +++ b/llvm/docs/RemoveDIsDebugInfo.md @@ -82,11 +82,11 @@ Utilities such as `findDbgUsers` and the like now have an optional argument that ## Examining debug info records at positions -Call `Instruction::getDbgValueRange()` to get the range of `DPValue` objects that are attached to an instruction. +Call `Instruction::getDbgRecordRange()` to get the range of `DPValue` objects that are attached to an instruction. ## Moving around, deleting -You can use `DPValue::removeFromParent` to unlink a `DPValue` from it's marker, and then `BasicBlock::insertDPValueBefore` or `BasicBlock::insertDPValueAfter` to re-insert the `DPValue` somewhere else. You cannot insert a `DPValue` at an arbitary point in a list of `DPValue`s (if you're doing this with `dbg.value`s then it's unlikely to be correct). +You can use `DPValue::removeFromParent` to unlink a `DPValue` from it's marker, and then `BasicBlock::insertDbgRecordBefore` or `BasicBlock::insertDbgRecordAfter` to re-insert the `DPValue` somewhere else. You cannot insert a `DPValue` at an arbitary point in a list of `DPValue`s (if you're doing this with `dbg.value`s then it's unlikely to be correct). Erase `DPValue`s by calling `eraseFromParent` or `deleteInstr` if it's already been removed. diff --git a/llvm/include/llvm/IR/BasicBlock.h b/llvm/include/llvm/IR/BasicBlock.h index 179305e9260f..5bac113c9b7b 100644 --- a/llvm/include/llvm/IR/BasicBlock.h +++ b/llvm/include/llvm/IR/BasicBlock.h @@ -97,16 +97,16 @@ public: /// instruction of this block. These are equivalent to dbg.value intrinsics /// that exist at the end of a basic block with no terminator (a transient /// state that occurs regularly). - void setTrailingDPValues(DPMarker *M); + void setTrailingDbgRecords(DPMarker *M); /// Fetch the collection of DPValues that "trail" after the last instruction - /// of this block, see \ref setTrailingDPValues. If there are none, returns + /// of this block, see \ref setTrailingDbgRecords. If there are none, returns /// nullptr. - DPMarker *getTrailingDPValues(); + DPMarker *getTrailingDbgRecords(); /// Delete any trailing DPValues at the end of this block, see - /// \ref setTrailingDPValues. - void deleteTrailingDPValues(); + /// \ref setTrailingDbgRecords. + void deleteTrailingDbgRecords(); void dumpDbgValues() const; @@ -121,10 +121,10 @@ public: DPMarker *getNextMarker(Instruction *I); /// Insert a DPValue into a block at the position given by \p I. - void insertDPValueAfter(DbgRecord *DPV, Instruction *I); + void insertDbgRecordAfter(DbgRecord *DPV, Instruction *I); /// Insert a DPValue into a block at the position given by \p Here. - void insertDPValueBefore(DbgRecord *DPV, InstListType::iterator Here); + void insertDbgRecordBefore(DbgRecord *DPV, InstListType::iterator Here); /// Eject any debug-info trailing at the end of a block. DPValues can /// transiently be located "off the end" of a block if the blocks terminator @@ -137,8 +137,8 @@ public: /// happens in RemoveDIs debug-info mode, some special patching-up needs to /// occur: inserting into the middle of a sequence of dbg.value intrinsics /// does not have an equivalent with DPValues. - void reinsertInstInDPValues(Instruction *I, - std::optional Pos); + void reinsertInstInDbgRecords(Instruction *I, + std::optional Pos); private: void setParent(Function *parent); diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h index a8faf415a3ea..507b652feeb0 100644 --- a/llvm/include/llvm/IR/DebugProgramInstruction.h +++ b/llvm/include/llvm/IR/DebugProgramInstruction.h @@ -577,9 +577,9 @@ public: void print(raw_ostream &ROS, ModuleSlotTracker &MST, bool IsForDebug) const; /// Produce a range over all the DPValues in this Marker. - iterator_range::iterator> getDbgValueRange(); + iterator_range::iterator> getDbgRecordRange(); iterator_range::const_iterator> - getDbgValueRange() const; + getDbgRecordRange() const; /// Transfer any DPValues from \p Src into this DPMarker. If \p InsertAtHead /// is true, place them before existing DPValues, otherwise afterwards. void absorbDebugValues(DPMarker &Src, bool InsertAtHead); @@ -590,11 +590,11 @@ public: DPMarker &Src, bool InsertAtHead); /// Insert a DPValue into this DPMarker, at the end of the list. If /// \p InsertAtHead is true, at the start. - void insertDPValue(DbgRecord *New, bool InsertAtHead); + void insertDbgRecord(DbgRecord *New, bool InsertAtHead); /// Insert a DPValue prior to a DPValue contained within this marker. - void insertDPValue(DbgRecord *New, DbgRecord *InsertBefore); + void insertDbgRecord(DbgRecord *New, DbgRecord *InsertBefore); /// Insert a DPValue after a DPValue contained within this marker. - void insertDPValueAfter(DbgRecord *New, DbgRecord *InsertAfter); + void insertDbgRecordAfter(DbgRecord *New, DbgRecord *InsertAfter); /// Clone all DPMarkers from \p From into this marker. There are numerous /// options to customise the source/destination, due to gnarliness, see class /// comment. @@ -606,11 +606,11 @@ public: std::optional::iterator> FromHere, bool InsertAtHead = false); /// Erase all DPValues in this DPMarker. - void dropDbgValues(); + void dropDbgRecords(); /// Erase a single DbgRecord from this marker. In an ideal future, we would /// never erase an assignment in this way, but it's the equivalent to /// erasing a debug intrinsic from a block. - void dropOneDbgValue(DbgRecord *DR); + void dropOneDbgRecord(DbgRecord *DR); /// We generally act like all llvm Instructions have a range of DPValues /// attached to them, but in reality sometimes we don't allocate the DPMarker @@ -621,7 +621,7 @@ public: /// that. static DPMarker EmptyDPMarker; static iterator_range::iterator> - getEmptyDPValueRange() { + getEmptyDbgRecordRange() { return make_range(EmptyDPMarker.StoredDPValues.end(), EmptyDPMarker.StoredDPValues.end()); } @@ -637,10 +637,10 @@ inline raw_ostream &operator<<(raw_ostream &OS, const DPMarker &Marker) { /// of DPMarker. Thus: it's pre-declared by users like Instruction, then an /// inlineable body defined here. inline iterator_range::iterator> -getDbgValueRange(DPMarker *DbgMarker) { +getDbgRecordRange(DPMarker *DbgMarker) { if (!DbgMarker) - return DPMarker::getEmptyDPValueRange(); - return DbgMarker->getDbgValueRange(); + return DPMarker::getEmptyDbgRecordRange(); + return DbgMarker->getDbgRecordRange(); } } // namespace llvm diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h index 75f399ec2fcd..817abd6afbca 100644 --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -41,7 +41,7 @@ template <> struct ilist_alloc_traits { static inline void deleteNode(Instruction *V); }; -iterator_range::iterator> getDbgValueRange(DPMarker *); +iterator_range::iterator> getDbgRecordRange(DPMarker *); class Instruction : public User, public ilist_node_with_parent::iterator> getDbgValueRange() const { - return llvm::getDbgValueRange(DbgMarker); + iterator_range::iterator> getDbgRecordRange() const { + return llvm::getDbgRecordRange(DbgMarker); } /// Return an iterator to the position of the "Next" DPValue after this /// instruction, or std::nullopt. This is the position to pass to - /// BasicBlock::reinsertInstInDPValues when re-inserting an instruction. + /// BasicBlock::reinsertInstInDbgRecords when re-inserting an instruction. std::optional::iterator> getDbgReinsertionPosition(); /// Returns true if any DPValues are attached to this instruction. - bool hasDbgValues() const; + bool hasDbgRecords() const; /// Transfer any DPValues on the position \p It onto this instruction, /// by simply adopting the sequence of DPValues (which is efficient) if /// possible, by merging two sequences otherwise. - void adoptDbgValues(BasicBlock *BB, InstListType::iterator It, - bool InsertAtHead); + void adoptDbgRecords(BasicBlock *BB, InstListType::iterator It, + bool InsertAtHead); /// Erase any DPValues attached to this instruction. - void dropDbgValues(); + void dropDbgRecords(); /// Erase a single DPValue \p I that is attached to this instruction. - void dropOneDbgValue(DbgRecord *I); + void dropOneDbgRecord(DbgRecord *I); /// Handle the debug-info implications of this instruction being removed. Any /// attached DPValues need to "fall" down onto the next instruction. diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 78bcd94e23fa..2e0f5ba82220 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -6527,7 +6527,7 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { // Attach any preceding debug values to this instruction. for (DbgRecordPtr &DR : TrailingDbgRecord) - BB->insertDPValueBefore(DR.release(), Inst->getIterator()); + BB->insertDbgRecordBefore(DR.release(), Inst->getIterator()); TrailingDbgRecord.clear(); } while (!Inst->isTerminator()); diff --git a/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp b/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp index 3b84624c3d4d..a4b819a735c6 100644 --- a/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp +++ b/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp @@ -225,7 +225,7 @@ void FunctionVarLocs::init(FunctionVarLocsBuilder &Builder) { // Any VarLocInfos attached to a DPValue should now be remapped to their // marker Instruction, in order of DPValue appearance and prior to any // VarLocInfos attached directly to that instruction. - for (const DPValue &DPV : DPValue::filter(I->getDbgValueRange())) { + for (const DPValue &DPV : DPValue::filter(I->getDbgRecordRange())) { // Even though DPV defines a variable location, VarLocsBeforeInst can // still be empty if that VarLoc was redundant. if (!Builder.VarLocsBeforeInst.count(&DPV)) @@ -829,7 +829,7 @@ class MemLocFragmentFill { void process(BasicBlock &BB, VarFragMap &LiveSet) { BBInsertBeforeMap[&BB].clear(); for (auto &I : BB) { - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) { + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { if (const auto *Locs = FnVarLocs->getWedge(&DPV)) { for (const VarLocInfo &Loc : *Locs) { addDef(Loc, &DPV, *I.getParent(), LiveSet); @@ -1494,15 +1494,15 @@ const char *locStr(AssignmentTrackingLowering::LocKind Loc) { VarLocInsertPt getNextNode(const DbgRecord *DPV) { auto NextIt = ++(DPV->getIterator()); - if (NextIt == DPV->getMarker()->getDbgValueRange().end()) + if (NextIt == DPV->getMarker()->getDbgRecordRange().end()) return DPV->getMarker()->MarkedInstr; return &*NextIt; } VarLocInsertPt getNextNode(const Instruction *Inst) { const Instruction *Next = Inst->getNextNode(); - if (!Next->hasDbgValues()) + if (!Next->hasDbgRecords()) return Next; - return &*Next->getDbgValueRange().begin(); + return &*Next->getDbgRecordRange().begin(); } VarLocInsertPt getNextNode(VarLocInsertPt InsertPt) { if (isa(InsertPt)) @@ -1888,7 +1888,7 @@ void AssignmentTrackingLowering::resetInsertionPoint(DPValue &After) { void AssignmentTrackingLowering::process(BasicBlock &BB, BlockInfo *LiveSet) { // If the block starts with DPValues, we need to process those DPValues as // their own frame without processing any instructions first. - bool ProcessedLeadingDPValues = !BB.begin()->hasDbgValues(); + bool ProcessedLeadingDPValues = !BB.begin()->hasDbgRecords(); for (auto II = BB.begin(), EI = BB.end(); II != EI;) { assert(VarsTouchedThisFrame.empty()); // Process the instructions in "frames". A "frame" includes a single @@ -1914,11 +1914,11 @@ void AssignmentTrackingLowering::process(BasicBlock &BB, BlockInfo *LiveSet) { // II is now either a debug intrinsic, a non-debug instruction with no // attached DPValues, or a non-debug instruction with attached unprocessed // DPValues. - if (II != EI && II->hasDbgValues()) { + if (II != EI && II->hasDbgRecords()) { // Skip over non-variable debug records (i.e., labels). They're going to // be read from IR (possibly re-ordering them within the debug record // range) rather than from the analysis results. - for (DPValue &DPV : DPValue::filter(II->getDbgValueRange())) { + for (DPValue &DPV : DPValue::filter(II->getDbgRecordRange())) { resetInsertionPoint(DPV); processDPValue(DPV, LiveSet); assert(LiveSet->isValid()); @@ -2175,7 +2175,7 @@ static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares( }; for (auto &BB : Fn) { for (auto &I : BB) { - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) ProcessDbgRecord(&DPV, DPDeclares); if (auto *DII = dyn_cast(&I)) { ProcessDbgRecord(DII, InstDeclares); @@ -2465,7 +2465,7 @@ bool AssignmentTrackingLowering::emitPromotedVarLocs( for (auto &BB : Fn) { for (auto &I : BB) { // Skip instructions other than dbg.values and dbg.assigns. - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) if (DPV.isDbgValue() || DPV.isDbgAssign()) TranslateDbgRecord(&DPV); auto *DVI = dyn_cast(&I); @@ -2567,7 +2567,7 @@ removeRedundantDbgLocsUsingBackwardScan(const BasicBlock *BB, } }; HandleLocsForWedge(&I); - for (DPValue &DPV : reverse(DPValue::filter(I.getDbgValueRange()))) + for (DPValue &DPV : reverse(DPValue::filter(I.getDbgRecordRange()))) HandleLocsForWedge(&DPV); } @@ -2632,7 +2632,7 @@ removeRedundantDbgLocsUsingForwardScan(const BasicBlock *BB, } }; - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) HandleLocsForWedge(&DPV); HandleLocsForWedge(&I); } @@ -2718,7 +2718,7 @@ removeUndefDbgLocsFromEntryBlock(const BasicBlock *BB, Changed = true; } }; - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) HandleLocsForWedge(&DPV); HandleLocsForWedge(&I); } diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 36f6cc83be2c..59a0c64d3c9f 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -2983,7 +2983,7 @@ class TypePromotionTransaction { Inst->insertBefore(*Point.BB, Position); } - Inst->getParent()->reinsertInstInDPValues(Inst, BeforeDPValue); + Inst->getParent()->reinsertInstInDbgRecords(Inst, BeforeDPValue); } }; @@ -8506,7 +8506,7 @@ bool CodeGenPrepare::fixupDbgValue(Instruction *I) { bool CodeGenPrepare::fixupDPValuesOnInst(Instruction &I) { bool AnyChange = false; - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) AnyChange |= fixupDPValue(DPV); return AnyChange; } @@ -8550,9 +8550,9 @@ static void DbgInserterHelper(DPValue *DPV, Instruction *VI) { DPV->removeFromParent(); BasicBlock *VIBB = VI->getParent(); if (isa(VI)) - VIBB->insertDPValueBefore(DPV, VIBB->getFirstInsertionPt()); + VIBB->insertDbgRecordBefore(DPV, VIBB->getFirstInsertionPt()); else - VIBB->insertDPValueAfter(DPV, VI); + VIBB->insertDbgRecordAfter(DPV, VI); } // A llvm.dbg.value may be using a value before its definition, due to @@ -8620,7 +8620,7 @@ bool CodeGenPrepare::placeDbgValues(Function &F) { // If this isn't a dbg.value, process any attached DPValue records // attached to this instruction. for (DPValue &DPV : llvm::make_early_inc_range( - DPValue::filter(Insn.getDbgValueRange()))) { + DPValue::filter(Insn.getDbgRecordRange()))) { if (DPV.Type != DPValue::LocationType::Value) continue; DbgProcessor(&DPV, &Insn); diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 365870f540da..94fdb37e283b 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -3277,7 +3277,7 @@ void IRTranslator::translateDbgDeclareRecord(Value *Address, bool HasArgList, void IRTranslator::translateDbgInfo(const Instruction &Inst, MachineIRBuilder &MIRBuilder) { - for (DbgRecord &DR : Inst.getDbgValueRange()) { + for (DbgRecord &DR : Inst.getDbgRecordRange()) { if (DPLabel *DPL = dyn_cast(&DR)) { MIRBuilder.setDebugLoc(DPL->getDebugLoc()); assert(DPL->getLabel() && "Missing label"); diff --git a/llvm/lib/CodeGen/SelectOptimize.cpp b/llvm/lib/CodeGen/SelectOptimize.cpp index 5609f481b22a..40898d284a09 100644 --- a/llvm/lib/CodeGen/SelectOptimize.cpp +++ b/llvm/lib/CodeGen/SelectOptimize.cpp @@ -648,10 +648,10 @@ void SelectOptimizeImpl::convertProfitableSIGroups(SelectGroups &ProfSIGroups) { // Duplicate implementation for DPValues, the non-instruction debug-info // record. Helper lambda for moving DPValues to the end block. auto TransferDPValues = [&](Instruction &I) { - for (auto &DPValue : llvm::make_early_inc_range(I.getDbgValueRange())) { + for (auto &DPValue : llvm::make_early_inc_range(I.getDbgRecordRange())) { DPValue.removeFromParent(); - EndBlock->insertDPValueBefore(&DPValue, - EndBlock->getFirstInsertionPt()); + EndBlock->insertDbgRecordBefore(&DPValue, + EndBlock->getFirstInsertionPt()); } }; diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp index 246762dd7ab6..cce91dbd9531 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1181,14 +1181,14 @@ bool FastISel::selectCall(const User *I) { } void FastISel::handleDbgInfo(const Instruction *II) { - if (!II->hasDbgValues()) + if (!II->hasDbgRecords()) return; // Clear any metadata. MIMD = MIMetadata(); // Reverse order of debug records, because fast-isel walks through backwards. - for (DbgRecord &DR : llvm::reverse(II->getDbgValueRange())) { + for (DbgRecord &DR : llvm::reverse(II->getDbgRecordRange())) { flushLocalValueMap(); recomputeInsertPt(); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 22e57d0d99e9..b6a35f7ad4c4 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1255,7 +1255,7 @@ void SelectionDAGBuilder::visitDbgInfo(const Instruction &I) { bool SkipDPValues = DAG.getFunctionVarLocs(); // Is there is any debug-info attached to this instruction, in the form of // DbgRecord non-instruction debug-info records. - for (DbgRecord &DR : I.getDbgValueRange()) { + for (DbgRecord &DR : I.getDbgRecordRange()) { if (DPLabel *DPL = dyn_cast(&DR)) { assert(DPL->getLabel() && "Missing label"); SDDbgLabel *SDV = diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 1c14e4da8e9d..c78c3ed294e4 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -1461,7 +1461,7 @@ static void processDbgDeclares(FunctionLoweringInfo &FuncInfo) { if (DI && processDbgDeclare(FuncInfo, DI->getAddress(), DI->getExpression(), DI->getVariable(), DI->getDebugLoc())) FuncInfo.PreprocessedDbgDeclares.insert(DI); - for (const DPValue &DPV : DPValue::filter(I.getDbgValueRange())) { + for (const DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { if (DPV.Type == DPValue::LocationType::Declare && processDbgDeclare(FuncInfo, DPV.getVariableLocationOp(0), DPV.getExpression(), DPV.getVariable(), diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index f2562c926e3b..1beb4c069a69 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1131,7 +1131,7 @@ void SlotTracker::processFunctionMetadata(const Function &F) { processGlobalObjectMetadata(F); for (auto &BB : F) { for (auto &I : BB) { - for (const DbgRecord &DR : I.getDbgValueRange()) + for (const DbgRecord &DR : I.getDbgRecordRange()) processDbgRecordMetadata(DR); processInstructionMetadata(I); } @@ -4097,7 +4097,7 @@ void AssemblyWriter::printBasicBlock(const BasicBlock *BB) { // Output all of the instructions in the basic block... for (const Instruction &I : *BB) { - for (const DbgRecord &DR : I.getDbgValueRange()) + for (const DbgRecord &DR : I.getDbgRecordRange()) printDbgRecordLine(DR); printInstructionLine(I); } diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp index 673e2f68249c..7ead7ce3bf08 100644 --- a/llvm/lib/IR/BasicBlock.cpp +++ b/llvm/lib/IR/BasicBlock.cpp @@ -52,11 +52,11 @@ DPMarker *BasicBlock::createMarker(InstListType::iterator It) { "Tried to create a marker in a non new debug-info block!"); if (It != end()) return createMarker(&*It); - DPMarker *DPM = getTrailingDPValues(); + DPMarker *DPM = getTrailingDbgRecords(); if (DPM) return DPM; DPM = new DPMarker(); - setTrailingDPValues(DPM); + setTrailingDbgRecords(DPM); return DPM; } @@ -91,7 +91,7 @@ void BasicBlock::convertToNewDbgValues() { DPMarker *Marker = I.DbgMarker; for (DbgRecord *DPV : DPVals) - Marker->insertDPValue(DPV, false); + Marker->insertDbgRecord(DPV, false); DPVals.clear(); } @@ -109,7 +109,7 @@ void BasicBlock::convertFromNewDbgValues() { continue; DPMarker &Marker = *Inst.DbgMarker; - for (DbgRecord &DR : Marker.getDbgValueRange()) + for (DbgRecord &DR : Marker.getDbgRecordRange()) InstList.insert(Inst.getIterator(), DR.createDebugIntrinsic(getModule(), nullptr)); @@ -119,7 +119,7 @@ void BasicBlock::convertFromNewDbgValues() { // Assume no trailing DPValues: we could technically create them at the end // of the block, after a terminator, but this would be non-cannonical and // indicates that something else is broken somewhere. - assert(!getTrailingDPValues()); + assert(!getTrailingDbgRecords()); } #ifndef NDEBUG @@ -711,7 +711,7 @@ void BasicBlock::flushTerminatorDbgValues() { return; // Are there any dangling DPValues? - DPMarker *TrailingDPValues = getTrailingDPValues(); + DPMarker *TrailingDPValues = getTrailingDbgRecords(); if (!TrailingDPValues) return; @@ -719,7 +719,7 @@ void BasicBlock::flushTerminatorDbgValues() { createMarker(Term); Term->DbgMarker->absorbDebugValues(*TrailingDPValues, false); TrailingDPValues->eraseFromParent(); - deleteTrailingDPValues(); + deleteTrailingDbgRecords(); } void BasicBlock::spliceDebugInfoEmptyBlock(BasicBlock::iterator Dest, @@ -754,13 +754,13 @@ void BasicBlock::spliceDebugInfoEmptyBlock(BasicBlock::iterator Dest, // occur when a block is optimised away and the terminator has been moved // somewhere else. if (Src->empty()) { - DPMarker *SrcTrailingDPValues = Src->getTrailingDPValues(); + DPMarker *SrcTrailingDPValues = Src->getTrailingDbgRecords(); if (!SrcTrailingDPValues) return; - Dest->adoptDbgValues(Src, Src->end(), InsertAtHead); - // adoptDbgValues should have released the trailing DPValues. - assert(!Src->getTrailingDPValues()); + Dest->adoptDbgRecords(Src, Src->end(), InsertAtHead); + // adoptDbgRecords should have released the trailing DPValues. + assert(!Src->getTrailingDbgRecords()); return; } @@ -771,7 +771,7 @@ void BasicBlock::spliceDebugInfoEmptyBlock(BasicBlock::iterator Dest, return; // Is there actually anything to transfer? - if (!First->hasDbgValues()) + if (!First->hasDbgRecords()) return; createMarker(Dest)->absorbDebugValues(*First->DbgMarker, InsertAtHead); @@ -817,16 +817,16 @@ void BasicBlock::spliceDebugInfo(BasicBlock::iterator Dest, BasicBlock *Src, // move the DPValues onto "First". They'll then be moved naturally in the // splice process. DPMarker *MoreDanglingDPValues = nullptr; - DPMarker *OurTrailingDPValues = getTrailingDPValues(); + DPMarker *OurTrailingDPValues = getTrailingDbgRecords(); if (Dest == end() && !Dest.getHeadBit() && OurTrailingDPValues) { // Are the "+" DPValues not supposed to move? If so, detach them // temporarily. - if (!First.getHeadBit() && First->hasDbgValues()) { + if (!First.getHeadBit() && First->hasDbgRecords()) { MoreDanglingDPValues = Src->getMarker(First); MoreDanglingDPValues->removeFromParent(); } - if (First->hasDbgValues()) { + if (First->hasDbgRecords()) { // Place them at the front, it would look like this: // Dest // | @@ -834,7 +834,7 @@ void BasicBlock::spliceDebugInfo(BasicBlock::iterator Dest, BasicBlock *Src, // Src-block: ~~~~~~~~++++B---B---B---B:::C // | | // First Last - First->adoptDbgValues(this, end(), true); + First->adoptDbgRecords(this, end(), true); } else { // No current marker, create one and absorb in. (FIXME: we can avoid an // allocation in the future). @@ -842,7 +842,7 @@ void BasicBlock::spliceDebugInfo(BasicBlock::iterator Dest, BasicBlock *Src, CurMarker->absorbDebugValues(*OurTrailingDPValues, false); OurTrailingDPValues->eraseFromParent(); } - deleteTrailingDPValues(); + deleteTrailingDbgRecords(); First.setHeadBit(true); } @@ -854,7 +854,7 @@ void BasicBlock::spliceDebugInfo(BasicBlock::iterator Dest, BasicBlock *Src, if (!MoreDanglingDPValues) return; - // FIXME: we could avoid an allocation here sometimes. (adoptDbgValues + // FIXME: we could avoid an allocation here sometimes. (adoptDbgRecords // requires an iterator). DPMarker *LastMarker = Src->createMarker(Last); LastMarker->absorbDebugValues(*MoreDanglingDPValues, true); @@ -946,11 +946,11 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, if (ReadFromTail && Src->getMarker(Last)) { DPMarker *FromLast = Src->getMarker(Last); if (LastIsEnd) { - Dest->adoptDbgValues(Src, Last, true); - // adoptDbgValues will release any trailers. - assert(!Src->getTrailingDPValues()); + Dest->adoptDbgRecords(Src, Last, true); + // adoptDbgRecords will release any trailers. + assert(!Src->getTrailingDbgRecords()); } else { - // FIXME: can we use adoptDbgValues here to reduce allocations? + // FIXME: can we use adoptDbgRecords here to reduce allocations? DPMarker *OntoDest = createMarker(Dest); OntoDest->absorbDebugValues(*FromLast, true); } @@ -959,9 +959,9 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, // If we're _not_ reading from the head of First, i.e. the "++++" DPValues, // move their markers onto Last. They remain in the Src block. No action // needed. - if (!ReadFromHead && First->hasDbgValues()) { + if (!ReadFromHead && First->hasDbgRecords()) { if (Last != Src->end()) { - Last->adoptDbgValues(Src, First, true); + Last->adoptDbgRecords(Src, First, true); } else { DPMarker *OntoLast = Src->createMarker(Last); DPMarker *FromFirst = Src->createMarker(First); @@ -990,11 +990,11 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, // any trailing debug-info at the end of the block would "normally" have // been pushed in front of "First". Move it there now. DPMarker *FirstMarker = getMarker(First); - DPMarker *TrailingDPValues = getTrailingDPValues(); + DPMarker *TrailingDPValues = getTrailingDbgRecords(); if (TrailingDPValues) { FirstMarker->absorbDebugValues(*TrailingDPValues, true); TrailingDPValues->eraseFromParent(); - deleteTrailingDPValues(); + deleteTrailingDbgRecords(); } } } @@ -1027,21 +1027,21 @@ void BasicBlock::splice(iterator Dest, BasicBlock *Src, iterator First, flushTerminatorDbgValues(); } -void BasicBlock::insertDPValueAfter(DbgRecord *DPV, Instruction *I) { +void BasicBlock::insertDbgRecordAfter(DbgRecord *DPV, Instruction *I) { assert(IsNewDbgInfoFormat); assert(I->getParent() == this); iterator NextIt = std::next(I->getIterator()); DPMarker *NextMarker = createMarker(NextIt); - NextMarker->insertDPValue(DPV, true); + NextMarker->insertDbgRecord(DPV, true); } -void BasicBlock::insertDPValueBefore(DbgRecord *DPV, - InstListType::iterator Where) { +void BasicBlock::insertDbgRecordBefore(DbgRecord *DPV, + InstListType::iterator Where) { assert(Where == end() || Where->getParent() == this); bool InsertAtHead = Where.getHeadBit(); DPMarker *M = createMarker(Where); - M->insertDPValue(DPV, InsertAtHead); + M->insertDbgRecord(DPV, InsertAtHead); } DPMarker *BasicBlock::getNextMarker(Instruction *I) { @@ -1050,13 +1050,13 @@ DPMarker *BasicBlock::getNextMarker(Instruction *I) { DPMarker *BasicBlock::getMarker(InstListType::iterator It) { if (It == end()) { - DPMarker *DPM = getTrailingDPValues(); + DPMarker *DPM = getTrailingDbgRecords(); return DPM; } return It->DbgMarker; } -void BasicBlock::reinsertInstInDPValues( +void BasicBlock::reinsertInstInDbgRecords( Instruction *I, std::optional Pos) { // "I" was originally removed from a position where it was // immediately in front of Pos. Any DPValues on that position then "fell down" @@ -1123,15 +1123,14 @@ void BasicBlock::validateInstrOrdering() const { } #endif -void BasicBlock::setTrailingDPValues(DPMarker *foo) { - getContext().pImpl->setTrailingDPValues(this, foo); +void BasicBlock::setTrailingDbgRecords(DPMarker *foo) { + getContext().pImpl->setTrailingDbgRecords(this, foo); } -DPMarker *BasicBlock::getTrailingDPValues() { - return getContext().pImpl->getTrailingDPValues(this); +DPMarker *BasicBlock::getTrailingDbgRecords() { + return getContext().pImpl->getTrailingDbgRecords(this); } -void BasicBlock::deleteTrailingDPValues() { - getContext().pImpl->deleteTrailingDPValues(this); +void BasicBlock::deleteTrailingDbgRecords() { + getContext().pImpl->deleteTrailingDbgRecords(this); } - diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index c0643f63c972..c673abd8bc30 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -1095,7 +1095,7 @@ void DIBuilder::insertDPValue(DPValue *DPV, BasicBlock *InsertBB, else if (InsertBB) InsertPt = InsertBB->end(); InsertPt.setHeadBit(InsertAtHead); - InsertBB->insertDPValueBefore(DPV, InsertPt); + InsertBB->insertDbgRecordBefore(DPV, InsertPt); } Instruction *DIBuilder::insertDbgIntrinsic(llvm::Function *IntrinsicFn, @@ -1137,9 +1137,9 @@ DbgInstPtr DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL, if (M.IsNewDbgInfoFormat) { DPLabel *DPL = new DPLabel(LabelInfo, DL); if (InsertBB && InsertBefore) - InsertBB->insertDPValueBefore(DPL, InsertBefore->getIterator()); + InsertBB->insertDbgRecordBefore(DPL, InsertBefore->getIterator()); else if (InsertBB) - InsertBB->insertDPValueBefore(DPL, InsertBB->end()); + InsertBB->insertDbgRecordBefore(DPL, InsertBB->end()); return DPL; } diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 68fd244e2569..e63b1e67dad7 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -241,7 +241,7 @@ void DebugInfoFinder::processInstruction(const Module &M, if (auto DbgLoc = I.getDebugLoc()) processLocation(M, DbgLoc.get()); - for (const DbgRecord &DPR : I.getDbgValueRange()) + for (const DbgRecord &DPR : I.getDbgRecordRange()) processDbgRecord(M, DPR); } @@ -579,7 +579,7 @@ bool llvm::stripDebugInfo(Function &F) { // DIAssignID are debug info metadata primitives. I.setMetadata(LLVMContext::MD_DIAssignID, nullptr); } - I.dropDbgValues(); + I.dropDbgRecords(); } } return Changed; @@ -896,7 +896,7 @@ bool llvm::stripNonLineTableDebugInfo(Module &M) { I.setMetadata("heapallocsite", nullptr); // Strip any DPValues attached. - I.dropDbgValues(); + I.dropDbgRecords(); } } } @@ -1828,7 +1828,7 @@ void at::deleteAll(Function *F) { SmallVector DPToDelete; for (BasicBlock &BB : *F) { for (Instruction &I : BB) { - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) if (DPV.isDbgAssign()) DPToDelete.push_back(&DPV); if (auto *DAI = dyn_cast(&I)) @@ -2257,7 +2257,7 @@ bool AssignmentTrackingPass::runOnFunction(Function &F) { }; for (auto &BB : F) { for (auto &I : BB) { - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) { + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { if (DPV.isDbgDeclare()) ProcessDeclare(&DPV, DPVDeclares); } diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index 5ff1e8c19db6..019b00c2e208 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -218,7 +218,7 @@ DPValue *DPValue::createLinkedDPVAssign(Instruction *LinkedInstr, Value *Val, auto *NewDPVAssign = DPValue::createDPVAssign(Val, Variable, Expression, cast(Link), Address, AddressExpression, DI); - LinkedInstr->getParent()->insertDPValueAfter(NewDPVAssign, LinkedInstr); + LinkedInstr->getParent()->insertDbgRecordAfter(NewDPVAssign, LinkedInstr); return NewDPVAssign; } @@ -515,7 +515,7 @@ void DbgRecord::insertBefore(DbgRecord *InsertBefore) { assert(InsertBefore->getMarker() && "Cannot insert a DbgRecord before a DbgRecord that does not have a " "DPMarker!"); - InsertBefore->getMarker()->insertDPValue(this, InsertBefore); + InsertBefore->getMarker()->insertDbgRecord(this, InsertBefore); } void DbgRecord::insertAfter(DbgRecord *InsertAfter) { assert(!getMarker() && @@ -523,7 +523,7 @@ void DbgRecord::insertAfter(DbgRecord *InsertAfter) { assert(InsertAfter->getMarker() && "Cannot insert a DbgRecord after a DbgRecord that does not have a " "DPMarker!"); - InsertAfter->getMarker()->insertDPValueAfter(this, InsertAfter); + InsertAfter->getMarker()->insertDbgRecordAfter(this, InsertAfter); } void DbgRecord::moveBefore(DbgRecord *MoveBefore) { assert(getMarker() && @@ -544,7 +544,7 @@ void DbgRecord::moveAfter(DbgRecord *MoveAfter) { // DPValues. DPMarker DPMarker::EmptyDPMarker; -void DPMarker::dropDbgValues() { +void DPMarker::dropDbgRecords() { while (!StoredDPValues.empty()) { auto It = StoredDPValues.begin(); DbgRecord *DR = &*It; @@ -553,7 +553,7 @@ void DPMarker::dropDbgValues() { } } -void DPMarker::dropOneDbgValue(DbgRecord *DR) { +void DPMarker::dropOneDbgRecord(DbgRecord *DR) { assert(DR->getMarker() == this); StoredDPValues.erase(DR->getIterator()); DR->deleteRecord(); @@ -587,7 +587,7 @@ void DPMarker::removeMarker() { // marker becomes the trailing marker of a degenerate block. BasicBlock::iterator NextIt = std::next(Owner->getIterator()); if (NextIt == getParent()->end()) { - getParent()->setTrailingDPValues(this); + getParent()->setTrailingDbgRecords(this); MarkedInstr = nullptr; } else { NextIt->DbgMarker = this; @@ -605,15 +605,15 @@ void DPMarker::removeFromParent() { void DPMarker::eraseFromParent() { if (MarkedInstr) removeFromParent(); - dropDbgValues(); + dropDbgRecords(); delete this; } -iterator_range DPMarker::getDbgValueRange() { +iterator_range DPMarker::getDbgRecordRange() { return make_range(StoredDPValues.begin(), StoredDPValues.end()); } iterator_range -DPMarker::getDbgValueRange() const { +DPMarker::getDbgRecordRange() const { return make_range(StoredDPValues.begin(), StoredDPValues.end()); } @@ -627,18 +627,18 @@ void DbgRecord::eraseFromParent() { deleteRecord(); } -void DPMarker::insertDPValue(DbgRecord *New, bool InsertAtHead) { +void DPMarker::insertDbgRecord(DbgRecord *New, bool InsertAtHead) { auto It = InsertAtHead ? StoredDPValues.begin() : StoredDPValues.end(); StoredDPValues.insert(It, *New); New->setMarker(this); } -void DPMarker::insertDPValue(DbgRecord *New, DbgRecord *InsertBefore) { +void DPMarker::insertDbgRecord(DbgRecord *New, DbgRecord *InsertBefore) { assert(InsertBefore->getMarker() == this && "DPValue 'InsertBefore' must be contained in this DPMarker!"); StoredDPValues.insert(InsertBefore->getIterator(), *New); New->setMarker(this); } -void DPMarker::insertDPValueAfter(DbgRecord *New, DbgRecord *InsertAfter) { +void DPMarker::insertDbgRecordAfter(DbgRecord *New, DbgRecord *InsertAfter) { assert(InsertAfter->getMarker() == this && "DPValue 'InsertAfter' must be contained in this DPMarker!"); StoredDPValues.insert(++(InsertAfter->getIterator()), *New); diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index 6b8c6e0c85ed..e0892398f434 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -161,7 +161,7 @@ void Instruction::insertBefore(BasicBlock &BB, // maintenence code that you intend the PHI to be ahead of everything, // including any debug-info. assert(!isa(this) && "Inserting PHI after debug-records!"); - adoptDbgValues(&BB, InsertPos, false); + adoptDbgRecords(&BB, InsertPos, false); } } @@ -232,7 +232,7 @@ void Instruction::moveBeforeImpl(BasicBlock &BB, InstListType::iterator I, // If we're inserting at point I, and not in front of the DPValues attached // there, then we should absorb the DPValues attached to I. if (!InsertAtHead && NextMarker && !NextMarker->empty()) { - adoptDbgValues(&BB, I, false); + adoptDbgRecords(&BB, I, false); } } @@ -244,7 +244,7 @@ iterator_range Instruction::cloneDebugInfoFrom( const Instruction *From, std::optional FromHere, bool InsertAtHead) { if (!From->DbgMarker) - return DPMarker::getEmptyDPValueRange(); + return DPMarker::getEmptyDbgRecordRange(); assert(getParent()->IsNewDbgInfoFormat); assert(getParent()->IsNewDbgInfoFormat == @@ -270,15 +270,15 @@ Instruction::getDbgReinsertionPosition() { return NextMarker->StoredDPValues.begin(); } -bool Instruction::hasDbgValues() const { return !getDbgValueRange().empty(); } +bool Instruction::hasDbgRecords() const { return !getDbgRecordRange().empty(); } -void Instruction::adoptDbgValues(BasicBlock *BB, BasicBlock::iterator It, - bool InsertAtHead) { +void Instruction::adoptDbgRecords(BasicBlock *BB, BasicBlock::iterator It, + bool InsertAtHead) { DPMarker *SrcMarker = BB->getMarker(It); auto ReleaseTrailingDPValues = [BB, It, SrcMarker]() { if (BB->end() == It) { SrcMarker->eraseFromParent(); - BB->deleteTrailingDPValues(); + BB->deleteTrailingDbgRecords(); } }; @@ -314,13 +314,13 @@ void Instruction::adoptDbgValues(BasicBlock *BB, BasicBlock::iterator It, } } -void Instruction::dropDbgValues() { +void Instruction::dropDbgRecords() { if (DbgMarker) - DbgMarker->dropDbgValues(); + DbgMarker->dropDbgRecords(); } -void Instruction::dropOneDbgValue(DbgRecord *DPV) { - DbgMarker->dropOneDbgValue(DPV); +void Instruction::dropOneDbgRecord(DbgRecord *DPV) { + DbgMarker->dropOneDbgRecord(DPV); } bool Instruction::comesBefore(const Instruction *Other) const { diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 547a02a6490e..c841b28ca438 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -1687,18 +1687,16 @@ public: SmallDenseMap TrailingDPValues; // Set, get and delete operations for TrailingDPValues. - void setTrailingDPValues(BasicBlock *B, DPMarker *M) { + void setTrailingDbgRecords(BasicBlock *B, DPMarker *M) { assert(!TrailingDPValues.count(B)); TrailingDPValues[B] = M; } - DPMarker *getTrailingDPValues(BasicBlock *B) { + DPMarker *getTrailingDbgRecords(BasicBlock *B) { return TrailingDPValues.lookup(B); } - void deleteTrailingDPValues(BasicBlock *B) { - TrailingDPValues.erase(B); - } + void deleteTrailingDbgRecords(BasicBlock *B) { TrailingDPValues.erase(B); } }; } // end namespace llvm diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 0e6c01802cfb..2b9dc745d7bf 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -682,9 +682,9 @@ void Verifier::visitDbgRecords(Instruction &I) { return; CheckDI(I.DbgMarker->MarkedInstr == &I, "Instruction has invalid DbgMarker", &I); - CheckDI(!isa(&I) || !I.hasDbgValues(), + CheckDI(!isa(&I) || !I.hasDbgRecords(), "PHI Node must not have any attached DbgRecords", &I); - for (DbgRecord &DR : I.getDbgValueRange()) { + for (DbgRecord &DR : I.getDbgRecordRange()) { CheckDI(DR.getMarker() == I.DbgMarker, "DbgRecord had invalid DbgMarker", &I, &DR); if (auto *Loc = @@ -3046,7 +3046,7 @@ void Verifier::visitBasicBlock(BasicBlock &BB) { // Confirm that no issues arise from the debug program. if (BB.IsNewDbgInfoFormat) - CheckDI(!BB.getTrailingDPValues(), "Basic Block has trailing DbgRecords!", + CheckDI(!BB.getTrailingDbgRecords(), "Basic Block has trailing DbgRecords!", &BB); } diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index e091ecbf5400..7c29d443df51 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -1277,7 +1277,7 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape, FrameDIVar, DBuilder.createExpression(), DILoc, DPValue::LocationType::Declare); BasicBlock::iterator It = Shape.getInsertPtAfterFramePtr(); - It->getParent()->insertDPValueBefore(NewDPV, It); + It->getParent()->insertDbgRecordBefore(NewDPV, It); } else { DBuilder.insertDeclare(Shape.FramePtr, FrameDIVar, DBuilder.createExpression(), DILoc, @@ -1891,7 +1891,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { new DPValue(ValueAsMetadata::get(CurrentReload), DDI->getVariable(), DDI->getExpression(), DDI->getDebugLoc(), DPValue::LocationType::Declare); - Builder.GetInsertPoint()->getParent()->insertDPValueBefore( + Builder.GetInsertPoint()->getParent()->insertDbgRecordBefore( NewDPV, Builder.GetInsertPoint()); } else { DIBuilder(*CurrentBlock->getParent()->getParent(), AllowUnresolved) @@ -1925,7 +1925,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { U->replaceUsesOfWith(Def, CurrentReload); // Instructions are added to Def's user list if the attached // debug records use Def. Update those now. - for (DPValue &DPV : DPValue::filter(U->getDbgValueRange())) + for (DPValue &DPV : DPValue::filter(U->getDbgRecordRange())) DPV.replaceVariableLocationOp(Def, CurrentReload, true); } } @@ -2996,7 +2996,7 @@ void coro::salvageDebugInfo( InsertPt = F->getEntryBlock().begin(); if (InsertPt) { DPV.removeFromParent(); - (*InsertPt)->getParent()->insertDPValueBefore(&DPV, *InsertPt); + (*InsertPt)->getParent()->insertDbgRecordBefore(&DPV, *InsertPt); } } } diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 58b95e43b899..086971a1f213 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -684,7 +684,7 @@ collectDbgVariableIntrinsics(Function &F) { SmallVector Intrinsics; SmallVector DPValues; for (auto &I : instructions(F)) { - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) DPValues.push_back(&DPV); if (auto *DVI = dyn_cast(&I)) Intrinsics.push_back(DVI); diff --git a/llvm/lib/Transforms/IPO/IROutliner.cpp b/llvm/lib/Transforms/IPO/IROutliner.cpp index 03d4d503b80a..37f4a8749fd8 100644 --- a/llvm/lib/Transforms/IPO/IROutliner.cpp +++ b/llvm/lib/Transforms/IPO/IROutliner.cpp @@ -725,7 +725,7 @@ static void moveFunctionData(Function &Old, Function &New, // program, it will cause incorrect reporting from a debugger if we keep // the same debug instructions. Drop non-intrinsic DPValues here, // collect intrinsics for removal later. - Val.dropDbgValues(); + Val.dropDbgRecords(); // We must handle the scoping of called functions differently than // other outlined instructions. diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp index 591be6be092c..ed5352e7d04a 100644 --- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp +++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp @@ -643,7 +643,7 @@ void MergeFunctions::filterInstsUnrelatedToPDI( BI != BIE; ++BI) { // Examine DPValues as they happen "before" the instruction. Are they // connected to parameters? - for (DPValue &DPV : DPValue::filter(BI->getDbgValueRange())) { + for (DPValue &DPV : DPValue::filter(BI->getDbgRecordRange())) { if (DPV.isDbgValue() || DPV.isDbgAssign()) { ExamineDbgValue(&DPV, PDPVRelated); } else { @@ -686,7 +686,7 @@ void MergeFunctions::filterInstsUnrelatedToPDI( // Collect the set of unrelated instructions and debug records. for (Instruction &I : *GEntryBlock) { - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) IsPDIRelated(&DPV, PDPVRelated, PDPVUnrelatedWL); IsPDIRelated(&I, PDIRelated, PDIUnrelatedWL); } diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 1a831805dc72..1688005de210 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3426,7 +3426,7 @@ void InstCombinerImpl::handleUnreachableFrom( if (Inst.isEHPad() || Inst.getType()->isTokenTy()) continue; // RemoveDIs: erase debug-info on this instruction manually. - Inst.dropDbgValues(); + Inst.dropDbgRecords(); eraseInstFromFunction(Inst); MadeIRChange = true; } @@ -4697,7 +4697,7 @@ void InstCombinerImpl::tryToSinkInstructionDPValues( // latest assignment. for (const Instruction *Inst : DupSet) { for (DPValue &DPV : - llvm::reverse(DPValue::filter(Inst->getDbgValueRange()))) { + llvm::reverse(DPValue::filter(Inst->getDbgRecordRange()))) { DebugVariable DbgUserVariable = DebugVariable(DPV.getVariable(), DPV.getExpression(), DPV.getDebugLoc()->getInlinedAt()); @@ -4762,7 +4762,7 @@ void InstCombinerImpl::tryToSinkInstructionDPValues( // InsertPtInst assert(InsertPos.getHeadBit()); for (DPValue *DPVClone : DPVClones) { - InsertPos->getParent()->insertDPValueBefore(DPVClone, InsertPos); + InsertPos->getParent()->insertDbgRecordBefore(DPVClone, InsertPos); LLVM_DEBUG(dbgs() << "SINK: " << *DPVClone << '\n'); } } diff --git a/llvm/lib/Transforms/Scalar/ADCE.cpp b/llvm/lib/Transforms/Scalar/ADCE.cpp index 95a9527126c1..4d901310efe5 100644 --- a/llvm/lib/Transforms/Scalar/ADCE.cpp +++ b/llvm/lib/Transforms/Scalar/ADCE.cpp @@ -548,7 +548,7 @@ ADCEChanged AggressiveDeadCodeElimination::removeDeadInstructions() { // attached to this instruction, and drop any for scopes that aren't alive, // like the rest of this loop does. Extending support to assignment tracking // is future work. - for (DbgRecord &DR : make_early_inc_range(I.getDbgValueRange())) { + for (DbgRecord &DR : make_early_inc_range(I.getDbgRecordRange())) { // Avoid removing a DPV that is linked to instructions because it holds // information about an existing store. if (DPValue *DPV = dyn_cast(&DR); DPV && DPV->isDbgAssign()) @@ -556,7 +556,7 @@ ADCEChanged AggressiveDeadCodeElimination::removeDeadInstructions() { continue; if (AliveScopes.count(DR.getDebugLoc()->getScope())) continue; - I.dropOneDbgValue(&DR); + I.dropOneDbgRecord(&DR); } // Check if the instruction is alive. diff --git a/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp b/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp index 47f663fa0cf0..b8571ba07489 100644 --- a/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp +++ b/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp @@ -403,7 +403,7 @@ static void splitCallSite(CallBase &CB, NewPN->insertBefore(*TailBB, TailBB->begin()); CurrentI->replaceAllUsesWith(NewPN); } - CurrentI->dropDbgValues(); + CurrentI->dropDbgRecords(); CurrentI->eraseFromParent(); // We are done once we handled the first original instruction in TailBB. if (CurrentI == OriginalBeginInst) diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp index 221b122caba2..1058a015017e 100644 --- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -401,7 +401,7 @@ static bool replaceFoldableUses(Instruction *Cond, Value *ToVal, Changed |= replaceNonLocalUsesWith(Cond, ToVal); for (Instruction &I : reverse(*KnownAtEndOfBB)) { // Replace any debug-info record users of Cond with ToVal. - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) DPV.replaceVariableLocationOp(Cond, ToVal, true); // Reached the Cond whose uses we are trying to replace, so there are no @@ -2111,7 +2111,7 @@ JumpThreadingPass::cloneInstructions(BasicBlock::iterator BI, // There may be DPValues on the terminator, clone directly from marker // to marker as there isn't an instruction there. - if (BE != RangeBB->end() && BE->hasDbgValues()) { + if (BE != RangeBB->end() && BE->hasDbgRecords()) { // Dump them at the end. DPMarker *Marker = RangeBB->getMarker(BE); DPMarker *EndMarker = NewBB->createMarker(NewBB->end()); @@ -3118,7 +3118,7 @@ bool JumpThreadingPass::threadGuard(BasicBlock *BB, IntrinsicInst *Guard, NewPN->insertBefore(InsertionPoint); Inst->replaceAllUsesWith(NewPN); } - Inst->dropDbgValues(); + Inst->dropDbgRecords(); Inst->eraseFromParent(); } return true; diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp index 4238098181af..8b078ddc4e74 100644 --- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -6711,7 +6711,7 @@ static void DbgGatherSalvagableDVI( SalvageableDVISCEVs.push_back(std::move(NewRec)); return true; }; - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) { + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { if (DPV.isDbgValue() || DPV.isDbgAssign()) ProcessDbgValue(&DPV); } diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp index 190fee11618b..e238f311a15b 100644 --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -5041,8 +5041,8 @@ static void insertNewDbgInst(DIBuilder &DIB, DPValue *Orig, AllocaInst *NewAddr, if (Orig->isDbgDeclare()) { DPValue *DPV = DPValue::createDPVDeclare( NewAddr, Orig->getVariable(), NewFragmentExpr, Orig->getDebugLoc()); - BeforeInst->getParent()->insertDPValueBefore(DPV, - BeforeInst->getIterator()); + BeforeInst->getParent()->insertDbgRecordBefore(DPV, + BeforeInst->getIterator()); return; } if (!NewAddr->hasMetadata(LLVMContext::MD_DIAssignID)) { diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp index 3d146086d31a..9fcaf2a89e56 100644 --- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp +++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp @@ -1260,7 +1260,7 @@ static BasicBlock *buildClonedLoopBlocks( Module *M = ClonedPH->getParent()->getParent(); for (auto *ClonedBB : NewBlocks) for (Instruction &I : *ClonedBB) { - RemapDPValueRange(M, I.getDbgValueRange(), VMap, + RemapDPValueRange(M, I.getDbgRecordRange(), VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); RemapInstruction(&I, VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); diff --git a/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp b/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp index 260f31b59ed2..8686570dfd2f 100644 --- a/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp +++ b/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp @@ -293,7 +293,7 @@ bool SpeculativeExecutionPass::considerHoistingFromTo( for (const auto &I : FromBlock) { // Make note of any DPValues that need hoisting. DPLabels // get left behind just like llvm.dbg.labels. - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) { + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { if (HasNoUnhoistedInstr(DPV.location_ops())) DPValuesToHoist[DPV.getInstruction()].push_back(&DPV); } @@ -320,8 +320,8 @@ bool SpeculativeExecutionPass::considerHoistingFromTo( if (DPValuesToHoist.contains(&*I)) { for (auto *DPV : DPValuesToHoist[&*I]) { DPV->removeFromParent(); - ToBlock.insertDPValueBefore(DPV, - ToBlock.getTerminator()->getIterator()); + ToBlock.insertDbgRecordBefore(DPV, + ToBlock.getTerminator()->getIterator()); } } // We have to increment I before moving Current as moving Current diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp index 5aa59acfa6df..2006b40e26d0 100644 --- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -386,7 +386,7 @@ static bool DPValuesRemoveRedundantDbgInstrsUsingBackwardScan(BasicBlock *BB) { SmallVector ToBeRemoved; SmallDenseSet VariableSet; for (auto &I : reverse(*BB)) { - for (DbgRecord &DR : reverse(I.getDbgValueRange())) { + for (DbgRecord &DR : reverse(I.getDbgRecordRange())) { if (isa(DR)) { // Emulate existing behaviour (see comment below for dbg.declares). // FIXME: Don't do this. @@ -504,7 +504,7 @@ static bool DPValuesRemoveRedundantDbgInstrsUsingForwardScan(BasicBlock *BB) { DenseMap, DIExpression *>> VariableMap; for (auto &I : *BB) { - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) { + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { if (DPV.getType() == DPValue::LocationType::Declare) continue; DebugVariable Key(DPV.getVariable(), std::nullopt, @@ -553,7 +553,7 @@ static bool DPValuesRemoveUndefDbgAssignsFromEntryBlock(BasicBlock *BB) { // Remove undef dbg.assign intrinsics that are encountered before // any non-undef intrinsics from the entry block. for (auto &I : *BB) { - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) { + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { if (!DPV.isDbgValue() && !DPV.isDbgAssign()) continue; bool IsDbgValueKind = diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp index c0f333364fa5..6931d1997aa6 100644 --- a/llvm/lib/Transforms/Utils/CloneFunction.cpp +++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp @@ -276,7 +276,7 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, // attached debug-info records. for (Instruction &II : *BB) { RemapInstruction(&II, VMap, RemapFlag, TypeMapper, Materializer); - RemapDPValueRange(II.getModule(), II.getDbgValueRange(), VMap, RemapFlag, + RemapDPValueRange(II.getModule(), II.getDbgRecordRange(), VMap, RemapFlag, TypeMapper, Materializer); } @@ -889,7 +889,7 @@ void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc, Function::iterator Begin = cast(VMap[StartingBB])->getIterator(); for (BasicBlock &BB : make_range(Begin, NewFunc->end())) { for (Instruction &I : BB) { - RemapDPValueRange(I.getModule(), I.getDbgValueRange(), VMap, + RemapDPValueRange(I.getModule(), I.getDbgRecordRange(), VMap, ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges, TypeMapper, Materializer); } @@ -990,7 +990,7 @@ void llvm::remapInstructionsInBlocks(ArrayRef Blocks, // Rewrite the code to refer to itself. for (auto *BB : Blocks) { for (auto &Inst : *BB) { - RemapDPValueRange(Inst.getModule(), Inst.getDbgValueRange(), VMap, + RemapDPValueRange(Inst.getModule(), Inst.getDbgRecordRange(), VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); RemapInstruction(&Inst, VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index ab2d25c3f17c..0fac5fc02e3f 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -1602,7 +1602,7 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc, }; auto UpdateDbgRecordsOnInst = [&](Instruction &I) -> void { - for (DbgRecord &DR : I.getDbgValueRange()) { + for (DbgRecord &DR : I.getDbgRecordRange()) { if (DPLabel *DPL = dyn_cast(&DR)) { UpdateDbgLabel(DPL); continue; @@ -1659,7 +1659,7 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc, for (auto *DII : DebugIntrinsicsToDelete) DII->eraseFromParent(); for (auto *DPV : DPVsToDelete) - DPV->getMarker()->MarkedInstr->dropOneDbgValue(DPV); + DPV->getMarker()->MarkedInstr->dropOneDbgRecord(DPV); DIB.finalizeSubprogram(NewSP); // Fix up the scope information attached to the line locations in the new @@ -1668,7 +1668,7 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc, if (const DebugLoc &DL = I.getDebugLoc()) I.setDebugLoc( DebugLoc::replaceInlinedAtSubprogram(DL, *NewSP, Ctx, Cache)); - for (DbgRecord &DR : I.getDbgValueRange()) + for (DbgRecord &DR : I.getDbgRecordRange()) DR.setDebugLoc(DebugLoc::replaceInlinedAtSubprogram(DR.getDebugLoc(), *NewSP, Ctx, Cache)); diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index 0e8e72678de6..1bbe76a92187 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1728,7 +1728,7 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI, for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { UpdateInst(*BI); - for (DbgRecord &DPV : BI->getDbgValueRange()) { + for (DbgRecord &DPV : BI->getDbgRecordRange()) { UpdateDPV(&DPV); } } @@ -1741,7 +1741,7 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI, BI = BI->eraseFromParent(); continue; } else { - BI->dropDbgValues(); + BI->dropDbgRecords(); } ++BI; } @@ -1829,7 +1829,7 @@ static void fixupAssignments(Function::iterator Start, Function::iterator End) { // attachment or use, replace it with a new version. for (auto BBI = Start; BBI != End; ++BBI) { for (Instruction &I : *BBI) { - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) { + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { if (DPV.isDbgAssign()) DPV.setAssignId(GetNewID(DPV.getAssignID())); } diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index a44536e34c92..7b74caac9e08 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1657,7 +1657,7 @@ static void insertDbgValueOrDPValue(DIBuilder &Builder, Value *DV, // DPValue directly instead of a dbg.value intrinsic. ValueAsMetadata *DVAM = ValueAsMetadata::get(DV); DPValue *DV = new DPValue(DVAM, DIVar, DIExpr, NewLoc.get()); - Instr->getParent()->insertDPValueBefore(DV, Instr); + Instr->getParent()->insertDbgRecordBefore(DV, Instr); } } @@ -1675,7 +1675,7 @@ static void insertDbgValueOrDPValueAfter(DIBuilder &Builder, Value *DV, // DPValue directly instead of a dbg.value intrinsic. ValueAsMetadata *DVAM = ValueAsMetadata::get(DV); DPValue *DV = new DPValue(DVAM, DIVar, DIExpr, NewLoc.get()); - Instr->getParent()->insertDPValueAfter(DV, &*Instr); + Instr->getParent()->insertDbgRecordAfter(DV, &*Instr); } } @@ -1794,7 +1794,7 @@ void llvm::ConvertDebugDeclareToDebugValue(DPValue *DPV, StoreInst *SI, DV = UndefValue::get(DV->getType()); ValueAsMetadata *DVAM = ValueAsMetadata::get(DV); DPValue *NewDPV = new DPValue(DVAM, DIVar, DIExpr, NewLoc.get()); - SI->getParent()->insertDPValueBefore(NewDPV, SI->getIterator()); + SI->getParent()->insertDbgRecordBefore(NewDPV, SI->getIterator()); } /// Inserts a llvm.dbg.value intrinsic after a phi that has an associated @@ -1856,7 +1856,7 @@ void llvm::ConvertDebugDeclareToDebugValue(DPValue *DPV, LoadInst *LI, // Create a DPValue directly and insert. ValueAsMetadata *LIVAM = ValueAsMetadata::get(LI); DPValue *DV = new DPValue(LIVAM, DIVar, DIExpr, NewLoc.get()); - LI->getParent()->insertDPValueAfter(DV, LI); + LI->getParent()->insertDbgRecordAfter(DV, LI); } /// Determine whether this alloca is either a VLA or an array. @@ -1911,7 +1911,7 @@ bool llvm::LowerDbgDeclare(Function &F) { for (Instruction &BI : FI) { if (auto *DDI = dyn_cast(&BI)) Dbgs.push_back(DDI); - for (DPValue &DPV : DPValue::filter(BI.getDbgValueRange())) { + for (DPValue &DPV : DPValue::filter(BI.getDbgRecordRange())) { if (DPV.getType() == DPValue::LocationType::Declare) DPVs.push_back(&DPV); } @@ -1996,7 +1996,7 @@ static void insertDPValuesForPHIs(BasicBlock *BB, // Map existing PHI nodes to their DPValues. DenseMap DbgValueMap; for (auto &I : *BB) { - for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) { + for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { for (Value *V : DPV.location_ops()) if (auto *Loc = dyn_cast_or_null(V)) DbgValueMap.insert({Loc, &DPV}); @@ -2044,7 +2044,7 @@ static void insertDPValuesForPHIs(BasicBlock *BB, auto InsertionPt = Parent->getFirstInsertionPt(); assert(InsertionPt != Parent->end() && "Ill-formed basic block"); - Parent->insertDPValueBefore(NewDbgII, InsertionPt); + Parent->insertDbgRecordBefore(NewDbgII, InsertionPt); } } @@ -2620,7 +2620,7 @@ static bool rewriteDebugUsers( LLVM_DEBUG(dbgs() << "MOVE: " << *DPV << '\n'); DPV->removeFromParent(); // Ensure there's a marker. - DomPoint.getParent()->insertDPValueAfter(DPV, &DomPoint); + DomPoint.getParent()->insertDbgRecordAfter(DPV, &DomPoint); Changed = true; } else if (!DT.dominates(&DomPoint, MarkedInstr)) { UndefOrSalvageDPV.insert(DPV); @@ -2766,7 +2766,7 @@ bool llvm::handleUnreachableTerminator( Instruction *I, SmallVectorImpl &PoisonedValues) { bool Changed = false; // RemoveDIs: erase debug-info on this instruction manually. - I->dropDbgValues(); + I->dropDbgRecords(); for (Use &U : I->operands()) { Value *Op = U.get(); if (isa(Op) && !Op->getType()->isTokenTy()) { @@ -2797,7 +2797,7 @@ llvm::removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB) { if (Inst->isEHPad() || Inst->getType()->isTokenTy()) { // EHPads can't have DPValues attached to them, but it might be possible // for things with token type. - Inst->dropDbgValues(); + Inst->dropDbgRecords(); EndInst = Inst; continue; } @@ -2806,7 +2806,7 @@ llvm::removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB) { else ++NumDeadInst; // RemoveDIs: erasing debug-info must be done manually. - Inst->dropDbgValues(); + Inst->dropDbgRecords(); Inst->eraseFromParent(); } return {NumDeadInst, NumDeadDbgInst}; @@ -3582,7 +3582,7 @@ void llvm::hoistAllInstructionsInto(BasicBlock *DomBlock, Instruction *InsertPt, if (I->isUsedByMetadata()) dropDebugUsers(*I); // RemoveDIs: drop debug-info too as the following code does. - I->dropDbgValues(); + I->dropDbgRecords(); if (I->isDebugOrPseudoInst()) { // Remove DbgInfo and pseudo probe Intrinsics. II = I->eraseFromParent(); diff --git a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp index cec47810e044..8c6af7afa875 100644 --- a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp @@ -554,7 +554,7 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { DbgIntrinsics.insert(makeHash(DII)); // Until RemoveDIs supports dbg.declares in DPValue format, we'll need // to collect DPValues attached to any other debug intrinsics. - for (const DPValue &DPV : DPValue::filter(DII->getDbgValueRange())) + for (const DPValue &DPV : DPValue::filter(DII->getDbgRecordRange())) DbgIntrinsics.insert(makeHash(&DPV)); } else { break; @@ -564,7 +564,7 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { // Build DPValue hashes for DPValues attached to the terminator, which isn't // considered in the loop above. for (const DPValue &DPV : - DPValue::filter(OrigPreheader->getTerminator()->getDbgValueRange())) + DPValue::filter(OrigPreheader->getTerminator()->getDbgRecordRange())) DbgIntrinsics.insert(makeHash(&DPV)); // Remember the local noalias scope declarations in the header. After the @@ -599,7 +599,7 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { // (Stored as a range because it gives us a natural way of testing whether // there were DPValues on the next instruction before we hoisted things). iterator_range NextDbgInsts = - (I != E) ? I->getDbgValueRange() : DPMarker::getEmptyDPValueRange(); + (I != E) ? I->getDbgRecordRange() : DPMarker::getEmptyDbgRecordRange(); while (I != E) { Instruction *Inst = &*I++; @@ -636,7 +636,7 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { DPV.eraseFromParent(); } - NextDbgInsts = I->getDbgValueRange(); + NextDbgInsts = I->getDbgRecordRange(); Inst->moveBefore(LoopEntryBranch); @@ -655,7 +655,7 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { auto Range = C->cloneDebugInfoFrom(Inst, NextDbgInsts.begin()); RemapDPValueRange(M, Range, ValueMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); - NextDbgInsts = DPMarker::getEmptyDPValueRange(); + NextDbgInsts = DPMarker::getEmptyDbgRecordRange(); // Erase anything we've seen before. for (DPValue &DPV : make_early_inc_range(DPValue::filter(Range))) if (DbgIntrinsics.count(makeHash(&DPV))) diff --git a/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp b/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp index 650f055356c0..ecd76b7c1fbf 100644 --- a/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp @@ -917,7 +917,7 @@ bool llvm::UnrollRuntimeLoopRemainder( for (Instruction &I : *BB) { RemapInstruction(&I, VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); - RemapDPValueRange(M, I.getDbgValueRange(), VMap, + RemapDPValueRange(M, I.getDbgRecordRange(), VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); } } diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp index 7491a99b03f6..05b02a42c58a 100644 --- a/llvm/lib/Transforms/Utils/LoopUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp @@ -634,7 +634,7 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE, // RemoveDIs: do the same as below for DPValues. if (Block->IsNewDbgInfoFormat) { for (DPValue &DPV : llvm::make_early_inc_range( - DPValue::filter(I.getDbgValueRange()))) { + DPValue::filter(I.getDbgRecordRange()))) { DebugVariable Key(DPV.getVariable(), DPV.getExpression(), DPV.getDebugLoc().get()); if (!DeadDebugSet.insert(Key).second) @@ -677,7 +677,7 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE, // repeatedly inserted before the first instruction. To replicate this // behaviour, do it backwards. for (DPValue *DPV : llvm::reverse(DeadDPValues)) - ExitBlock->insertDPValueBefore(DPV, InsertDbgValueBefore); + ExitBlock->insertDbgRecordBefore(DPV, InsertDbgValueBefore); } // Remove the block from the reference counting scheme, so that we can diff --git a/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp b/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp index bfe474d82045..ed06d3e7f452 100644 --- a/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp +++ b/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp @@ -110,7 +110,7 @@ Instruction *getUntagLocationIfFunctionExit(Instruction &Inst) { void StackInfoBuilder::visit(Instruction &Inst) { // Visit non-intrinsic debug-info records attached to Inst. - for (DPValue &DPV : DPValue::filter(Inst.getDbgValueRange())) { + for (DPValue &DPV : DPValue::filter(Inst.getDbgRecordRange())) { auto AddIfInteresting = [&](Value *V) { if (auto *AI = dyn_cast_or_null(V)) { if (!isInterestingAlloca(*AI)) diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 5b9a38c0b74e..0f3d1403481d 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1535,7 +1535,7 @@ static bool shouldHoistCommonInstructions(Instruction *I1, Instruction *I2, static void hoistLockstepIdenticalDPValues(Instruction *TI, Instruction *I1, SmallVectorImpl &OtherInsts) { - if (!I1->hasDbgValues()) + if (!I1->hasDbgRecords()) return; using CurrentAndEndIt = std::pair; @@ -1557,12 +1557,12 @@ hoistLockstepIdenticalDPValues(Instruction *TI, Instruction *I1, // Collect the iterators. Itrs.push_back( - {I1->getDbgValueRange().begin(), I1->getDbgValueRange().end()}); + {I1->getDbgRecordRange().begin(), I1->getDbgRecordRange().end()}); for (Instruction *Other : OtherInsts) { - if (!Other->hasDbgValues()) + if (!Other->hasDbgRecords()) return; Itrs.push_back( - {Other->getDbgValueRange().begin(), Other->getDbgValueRange().end()}); + {Other->getDbgRecordRange().begin(), Other->getDbgRecordRange().end()}); } // Iterate in lock-step until any of the DbgRecord lists are exausted. If @@ -1576,7 +1576,7 @@ hoistLockstepIdenticalDPValues(Instruction *TI, Instruction *I1, DbgRecord &DR = *Pair.first++; if (HoistDPVs) { DR.removeFromParent(); - TI->getParent()->insertDPValueBefore(&DR, TI->getIterator()); + TI->getParent()->insertDbgRecordBefore(&DR, TI->getIterator()); } } } @@ -3207,10 +3207,10 @@ bool SimplifyCFGOpt::SpeculativelyExecuteBB(BranchInst *BI, // instructions, in the same way that dbg.value intrinsics are dropped at the // end of this block. for (auto &It : make_range(ThenBB->begin(), ThenBB->end())) - for (DbgRecord &DR : make_early_inc_range(It.getDbgValueRange())) + for (DbgRecord &DR : make_early_inc_range(It.getDbgRecordRange())) // Drop all records except assign-kind DPValues (dbg.assign equivalent). if (DPValue *DPV = dyn_cast(&DR); !DPV || !DPV->isDbgAssign()) - It.dropOneDbgValue(&DR); + It.dropOneDbgRecord(&DR); BB->splice(BI->getIterator(), ThenBB, ThenBB->begin(), std::prev(ThenBB->end())); @@ -3849,7 +3849,7 @@ static bool performBranchToCommonDestFolding(BranchInst *BI, BranchInst *PBI, if (PredBlock->IsNewDbgInfoFormat) { PredBlock->getTerminator()->cloneDebugInfoFrom(BB->getTerminator()); for (DPValue &DPV : - DPValue::filter(PredBlock->getTerminator()->getDbgValueRange())) { + DPValue::filter(PredBlock->getTerminator()->getDbgRecordRange())) { RemapDPValue(M, &DPV, VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); } @@ -5308,7 +5308,7 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) { // Debug-info records on the unreachable inst itself should be deleted, as // below we delete everything past the final executable instruction. - UI->dropDbgValues(); + UI->dropDbgRecords(); // If there are any instructions immediately before the unreachable that can // be removed, do so. @@ -5328,7 +5328,7 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) { // If we're deleting this, we're deleting any subsequent dbg.values, so // delete DPValue records of variable information. - BBI->dropDbgValues(); + BBI->dropDbgRecords(); // Delete this instruction (any uses are guaranteed to be dead) BBI->replaceAllUsesWith(PoisonValue::get(BBI->getType())); diff --git a/llvm/lib/Transforms/Utils/ValueMapper.cpp b/llvm/lib/Transforms/Utils/ValueMapper.cpp index 91ab2795a4b9..3da161043d6c 100644 --- a/llvm/lib/Transforms/Utils/ValueMapper.cpp +++ b/llvm/lib/Transforms/Utils/ValueMapper.cpp @@ -1066,7 +1066,7 @@ void Mapper::remapFunction(Function &F) { for (BasicBlock &BB : F) { for (Instruction &I : BB) { remapInstruction(&I); - for (DbgRecord &DR : I.getDbgValueRange()) + for (DbgRecord &DR : I.getDbgRecordRange()) remapDPValue(DR); } } diff --git a/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.cpp b/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.cpp index 94b12eb34cf6..2f3d4cac9fa0 100644 --- a/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.cpp @@ -29,7 +29,7 @@ static void extractDbgRecordsFromModule(Oracle &O, ReducerWorkItem &WorkItem) { for (auto &F : M) for (auto &BB : F) for (auto &I : BB) - for (DbgRecord &DR : llvm::make_early_inc_range(I.getDbgValueRange())) + for (DbgRecord &DR : llvm::make_early_inc_range(I.getDbgRecordRange())) if (!O.shouldKeep()) DR.eraseFromParent(); } diff --git a/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp b/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp index b773bffd7a03..e23c7eaa4930 100644 --- a/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp +++ b/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp @@ -80,9 +80,9 @@ TEST(BasicBlockDbgInfoTest, InsertAfterSelf) { Instruction *Inst1 = &*BB.begin(); Instruction *Inst2 = &*std::next(BB.begin()); Instruction *RetInst = &*std::next(Inst2->getIterator()); - EXPECT_TRUE(Inst1->hasDbgValues()); - EXPECT_TRUE(Inst2->hasDbgValues()); - EXPECT_FALSE(RetInst->hasDbgValues()); + EXPECT_TRUE(Inst1->hasDbgRecords()); + EXPECT_TRUE(Inst2->hasDbgRecords()); + EXPECT_FALSE(RetInst->hasDbgRecords()); // If we move Inst2 to be after Inst1, then it comes _immediately_ after. Were // we in dbg.value form we would then have: @@ -94,14 +94,14 @@ TEST(BasicBlockDbgInfoTest, InsertAfterSelf) { Inst2->moveAfter(Inst1); // Inst1 should only have one DPValue on it. - EXPECT_TRUE(Inst1->hasDbgValues()); - auto Range1 = Inst1->getDbgValueRange(); + EXPECT_TRUE(Inst1->hasDbgRecords()); + auto Range1 = Inst1->getDbgRecordRange(); EXPECT_EQ(std::distance(Range1.begin(), Range1.end()), 1u); // Inst2 should have none. - EXPECT_FALSE(Inst2->hasDbgValues()); + EXPECT_FALSE(Inst2->hasDbgRecords()); // While the return inst should now have one on it. - EXPECT_TRUE(RetInst->hasDbgValues()); - auto Range2 = RetInst->getDbgValueRange(); + EXPECT_TRUE(RetInst->hasDbgRecords()); + auto Range2 = RetInst->getDbgRecordRange(); EXPECT_EQ(std::distance(Range2.begin(), Range2.end()), 1u); M->convertFromNewDbgValues(); @@ -171,12 +171,12 @@ TEST(BasicBlockDbgInfoTest, MarkerOperations) { EXPECT_TRUE(Marker2->StoredDPValues.empty()); // This should appear in Marker1. - BB.insertDPValueBefore(DPV1, BB.begin()); + BB.insertDbgRecordBefore(DPV1, BB.begin()); EXPECT_EQ(Marker1->StoredDPValues.size(), 1u); EXPECT_EQ(DPV1, &*Marker1->StoredDPValues.begin()); // This should attach to Marker2. - BB.insertDPValueAfter(DPV2, &*BB.begin()); + BB.insertDbgRecordAfter(DPV2, &*BB.begin()); EXPECT_EQ(Marker2->StoredDPValues.size(), 1u); EXPECT_EQ(DPV2, &*Marker2->StoredDPValues.begin()); @@ -189,23 +189,23 @@ TEST(BasicBlockDbgInfoTest, MarkerOperations) { EXPECT_EQ(Marker2->StoredDPValues.size(), 2u); // They should also be in the correct order. SmallVector DPVs; - for (DbgRecord &DPV : Marker2->getDbgValueRange()) + for (DbgRecord &DPV : Marker2->getDbgRecordRange()) DPVs.push_back(&DPV); EXPECT_EQ(DPVs[0], DPV1); EXPECT_EQ(DPVs[1], DPV2); // If we remove the end instruction, the DPValues should fall down into // the trailing marker. - EXPECT_EQ(BB.getTrailingDPValues(), nullptr); + EXPECT_EQ(BB.getTrailingDbgRecords(), nullptr); Instr2->removeFromParent(); EXPECT_TRUE(BB.empty()); - EndMarker = BB.getTrailingDPValues(); + EndMarker = BB.getTrailingDbgRecords(); ASSERT_NE(EndMarker, nullptr); EXPECT_EQ(EndMarker->StoredDPValues.size(), 2u); // Again, these should arrive in the correct order. DPVs.clear(); - for (DbgRecord &DPV : EndMarker->getDbgValueRange()) + for (DbgRecord &DPV : EndMarker->getDbgRecordRange()) DPVs.push_back(&DPV); EXPECT_EQ(DPVs[0], DPV1); EXPECT_EQ(DPVs[1], DPV2); @@ -222,11 +222,11 @@ TEST(BasicBlockDbgInfoTest, MarkerOperations) { EXPECT_EQ(Instr1->DbgMarker->StoredDPValues.size(), 2u); // We should de-allocate the trailing marker when something is inserted // at end(). - EXPECT_EQ(BB.getTrailingDPValues(), nullptr); + EXPECT_EQ(BB.getTrailingDbgRecords(), nullptr); // Remove Instr1: now the DPValues will fall down again, Instr1->removeFromParent(); - EndMarker = BB.getTrailingDPValues(); + EndMarker = BB.getTrailingDbgRecords(); EXPECT_EQ(EndMarker->StoredDPValues.size(), 2u); // Inserting a terminator, however it's intended, should dislodge the @@ -235,7 +235,7 @@ TEST(BasicBlockDbgInfoTest, MarkerOperations) { // end forever. Instr2->insertBefore(BB, BB.begin()); EXPECT_EQ(Instr2->DbgMarker->StoredDPValues.size(), 2u); - EXPECT_EQ(BB.getTrailingDPValues(), nullptr); + EXPECT_EQ(BB.getTrailingDbgRecords(), nullptr); // Teardown, Instr1->insertBefore(BB, BB.begin()); @@ -393,7 +393,7 @@ TEST(BasicBlockDbgInfoTest, InstrDbgAccess) { ASSERT_EQ(CInst->DbgMarker->StoredDPValues.size(), 1u); DbgRecord *DPV1 = &*CInst->DbgMarker->StoredDPValues.begin(); ASSERT_TRUE(DPV1); - EXPECT_FALSE(BInst->hasDbgValues()); + EXPECT_FALSE(BInst->hasDbgRecords()); // Clone DPValues from one inst to another. Other arguments to clone are // tested in DPMarker test. @@ -405,23 +405,23 @@ TEST(BasicBlockDbgInfoTest, InstrDbgAccess) { EXPECT_NE(DPV1, DPV2); // We should be able to get a range over exactly the same information. - auto Range2 = BInst->getDbgValueRange(); + auto Range2 = BInst->getDbgRecordRange(); EXPECT_EQ(Range1.begin(), Range2.begin()); EXPECT_EQ(Range1.end(), Range2.end()); // We should be able to query if there are DPValues, - EXPECT_TRUE(BInst->hasDbgValues()); - EXPECT_TRUE(CInst->hasDbgValues()); - EXPECT_FALSE(DInst->hasDbgValues()); + EXPECT_TRUE(BInst->hasDbgRecords()); + EXPECT_TRUE(CInst->hasDbgRecords()); + EXPECT_FALSE(DInst->hasDbgRecords()); // Dropping should be easy, - BInst->dropDbgValues(); - EXPECT_FALSE(BInst->hasDbgValues()); + BInst->dropDbgRecords(); + EXPECT_FALSE(BInst->hasDbgRecords()); EXPECT_EQ(BInst->DbgMarker->StoredDPValues.size(), 0u); // And we should be able to drop individual DPValues. - CInst->dropOneDbgValue(DPV1); - EXPECT_FALSE(CInst->hasDbgValues()); + CInst->dropOneDbgRecord(DPV1); + EXPECT_FALSE(CInst->hasDbgRecords()); EXPECT_EQ(CInst->DbgMarker->StoredDPValues.size(), 0u); UseNewDbgInfoFormat = false; @@ -539,7 +539,7 @@ protected: void TearDown() override { UseNewDbgInfoFormat = false; } bool InstContainsDPValue(Instruction *I, DPValue *DPV) { - for (DbgRecord &D : I->getDbgValueRange()) { + for (DbgRecord &D : I->getDbgRecordRange()) { if (&D == DPV) { // Confirm too that the links between the records are correct. EXPECT_EQ(DPV->Marker, I->DbgMarker); @@ -552,7 +552,7 @@ protected: bool CheckDPVOrder(Instruction *I, SmallVector CheckVals) { SmallVector Vals; - for (DbgRecord &D : I->getDbgValueRange()) + for (DbgRecord &D : I->getDbgRecordRange()) Vals.push_back(&D); EXPECT_EQ(Vals.size(), CheckVals.size()); @@ -1161,7 +1161,7 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceTrailing) { // Begin by forcing entry block to have dangling DPValue. Entry.getTerminator()->eraseFromParent(); - ASSERT_NE(Entry.getTrailingDPValues(), nullptr); + ASSERT_NE(Entry.getTrailingDbgRecords(), nullptr); EXPECT_TRUE(Entry.empty()); // Now transfer the entire contents of the exit block into the entry. @@ -1222,12 +1222,12 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsert) { ASSERT_TRUE(isa(RetInst)); // add and sub should both have one DPValue on add and ret. - EXPECT_FALSE(SubInst->hasDbgValues()); - EXPECT_TRUE(AddInst->hasDbgValues()); - EXPECT_TRUE(RetInst->hasDbgValues()); - auto R1 = AddInst->getDbgValueRange(); + EXPECT_FALSE(SubInst->hasDbgRecords()); + EXPECT_TRUE(AddInst->hasDbgRecords()); + EXPECT_TRUE(RetInst->hasDbgRecords()); + auto R1 = AddInst->getDbgRecordRange(); EXPECT_EQ(std::distance(R1.begin(), R1.end()), 1u); - auto R2 = RetInst->getDbgValueRange(); + auto R2 = RetInst->getDbgRecordRange(); EXPECT_EQ(std::distance(R2.begin(), R2.end()), 1u); // The Supported (TM) code sequence for removing then reinserting insts @@ -1239,19 +1239,19 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsert) { // We should have a re-insertion position. ASSERT_TRUE(Pos); // Both DPValues should now be attached to the ret inst. - auto R3 = RetInst->getDbgValueRange(); + auto R3 = RetInst->getDbgRecordRange(); EXPECT_EQ(std::distance(R3.begin(), R3.end()), 2u); // Re-insert and re-insert. AddInst->insertAfter(SubInst); - Entry.reinsertInstInDPValues(AddInst, Pos); + Entry.reinsertInstInDbgRecords(AddInst, Pos); // We should be back into a position of having one DPValue on add and ret. - EXPECT_FALSE(SubInst->hasDbgValues()); - EXPECT_TRUE(AddInst->hasDbgValues()); - EXPECT_TRUE(RetInst->hasDbgValues()); - auto R4 = AddInst->getDbgValueRange(); + EXPECT_FALSE(SubInst->hasDbgRecords()); + EXPECT_TRUE(AddInst->hasDbgRecords()); + EXPECT_TRUE(RetInst->hasDbgRecords()); + auto R4 = AddInst->getDbgRecordRange(); EXPECT_EQ(std::distance(R4.begin(), R4.end()), 1u); - auto R5 = RetInst->getDbgValueRange(); + auto R5 = RetInst->getDbgRecordRange(); EXPECT_EQ(std::distance(R5.begin(), R5.end()), 1u); UseNewDbgInfoFormat = false; @@ -1300,10 +1300,10 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsertForOneDPValue) { ASSERT_TRUE(isa(RetInst)); // There should be one DPValue. - EXPECT_FALSE(SubInst->hasDbgValues()); - EXPECT_TRUE(AddInst->hasDbgValues()); - EXPECT_FALSE(RetInst->hasDbgValues()); - auto R1 = AddInst->getDbgValueRange(); + EXPECT_FALSE(SubInst->hasDbgRecords()); + EXPECT_TRUE(AddInst->hasDbgRecords()); + EXPECT_FALSE(RetInst->hasDbgRecords()); + auto R1 = AddInst->getDbgRecordRange(); EXPECT_EQ(std::distance(R1.begin(), R1.end()), 1u); // The Supported (TM) code sequence for removing then reinserting insts: @@ -1314,18 +1314,18 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsertForOneDPValue) { // No re-insertion position as there were no DPValues on the ret. ASSERT_FALSE(Pos); // The single DPValue should now be attached to the ret inst. - EXPECT_TRUE(RetInst->hasDbgValues()); - auto R2 = RetInst->getDbgValueRange(); + EXPECT_TRUE(RetInst->hasDbgRecords()); + auto R2 = RetInst->getDbgRecordRange(); EXPECT_EQ(std::distance(R2.begin(), R2.end()), 1u); // Re-insert and re-insert. AddInst->insertAfter(SubInst); - Entry.reinsertInstInDPValues(AddInst, Pos); + Entry.reinsertInstInDbgRecords(AddInst, Pos); // We should be back into a position of having one DPValue on the AddInst. - EXPECT_FALSE(SubInst->hasDbgValues()); - EXPECT_TRUE(AddInst->hasDbgValues()); - EXPECT_FALSE(RetInst->hasDbgValues()); - auto R3 = AddInst->getDbgValueRange(); + EXPECT_FALSE(SubInst->hasDbgRecords()); + EXPECT_TRUE(AddInst->hasDbgRecords()); + EXPECT_FALSE(RetInst->hasDbgRecords()); + auto R3 = AddInst->getDbgRecordRange(); EXPECT_EQ(std::distance(R3.begin(), R3.end()), 1u); UseNewDbgInfoFormat = false; @@ -1376,7 +1376,7 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty1) { // Begin by forcing entry block to have dangling DPValue. Entry.getTerminator()->eraseFromParent(); - ASSERT_NE(Entry.getTrailingDPValues(), nullptr); + ASSERT_NE(Entry.getTrailingDbgRecords(), nullptr); EXPECT_TRUE(Entry.empty()); // Now transfer the entire contents of the exit block into the entry. This @@ -1386,10 +1386,10 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty1) { // We should now have two dbg.values on the first instruction, and they // should be in the correct order of %a, then 0. Instruction *BInst = &*Entry.begin(); - ASSERT_TRUE(BInst->hasDbgValues()); + ASSERT_TRUE(BInst->hasDbgRecords()); EXPECT_EQ(BInst->DbgMarker->StoredDPValues.size(), 2u); SmallVector DPValues; - for (DbgRecord &DPV : BInst->getDbgValueRange()) + for (DbgRecord &DPV : BInst->getDbgRecordRange()) DPValues.push_back(cast(&DPV)); EXPECT_EQ(DPValues[0]->getVariableLocationOp(0), F.getArg(0)); @@ -1398,7 +1398,7 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty1) { EXPECT_EQ(cast(SecondDPVValue)->getZExtValue(), 0ull); // No trailing DPValues in the entry block now. - EXPECT_EQ(Entry.getTrailingDPValues(), nullptr); + EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr); UseNewDbgInfoFormat = false; } @@ -1446,7 +1446,7 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty2) { // Begin by forcing entry block to have dangling DPValue. Entry.getTerminator()->eraseFromParent(); - ASSERT_NE(Entry.getTrailingDPValues(), nullptr); + ASSERT_NE(Entry.getTrailingDbgRecords(), nullptr); EXPECT_TRUE(Entry.empty()); // Now transfer into the entry block -- fetching the first instruction with @@ -1456,23 +1456,23 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty2) { // We should now have one dbg.values on the first instruction, %a. Instruction *BInst = &*Entry.begin(); - ASSERT_TRUE(BInst->hasDbgValues()); + ASSERT_TRUE(BInst->hasDbgRecords()); EXPECT_EQ(BInst->DbgMarker->StoredDPValues.size(), 1u); SmallVector DPValues; - for (DbgRecord &DPV : BInst->getDbgValueRange()) + for (DbgRecord &DPV : BInst->getDbgRecordRange()) DPValues.push_back(cast(&DPV)); EXPECT_EQ(DPValues[0]->getVariableLocationOp(0), F.getArg(0)); // No trailing DPValues in the entry block now. - EXPECT_EQ(Entry.getTrailingDPValues(), nullptr); + EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr); // We should have nothing left in the exit block... EXPECT_TRUE(Exit.empty()); // ... except for some dangling DPValues. - EXPECT_NE(Exit.getTrailingDPValues(), nullptr); - EXPECT_FALSE(Exit.getTrailingDPValues()->empty()); - Exit.getTrailingDPValues()->eraseFromParent(); - Exit.deleteTrailingDPValues(); + EXPECT_NE(Exit.getTrailingDbgRecords(), nullptr); + EXPECT_FALSE(Exit.getTrailingDbgRecords()->empty()); + Exit.getTrailingDbgRecords()->eraseFromParent(); + Exit.deleteTrailingDbgRecords(); UseNewDbgInfoFormat = false; } @@ -1517,14 +1517,14 @@ TEST(BasicBlockDbgInfoTest, DbgMoveToEnd) { // Move the return to the end of the entry block. Instruction *Br = Entry.getTerminator(); Instruction *Ret = Exit.getTerminator(); - EXPECT_EQ(Entry.getTrailingDPValues(), nullptr); + EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr); Ret->moveBefore(Entry, Entry.end()); Br->eraseFromParent(); // There should continue to not be any debug-info anywhere. - EXPECT_EQ(Entry.getTrailingDPValues(), nullptr); - EXPECT_EQ(Exit.getTrailingDPValues(), nullptr); - EXPECT_FALSE(Ret->hasDbgValues()); + EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr); + EXPECT_EQ(Exit.getTrailingDbgRecords(), nullptr); + EXPECT_FALSE(Ret->hasDbgRecords()); UseNewDbgInfoFormat = false; } diff --git a/llvm/unittests/IR/DebugInfoTest.cpp b/llvm/unittests/IR/DebugInfoTest.cpp index c99f928de8a9..0b019c26148b 100644 --- a/llvm/unittests/IR/DebugInfoTest.cpp +++ b/llvm/unittests/IR/DebugInfoTest.cpp @@ -952,10 +952,10 @@ TEST(MetadataTest, ConvertDbgToDPValue) { ExitBlock->createMarker(RetInst); // Insert DPValues into markers, order should come out DPV2, DPV1. - FirstInst->DbgMarker->insertDPValue(DPV1, false); - FirstInst->DbgMarker->insertDPValue(DPV2, true); + FirstInst->DbgMarker->insertDbgRecord(DPV1, false); + FirstInst->DbgMarker->insertDbgRecord(DPV2, true); unsigned int ItCount = 0; - for (DbgRecord &Item : FirstInst->DbgMarker->getDbgValueRange()) { + for (DbgRecord &Item : FirstInst->DbgMarker->getDbgRecordRange()) { EXPECT_TRUE((&Item == DPV2 && ItCount == 0) || (&Item == DPV1 && ItCount == 1)); EXPECT_EQ(Item.getMarker(), FirstInst->DbgMarker); @@ -969,7 +969,7 @@ TEST(MetadataTest, ConvertDbgToDPValue) { // Check these things store the same information; but that they're not the same // objects. for (DPValue &Item : - DPValue::filter(RetInst->DbgMarker->getDbgValueRange())) { + DPValue::filter(RetInst->DbgMarker->getDbgRecordRange())) { EXPECT_TRUE((Item.getRawLocation() == DPV2->getRawLocation() && ItCount == 0) || (Item.getRawLocation() == DPV1->getRawLocation() && ItCount == 1)); @@ -979,11 +979,11 @@ TEST(MetadataTest, ConvertDbgToDPValue) { ++ItCount; } - RetInst->DbgMarker->dropDbgValues(); + RetInst->DbgMarker->dropDbgRecords(); EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 0u); // Try cloning one single DPValue. - auto DIIt = std::next(FirstInst->DbgMarker->getDbgValueRange().begin()); + auto DIIt = std::next(FirstInst->DbgMarker->getDbgRecordRange().begin()); RetInst->DbgMarker->cloneDebugInfoFrom(FirstInst->DbgMarker, DIIt, false); EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 1u); // The second DPValue should have been cloned; it should have the same values @@ -992,7 +992,7 @@ TEST(MetadataTest, ConvertDbgToDPValue) { ->getRawLocation(), DPV1->getRawLocation()); // We should be able to drop individual DPValues. - RetInst->DbgMarker->dropOneDbgValue( + RetInst->DbgMarker->dropOneDbgRecord( &*RetInst->DbgMarker->StoredDPValues.begin()); // "Aborb" a DPMarker: this means pretend that the instruction it's attached @@ -1001,7 +1001,7 @@ TEST(MetadataTest, ConvertDbgToDPValue) { EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 2u); // Should be the DPV1 and DPV2 objects. ItCount = 0; - for (DbgRecord &Item : RetInst->DbgMarker->getDbgValueRange()) { + for (DbgRecord &Item : RetInst->DbgMarker->getDbgRecordRange()) { EXPECT_TRUE((&Item == DPV2 && ItCount == 0) || (&Item == DPV1 && ItCount == 1)); EXPECT_EQ(Item.getMarker(), RetInst->DbgMarker); @@ -1017,12 +1017,12 @@ TEST(MetadataTest, ConvertDbgToDPValue) { RetInst->DbgMarker->removeMarker(); RetInst->eraseFromParent(); - DPMarker *EndMarker = ExitBlock->getTrailingDPValues(); + DPMarker *EndMarker = ExitBlock->getTrailingDbgRecords(); ASSERT_NE(EndMarker, nullptr); EXPECT_EQ(EndMarker->StoredDPValues.size(), 2u); // Test again that it's those two DPValues, DPV1 and DPV2. ItCount = 0; - for (DbgRecord &Item : EndMarker->getDbgValueRange()) { + for (DbgRecord &Item : EndMarker->getDbgRecordRange()) { EXPECT_TRUE((&Item == DPV2 && ItCount == 0) || (&Item == DPV1 && ItCount == 1)); EXPECT_EQ(Item.getMarker(), EndMarker); @@ -1034,7 +1034,7 @@ TEST(MetadataTest, ConvertDbgToDPValue) { // The record of those trailing DPValues would dangle and cause an assertion // failure if it lived until the end of the LLVMContext. - ExitBlock->deleteTrailingDPValues(); + ExitBlock->deleteTrailingDbgRecords(); } TEST(MetadataTest, DPValueConversionRoutines) { @@ -1117,14 +1117,14 @@ TEST(MetadataTest, DPValueConversionRoutines) { EXPECT_EQ(FirstInst->DbgMarker->StoredDPValues.size(), 1u); DPValue *DPV1 = - cast(&*FirstInst->DbgMarker->getDbgValueRange().begin()); + cast(&*FirstInst->DbgMarker->getDbgRecordRange().begin()); EXPECT_EQ(DPV1->getMarker(), FirstInst->DbgMarker); // Should point at %a, an argument. EXPECT_TRUE(isa(DPV1->getVariableLocationOp(0))); EXPECT_EQ(SecondInst->DbgMarker->StoredDPValues.size(), 1u); DPValue *DPV2 = - cast(&*SecondInst->DbgMarker->getDbgValueRange().begin()); + cast(&*SecondInst->DbgMarker->getDbgRecordRange().begin()); EXPECT_EQ(DPV2->getMarker(), SecondInst->DbgMarker); // Should point at FirstInst. EXPECT_EQ(DPV2->getVariableLocationOp(0), FirstInst); diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp index cece65974c01..139e8832c97b 100644 --- a/llvm/unittests/IR/IRBuilderTest.cpp +++ b/llvm/unittests/IR/IRBuilderTest.cpp @@ -872,15 +872,15 @@ TEST_F(IRBuilderTest, createFunction) { TEST_F(IRBuilderTest, DIBuilder) { auto GetLastDbgRecord = [](const Instruction *I) -> DbgRecord * { - if (I->getDbgValueRange().empty()) + if (I->getDbgRecordRange().empty()) return nullptr; - return &*std::prev(I->getDbgValueRange().end()); + return &*std::prev(I->getDbgRecordRange().end()); }; auto ExpectOrder = [&](DbgInstPtr First, BasicBlock::iterator Second) { if (M->IsNewDbgInfoFormat) { EXPECT_TRUE(First.is()); - EXPECT_FALSE(Second->getDbgValueRange().empty()); + EXPECT_FALSE(Second->getDbgRecordRange().empty()); EXPECT_EQ(GetLastDbgRecord(&*Second), First.get()); } else { EXPECT_TRUE(First.is()); @@ -951,7 +951,7 @@ TEST_F(IRBuilderTest, DIBuilder) { I, VarX, DIB.createExpression(), VarLoc, BB); I = Builder.CreateAlloca(Builder.getInt32Ty()); ExpectOrder(VarXValue, I->getIterator()); - EXPECT_EQ(BB->getTrailingDPValues(), nullptr); + EXPECT_EQ(BB->getTrailingDbgRecords(), nullptr); } { /* dbg.declare | DPValue::Declare */ ExpectOrder(DIB.insertDeclare(I, VarY, DIB.createExpression(), VarLoc, I), @@ -961,7 +961,7 @@ TEST_F(IRBuilderTest, DIBuilder) { DIB.insertDeclare(I, VarY, DIB.createExpression(), VarLoc, BB); I = Builder.CreateAlloca(Builder.getInt32Ty()); ExpectOrder(VarYDeclare, I->getIterator()); - EXPECT_EQ(BB->getTrailingDPValues(), nullptr); + EXPECT_EQ(BB->getTrailingDbgRecords(), nullptr); } { /* dbg.assign | DPValue::Assign */ I = Builder.CreateAlloca(Builder.getInt32Ty()); @@ -974,7 +974,7 @@ TEST_F(IRBuilderTest, DIBuilder) { DIB.createExpression(), VarLoc); I = Builder.CreateAlloca(Builder.getInt32Ty()); ExpectOrder(VarXAssign, I->getIterator()); - EXPECT_EQ(BB->getTrailingDPValues(), nullptr); + EXPECT_EQ(BB->getTrailingDbgRecords(), nullptr); } Builder.CreateRet(nullptr); diff --git a/llvm/unittests/IR/ValueTest.cpp b/llvm/unittests/IR/ValueTest.cpp index 6146719bb296..97c8fea3c6db 100644 --- a/llvm/unittests/IR/ValueTest.cpp +++ b/llvm/unittests/IR/ValueTest.cpp @@ -376,11 +376,11 @@ TEST(ValueTest, replaceUsesOutsideBlockDPValue) { BasicBlock *Exit = GetNext(Entry); Instruction *Ret = &Exit->front(); - EXPECT_TRUE(Branch->hasDbgValues()); - EXPECT_TRUE(Ret->hasDbgValues()); + EXPECT_TRUE(Branch->hasDbgRecords()); + EXPECT_TRUE(Ret->hasDbgRecords()); - DPValue *DPV1 = cast(&*Branch->getDbgValueRange().begin()); - DPValue *DPV2 = cast(&*Ret->getDbgValueRange().begin()); + DPValue *DPV1 = cast(&*Branch->getDbgRecordRange().begin()); + DPValue *DPV2 = cast(&*Ret->getDbgRecordRange().begin()); A->replaceUsesOutsideBlock(B, Entry); // These users are in Entry so shouldn't be changed. diff --git a/llvm/unittests/Transforms/Utils/DebugifyTest.cpp b/llvm/unittests/Transforms/Utils/DebugifyTest.cpp index 1ec9402b8aa9..89fa1334b427 100644 --- a/llvm/unittests/Transforms/Utils/DebugifyTest.cpp +++ b/llvm/unittests/Transforms/Utils/DebugifyTest.cpp @@ -61,7 +61,7 @@ struct DebugValueDrop : public FunctionPass { if (auto *DVI = dyn_cast(&I)) Dbgs.push_back(DVI); // If there are any non-intrinsic records (DPValues), drop those too. - I.dropDbgValues(); + I.dropDbgRecords(); } } diff --git a/llvm/unittests/Transforms/Utils/LocalTest.cpp b/llvm/unittests/Transforms/Utils/LocalTest.cpp index 822577410457..87a2a2ae4700 100644 --- a/llvm/unittests/Transforms/Utils/LocalTest.cpp +++ b/llvm/unittests/Transforms/Utils/LocalTest.cpp @@ -1327,7 +1327,7 @@ TEST(Local, ReplaceDPValue) { RetInst->DbgMarker = new DPMarker(); RetInst->DbgMarker->MarkedInstr = RetInst; DPValue *DPV = new DPValue(DVI); - RetInst->DbgMarker->insertDPValue(DPV, false); + RetInst->DbgMarker->insertDbgRecord(DPV, false); // ... and erase the dbg.value. DVI->eraseFromParent(); -- GitLab From 0fe271c35368a9190661bcca87101fc0916d6a8b Mon Sep 17 00:00:00 2001 From: Fanbo Meng Date: Tue, 12 Mar 2024 10:56:51 -0400 Subject: [PATCH 253/953] [SystemZ][z/OS] Add missing include header to AutoConvert.cpp to fix build (#84909) ba13fa2a5d57581bff1a7e9322234af30f4882f6 added usages of `errnoAsErrorCode()` to AutoConvert.cpp, need to include Error.h header to fix build failure. --- llvm/lib/Support/AutoConvert.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/lib/Support/AutoConvert.cpp b/llvm/lib/Support/AutoConvert.cpp index 74842e9167bd..c509284ee916 100644 --- a/llvm/lib/Support/AutoConvert.cpp +++ b/llvm/lib/Support/AutoConvert.cpp @@ -14,6 +14,7 @@ #ifdef __MVS__ #include "llvm/Support/AutoConvert.h" +#include "llvm/Support/Error.h" #include #include #include -- GitLab From f32b04d4ea91ad1018c25a1d4178cc4392d34968 Mon Sep 17 00:00:00 2001 From: NagyDonat Date: Tue, 12 Mar 2024 16:01:04 +0100 Subject: [PATCH 254/953] Revert "[analyzer] Accept C library functions from the `std` namespace" (#84926) Reverts llvm/llvm-project#84469 because it causes buildbot failures. I'll examine them and re-submit the change. --- .../Core/PathSensitive/CallDescription.h | 8 +- .../StaticAnalyzer/Core/CheckerContext.cpp | 8 +- clang/unittests/StaticAnalyzer/CMakeLists.txt | 1 - .../StaticAnalyzer/IsCLibraryFunctionTest.cpp | 89 ------------------- .../clang/unittests/StaticAnalyzer/BUILD.gn | 1 - 5 files changed, 9 insertions(+), 98 deletions(-) delete mode 100644 clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h index b4e1636130ca..3432d2648633 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h @@ -41,8 +41,12 @@ public: /// - We also accept calls where the number of arguments or parameters is /// greater than the specified value. /// For the exact heuristics, see CheckerContext::isCLibraryFunction(). - /// (This mode only matches functions that are declared either directly - /// within a TU or in the namespace `std`.) + /// Note that functions whose declaration context is not a TU (e.g. + /// methods, functions in namespaces) are not accepted as C library + /// functions. + /// FIXME: If I understand it correctly, this discards calls where C++ code + /// refers a C library function through the namespace `std::` via headers + /// like . CLibrary, /// Matches "simple" functions that are not methods. (Static methods are diff --git a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp index 1a9bff529e9b..d6d4cec9dd3d 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp @@ -87,11 +87,9 @@ bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD, if (!II) return false; - // C library functions are either declared directly within a TU (the common - // case) or they are accessed through the namespace `std` (when they are used - // in C++ via headers like ). - const DeclContext *DC = FD->getDeclContext()->getRedeclContext(); - if (!(DC->isTranslationUnit() || DC->isStdNamespace())) + // Look through 'extern "C"' and anything similar invented in the future. + // If this function is not in TU directly, it is not a C library function. + if (!FD->getDeclContext()->getRedeclContext()->isTranslationUnit()) return false; // If this function is not externally visible, it is not a C library function. diff --git a/clang/unittests/StaticAnalyzer/CMakeLists.txt b/clang/unittests/StaticAnalyzer/CMakeLists.txt index db56e77331b8..775f0f8486b8 100644 --- a/clang/unittests/StaticAnalyzer/CMakeLists.txt +++ b/clang/unittests/StaticAnalyzer/CMakeLists.txt @@ -11,7 +11,6 @@ add_clang_unittest(StaticAnalysisTests CallEventTest.cpp ConflictingEvalCallsTest.cpp FalsePositiveRefutationBRVisitorTest.cpp - IsCLibraryFunctionTest.cpp NoStateChangeFuncVisitorTest.cpp ParamRegionTest.cpp RangeSetTest.cpp diff --git a/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp b/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp deleted file mode 100644 index 19c66cc6bee1..000000000000 --- a/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/ASTMatchers/ASTMatchers.h" -#include "clang/Analysis/AnalysisDeclContext.h" -#include "clang/Frontend/ASTUnit.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" -#include "clang/Tooling/Tooling.h" -#include "gtest/gtest.h" - -#include - -using namespace clang; -using namespace ento; -using namespace ast_matchers; - -testing::AssertionResult extractFunctionDecl(StringRef Code, - const FunctionDecl *&Result) { - auto ASTUnit = tooling::buildASTFromCode(Code); - if (!ASTUnit) - return testing::AssertionFailure() << "AST construction failed"; - - ASTContext &Context = ASTUnit->getASTContext(); - if (Context.getDiagnostics().hasErrorOccurred()) - return testing::AssertionFailure() << "Compilation error"; - - auto Matches = ast_matchers::match(functionDecl().bind("fn"), Context); - if (Matches.empty()) - return testing::AssertionFailure() << "No function declaration found"; - - if (Matches.size() > 1) - return testing::AssertionFailure() - << "Multiple function declarations found"; - - Result = Matches[0].getNodeAs("fn"); - return testing::AssertionSuccess(); -} - -TEST(IsCLibraryFunctionTest, AcceptsGlobal) { - const FunctionDecl *Result; - ASSERT_TRUE(extractFunctionDecl(R"cpp(void fun();)cpp", Result)); - EXPECT_TRUE(CheckerContext::isCLibraryFunction(Result)); -} - -TEST(IsCLibraryFunctionTest, AcceptsExternCGlobal) { - const FunctionDecl *Result; - ASSERT_TRUE( - extractFunctionDecl(R"cpp(extern "C" { void fun(); })cpp", Result)); - EXPECT_TRUE(CheckerContext::isCLibraryFunction(Result)); -} - -TEST(IsCLibraryFunctionTest, RejectsNoInlineNoExternalLinkage) { - // Functions that are neither inlined nor externally visible cannot be C library functions. - const FunctionDecl *Result; - ASSERT_TRUE(extractFunctionDecl(R"cpp(static void fun();)cpp", Result)); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); -} - -TEST(IsCLibraryFunctionTest, RejectsAnonymousNamespace) { - const FunctionDecl *Result; - ASSERT_TRUE( - extractFunctionDecl(R"cpp(namespace { void fun(); })cpp", Result)); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); -} - -TEST(IsCLibraryFunctionTest, AcceptsStdNamespace) { - const FunctionDecl *Result; - ASSERT_TRUE( - extractFunctionDecl(R"cpp(namespace std { void fun(); })cpp", Result)); - EXPECT_TRUE(CheckerContext::isCLibraryFunction(Result)); -} - -TEST(IsCLibraryFunctionTest, RejectsOtherNamespaces) { - const FunctionDecl *Result; - ASSERT_TRUE( - extractFunctionDecl(R"cpp(namespace stdx { void fun(); })cpp", Result)); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); -} - -TEST(IsCLibraryFunctionTest, RejectsClassStatic) { - const FunctionDecl *Result; - ASSERT_TRUE( - extractFunctionDecl(R"cpp(class A { static void fun(); };)cpp", Result)); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); -} - -TEST(IsCLibraryFunctionTest, RejectsClassMember) { - const FunctionDecl *Result; - ASSERT_TRUE(extractFunctionDecl(R"cpp(class A { void fun(); };)cpp", Result)); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result)); -} diff --git a/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn index 9c240cff1816..01c2b6ced336 100644 --- a/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn @@ -19,7 +19,6 @@ unittest("StaticAnalysisTests") { "CallEventTest.cpp", "ConflictingEvalCallsTest.cpp", "FalsePositiveRefutationBRVisitorTest.cpp", - "IsCLibraryFunctionTest.cpp", "NoStateChangeFuncVisitorTest.cpp", "ParamRegionTest.cpp", "RangeSetTest.cpp", -- GitLab From 083da46ff07170471f8bb9ed2947f6ebc725670b Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 12 Mar 2024 08:02:54 -0700 Subject: [PATCH 255/953] [clang][deps] Fix dependency scanning with -working-directory (#84525) Stop overriding -working-directory to CWD during argument parsing, which should no longer necessary after we set the VFS working directory, and set FSOpts correctly after parsing arguments so that working-directory behaves correctly. --- .../DependencyScanningWorker.cpp | 14 ++++----- .../ClangScanDeps/working-directory-option.c | 30 +++++++++++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 clang/test/ClangScanDeps/working-directory-option.c diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 2b882f8a5e07..76f3d950a13b 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -296,7 +296,7 @@ public: DisableFree(DisableFree), ModuleName(ModuleName) {} bool runInvocation(std::shared_ptr Invocation, - FileManager *FileMgr, + FileManager *DriverFileMgr, std::shared_ptr PCHContainerOps, DiagnosticConsumer *DiagConsumer) override { // Make a deep copy of the original Clang invocation. @@ -342,12 +342,13 @@ public: ScanInstance.getHeaderSearchOpts().ModulesIncludeVFSUsage = any(OptimizeArgs & ScanningOptimizations::VFS); - ScanInstance.setFileManager(FileMgr); // Support for virtual file system overlays. - FileMgr->setVirtualFileSystem(createVFSFromCompilerInvocation( + auto FS = createVFSFromCompilerInvocation( ScanInstance.getInvocation(), ScanInstance.getDiagnostics(), - FileMgr->getVirtualFileSystemPtr())); + DriverFileMgr->getVirtualFileSystemPtr()); + // Create a new FileManager to match the invocation's FileSystemOptions. + auto *FileMgr = ScanInstance.createFileManager(FS); ScanInstance.createSourceManager(*FileMgr); // Store the list of prebuilt module files into header search options. This @@ -624,9 +625,8 @@ bool DependencyScanningWorker::computeDependencies( ModifiedCommandLine ? *ModifiedCommandLine : CommandLine; auto &FinalFS = ModifiedFS ? ModifiedFS : BaseFS; - FileSystemOptions FSOpts; - FSOpts.WorkingDir = WorkingDirectory.str(); - auto FileMgr = llvm::makeIntrusiveRefCnt(FSOpts, FinalFS); + auto FileMgr = + llvm::makeIntrusiveRefCnt(FileSystemOptions{}, FinalFS); std::vector FinalCCommandLine(FinalCommandLine.size(), nullptr); llvm::transform(FinalCommandLine, FinalCCommandLine.begin(), diff --git a/clang/test/ClangScanDeps/working-directory-option.c b/clang/test/ClangScanDeps/working-directory-option.c new file mode 100644 index 000000000000..d57497d405d3 --- /dev/null +++ b/clang/test/ClangScanDeps/working-directory-option.c @@ -0,0 +1,30 @@ +// Test that -working-directory works even when it differs from the working +// directory of the filesystem. + +// RUN: rm -rf %t +// RUN: mkdir -p %t/other +// RUN: split-file %s %t +// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json + +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full \ +// RUN: > %t/deps.json + +// RUN: cat %t/deps.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t + +// CHECK: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/cwd/t.c" +// CHECK-NEXT: "[[PREFIX]]/cwd/relative/h1.h" +// CHECK-NEXT: ] +// CHECK-NEXT: "input-file": "[[PREFIX]]/cwd/t.c" + +//--- cdb.json.template +[{ + "directory": "DIR/other", + "command": "clang -c t.c -I relative -working-directory DIR/cwd", + "file": "DIR/cwd/t.c" +}] + +//--- cwd/relative/h1.h + +//--- cwd/t.c +#include "h1.h" -- GitLab From 3238b92142c8fb70a1b2c72ee06bb47d57229dc9 Mon Sep 17 00:00:00 2001 From: Bjorn Pettersson Date: Tue, 12 Mar 2024 15:19:30 +0100 Subject: [PATCH 256/953] [LoopSimplifyCFG] Drop no longer needed DependenceAnalysis.h include --- llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp b/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp index 028a487ecdbc..ae9103d0608a 100644 --- a/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp +++ b/llvm/lib/Transforms/Scalar/LoopSimplifyCFG.cpp @@ -16,7 +16,6 @@ #include "llvm/Transforms/Scalar/LoopSimplifyCFG.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Analysis/DependenceAnalysis.h" #include "llvm/Analysis/DomTreeUpdater.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopIterator.h" -- GitLab From 4d0f79e346ceb0ddb25a94053c612a5b34a72100 Mon Sep 17 00:00:00 2001 From: Bjorn Pettersson Date: Tue, 12 Mar 2024 16:02:02 +0100 Subject: [PATCH 257/953] Pre commit test cases SRL/SRA support in canCreateUndefOrPoison. NFC Add test cases to show that we can't push freeze through SRA/SRL with 'exact' flag when there are multiple uses. --- llvm/test/CodeGen/X86/freeze-binary.ll | 48 ++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/llvm/test/CodeGen/X86/freeze-binary.ll b/llvm/test/CodeGen/X86/freeze-binary.ll index defd81e6ab77..b212e9438e1b 100644 --- a/llvm/test/CodeGen/X86/freeze-binary.ll +++ b/llvm/test/CodeGen/X86/freeze-binary.ll @@ -488,6 +488,30 @@ define i32 @freeze_ashr_exact(i32 %a0) nounwind { ret i32 %z } +define i32 @freeze_ashr_exact_extra_use(i32 %a0, ptr %escape) nounwind { +; X86-LABEL: freeze_ashr_exact_extra_use: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: sarl $3, %eax +; X86-NEXT: movl %eax, (%ecx) +; X86-NEXT: sarl $6, %eax +; X86-NEXT: retl +; +; X64-LABEL: freeze_ashr_exact_extra_use: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: sarl $3, %eax +; X64-NEXT: movl %eax, (%rsi) +; X64-NEXT: sarl $6, %eax +; X64-NEXT: retq + %x = ashr exact i32 %a0, 3 + %y = freeze i32 %x + %z = ashr i32 %y, 6 + store i32 %x, ptr %escape + ret i32 %z +} + define i32 @freeze_ashr_outofrange(i32 %a0) nounwind { ; X86-LABEL: freeze_ashr_outofrange: ; X86: # %bb.0: @@ -597,6 +621,30 @@ define i32 @freeze_lshr_exact(i32 %a0) nounwind { ret i32 %z } +define i32 @freeze_lshr_exact_extra_use(i32 %a0, ptr %escape) nounwind { +; X86-LABEL: freeze_lshr_exact_extra_use: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shrl $3, %eax +; X86-NEXT: movl %eax, (%ecx) +; X86-NEXT: shrl $5, %eax +; X86-NEXT: retl +; +; X64-LABEL: freeze_lshr_exact_extra_use: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: shrl $3, %eax +; X64-NEXT: movl %eax, (%rsi) +; X64-NEXT: shrl $5, %eax +; X64-NEXT: retq + %x = lshr exact i32 %a0, 3 + %y = freeze i32 %x + %z = lshr i32 %y, 5 + store i32 %x, ptr %escape + ret i32 %z +} + define i32 @freeze_lshr_outofrange(i32 %a0) nounwind { ; X86-LABEL: freeze_lshr_outofrange: ; X86: # %bb.0: -- GitLab From beba307c5bc206168bdea3b893e02ea31579fe62 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 12 Mar 2024 16:23:25 +0100 Subject: [PATCH 258/953] [LSR] Clear SCEVExpander before deleting phi nodes Fixes https://github.com/llvm/llvm-project/issues/84709. --- .../Transforms/Scalar/LoopStrengthReduce.cpp | 2 ++ .../Transforms/LoopStrengthReduce/pr84709.ll | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 llvm/test/Transforms/LoopStrengthReduce/pr84709.ll diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp index 8b078ddc4e74..c4e1a0db8b32 100644 --- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -6971,6 +6971,7 @@ static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE, Rewriter.setDebugType(DEBUG_TYPE); #endif unsigned numFolded = Rewriter.replaceCongruentIVs(L, &DT, DeadInsts, &TTI); + Rewriter.clear(); if (numFolded) { Changed = true; RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadInsts, &TLI, @@ -6989,6 +6990,7 @@ static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE, SCEVExpander Rewriter(SE, DL, "lsr", true); int Rewrites = rewriteLoopExitValues(L, &LI, &TLI, &SE, &TTI, Rewriter, &DT, UnusedIndVarInLoop, DeadInsts); + Rewriter.clear(); if (Rewrites) { Changed = true; RecursivelyDeleteTriviallyDeadInstructionsPermissive(DeadInsts, &TLI, diff --git a/llvm/test/Transforms/LoopStrengthReduce/pr84709.ll b/llvm/test/Transforms/LoopStrengthReduce/pr84709.ll new file mode 100644 index 000000000000..99794d01242c --- /dev/null +++ b/llvm/test/Transforms/LoopStrengthReduce/pr84709.ll @@ -0,0 +1,34 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -passes=loop-reduce < %s | FileCheck %s + +; Make sure it does not assert. +define i64 @test() { +; CHECK-LABEL: define i64 @test() { +; CHECK-NEXT: bb: +; CHECK-NEXT: br label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: br label [[BB2:%.*]] +; CHECK: bb2: +; CHECK-NEXT: br i1 true, label [[BB5:%.*]], label [[BB2]] +; CHECK: bb5: +; CHECK-NEXT: br label [[BB1]] +; +bb: + br label %bb1 + +bb1: + %phi = phi i8 [ %zext6, %bb5 ], [ 0, %bb ] + br label %bb2 + +bb2: + %phi3 = phi i8 [ %add, %bb2 ], [ %phi, %bb1 ] + %phi4 = phi i32 [ 0, %bb2 ], [ 1, %bb1 ] + %add = add i8 %phi3, 1 + br i1 true, label %bb5, label %bb2 + +bb5: + %zext = zext i8 %add to i32 + %icmp = icmp sge i32 %phi4, 0 + %zext6 = zext i1 %icmp to i8 + br label %bb1 +} -- GitLab From 08dd645c15a091a53313e278d8f3c090e7c385d1 Mon Sep 17 00:00:00 2001 From: Nemanja Ivanovic Date: Tue, 12 Mar 2024 16:26:49 +0100 Subject: [PATCH 259/953] [RISC-V] Bad immediate value for Zcmp instructions with E extension (#84925) When we are using the Zcmp extension together with the E extension in 32-bit mode and we need to spill both callee-saved registers as well as needing a couple of 32-bit stack slots, we emit a meaningless stack adjustment with cm.push/cm.popret. Furthermore this leads to the stack slot for the ra being clobbered so control returns to a random location. This is just a pre-commit test so that the PR for the fix shows the difference in code generation. --- .../CodeGen/RISCV/zcmp-additional-stack.ll | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll diff --git a/llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll b/llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll new file mode 100644 index 000000000000..e5c2e0180ee0 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll @@ -0,0 +1,49 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=riscv32 -mattr=+zcmp,+e -target-abi ilp32e -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV32 +define ptr @func(ptr %s, i32 %_c, ptr %incdec.ptr, i1 %0, i8 %conv14) #0 { +; RV32-LABEL: func: +; RV32: # %bb.0: # %entry +; RV32-NEXT: cm.push {ra, s0-s1}, -24 +; RV32-NEXT: .cfi_def_cfa_offset 24 +; RV32-NEXT: .cfi_offset ra, -12 +; RV32-NEXT: .cfi_offset s0, -8 +; RV32-NEXT: .cfi_offset s1, -4 +; RV32-NEXT: sw a4, 4(sp) # 4-byte Folded Spill +; RV32-NEXT: sw a2, 0(sp) # 4-byte Folded Spill +; RV32-NEXT: mv a2, a1 +; RV32-NEXT: mv s1, a0 +; RV32-NEXT: li a0, 1 +; RV32-NEXT: andi a3, a3, 1 +; RV32-NEXT: .LBB0_1: # %while.body +; RV32-NEXT: # =>This Inner Loop Header: Depth=1 +; RV32-NEXT: mv s0, a0 +; RV32-NEXT: li a0, 0 +; RV32-NEXT: bnez a3, .LBB0_1 +; RV32-NEXT: # %bb.2: # %while.end +; RV32-NEXT: lui a0, 4112 +; RV32-NEXT: addi a1, a0, 257 +; RV32-NEXT: mv a0, a2 +; RV32-NEXT: call __mulsi3 +; RV32-NEXT: sw a0, 0(zero) +; RV32-NEXT: andi s0, s0, 1 +; RV32-NEXT: lw a0, 0(sp) # 4-byte Folded Reload +; RV32-NEXT: add s0, s0, a0 +; RV32-NEXT: lw a0, 4(sp) # 4-byte Folded Reload +; RV32-NEXT: sb a0, 0(s0) +; RV32-NEXT: mv a0, s1 +; RV32-NEXT: cm.popret {ra, s0-s1}, 24 +entry: + br label %while.body + +while.body: ; preds = %while.body, %entry + %n.addr.042 = phi i32 [ 1, %entry ], [ 0, %while.body ] + br i1 %0, label %while.body, label %while.end + +while.end: ; preds = %while.body + %or5 = mul i32 %_c, 16843009 + store i32 %or5, ptr null, align 4 + %1 = and i32 %n.addr.042, 1 + %scevgep = getelementptr i8, ptr %incdec.ptr, i32 %1 + store i8 %conv14, ptr %scevgep, align 1 + ret ptr %s +} -- GitLab From bae47d48b632a4fa1dce5591bc0783360cf69e28 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Tue, 12 Mar 2024 08:38:34 -0700 Subject: [PATCH 260/953] [libc] fix another build failure from using limits.h (#84827) My GCC build is failing with issues similar why we added our own. Looks like we missed one spot. See also: commit 72ce62941579 ("[libc] Add C23 limits.h header. (#78887)") --- libc/test/src/__support/CMakeLists.txt | 1 + libc/test/src/__support/integer_to_string_test.cpp | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libc/test/src/__support/CMakeLists.txt b/libc/test/src/__support/CMakeLists.txt index 91dd0dc4decf..51b897f8b595 100644 --- a/libc/test/src/__support/CMakeLists.txt +++ b/libc/test/src/__support/CMakeLists.txt @@ -78,6 +78,7 @@ add_libc_test( SRCS integer_to_string_test.cpp DEPENDS + libc.src.__support.CPP.limits libc.src.__support.CPP.string_view libc.src.__support.integer_literals libc.src.__support.integer_to_string diff --git a/libc/test/src/__support/integer_to_string_test.cpp b/libc/test/src/__support/integer_to_string_test.cpp index a2a80c81b9f6..270fddd828b6 100644 --- a/libc/test/src/__support/integer_to_string_test.cpp +++ b/libc/test/src/__support/integer_to_string_test.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "src/__support/CPP/limits.h" #include "src/__support/CPP/span.h" #include "src/__support/CPP/string_view.h" #include "src/__support/UInt.h" @@ -15,8 +16,6 @@ #include "test/UnitTest/Test.h" -#include "limits.h" - using LIBC_NAMESPACE::IntegerToString; using LIBC_NAMESPACE::cpp::span; using LIBC_NAMESPACE::cpp::string_view; -- GitLab From f0c0ddae45ec929d023232d2ff0b75b7f09853c2 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Tue, 12 Mar 2024 08:39:17 -0700 Subject: [PATCH 261/953] [libc] implement the final macros for stdbit.h support (#84798) Relevant sections of n3096: - 7.18.1p1 - 7.18.2 --- libc/docs/c23.rst | 2 +- libc/docs/stdbit.rst | 8 ++++---- libc/include/llvm-libc-macros/stdbit-macros.h | 5 +++++ libc/spec/stdc.td | 4 ++++ libc/test/include/stdbit_test.cpp | 17 +++++++++++++++++ 5 files changed, 31 insertions(+), 5 deletions(-) diff --git a/libc/docs/c23.rst b/libc/docs/c23.rst index 24cef8539393..3f64722bc8e6 100644 --- a/libc/docs/c23.rst +++ b/libc/docs/c23.rst @@ -75,7 +75,7 @@ Additions: * dfmal * fsqrt* * dsqrtl -* stdbit.h (New header) +* stdbit.h (New header) |check| * stdckdint.h (New header) |check| * stddef.h diff --git a/libc/docs/stdbit.rst b/libc/docs/stdbit.rst index 9b4974cf1479..d42f79382462 100644 --- a/libc/docs/stdbit.rst +++ b/libc/docs/stdbit.rst @@ -110,10 +110,10 @@ Macros ========================= ========= Macro Name Available ========================= ========= -__STDC_VERSION_STDBIT_H__ -__STDC_ENDIAN_LITTLE__ -__STDC_ENDIAN_BIG__ -__STDC_ENDIAN_NATIVE__ +__STDC_VERSION_STDBIT_H__ |check| +__STDC_ENDIAN_LITTLE__ |check| +__STDC_ENDIAN_BIG__ |check| +__STDC_ENDIAN_NATIVE__ |check| stdc_leading_zeros |check| stdc_leading_ones |check| stdc_trailing_zeros |check| diff --git a/libc/include/llvm-libc-macros/stdbit-macros.h b/libc/include/llvm-libc-macros/stdbit-macros.h index 10c0fac3c8dd..c5b2f0977834 100644 --- a/libc/include/llvm-libc-macros/stdbit-macros.h +++ b/libc/include/llvm-libc-macros/stdbit-macros.h @@ -9,6 +9,11 @@ #ifndef __LLVM_LIBC_MACROS_STDBIT_MACROS_H #define __LLVM_LIBC_MACROS_STDBIT_MACROS_H +#define __STDC_VERSION_STDBIT_H__ 202311L +#define __STDC_ENDIAN_LITTLE__ __ORDER_LITTLE_ENDIAN__ +#define __STDC_ENDIAN_BIG__ __ORDER_BIG_ENDIAN__ +#define __STDC_ENDIAN_NATIVE__ __BYTE_ORDER__ + // TODO(https://github.com/llvm/llvm-project/issues/80509): support _BitInt(). #ifdef __cplusplus inline unsigned stdc_leading_zeros(unsigned char x) { diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index 1f14fe758130..1f9917b1f073 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -805,6 +805,10 @@ def StdC : StandardSpec<"stdc"> { HeaderSpec StdBit = HeaderSpec< "stdbit.h", [ + Macro<"__STDC_VERSION_STDBIT_H__">, + Macro<"__STDC_ENDIAN_LITTLE__">, + Macro<"__STDC_ENDIAN_BIG__">, + Macro<"__STDC_ENDIAN_NATIVE__">, Macro<"stdc_leading_zeros">, Macro<"stdc_leading_ones">, Macro<"stdc_trailing_zeros">, diff --git a/libc/test/include/stdbit_test.cpp b/libc/test/include/stdbit_test.cpp index f3227eb86959..bee1a19f9c03 100644 --- a/libc/test/include/stdbit_test.cpp +++ b/libc/test/include/stdbit_test.cpp @@ -141,3 +141,20 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroBitCeil) { EXPECT_EQ(stdc_bit_ceil(0UL), 0x6DUL); EXPECT_EQ(stdc_bit_ceil(0ULL), 0x6EULL); } + +TEST(LlvmLibcStdbitTest, VersionMacro) { + // 7.18.1p2 an integer constant expression with a value equivalent to 202311L. + EXPECT_EQ(__STDC_VERSION_STDBIT_H__, 202311L); +} + +TEST(LlvmLibcStdbitTest, EndianMacros) { + // 7.18.2p3 The values of the integer constant expressions for + // __STDC_ENDIAN_LITTLE__ and __STDC_ENDIAN_BIG__ are not equal. + EXPECT_NE(__STDC_ENDIAN_LITTLE__, __STDC_ENDIAN_BIG__); + // The standard does allow for __STDC_ENDIAN_NATIVE__ to be an integer + // constant expression with an implementation defined value for non-big or + // little endianness environments. I assert such machines are no longer + // relevant. + EXPECT_TRUE(__STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_LITTLE__ || + __STDC_ENDIAN_NATIVE__ == __STDC_ENDIAN_BIG__); +} -- GitLab From 9f69d3cf88905df5006f93dce536b7e73c0b1735 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Tue, 12 Mar 2024 10:39:40 -0500 Subject: [PATCH 262/953] [Libomptarget] Use NVPTX lane id intrinsic in DeviceRTL (#84928) Summary: We are currently taking the lower 5 bites of the thread ID as the warp ID. This doesn't work in non-1D grids and is also slower than just using the dedicated hardware register. --- openmp/libomptarget/DeviceRTL/src/Mapping.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openmp/libomptarget/DeviceRTL/src/Mapping.cpp b/openmp/libomptarget/DeviceRTL/src/Mapping.cpp index 31dd8054dec3..b2028a8fb4f5 100644 --- a/openmp/libomptarget/DeviceRTL/src/Mapping.cpp +++ b/openmp/libomptarget/DeviceRTL/src/Mapping.cpp @@ -172,10 +172,7 @@ uint32_t getThreadIdInBlock(int32_t Dim) { UNREACHABLE("Dim outside range!"); } -uint32_t getThreadIdInWarp() { - return impl::getThreadIdInBlock(mapping::DIM_X) & - (mapping::getWarpSize() - 1); -} +uint32_t getThreadIdInWarp() { return __nvvm_read_ptx_sreg_laneid(); } uint32_t getBlockIdInKernel(int32_t Dim) { switch (Dim) { -- GitLab From 392436383a52bc5e188bd28bec5bc71b3cb5384a Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Tue, 12 Mar 2024 08:39:50 -0700 Subject: [PATCH 263/953] [libc] fix typo in stdbit.h macro spec files (#84780) --- libc/spec/stdc.td | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index 1f9917b1f073..e012d0dee089 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -820,9 +820,9 @@ def StdC : StandardSpec<"stdc"> { Macro<"stdc_count_zeros">, Macro<"stdc_count_ones">, Macro<"stdc_has_single_bit">, - Macro<"std_bit_width">, - Macro<"std_bit_floor">, - Macro<"std_bit_ceil"> + Macro<"stdc_bit_width">, + Macro<"stdc_bit_floor">, + Macro<"stdc_bit_ceil"> ], // Macros [], // Types [], // Enumerations -- GitLab From c167a2588737613558bd7be4c9280603e89281ac Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Tue, 12 Mar 2024 10:40:35 -0500 Subject: [PATCH 264/953] [libc] Fix lane-id utility function not using built-in (#84902) Summary: Previously we got the lane-id from taking the global thread ID and taking off the bottom 5 bits. This works but is inefficient compared to the NVPTX intrinsic simply dedicated to get this value. --- libc/src/__support/GPU/nvptx/utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/src/__support/GPU/nvptx/utils.h b/libc/src/__support/GPU/nvptx/utils.h index a92c8847b6ec..fe9da4e8e6cb 100644 --- a/libc/src/__support/GPU/nvptx/utils.h +++ b/libc/src/__support/GPU/nvptx/utils.h @@ -97,7 +97,7 @@ LIBC_INLINE uint32_t get_lane_size() { return 32; } /// Returns the id of the thread inside of a CUDA warp executing together. [[clang::convergent]] LIBC_INLINE uint32_t get_lane_id() { - return get_thread_id() & (get_lane_size() - 1); + return __nvvm_read_ptx_sreg_laneid(); } /// Returns the bit-mask of active threads in the current warp. -- GitLab From 261e5648e70b363aecf86acfcd7fb416eb48fb7b Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Tue, 12 Mar 2024 10:40:49 -0500 Subject: [PATCH 265/953] [libc] Add utility functions for warp-level scan and reduction (#84866) Summary: The GPU uses a SIMT execution model. That means that each value actually belongs to a group of 32 or 64 other lanes executing next to it. These platforms offer some intrinsic fuctions to actually take elements from neighboring lanes. With these we can do parallel scans or reductions. These functions do not have an immediate user, but will be used in the allocator interface that is in-progress and are generally good to have. This patch is a precommit for these new utilitly functions. --- libc/src/__support/GPU/amdgpu/utils.h | 6 ++ libc/src/__support/GPU/generic/utils.h | 2 + libc/src/__support/GPU/nvptx/utils.h | 8 +++ libc/src/__support/GPU/utils.h | 19 ++++++ .../integration/src/__support/CMakeLists.txt | 3 + .../src/__support/GPU/CMakeLists.txt | 11 ++++ .../src/__support/GPU/scan_reduce.cpp | 62 +++++++++++++++++++ 7 files changed, 111 insertions(+) create mode 100644 libc/test/integration/src/__support/GPU/CMakeLists.txt create mode 100644 libc/test/integration/src/__support/GPU/scan_reduce.cpp diff --git a/libc/src/__support/GPU/amdgpu/utils.h b/libc/src/__support/GPU/amdgpu/utils.h index 75f0b5744ebd..9b520a6bcf38 100644 --- a/libc/src/__support/GPU/amdgpu/utils.h +++ b/libc/src/__support/GPU/amdgpu/utils.h @@ -145,6 +145,12 @@ LIBC_INLINE uint32_t get_lane_size() { __builtin_amdgcn_wave_barrier(); } +/// Shuffles the the lanes inside the wavefront according to the given index. +[[clang::convergent]] LIBC_INLINE uint32_t shuffle(uint64_t, uint32_t idx, + uint32_t x) { + return __builtin_amdgcn_ds_bpermute(idx << 2, x); +} + /// Returns the current value of the GPU's processor clock. /// NOTE: The RDNA3 and RDNA2 architectures use a 20-bit cycle counter. LIBC_INLINE uint64_t processor_clock() { return __builtin_readcyclecounter(); } diff --git a/libc/src/__support/GPU/generic/utils.h b/libc/src/__support/GPU/generic/utils.h index c6c3c01cf7d5..b6df59f7aa9e 100644 --- a/libc/src/__support/GPU/generic/utils.h +++ b/libc/src/__support/GPU/generic/utils.h @@ -67,6 +67,8 @@ LIBC_INLINE void sync_threads() {} LIBC_INLINE void sync_lane(uint64_t) {} +LIBC_INLINE uint32_t shuffle(uint64_t, uint32_t, uint32_t x) { return x; } + LIBC_INLINE uint64_t processor_clock() { return 0; } LIBC_INLINE uint64_t fixed_frequency_clock() { return 0; } diff --git a/libc/src/__support/GPU/nvptx/utils.h b/libc/src/__support/GPU/nvptx/utils.h index fe9da4e8e6cb..3f19afb83648 100644 --- a/libc/src/__support/GPU/nvptx/utils.h +++ b/libc/src/__support/GPU/nvptx/utils.h @@ -126,6 +126,14 @@ LIBC_INLINE uint32_t get_lane_size() { return 32; } __nvvm_bar_warp_sync(static_cast(mask)); } +/// Shuffles the the lanes inside the warp according to the given index. +[[clang::convergent]] LIBC_INLINE uint32_t shuffle(uint64_t lane_mask, + uint32_t idx, uint32_t x) { + uint32_t mask = static_cast(lane_mask); + uint32_t bitmask = (mask >> idx) & 1; + return -bitmask & __nvvm_shfl_sync_idx_i32(mask, x, idx, get_lane_size() - 1); +} + /// Returns the current value of the GPU's processor clock. LIBC_INLINE uint64_t processor_clock() { return __builtin_readcyclecounter(); } diff --git a/libc/src/__support/GPU/utils.h b/libc/src/__support/GPU/utils.h index 0f9167cdee06..93022e8de811 100644 --- a/libc/src/__support/GPU/utils.h +++ b/libc/src/__support/GPU/utils.h @@ -31,6 +31,25 @@ LIBC_INLINE bool is_first_lane(uint64_t lane_mask) { return gpu::get_lane_id() == get_first_lane_id(lane_mask); } +/// Gets the sum of all lanes inside the warp or wavefront. +LIBC_INLINE uint32_t reduce(uint64_t lane_mask, uint32_t x) { + for (uint32_t step = gpu::get_lane_size() / 2; step > 0; step /= 2) { + uint32_t index = step + gpu::get_lane_id(); + x += gpu::shuffle(lane_mask, index, x); + } + return gpu::broadcast_value(lane_mask, x); +} + +/// Gets the accumulator scan of the threads in the warp or wavefront. +LIBC_INLINE uint32_t scan(uint64_t lane_mask, uint32_t x) { + for (uint32_t step = 1; step < gpu::get_lane_size(); step *= 2) { + uint32_t index = gpu::get_lane_id() - step; + uint32_t bitmask = gpu::get_lane_id() >= step; + x += -bitmask & gpu::shuffle(lane_mask, index, x); + } + return x; +} + } // namespace gpu } // namespace LIBC_NAMESPACE diff --git a/libc/test/integration/src/__support/CMakeLists.txt b/libc/test/integration/src/__support/CMakeLists.txt index 7c853ff10259..b5b6557e8d68 100644 --- a/libc/test/integration/src/__support/CMakeLists.txt +++ b/libc/test/integration/src/__support/CMakeLists.txt @@ -1 +1,4 @@ add_subdirectory(threads) +if(LIBC_TARGET_OS_IS_GPU) + add_subdirectory(GPU) +endif() diff --git a/libc/test/integration/src/__support/GPU/CMakeLists.txt b/libc/test/integration/src/__support/GPU/CMakeLists.txt new file mode 100644 index 000000000000..7811e0da45dd --- /dev/null +++ b/libc/test/integration/src/__support/GPU/CMakeLists.txt @@ -0,0 +1,11 @@ +add_custom_target(libc-support-gpu-tests) +add_dependencies(libc-integration-tests libc-support-gpu-tests) + +add_integration_test( + scan_reduce_test + SUITE libc-support-gpu-tests + SRCS + scan_reduce.cpp + LOADER_ARGS + --threads 64 +) diff --git a/libc/test/integration/src/__support/GPU/scan_reduce.cpp b/libc/test/integration/src/__support/GPU/scan_reduce.cpp new file mode 100644 index 000000000000..bc621c3300cb --- /dev/null +++ b/libc/test/integration/src/__support/GPU/scan_reduce.cpp @@ -0,0 +1,62 @@ +//===-- Test for the parallel scan and reduction operations on the GPU ----===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/bit.h" +#include "src/__support/GPU/utils.h" +#include "test/IntegrationTest/test.h" + +using namespace LIBC_NAMESPACE; + +static uint32_t sum(uint32_t n) { return n * (n + 1) / 2; } + +// Tests a reduction within a convergant warp or wavefront using some known +// values. For example, if every element in the lane is one, then the sum should +// be the size of the warp or wavefront, i.e. 1 + 1 + 1 ... + 1. +static void test_reduce() { + uint64_t mask = gpu::get_lane_mask(); + uint32_t x = gpu::reduce(mask, 1); + EXPECT_EQ(x, gpu::get_lane_size()); + + uint32_t y = gpu::reduce(mask, gpu::get_lane_id()); + EXPECT_EQ(y, sum(gpu::get_lane_size() - 1)); + + uint32_t z = 0; + if (gpu::get_lane_id() % 2) + z = gpu::reduce(gpu::get_lane_mask(), 1); + gpu::sync_lane(mask); + + EXPECT_EQ(z, gpu::get_lane_id() % 2 ? gpu::get_lane_size() / 2 : 0); +} + +// Tests an accumulation scan within a convergent warp or wavefront using some +// known values. For example, if every element in the lane is one, then the scan +// should have each element be equivalent to its ID, i.e. 1, 1 + 1, ... +static void test_scan() { + uint64_t mask = gpu::get_lane_mask(); + + uint32_t x = gpu::scan(mask, 1); + EXPECT_EQ(x, gpu::get_lane_id() + 1); + + uint32_t y = gpu::scan(mask, gpu::get_lane_id()); + EXPECT_EQ(y, sum(gpu::get_lane_id())); + + uint32_t z = 0; + if (gpu::get_lane_id() % 2) + z = gpu::scan(gpu::get_lane_mask(), 1); + gpu::sync_lane(mask); + + EXPECT_EQ(z, gpu::get_lane_id() % 2 ? gpu::get_lane_id() / 2 + 1 : 0); +} + +TEST_MAIN(int argc, char **argv, char **envp) { + test_reduce(); + + test_scan(); + + return 0; +} -- GitLab From 0ebf511ad011a83022edb171e044c98d9d16b1fa Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Tue, 12 Mar 2024 08:44:06 -0700 Subject: [PATCH 266/953] [libc] move non functions to math_extras (#84818) As per TODOs added in https://github.com/llvm/llvm-project/pull/84035/commits/48b0bc837085a38ff1de33010d9222363f70238f. --- libc/src/__support/CMakeLists.txt | 1 + libc/src/__support/CPP/bit.h | 37 --------------- libc/src/__support/math_extras.h | 37 ++++++++++++++- libc/src/stdbit/CMakeLists.txt | 46 +++++++++++-------- libc/src/stdbit/stdc_count_zeros_uc.cpp | 4 +- libc/src/stdbit/stdc_count_zeros_ui.cpp | 4 +- libc/src/stdbit/stdc_count_zeros_ul.cpp | 4 +- libc/src/stdbit/stdc_count_zeros_ull.cpp | 4 +- libc/src/stdbit/stdc_count_zeros_us.cpp | 4 +- libc/src/stdbit/stdc_first_leading_one_uc.cpp | 4 +- libc/src/stdbit/stdc_first_leading_one_ui.cpp | 4 +- libc/src/stdbit/stdc_first_leading_one_ul.cpp | 4 +- .../src/stdbit/stdc_first_leading_one_ull.cpp | 4 +- libc/src/stdbit/stdc_first_leading_one_us.cpp | 4 +- .../src/stdbit/stdc_first_leading_zero_uc.cpp | 4 +- .../src/stdbit/stdc_first_leading_zero_ui.cpp | 4 +- .../src/stdbit/stdc_first_leading_zero_ul.cpp | 4 +- .../stdbit/stdc_first_leading_zero_ull.cpp | 4 +- .../src/stdbit/stdc_first_leading_zero_us.cpp | 4 +- .../src/stdbit/stdc_first_trailing_one_uc.cpp | 4 +- .../src/stdbit/stdc_first_trailing_one_ui.cpp | 4 +- .../src/stdbit/stdc_first_trailing_one_ul.cpp | 4 +- .../stdbit/stdc_first_trailing_one_ull.cpp | 4 +- .../src/stdbit/stdc_first_trailing_one_us.cpp | 4 +- .../stdbit/stdc_first_trailing_zero_uc.cpp | 4 +- .../stdbit/stdc_first_trailing_zero_ui.cpp | 4 +- .../stdbit/stdc_first_trailing_zero_ul.cpp | 4 +- .../stdbit/stdc_first_trailing_zero_ull.cpp | 4 +- .../stdbit/stdc_first_trailing_zero_us.cpp | 4 +- libc/test/src/__support/CPP/bit_test.cpp | 32 ------------- libc/test/src/__support/math_extras_test.cpp | 40 ++++++++++++++++ 31 files changed, 154 insertions(+), 139 deletions(-) diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt index 2e5a026bf423..4c1f271e1df4 100644 --- a/libc/src/__support/CMakeLists.txt +++ b/libc/src/__support/CMakeLists.txt @@ -34,6 +34,7 @@ add_header_library( HDRS math_extras.h DEPENDS + libc.src.__support.CPP.bit libc.src.__support.CPP.limits libc.src.__support.CPP.type_traits libc.src.__support.macros.attributes diff --git a/libc/src/__support/CPP/bit.h b/libc/src/__support/CPP/bit.h index 1a05728b8506..3f2fbec94405 100644 --- a/libc/src/__support/CPP/bit.h +++ b/libc/src/__support/CPP/bit.h @@ -239,36 +239,6 @@ LIBC_INLINE constexpr To bit_or_static_cast(const From &from) { } } -// TODO: remove from 'bit.h' as it is not a standard function. -template -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> -first_leading_zero(T value) { - return value == cpp::numeric_limits::max() ? 0 : countl_one(value) + 1; -} - -// TODO: remove from 'bit.h' as it is not a standard function. -template -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> -first_leading_one(T value) { - return first_leading_zero(static_cast(~value)); -} - -// TODO: remove from 'bit.h' as it is not a standard function. -template -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> -first_trailing_zero(T value) { - return value == cpp::numeric_limits::max() - ? 0 - : countr_zero(static_cast(~value)) + 1; -} - -// TODO: remove from 'bit.h' as it is not a standard function. -template -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> -first_trailing_one(T value) { - return value == cpp::numeric_limits::max() ? 0 : countr_zero(value) + 1; -} - /// Count number of 1's aka population count or Hamming weight. /// /// Only unsigned integral types are allowed. @@ -294,13 +264,6 @@ ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll) // TODO: 128b specializations? #undef ADD_SPECIALIZATION -// TODO: remove from 'bit.h' as it is not a standard function. -template -[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> -count_zeros(T value) { - return popcount(static_cast(~value)); -} - } // namespace LIBC_NAMESPACE::cpp #endif // LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H diff --git a/libc/src/__support/math_extras.h b/libc/src/__support/math_extras.h index c6b458ddecda..28ee1be8b999 100644 --- a/libc/src/__support/math_extras.h +++ b/libc/src/__support/math_extras.h @@ -10,7 +10,8 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H #define LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H -#include "src/__support/CPP/limits.h" // CHAR_BIT +#include "src/__support/CPP/bit.h" // countl_one, countr_zero +#include "src/__support/CPP/limits.h" // CHAR_BIT, numeric_limits #include "src/__support/CPP/type_traits.h" // is_unsigned_v #include "src/__support/macros/attributes.h" // LIBC_INLINE #include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN @@ -226,6 +227,40 @@ sub_with_borrow(unsigned long long a, unsigned long long b, #endif // LIBC_HAS_BUILTIN(__builtin_subc) +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +first_leading_zero(T value) { + return value == cpp::numeric_limits::max() ? 0 + : cpp::countl_one(value) + 1; +} + +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +first_leading_one(T value) { + return first_leading_zero(static_cast(~value)); +} + +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +first_trailing_zero(T value) { + return value == cpp::numeric_limits::max() + ? 0 + : cpp::countr_zero(static_cast(~value)) + 1; +} + +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +first_trailing_one(T value) { + return value == cpp::numeric_limits::max() ? 0 + : cpp::countr_zero(value) + 1; +} + +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +count_zeros(T value) { + return cpp::popcount(static_cast(~value)); +} + } // namespace LIBC_NAMESPACE #endif // LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H diff --git a/libc/src/stdbit/CMakeLists.txt b/libc/src/stdbit/CMakeLists.txt index 2aef2029f2df..0c22b1d2617a 100644 --- a/libc/src/stdbit/CMakeLists.txt +++ b/libc/src/stdbit/CMakeLists.txt @@ -1,30 +1,38 @@ +function(declare_dependencies prefixes dependencies) + set(suffixes c s i l ll) + foreach(prefix ${prefixes}) + foreach(suffix IN LISTS suffixes) + add_entrypoint_object( + stdc_${prefix}_u${suffix} + SRCS + stdc_${prefix}_u${suffix}.cpp + HDRS + stdc_${prefix}_u${suffix}.h + DEPENDS + ${dependencies} + ) + endforeach() + endforeach() +endfunction() + + set(prefixes leading_zeros leading_ones trailing_zeros trailing_ones - first_leading_zero - first_leading_one - first_trailing_zero - first_trailing_one - count_zeros count_ones has_single_bit bit_width bit_floor bit_ceil ) -set(suffixes c s i l ll) -foreach(prefix IN LISTS prefixes) - foreach(suffix IN LISTS suffixes) - add_entrypoint_object( - stdc_${prefix}_u${suffix} - SRCS - stdc_${prefix}_u${suffix}.cpp - HDRS - stdc_${prefix}_u${suffix}.h - DEPENDS - libc.src.__support.CPP.bit - ) - endforeach() -endforeach() +declare_dependencies("${prefixes}" libc.src.__support.CPP.bit) +set(prefixes + first_leading_zero + first_leading_one + first_trailing_zero + first_trailing_one + count_zeros +) +declare_dependencies("${prefixes}" libc.src.__support.math_extras) diff --git a/libc/src/stdbit/stdc_count_zeros_uc.cpp b/libc/src/stdbit/stdc_count_zeros_uc.cpp index 22c57bd60c38..309ebb55e0fa 100644 --- a/libc/src/stdbit/stdc_count_zeros_uc.cpp +++ b/libc/src/stdbit/stdc_count_zeros_uc.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_count_zeros_uc.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_zeros_uc, (unsigned char value)) { - return static_cast(cpp::count_zeros(value)); + return static_cast(count_zeros(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_count_zeros_ui.cpp b/libc/src/stdbit/stdc_count_zeros_ui.cpp index 6a1defd9d555..31ea907b24de 100644 --- a/libc/src/stdbit/stdc_count_zeros_ui.cpp +++ b/libc/src/stdbit/stdc_count_zeros_ui.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_count_zeros_ui.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_zeros_ui, (unsigned value)) { - return static_cast(cpp::count_zeros(value)); + return static_cast(count_zeros(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_count_zeros_ul.cpp b/libc/src/stdbit/stdc_count_zeros_ul.cpp index ceab32ef9ac3..f5df5c49f131 100644 --- a/libc/src/stdbit/stdc_count_zeros_ul.cpp +++ b/libc/src/stdbit/stdc_count_zeros_ul.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_count_zeros_ul.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_zeros_ul, (unsigned long value)) { - return static_cast(cpp::count_zeros(value)); + return static_cast(count_zeros(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_count_zeros_ull.cpp b/libc/src/stdbit/stdc_count_zeros_ull.cpp index 2f57f727a691..6a9c8f04a799 100644 --- a/libc/src/stdbit/stdc_count_zeros_ull.cpp +++ b/libc/src/stdbit/stdc_count_zeros_ull.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_count_zeros_ull.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_zeros_ull, (unsigned long long value)) { - return static_cast(cpp::count_zeros(value)); + return static_cast(count_zeros(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_count_zeros_us.cpp b/libc/src/stdbit/stdc_count_zeros_us.cpp index fc06836ee292..c08186ec6e87 100644 --- a/libc/src/stdbit/stdc_count_zeros_us.cpp +++ b/libc/src/stdbit/stdc_count_zeros_us.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_count_zeros_us.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_zeros_us, (unsigned short value)) { - return static_cast(cpp::count_zeros(value)); + return static_cast(count_zeros(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_one_uc.cpp b/libc/src/stdbit/stdc_first_leading_one_uc.cpp index 02871595fdb6..2e28ed3bb6f8 100644 --- a/libc/src/stdbit/stdc_first_leading_one_uc.cpp +++ b/libc/src/stdbit/stdc_first_leading_one_uc.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_first_leading_one_uc.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_one_uc, (unsigned char value)) { - return static_cast(cpp::first_leading_one(value)); + return static_cast(first_leading_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_one_ui.cpp b/libc/src/stdbit/stdc_first_leading_one_ui.cpp index a6c7ef5a8339..a07a39b09d9f 100644 --- a/libc/src/stdbit/stdc_first_leading_one_ui.cpp +++ b/libc/src/stdbit/stdc_first_leading_one_ui.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_first_leading_one_ui.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_one_ui, (unsigned value)) { - return static_cast(cpp::first_leading_one(value)); + return static_cast(first_leading_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_one_ul.cpp b/libc/src/stdbit/stdc_first_leading_one_ul.cpp index d1bcab5dda02..4350fb7826b4 100644 --- a/libc/src/stdbit/stdc_first_leading_one_ul.cpp +++ b/libc/src/stdbit/stdc_first_leading_one_ul.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_first_leading_one_ul.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_one_ul, (unsigned long value)) { - return static_cast(cpp::first_leading_one(value)); + return static_cast(first_leading_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_one_ull.cpp b/libc/src/stdbit/stdc_first_leading_one_ull.cpp index 7be8f1051ec2..57a5ae368e11 100644 --- a/libc/src/stdbit/stdc_first_leading_one_ull.cpp +++ b/libc/src/stdbit/stdc_first_leading_one_ull.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_leading_one_ull.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_one_ull, (unsigned long long value)) { - return static_cast(cpp::first_leading_one(value)); + return static_cast(first_leading_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_one_us.cpp b/libc/src/stdbit/stdc_first_leading_one_us.cpp index 7a4c7e673f36..f14433b13f35 100644 --- a/libc/src/stdbit/stdc_first_leading_one_us.cpp +++ b/libc/src/stdbit/stdc_first_leading_one_us.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_leading_one_us.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_one_us, (unsigned short value)) { - return static_cast(cpp::first_leading_one(value)); + return static_cast(first_leading_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_zero_uc.cpp b/libc/src/stdbit/stdc_first_leading_zero_uc.cpp index ffc1d9247406..6e2164256f17 100644 --- a/libc/src/stdbit/stdc_first_leading_zero_uc.cpp +++ b/libc/src/stdbit/stdc_first_leading_zero_uc.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_leading_zero_uc.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_zero_uc, (unsigned char value)) { - return static_cast(cpp::first_leading_zero(value)); + return static_cast(first_leading_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_zero_ui.cpp b/libc/src/stdbit/stdc_first_leading_zero_ui.cpp index 1eeab2963e6a..cb733a94c0d8 100644 --- a/libc/src/stdbit/stdc_first_leading_zero_ui.cpp +++ b/libc/src/stdbit/stdc_first_leading_zero_ui.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_first_leading_zero_ui.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_zero_ui, (unsigned value)) { - return static_cast(cpp::first_leading_zero(value)); + return static_cast(first_leading_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_zero_ul.cpp b/libc/src/stdbit/stdc_first_leading_zero_ul.cpp index 6743d3eda516..8a3930a271ed 100644 --- a/libc/src/stdbit/stdc_first_leading_zero_ul.cpp +++ b/libc/src/stdbit/stdc_first_leading_zero_ul.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_leading_zero_ul.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_zero_ul, (unsigned long value)) { - return static_cast(cpp::first_leading_zero(value)); + return static_cast(first_leading_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_zero_ull.cpp b/libc/src/stdbit/stdc_first_leading_zero_ull.cpp index 8128dd3d59a7..5a69197a8299 100644 --- a/libc/src/stdbit/stdc_first_leading_zero_ull.cpp +++ b/libc/src/stdbit/stdc_first_leading_zero_ull.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_leading_zero_ull.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_zero_ull, (unsigned long long value)) { - return static_cast(cpp::first_leading_zero(value)); + return static_cast(first_leading_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_leading_zero_us.cpp b/libc/src/stdbit/stdc_first_leading_zero_us.cpp index d931535e7690..6482c8654db3 100644 --- a/libc/src/stdbit/stdc_first_leading_zero_us.cpp +++ b/libc/src/stdbit/stdc_first_leading_zero_us.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_leading_zero_us.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_leading_zero_us, (unsigned short value)) { - return static_cast(cpp::first_leading_zero(value)); + return static_cast(first_leading_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_one_uc.cpp b/libc/src/stdbit/stdc_first_trailing_one_uc.cpp index 6ed35966be61..d3e8825eef00 100644 --- a/libc/src/stdbit/stdc_first_trailing_one_uc.cpp +++ b/libc/src/stdbit/stdc_first_trailing_one_uc.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_one_uc.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_one_uc, (unsigned char value)) { - return static_cast(cpp::first_trailing_one(value)); + return static_cast(first_trailing_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_one_ui.cpp b/libc/src/stdbit/stdc_first_trailing_one_ui.cpp index a89083bd4950..842bd6995050 100644 --- a/libc/src/stdbit/stdc_first_trailing_one_ui.cpp +++ b/libc/src/stdbit/stdc_first_trailing_one_ui.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_first_trailing_one_ui.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_one_ui, (unsigned value)) { - return static_cast(cpp::first_trailing_one(value)); + return static_cast(first_trailing_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_one_ul.cpp b/libc/src/stdbit/stdc_first_trailing_one_ul.cpp index f30078d0f5ff..0497d1d77811 100644 --- a/libc/src/stdbit/stdc_first_trailing_one_ul.cpp +++ b/libc/src/stdbit/stdc_first_trailing_one_ul.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_one_ul.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_one_ul, (unsigned long value)) { - return static_cast(cpp::first_trailing_one(value)); + return static_cast(first_trailing_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_one_ull.cpp b/libc/src/stdbit/stdc_first_trailing_one_ull.cpp index 2e526a890cda..6e062dd27cdd 100644 --- a/libc/src/stdbit/stdc_first_trailing_one_ull.cpp +++ b/libc/src/stdbit/stdc_first_trailing_one_ull.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_one_ull.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_one_ull, (unsigned long long value)) { - return static_cast(cpp::first_trailing_one(value)); + return static_cast(first_trailing_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_one_us.cpp b/libc/src/stdbit/stdc_first_trailing_one_us.cpp index e4c88e0d7906..e90158f10204 100644 --- a/libc/src/stdbit/stdc_first_trailing_one_us.cpp +++ b/libc/src/stdbit/stdc_first_trailing_one_us.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_one_us.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_one_us, (unsigned short value)) { - return static_cast(cpp::first_trailing_one(value)); + return static_cast(first_trailing_one(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_zero_uc.cpp b/libc/src/stdbit/stdc_first_trailing_zero_uc.cpp index 5825d5d441c5..a6939f6286b3 100644 --- a/libc/src/stdbit/stdc_first_trailing_zero_uc.cpp +++ b/libc/src/stdbit/stdc_first_trailing_zero_uc.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_zero_uc.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_zero_uc, (unsigned char value)) { - return static_cast(cpp::first_trailing_zero(value)); + return static_cast(first_trailing_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_zero_ui.cpp b/libc/src/stdbit/stdc_first_trailing_zero_ui.cpp index 3b51b5fa22c3..7a50b696afff 100644 --- a/libc/src/stdbit/stdc_first_trailing_zero_ui.cpp +++ b/libc/src/stdbit/stdc_first_trailing_zero_ui.cpp @@ -8,13 +8,13 @@ #include "src/stdbit/stdc_first_trailing_zero_ui.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_zero_ui, (unsigned value)) { - return static_cast(cpp::first_trailing_zero(value)); + return static_cast(first_trailing_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_zero_ul.cpp b/libc/src/stdbit/stdc_first_trailing_zero_ul.cpp index abf122944a76..88acbabdf2d9 100644 --- a/libc/src/stdbit/stdc_first_trailing_zero_ul.cpp +++ b/libc/src/stdbit/stdc_first_trailing_zero_ul.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_zero_ul.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_zero_ul, (unsigned long value)) { - return static_cast(cpp::first_trailing_zero(value)); + return static_cast(first_trailing_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_zero_ull.cpp b/libc/src/stdbit/stdc_first_trailing_zero_ull.cpp index 336e7d6e075f..92df8f284e8b 100644 --- a/libc/src/stdbit/stdc_first_trailing_zero_ull.cpp +++ b/libc/src/stdbit/stdc_first_trailing_zero_ull.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_zero_ull.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_zero_ull, (unsigned long long value)) { - return static_cast(cpp::first_trailing_zero(value)); + return static_cast(first_trailing_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_first_trailing_zero_us.cpp b/libc/src/stdbit/stdc_first_trailing_zero_us.cpp index b7d05047b272..86caa20dd3bd 100644 --- a/libc/src/stdbit/stdc_first_trailing_zero_us.cpp +++ b/libc/src/stdbit/stdc_first_trailing_zero_us.cpp @@ -8,14 +8,14 @@ #include "src/stdbit/stdc_first_trailing_zero_us.h" -#include "src/__support/CPP/bit.h" #include "src/__support/common.h" +#include "src/__support/math_extras.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_first_trailing_zero_us, (unsigned short value)) { - return static_cast(cpp::first_trailing_zero(value)); + return static_cast(first_trailing_zero(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/test/src/__support/CPP/bit_test.cpp b/libc/test/src/__support/CPP/bit_test.cpp index 3deb1f41dcf8..cee5b90c8f4b 100644 --- a/libc/test/src/__support/CPP/bit_test.cpp +++ b/libc/test/src/__support/CPP/bit_test.cpp @@ -228,38 +228,6 @@ TEST(LlvmLibcBitTest, Rotr) { rotr(0x12345678deadbeefULL, -19)); } -TYPED_TEST(LlvmLibcBitTest, FirstLeadingZero, UnsignedTypesNoBigInt) { - EXPECT_EQ(first_leading_zero(cpp::numeric_limits::max()), 0); - for (int i = 0U; i != cpp::numeric_limits::digits; ++i) - EXPECT_EQ(first_leading_zero(~(T(1) << i)), - cpp::numeric_limits::digits - i); -} - -TYPED_TEST(LlvmLibcBitTest, FirstLeadingOne, UnsignedTypesNoBigInt) { - EXPECT_EQ(first_leading_one(static_cast(0)), 0); - for (int i = 0U; i != cpp::numeric_limits::digits; ++i) - EXPECT_EQ(first_leading_one(T(1) << i), - cpp::numeric_limits::digits - i); -} - -TYPED_TEST(LlvmLibcBitTest, FirstTrailingZero, UnsignedTypesNoBigInt) { - EXPECT_EQ(first_trailing_zero(cpp::numeric_limits::max()), 0); - for (int i = 0U; i != cpp::numeric_limits::digits; ++i) - EXPECT_EQ(first_trailing_zero(~(T(1) << i)), i + 1); -} - -TYPED_TEST(LlvmLibcBitTest, FirstTrailingOne, UnsignedTypesNoBigInt) { - EXPECT_EQ(first_trailing_one(cpp::numeric_limits::max()), 0); - for (int i = 0U; i != cpp::numeric_limits::digits; ++i) - EXPECT_EQ(first_trailing_one(T(1) << i), i + 1); -} - -TYPED_TEST(LlvmLibcBitTest, CountZeros, UnsignedTypesNoBigInt) { - EXPECT_EQ(count_zeros(T(0)), cpp::numeric_limits::digits); - for (int i = 0; i != cpp::numeric_limits::digits; ++i) - EXPECT_EQ(count_zeros(cpp::numeric_limits::max() >> i), i); -} - TYPED_TEST(LlvmLibcBitTest, CountOnes, UnsignedTypesNoBigInt) { EXPECT_EQ(popcount(T(0)), 0); for (int i = 0; i != cpp::numeric_limits::digits; ++i) diff --git a/libc/test/src/__support/math_extras_test.cpp b/libc/test/src/__support/math_extras_test.cpp index ed064363d446..e642248881a4 100644 --- a/libc/test/src/__support/math_extras_test.cpp +++ b/libc/test/src/__support/math_extras_test.cpp @@ -13,6 +13,14 @@ namespace LIBC_NAMESPACE { +// TODO: add UInt<128> support. +using UnsignedTypesNoBigInt = testing::TypeList< +#if defined(LIBC_TYPES_HAS_INT128) + __uint128_t, +#endif // LIBC_TYPES_HAS_INT128 + unsigned char, unsigned short, unsigned int, unsigned long, + unsigned long long>; + TEST(LlvmLibcBlockMathExtrasTest, mask_trailing_ones) { EXPECT_EQ(0_u8, (mask_leading_ones())); EXPECT_EQ(0_u8, (mask_trailing_ones())); @@ -61,4 +69,36 @@ TEST(LlvmLibcBlockMathExtrasTest, mask_trailing_ones) { (mask_leading_ones())); } +TYPED_TEST(LlvmLibcBitTest, FirstLeadingZero, UnsignedTypesNoBigInt) { + EXPECT_EQ(first_leading_zero(cpp::numeric_limits::max()), 0); + for (int i = 0U; i != cpp::numeric_limits::digits; ++i) + EXPECT_EQ(first_leading_zero(~(T(1) << i)), + cpp::numeric_limits::digits - i); +} + +TYPED_TEST(LlvmLibcBitTest, FirstLeadingOne, UnsignedTypesNoBigInt) { + EXPECT_EQ(first_leading_one(static_cast(0)), 0); + for (int i = 0U; i != cpp::numeric_limits::digits; ++i) + EXPECT_EQ(first_leading_one(T(1) << i), + cpp::numeric_limits::digits - i); +} + +TYPED_TEST(LlvmLibcBitTest, FirstTrailingZero, UnsignedTypesNoBigInt) { + EXPECT_EQ(first_trailing_zero(cpp::numeric_limits::max()), 0); + for (int i = 0U; i != cpp::numeric_limits::digits; ++i) + EXPECT_EQ(first_trailing_zero(~(T(1) << i)), i + 1); +} + +TYPED_TEST(LlvmLibcBitTest, FirstTrailingOne, UnsignedTypesNoBigInt) { + EXPECT_EQ(first_trailing_one(cpp::numeric_limits::max()), 0); + for (int i = 0U; i != cpp::numeric_limits::digits; ++i) + EXPECT_EQ(first_trailing_one(T(1) << i), i + 1); +} + +TYPED_TEST(LlvmLibcBitTest, CountZeros, UnsignedTypesNoBigInt) { + EXPECT_EQ(count_zeros(T(0)), cpp::numeric_limits::digits); + for (int i = 0; i != cpp::numeric_limits::digits; ++i) + EXPECT_EQ(count_zeros(cpp::numeric_limits::max() >> i), i); +} + } // namespace LIBC_NAMESPACE -- GitLab From 87dc068280aaddc98acb7865ae3df1d248f4a170 Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Tue, 12 Mar 2024 09:03:28 -0700 Subject: [PATCH 267/953] [lldb] [debugserver] Handle interrupted reads correctly (#84872) The first half of this patch is a long-standing annoyance, if I attach to debugserver with lldb while it is waiting for an lldb connection, the syscall is interrupted and it doesn't retry, debugserver exits immediately. The second half is a request from another tool that is communicating with debugserver, that we retry reads on our sockets in the same way. I haven't dug in to the details of how they're communicating that this is necessary, but the best I've been able to find reading the POSIX API docs, this is fine. rdar://117113298 --- lldb/tools/debugserver/source/RNBSocket.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lldb/tools/debugserver/source/RNBSocket.cpp b/lldb/tools/debugserver/source/RNBSocket.cpp index 1282ea221625..fc55dbf2e1f1 100644 --- a/lldb/tools/debugserver/source/RNBSocket.cpp +++ b/lldb/tools/debugserver/source/RNBSocket.cpp @@ -120,8 +120,13 @@ rnb_err_t RNBSocket::Listen(const char *listen_host, uint16_t port, while (!accept_connection) { struct kevent event_list[4]; - int num_events = - kevent(queue_id, events.data(), events.size(), event_list, 4, NULL); + int num_events; + do { + errno = 0; + num_events = + kevent(queue_id, events.data(), events.size(), event_list, 4, NULL); + } while (num_events == -1 && + (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)); if (num_events < 0) { err.SetError(errno, DNBError::MachKernel); @@ -291,7 +296,12 @@ rnb_err_t RNBSocket::Read(std::string &p) { // DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s calling read()", // (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); DNBError err; - ssize_t bytesread = read(m_fd, buf, sizeof(buf)); + ssize_t bytesread; + do { + errno = 0; + bytesread = read(m_fd, buf, sizeof(buf)); + } while (bytesread == -1 && + (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)); if (bytesread <= 0) err.SetError(errno, DNBError::POSIX); else -- GitLab From fa1d13590cfd0be77c452cca929bc32efb456627 Mon Sep 17 00:00:00 2001 From: Jake Egan Date: Tue, 12 Mar 2024 12:03:42 -0400 Subject: [PATCH 268/953] [AIX][tests] Disable failing tests on AIX These new tests are failing on the AIX bot because the -I option isn't supported. Disable these tests for now until they can be fixed. --- llvm/test/CodeGen/AMDGPU/lds-run-twice-absolute-md.ll | 2 ++ llvm/test/CodeGen/AMDGPU/lds-run-twice.ll | 2 ++ 2 files changed, 4 insertions(+) diff --git a/llvm/test/CodeGen/AMDGPU/lds-run-twice-absolute-md.ll b/llvm/test/CodeGen/AMDGPU/lds-run-twice-absolute-md.ll index 52b44eea35c8..51e10d903797 100644 --- a/llvm/test/CodeGen/AMDGPU/lds-run-twice-absolute-md.ll +++ b/llvm/test/CodeGen/AMDGPU/lds-run-twice-absolute-md.ll @@ -1,3 +1,5 @@ +; XFAIL: target={{.*}}-aix{{.*}} + ; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds %s -o %t.ll ; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds %t.ll -o %t.second.ll ; RUN: diff -ub %t.ll %t.second.ll -I ".*ModuleID.*" diff --git a/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll b/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll index b830ccb944a2..e121f0da327d 100644 --- a/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll +++ b/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll @@ -1,3 +1,5 @@ +; XFAIL: target={{.*}}-aix{{.*}} + ; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds %s -o %t.ll ; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds %t.ll -o %t.second.ll ; RUN: diff -ub %t.ll %t.second.ll -I ".*ModuleID.*" -- GitLab From 65eea3e5dc907c3059c57ab4d16770522c5b9fb0 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Tue, 12 Mar 2024 17:26:39 +0100 Subject: [PATCH 269/953] [libc++][TZDB] Fixes parsing interleaved rules. (#84808) Typically the rules in the database are contiguous, but that is not a requirement. This fixes the case when they are not. --------- Co-authored-by: Louis Dionne --- libcxx/src/tzdb.cpp | 27 ++++++++++++++++--- .../time.zone/time.zone.db/rules.pass.cpp | 24 +++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/libcxx/src/tzdb.cpp b/libcxx/src/tzdb.cpp index 2bb801e48694..0307f754caab 100644 --- a/libcxx/src/tzdb.cpp +++ b/libcxx/src/tzdb.cpp @@ -511,14 +511,33 @@ static string __parse_version(istream& __input) { return chrono::__parse_string(__input); } +[[nodiscard]] +static __tz::__rule& __create_entry(__tz::__rules_storage_type& __rules, const string& __name) { + auto __result = [&]() -> __tz::__rule& { + auto& __rule = __rules.emplace_back(__name, vector<__tz::__rule>{}); + return __rule.second.emplace_back(); + }; + + if (__rules.empty()) + return __result(); + + // Typically rules are in contiguous order in the database. + // But there are exceptions, some rules are interleaved. + if (__rules.back().first == __name) + return __rules.back().second.emplace_back(); + + if (auto __it = ranges::find(__rules, __name, [](const auto& __r) { return __r.first; }); + __it != ranges::end(__rules)) + return __it->second.emplace_back(); + + return __result(); +} + static void __parse_rule(tzdb& __tzdb, __tz::__rules_storage_type& __rules, istream& __input) { chrono::__skip_mandatory_whitespace(__input); string __name = chrono::__parse_string(__input); - if (__rules.empty() || __rules.back().first != __name) - __rules.emplace_back(__name, vector<__tz::__rule>{}); - - __tz::__rule& __rule = __rules.back().second.emplace_back(); + __tz::__rule& __rule = __create_entry(__rules, __name); chrono::__skip_mandatory_whitespace(__input); __rule.__from = chrono::__parse_year(__input); diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp index 5ae2ed1e91eb..4814f4aad87f 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp @@ -550,6 +550,29 @@ R a 0 1 - Ja Su>=31 1w 2s abc assert(result.rules[0].second[2].__letters == "abc"); } +static void test_mixed_order() { + // This is a part of the real database. The interesting part is that the + // rules NZ and Chatham are interleaved. Make sure the parse algorithm + // handles this correctly. + parse_result result{ + R"( +# Since 1957 Chatham has been 45 minutes ahead of NZ, but until 2018a +# there was no documented single notation for the date and time of this +# transition. Duplicate the Rule lines for now, to give the 2018a change +# time to percolate out. +Rule NZ 1974 only - Nov Sun>=1 2:00s 1:00 D +Rule Chatham 1974 only - Nov Sun>=1 2:45s 1:00 - +Rule NZ 1975 only - Feb lastSun 2:00s 0 S +Rule Chatham 1975 only - Feb lastSun 2:45s 0 - +Rule NZ 1975 1988 - Oct lastSun 2:00s 1:00 D +Rule Chatham 1975 1988 - Oct lastSun 2:45s 1:00 - +)"}; + + assert(result.rules.size() == 2); + assert(result.rules[0].second.size() == 3); + assert(result.rules[1].second.size() == 3); +} + int main(int, const char**) { test_invalid(); test_name(); @@ -560,6 +583,7 @@ int main(int, const char**) { test_at(); test_save(); test_letter(); + test_mixed_order(); return 0; } -- GitLab From af21659c8c5c1d16b9bc5e745aaaf49b322f64d7 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Tue, 12 Mar 2024 17:28:15 +0100 Subject: [PATCH 270/953] [libc++][CI] Installs tzdata package in Docker. (#84643) This allows testing the time zone information in the CI. This is needed to let https://github.com/llvm/llvm-project/pull/82108 pass the CI. --- libcxx/utils/ci/Dockerfile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libcxx/utils/ci/Dockerfile b/libcxx/utils/ci/Dockerfile index 225de937cc86..178cba415933 100644 --- a/libcxx/utils/ci/Dockerfile +++ b/libcxx/utils/ci/Dockerfile @@ -65,6 +65,12 @@ RUN < Date: Tue, 12 Mar 2024 17:31:22 +0100 Subject: [PATCH 271/953] [clang][ASTMatchers] Fix forEachArgumentWithParam* for deducing "this" operator calls (#84887) This is a follow-up commit of #84446. In this patch, I demonstrate that `forEachArgumentWithParam` and `forEachArgumentWithParamType` did not correctly handle the presence of the explicit object parameter for operator calls. Prior to this patch, the matcher would skip the first (and only) argument of the operator call if the explicit object param was used. Note that I had to move the definition of `isExplicitObjectMemberFunction`, to be declared before the matcher I fix to be visible. I also had to do some gymnastics for passing the language standard version command-line flags to the invocation as `matchAndVerifyResultTrue` wasn't really considered for non-c++11 code. See the that it always prepends `-std=gnu++11` to the command-line arguments. I workarounded it by accepting extra args, which get appended, thus possibly overriding the hardcoded arguments. I'm not sure if this qualifies for backporting to clang-18 (probably not because its not a crash, but a semantic problem), but I figure it might be useful for some vendors (like us). But we are also happy to cherry-pick this fix to downstream. Let me know if you want this to be backported or not. CPP-5074 --- clang/docs/ReleaseNotes.rst | 2 + clang/include/clang/ASTMatchers/ASTMatchers.h | 59 ++++++++--------- clang/unittests/ASTMatchers/ASTMatchersTest.h | 36 +++++++---- .../ASTMatchers/ASTMatchersTraversalTest.cpp | 63 +++++++++++++++++++ 4 files changed, 119 insertions(+), 41 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 6c30af304d98..2842b63197ff 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -450,6 +450,8 @@ AST Matchers - ``isInStdNamespace`` now supports Decl declared with ``extern "C++"``. - Add ``isExplicitObjectMemberFunction``. +- Fixed ``forEachArgumentWithParam`` and ``forEachArgumentWithParamType`` to + not skip the explicit object parameter for operator calls. clang-format ------------ diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 96dbcdc344e1..2f71053d030f 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -5032,6 +5032,25 @@ AST_POLYMORPHIC_MATCHER_P2(hasParameter, && InnerMatcher.matches(*Node.parameters()[N], Finder, Builder)); } +/// Matches if the given method declaration declares a member function with an +/// explicit object parameter. +/// +/// Given +/// \code +/// struct A { +/// int operator-(this A, int); +/// void fun(this A &&self); +/// static int operator()(int); +/// int operator+(int); +/// }; +/// \endcode +/// +/// cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two +/// methods but not the last two. +AST_MATCHER(CXXMethodDecl, isExplicitObjectMemberFunction) { + return Node.isExplicitObjectMemberFunction(); +} + /// Matches all arguments and their respective ParmVarDecl. /// /// Given @@ -5060,10 +5079,12 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam, // argument of the method which should not be matched against a parameter, so // we skip over it here. BoundNodesTreeBuilder Matches; - unsigned ArgIndex = cxxOperatorCallExpr(callee(cxxMethodDecl())) - .matches(Node, Finder, &Matches) - ? 1 - : 0; + unsigned ArgIndex = + cxxOperatorCallExpr( + callee(cxxMethodDecl(unless(isExplicitObjectMemberFunction())))) + .matches(Node, Finder, &Matches) + ? 1 + : 0; int ParamIndex = 0; bool Matched = false; for (; ArgIndex < Node.getNumArgs(); ++ArgIndex) { @@ -5121,11 +5142,12 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParamType, // argument of the method which should not be matched against a parameter, so // we skip over it here. BoundNodesTreeBuilder Matches; - unsigned ArgIndex = cxxOperatorCallExpr(callee(cxxMethodDecl())) - .matches(Node, Finder, &Matches) - ? 1 - : 0; - + unsigned ArgIndex = + cxxOperatorCallExpr( + callee(cxxMethodDecl(unless(isExplicitObjectMemberFunction())))) + .matches(Node, Finder, &Matches) + ? 1 + : 0; const FunctionProtoType *FProto = nullptr; if (const auto *Call = dyn_cast(&Node)) { @@ -6366,25 +6388,6 @@ AST_MATCHER(CXXMethodDecl, isConst) { return Node.isConst(); } -/// Matches if the given method declaration declares a member function with an -/// explicit object parameter. -/// -/// Given -/// \code -/// struct A { -/// int operator-(this A, int); -/// void fun(this A &&self); -/// static int operator()(int); -/// int operator+(int); -/// }; -/// \endcode -/// -/// cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two -/// methods but not the last two. -AST_MATCHER(CXXMethodDecl, isExplicitObjectMemberFunction) { - return Node.isExplicitObjectMemberFunction(); -} - /// Matches if the given method declaration declares a copy assignment /// operator. /// diff --git a/clang/unittests/ASTMatchers/ASTMatchersTest.h b/clang/unittests/ASTMatchers/ASTMatchersTest.h index 1ed1b5958a8b..e98129953157 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTest.h +++ b/clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -293,7 +293,8 @@ testing::AssertionResult notMatchesWithOpenMP51(const Twine &Code, template testing::AssertionResult matchAndVerifyResultConditionally( const Twine &Code, const T &AMatcher, - std::unique_ptr FindResultVerifier, bool ExpectResult) { + std::unique_ptr FindResultVerifier, bool ExpectResult, + ArrayRef Args = {}, StringRef Filename = "input.cc") { bool VerifiedResult = false; MatchFinder Finder; VerifyMatch VerifyVerifiedResult(std::move(FindResultVerifier), @@ -304,9 +305,13 @@ testing::AssertionResult matchAndVerifyResultConditionally( // Some tests use typeof, which is a gnu extension. Using an explicit // unknown-unknown triple is good for a large speedup, because it lets us // avoid constructing a full system triple. - std::vector Args = {"-std=gnu++11", "-target", - "i386-unknown-unknown"}; - if (!runToolOnCodeWithArgs(Factory->create(), Code, Args)) { + std::vector CompileArgs = {"-std=gnu++11", "-target", + "i386-unknown-unknown"}; + // Append additional arguments at the end to allow overriding the default + // choices that we made above. + llvm::copy(Args, std::back_inserter(CompileArgs)); + + if (!runToolOnCodeWithArgs(Factory->create(), Code, CompileArgs, Filename)) { return testing::AssertionFailure() << "Parsing error in \"" << Code << "\""; } if (!VerifiedResult && ExpectResult) { @@ -319,8 +324,8 @@ testing::AssertionResult matchAndVerifyResultConditionally( VerifiedResult = false; SmallString<256> Buffer; - std::unique_ptr AST( - buildASTFromCodeWithArgs(Code.toStringRef(Buffer), Args)); + std::unique_ptr AST(buildASTFromCodeWithArgs( + Code.toStringRef(Buffer), CompileArgs, Filename)); if (!AST.get()) return testing::AssertionFailure() << "Parsing error in \"" << Code << "\" while building AST"; @@ -339,19 +344,24 @@ testing::AssertionResult matchAndVerifyResultConditionally( // FIXME: Find better names for these functions (or document what they // do more precisely). template -testing::AssertionResult matchAndVerifyResultTrue( - const Twine &Code, const T &AMatcher, - std::unique_ptr FindResultVerifier) { - return matchAndVerifyResultConditionally(Code, AMatcher, - std::move(FindResultVerifier), true); +testing::AssertionResult +matchAndVerifyResultTrue(const Twine &Code, const T &AMatcher, + std::unique_ptr FindResultVerifier, + ArrayRef Args = {}, + StringRef Filename = "input.cc") { + return matchAndVerifyResultConditionally( + Code, AMatcher, std::move(FindResultVerifier), + /*ExpectResult=*/true, Args, Filename); } template testing::AssertionResult matchAndVerifyResultFalse( const Twine &Code, const T &AMatcher, - std::unique_ptr FindResultVerifier) { + std::unique_ptr FindResultVerifier, + ArrayRef Args = {}, StringRef Filename = "input.cc") { return matchAndVerifyResultConditionally( - Code, AMatcher, std::move(FindResultVerifier), false); + Code, AMatcher, std::move(FindResultVerifier), + /*ExpectResult=*/false, Args, Filename); } // Implements a run method that returns whether BoundNodes contains a diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index 6911d7600a71..f198dc71eb83 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -985,6 +985,38 @@ TEST(ForEachArgumentWithParam, HandlesBoundNodesForNonMatches) { std::make_unique>("v", 4))); } +TEST_P(ASTMatchersTest, + ForEachArgumentWithParamMatchesExplicitObjectParamOnOperatorCalls) { + if (!GetParam().isCXX23OrLater()) { + return; + } + + auto DeclRef = declRefExpr(to(varDecl().bind("declOfArg"))).bind("arg"); + auto SelfParam = parmVarDecl().bind("param"); + StatementMatcher CallExpr = + callExpr(forEachArgumentWithParam(DeclRef, SelfParam)); + + StringRef S = R"cpp( + struct A { + int operator()(this const A &self); + }; + A obj; + int global = obj(); + )cpp"; + + auto Args = GetParam().getCommandLineArgs(); + auto Filename = getFilenameForTesting(GetParam().Language); + + EXPECT_TRUE(matchAndVerifyResultTrue( + S, CallExpr, + std::make_unique>("param", "self"), Args, + Filename)); + EXPECT_TRUE(matchAndVerifyResultTrue( + S, CallExpr, + std::make_unique>("declOfArg", "obj"), Args, + Filename)); +} + TEST(ForEachArgumentWithParamType, ReportsNoFalsePositives) { StatementMatcher ArgumentY = declRefExpr(to(varDecl(hasName("y")))).bind("arg"); @@ -1168,6 +1200,37 @@ TEST(ForEachArgumentWithParamType, MatchesVariadicFunctionPtrCalls) { S, CallExpr, std::make_unique>("arg"))); } +TEST_P(ASTMatchersTest, + ForEachArgumentWithParamTypeMatchesExplicitObjectParamOnOperatorCalls) { + if (!GetParam().isCXX23OrLater()) { + return; + } + + auto DeclRef = declRefExpr(to(varDecl().bind("declOfArg"))).bind("arg"); + auto SelfTy = qualType(asString("const A &")).bind("selfType"); + StatementMatcher CallExpr = + callExpr(forEachArgumentWithParamType(DeclRef, SelfTy)); + + StringRef S = R"cpp( + struct A { + int operator()(this const A &self); + }; + A obj; + int global = obj(); + )cpp"; + + auto Args = GetParam().getCommandLineArgs(); + auto Filename = getFilenameForTesting(GetParam().Language); + + EXPECT_TRUE(matchAndVerifyResultTrue( + S, CallExpr, std::make_unique>("selfType"), + Args, Filename)); + EXPECT_TRUE(matchAndVerifyResultTrue( + S, CallExpr, + std::make_unique>("declOfArg", "obj"), Args, + Filename)); +} + TEST(QualType, hasCanonicalType) { EXPECT_TRUE(notMatches("typedef int &int_ref;" "int a;" -- GitLab From c8cc7903b373589cc85271987980ae277145df7c Mon Sep 17 00:00:00 2001 From: XChy Date: Wed, 13 Mar 2024 00:33:50 +0800 Subject: [PATCH 272/953] [SelectionDAG] Replace some basic patterns in visitADDLike with SDPatternMatch (#84759) Resolves #84745. Based on SDPatternMatch introduced by #78654, this patch replaces some of basic patterns in `visitADDLike` with corresponding patterns in SDPatternMatch. This patch only replaces original folds, instead of introducing new ones. --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 55 +++++++++---------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 5476ef879714..735cec8ecc06 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -38,6 +38,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/SDPatternMatch.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGAddressAnalysis.h" #include "llvm/CodeGen/SelectionDAGNodes.h" @@ -79,6 +80,7 @@ #include "MatchContext.h" using namespace llvm; +using namespace llvm::SDPatternMatch; #define DEBUG_TYPE "dagcombine" @@ -2697,52 +2699,45 @@ SDValue DAGCombiner::visitADDLike(SDNode *N) { reassociateReduction(ISD::VECREDUCE_ADD, ISD::ADD, DL, VT, N0, N1)) return SD; } + + SDValue A, B, C; + // fold ((0-A) + B) -> B-A - if (N0.getOpcode() == ISD::SUB && isNullOrNullSplat(N0.getOperand(0))) - return DAG.getNode(ISD::SUB, DL, VT, N1, N0.getOperand(1)); + if (sd_match(N0, m_Sub(m_Zero(), m_Value(A)))) + return DAG.getNode(ISD::SUB, DL, VT, N1, A); // fold (A + (0-B)) -> A-B - if (N1.getOpcode() == ISD::SUB && isNullOrNullSplat(N1.getOperand(0))) - return DAG.getNode(ISD::SUB, DL, VT, N0, N1.getOperand(1)); + if (sd_match(N1, m_Sub(m_Zero(), m_Value(B)))) + return DAG.getNode(ISD::SUB, DL, VT, N0, B); // fold (A+(B-A)) -> B - if (N1.getOpcode() == ISD::SUB && N0 == N1.getOperand(1)) - return N1.getOperand(0); + if (sd_match(N1, m_Sub(m_Value(B), m_Specific(N0)))) + return B; // fold ((B-A)+A) -> B - if (N0.getOpcode() == ISD::SUB && N1 == N0.getOperand(1)) - return N0.getOperand(0); + if (sd_match(N0, m_Sub(m_Value(B), m_Specific(N1)))) + return B; // fold ((A-B)+(C-A)) -> (C-B) - if (N0.getOpcode() == ISD::SUB && N1.getOpcode() == ISD::SUB && - N0.getOperand(0) == N1.getOperand(1)) - return DAG.getNode(ISD::SUB, DL, VT, N1.getOperand(0), - N0.getOperand(1)); + if (sd_match(N0, m_Sub(m_Value(A), m_Value(B))) && + sd_match(N1, m_Sub(m_Value(C), m_Specific(A)))) + return DAG.getNode(ISD::SUB, DL, VT, C, B); // fold ((A-B)+(B-C)) -> (A-C) - if (N0.getOpcode() == ISD::SUB && N1.getOpcode() == ISD::SUB && - N0.getOperand(1) == N1.getOperand(0)) - return DAG.getNode(ISD::SUB, DL, VT, N0.getOperand(0), - N1.getOperand(1)); + if (sd_match(N0, m_Sub(m_Value(A), m_Value(B))) && + sd_match(N1, m_Sub(m_Specific(B), m_Value(C)))) + return DAG.getNode(ISD::SUB, DL, VT, A, C); // fold (A+(B-(A+C))) to (B-C) - if (N1.getOpcode() == ISD::SUB && N1.getOperand(1).getOpcode() == ISD::ADD && - N0 == N1.getOperand(1).getOperand(0)) - return DAG.getNode(ISD::SUB, DL, VT, N1.getOperand(0), - N1.getOperand(1).getOperand(1)); - // fold (A+(B-(C+A))) to (B-C) - if (N1.getOpcode() == ISD::SUB && N1.getOperand(1).getOpcode() == ISD::ADD && - N0 == N1.getOperand(1).getOperand(1)) - return DAG.getNode(ISD::SUB, DL, VT, N1.getOperand(0), - N1.getOperand(1).getOperand(0)); + if (sd_match(N1, m_Sub(m_Value(B), m_Add(m_Specific(N0), m_Value(C))))) + return DAG.getNode(ISD::SUB, DL, VT, B, C); // fold (A+((B-A)+or-C)) to (B+or-C) - if ((N1.getOpcode() == ISD::SUB || N1.getOpcode() == ISD::ADD) && - N1.getOperand(0).getOpcode() == ISD::SUB && - N0 == N1.getOperand(0).getOperand(1)) - return DAG.getNode(N1.getOpcode(), DL, VT, N1.getOperand(0).getOperand(0), - N1.getOperand(1)); + if (sd_match(N1, + m_AnyOf(m_Add(m_Sub(m_Value(B), m_Specific(N0)), m_Value(C)), + m_Sub(m_Sub(m_Value(B), m_Specific(N0)), m_Value(C))))) + return DAG.getNode(N1.getOpcode(), DL, VT, B, C); // fold (A-B)+(C-D) to (A+C)-(B+D) when A or C is constant if (N0.getOpcode() == ISD::SUB && N1.getOpcode() == ISD::SUB && -- GitLab From bd72ebd8d1ec3e97ca666623aa628d653a1d54a5 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Tue, 12 Mar 2024 22:05:47 +0530 Subject: [PATCH 273/953] AMDGPU: Add some more mfma hazard recognizer tests (#84727) --- .../CodeGen/AMDGPU/mai-hazards-gfx940.mir | 454 ++++++++++++++++++ 1 file changed, 454 insertions(+) diff --git a/llvm/test/CodeGen/AMDGPU/mai-hazards-gfx940.mir b/llvm/test/CodeGen/AMDGPU/mai-hazards-gfx940.mir index 4d307a444b19..a98b02d792d9 100644 --- a/llvm/test/CodeGen/AMDGPU/mai-hazards-gfx940.mir +++ b/llvm/test/CodeGen/AMDGPU/mai-hazards-gfx940.mir @@ -2028,3 +2028,457 @@ body: | $agpr0_agpr1 = V_MFMA_F64_4X4X4F64_e64 $agpr0_agpr1, $agpr0_agpr1, $agpr0_agpr1, 0, 0, 0, implicit $mode, implicit $exec BUFFER_STORE_DWORDX2_OFFEN_exact $vgpr2_vgpr3, $vgpr0, $sgpr0_sgpr1_sgpr2_sgpr3, 0, 0, 0, 0, implicit $exec ... + +... +# 2 pass source +# GCN-LABEL: name: xdl_mfma_2pass_write_vgpr_xdl_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_mfma_2pass_write_vgpr_xdl_mfma_read_overlap_srcc +body: | + bb.0: + + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr2_vgpr3_vgpr4_vgpr5, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 2 pass source +# GCN-LABEL: name: xdl_mfma_2pass_write_vgpr_xdl_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 4 +# GCN-NEXT: V_MFMA +name: xdl_mfma_2pass_write_vgpr_xdl_mfma_read_overlap_srca +body: | + bb.0: + + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr0_vgpr1, $vgpr6_vgpr7, $vgpr8_vgpr9_vgpr10_vgpr11, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 2 pass source +# GCN-LABEL: name: xdl_mfma_2pass_write_vgpr_xdl_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 4 +# GCN-NEXT: V_MFMA +name: xdl_mfma_2pass_write_vgpr_xdl_mfma_read_overlap_srcb +body: | + bb.0: + + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr6_vgpr7, $vgpr2_vgpr3, $vgpr8_vgpr9_vgpr10_vgpr11, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 4 pass source +# GCN-LABEL: name: xdl_mfma_4pass_write_vgpr_xdl_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 4 +# GCN-NEXT: V_MFMA +name: xdl_mfma_4pass_write_vgpr_xdl_mfma_read_overlap_srcc +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr8_vgpr9, $vgpr10_vgpr11, $vgpr2_vgpr3_vgpr4_vgpr5, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 4 pass source +# GCN-LABEL: name: xdl_mfma_4pass_write_vgpr_xdl_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 6 +# GCN-NEXT: V_MFMA +name: xdl_mfma_4pass_write_vgpr_xdl_mfma_read_overlap_srca +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr2_vgpr3, $vgpr10_vgpr11, $vgpr6_vgpr7_vgpr8_vgpr9, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 4 pass source +# GCN-LABEL: name: xdl_mfma_4pass_write_vgpr_xdl_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 6 +# GCN-NEXT: V_MFMA +name: xdl_mfma_4pass_write_vgpr_xdl_mfma_read_overlap_srcb +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr10_vgpr11, $vgpr2_vgpr3, $vgpr6_vgpr7_vgpr8_vgpr9, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 2 pass source +# GCN-LABEL: name: xdl_mfma_2pass_write_vgpr_sgemm_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_mfma_2pass_write_vgpr_sgemm_mfma_read_overlap_srcc +body: | + bb.0: + + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X1F32_vgprcd_e64 $vgpr6, $vgpr8, $vgpr2_vgpr3_vgpr4_vgpr5, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 2 pass source +# GCN-LABEL: name: xdl_mfma_2pass_write_vgpr_sgemm_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 4 +# GCN-NEXT: V_MFMA +name: xdl_mfma_2pass_write_vgpr_sgemm_mfma_read_overlap_srca +body: | + bb.0: + + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X1F32_vgprcd_e64 $vgpr1, $vgpr8, $vgpr6_vgpr7_vgpr8_vgpr9, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 2 pass source +# GCN-LABEL: name: xdl_mfma_2pass_write_vgpr_sgemm_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 4 +# GCN-NEXT: V_MFMA +name: xdl_mfma_2pass_write_vgpr_sgemm_mfma_read_overlap_srcb +body: | + bb.0: + + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X4F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X1F32_vgprcd_e64 $vgpr8, $vgpr1, $vgpr6_vgpr7_vgpr8_vgpr9, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 4 pass source +# GCN-LABEL: name: xdl_mfma_4pass_write_vgpr_sgemm_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 4 +# GCN-NEXT: V_MFMA +name: xdl_mfma_4pass_write_vgpr_sgemm_mfma_read_overlap_srcc +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X1F32_vgprcd_e64 $vgpr8, $vgpr9, $vgpr2_vgpr3_vgpr4_vgpr5, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 4 pass source +# GCN-LABEL: name: xdl_mfma_4pass_write_vgpr_sgemm_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 6 +# GCN-NEXT: V_MFMA +name: xdl_mfma_4pass_write_vgpr_sgemm_mfma_read_overlap_srca +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X1F32_vgprcd_e64 $vgpr1, $vgpr8, $vgpr6_vgpr7_vgpr8_vgpr9, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 4 pass source +# GCN-LABEL: name: xdl_mfma_4pass_write_vgpr_sgemm_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 6 +# GCN-NEXT: V_MFMA +name: xdl_mfma_4pass_write_vgpr_sgemm_mfma_read_overlap_srcb +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_16X16X16F16_vgprcd_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $vgpr0_vgpr1_vgpr2_vgpr3, 1, 2, 3, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3 = V_MFMA_F32_4X4X1F32_vgprcd_e64 $vgpr8, $vgpr1, $vgpr6_vgpr7_vgpr8_vgpr9, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 8 pass source +# GCN-LABEL: name: xdl_mfma_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 0 +# GCN-NEXT: V_MFMA +name: xdl_mfma_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcc +body: | + bb.0: + renamable $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr0_vgpr1, killed $vgpr2_vgpr3, 1065353216, 0, 0, 0, implicit $mode, implicit $exec + + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr18, $vgpr19, $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 8 pass source +# GCN-LABEL: name: xdl_mfma_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_mfma_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srca +body: | + bb.0: + renamable $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr0_vgpr1, killed $vgpr2_vgpr3, 1065353216, 0, 0, 0, implicit $mode, implicit $exec + + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr0, $vgpr33, $vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 8 pass source +# GCN-LABEL: name: xdl_mfma_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_mfma_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcb +body: | + bb.0: + renamable $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr0_vgpr1, killed $vgpr2_vgpr3, 1065353216, 0, 0, 0, implicit $mode, implicit $exec + + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr33, $vgpr1, $vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 16 pass source +# GCN-LABEL: name: xdl_16pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 0 +# GCN-NEXT: V_MFMA +name: xdl_16pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcc +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec + + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X2F32_vgprcd_e64 killed $vgpr32, killed $vgpr33, $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 16 pass source +# GCN-LABEL: name: xdl_16pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_16pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srca +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X2F32_vgprcd_e64 killed $vgpr0, killed $vgpr33, $vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37_vgpr38_vgpr39_vgpr40_vgpr41_vgpr42_vgpr43_vgpr44_vgpr45_vgpr46_vgpr47, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 16 pass source +# GCN-LABEL: name: xdl_16pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_16pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcb +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X2F32_vgprcd_e64 killed $vgpr33, killed $vgpr0, $vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37_vgpr38_vgpr39_vgpr40_vgpr41_vgpr42_vgpr43_vgpr44_vgpr45_vgpr46_vgpr47, 1, 2, 3, implicit $mode, implicit $exec + +... + +... +# 8 pass source +# GCN-LABEL: name: nonxdl_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: V_MFMA +name: nonxdl_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcc +body: | + bb.0: + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr18, $vgpr19, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, 0, 0, 0, implicit $mode, implicit $exec + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr18, $vgpr19, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 8 pass source +# GCN-LABEL: name: nonxdl_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 1 +# GCN-NEXT: V_MFMA +name: nonxdl_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srca +body: | + bb.0: + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr18, $vgpr19, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, 0, 0, 0, implicit $mode, implicit $exec + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr3, $vgpr19, $vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 8 pass source +# GCN-LABEL: name: nonxdl_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 1 +# GCN-NEXT: V_MFMA +name: nonxdl_8pass_write_vgpr_nonxdl_sgemm_mfma_read_overlap_srcb +body: | + bb.0: + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr18, $vgpr19, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15, 0, 0, 0, implicit $mode, implicit $exec + $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17 = V_MFMA_F32_16X16X1F32_vgprcd_e64 $vgpr19, $vgpr3, $vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33, 0, 0, 0, implicit $mode, implicit $exec +... +... +# 8 pass source +# GCN-LABEL: name: xdl_mfma_8pass_write_vgpr_xdl_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 0 +# GCN-NEXT: V_MFMA +name: xdl_mfma_8pass_write_vgpr_xdl_mfma_read_overlap_srcc +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr0_vgpr1, killed $vgpr2_vgpr3, 1065353216, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr18_vgpr19, killed $vgpr20_vgpr21, $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 8 pass source +# GCN-LABEL: name: xdl_mfma_8pass_write_vgpr_xdl_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_mfma_8pass_write_vgpr_xdl_mfma_read_overlap_srca +body: | + bb.0: + renamable $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr0_vgpr1, killed $vgpr2_vgpr3, 1065353216, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr2_vgpr3, killed $vgpr36_vgpr37, $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 8 pass source +# GCN-LABEL: name: xdl_mfma_8pass_write_vgpr_xdl_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_mfma_8pass_write_vgpr_xdl_mfma_read_overlap_srcb +body: | + bb.0: + renamable $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr0_vgpr1, killed $vgpr2_vgpr3, 1065353216, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15 = V_MFMA_F32_32X32X8F16_vgprcd_e64 killed $vgpr36_vgpr37, killed $vgpr2_vgpr3, $vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec +... + +... +# 16 pass source +# GCN-LABEL: name: xdl_16pass_write_vgpr_xdl_mfma_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 0 +# GCN-NEXT: V_MFMA +name: xdl_16pass_write_vgpr_xdl_mfma_read_overlap_srcc +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31_vgpr32_vgpr33, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 16 pass source +# GCN-LABEL: name: xdl_16pass_write_vgpr_xdl_mfma_read_overlap_srca +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_16pass_write_vgpr_xdl_mfma_read_overlap_srca +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr2_vgpr3, $vgpr128_vgpr129, $vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37_vgpr38_vgpr39_vgpr40_vgpr41_vgpr42_vgpr43_vgpr44_vgpr45_vgpr46_vgpr47_vgpr48_vgpr49_vgpr50_vgpr51_vgpr52_vgpr53_vgpr54_vgpr55_vgpr56_vgpr57_vgpr58_vgpr59_vgpr60_vgpr61_vgpr62_vgpr63, 0, 0, 0, implicit $mode, implicit $exec + + +... + +... +# 16 pass source +# GCN-LABEL: name: xdl_16pass_write_vgpr_xdl_mfma_read_overlap_srcb +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_MFMA +name: xdl_16pass_write_vgpr_xdl_mfma_read_overlap_srcb +body: | + bb.0: + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31, 0, 0, 0, implicit $mode, implicit $exec + $vgpr0_vgpr1_vgpr2_vgpr3_vgpr4_vgpr5_vgpr6_vgpr7_vgpr8_vgpr9_vgpr10_vgpr11_vgpr12_vgpr13_vgpr14_vgpr15_vgpr16_vgpr17_vgpr18_vgpr19_vgpr20_vgpr21_vgpr22_vgpr23_vgpr24_vgpr25_vgpr26_vgpr27_vgpr28_vgpr29_vgpr30_vgpr31 = V_MFMA_F32_32X32X4F16_vgprcd_e64 $vgpr128_vgpr129, $vgpr2_vgpr3, $vgpr32_vgpr33_vgpr34_vgpr35_vgpr36_vgpr37_vgpr38_vgpr39_vgpr40_vgpr41_vgpr42_vgpr43_vgpr44_vgpr45_vgpr46_vgpr47_vgpr48_vgpr49_vgpr50_vgpr51_vgpr52_vgpr53_vgpr54_vgpr55_vgpr56_vgpr57_vgpr58_vgpr59_vgpr60_vgpr61_vgpr62_vgpr63, 0, 0, 0, implicit $mode, implicit $exec + +... + +... +# 2 pass source +# GCN-LABEL: name: xdl_mfma_2pass_write_agpr_smfmac_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 2 +# GCN-NEXT: V_SMFMAC_ +name: xdl_mfma_2pass_write_agpr_smfmac_read_overlap_srcc +body: | + bb.0: + + $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X4F16_e64 $vgpr4_vgpr5, $vgpr6_vgpr7, $agpr0_agpr1_agpr2_agpr3, 1, 2, 3, implicit $mode, implicit $exec + $agpr2_agpr3_agpr4_agpr5 = V_SMFMAC_F32_16X16X32_F16_e64 $vgpr0_vgpr1, $vgpr2_vgpr3_vgpr4_vgpr5, $vgpr32, 0, 0, $agpr2_agpr3_agpr4_agpr5, implicit $mode, implicit $exec + +... + +... +# GCN-LABEL: name: xdl_4pass_mfma_write_agpr_smfmac_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 4 +# GCN-NEXT: V_SMFMAC_ +name: xdl_4pass_mfma_write_agpr_smfmac_read_overlap_srcc +body: | + bb.0: + $agpr0_agpr1_agpr2_agpr3 = V_MFMA_I32_16X16X32I8_e64 $vgpr0_vgpr1, $vgpr2_vgpr3, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + $agpr2_agpr3_agpr4_agpr5 = V_SMFMAC_F32_16X16X32_F16_e64 $vgpr0_vgpr1, $vgpr2_vgpr3_vgpr4_vgpr5, $vgpr32, 0, 0, $agpr2_agpr3_agpr4_agpr5, implicit $mode, implicit $exec + +... + +... +# GCN-LABEL: name: xdl_8pass_mfma_write_agpr_smfmac_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 0 +# GCN-NEXT: V_SMFMAC_ +name: xdl_8pass_mfma_write_agpr_smfmac_read_overlap_srcc +body: | + bb.0: + renamable $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X8F16_e64 killed $vgpr0_vgpr1, killed $vgpr2_vgpr3, 1065353216, 0, 0, 0, implicit $mode, implicit $exec + $agpr2_agpr3_agpr4_agpr5 = V_SMFMAC_F32_16X16X32_F16_e64 $vgpr0_vgpr1, $vgpr2_vgpr3_vgpr4_vgpr5, $vgpr32, 0, 0, $agpr2_agpr3_agpr4_agpr5, implicit $mode, implicit $exec +... + +... +# GCN-LABEL: name: xdl_16pass_mfma_write_agpr_smfmac_read_overlap_srcc +# GCN: V_MFMA +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 7 +# GCN-NEXT: S_NOP 0 +# GCN-NEXT: V_SMFMAC_ +name: xdl_16pass_mfma_write_agpr_smfmac_read_overlap_srcc +body: | + bb.0: + $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15_agpr16_agpr17_agpr18_agpr19_agpr20_agpr21_agpr22_agpr23_agpr24_agpr25_agpr26_agpr27_agpr28_agpr29_agpr30_agpr31 = V_MFMA_F32_32X32X4F16_e64 $vgpr126_vgpr127, $vgpr128_vgpr129, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15_agpr16_agpr17_agpr18_agpr19_agpr20_agpr21_agpr22_agpr23_agpr24_agpr25_agpr26_agpr27_agpr28_agpr29_agpr30_agpr31, 0, 0, 0, implicit $mode, implicit $exec + $agpr2_agpr3_agpr4_agpr5 = V_SMFMAC_F32_16X16X32_F16_e64 $vgpr0_vgpr1, $vgpr2_vgpr3_vgpr4_vgpr5, $vgpr32, 0, 0, $agpr2_agpr3_agpr4_agpr5, implicit $mode, implicit $exec +... -- GitLab From e09761944cea4aeafadd055b9510ef9f0e9a7338 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Tue, 12 Mar 2024 18:04:14 +0100 Subject: [PATCH 274/953] [libc++] Improves UB handling in ios_base destructor. (#76525) Destroying an ios_base object before it is properly initialized is undefined behavior. Unlike typical C++ classes the initialization is not done in the constructor, but in a dedicated init function. Due to virtual inheritance of the basic_ios object in ostream and friends this undefined behaviour can be triggered when inheriting from classes that can throw in their constructor and inheriting from ostream. Use the __loc_ member of ios_base as sentinel to detect whether the object has or has not been initialized. Addresses https://github.com/llvm/llvm-project/issues/57964 --- libcxx/include/ios | 12 ++- libcxx/src/ios.cpp | 4 + .../ios.base.cons/dtor.uninitialized.pass.cpp | 80 +++++++++++++++++++ 3 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 libcxx/test/libcxx/input.output/iostreams.base/ios.base/ios.base.cons/dtor.uninitialized.pass.cpp diff --git a/libcxx/include/ios b/libcxx/include/ios index 4b1306fc2ad8..00c1d5c2d4bc 100644 --- a/libcxx/include/ios +++ b/libcxx/include/ios @@ -359,7 +359,13 @@ public: } protected: - _LIBCPP_HIDE_FROM_ABI ios_base() { // purposefully does no initialization + _LIBCPP_HIDE_FROM_ABI ios_base() : __loc_(nullptr) { + // Purposefully does no initialization + // + // Except for the locale, this is a sentinel to avoid destroying + // an uninitialized object. See + // test/libcxx/input.output/iostreams.base/ios.base/ios.base.cons/dtor.uninitialized.pass.cpp + // for the details. } void init(void* __sb); @@ -571,7 +577,9 @@ public: _LIBCPP_HIDE_FROM_ABI char_type widen(char __c) const; protected: - _LIBCPP_HIDE_FROM_ABI basic_ios() { // purposefully does no initialization + _LIBCPP_HIDE_FROM_ABI basic_ios() { + // purposefully does no initialization + // since the destructor does nothing this does not have ios_base issues. } _LIBCPP_HIDE_FROM_ABI void init(basic_streambuf* __sb); diff --git a/libcxx/src/ios.cpp b/libcxx/src/ios.cpp index d58827fa1255..a727855c4655 100644 --- a/libcxx/src/ios.cpp +++ b/libcxx/src/ios.cpp @@ -195,6 +195,10 @@ void ios_base::register_callback(event_callback fn, int index) { } ios_base::~ios_base() { + // Avoid UB when not properly initialized. See ios_base::ios_base for + // more information. + if (!__loc_) + return; __call_callbacks(erase_event); locale& loc_storage = *reinterpret_cast(&__loc_); loc_storage.~locale(); diff --git a/libcxx/test/libcxx/input.output/iostreams.base/ios.base/ios.base.cons/dtor.uninitialized.pass.cpp b/libcxx/test/libcxx/input.output/iostreams.base/ios.base/ios.base.cons/dtor.uninitialized.pass.cpp new file mode 100644 index 000000000000..ea42203d0544 --- /dev/null +++ b/libcxx/test/libcxx/input.output/iostreams.base/ios.base/ios.base.cons/dtor.uninitialized.pass.cpp @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-exceptions + +// The fix for issue 57964 requires an updated dylib due to explicit +// instantiations. That means Apple backdeployment targets remain broken. +// UNSUPPORTED: using-built-library-before-llvm-19 + +// + +// class ios_base + +// ~ios_base() +// +// Destroying a constructed ios_base object that has not been +// initialized by basic_ios::init is undefined behaviour. This can +// happen in practice, make sure the undefined behaviour is handled +// gracefully. +// +// +// [ios.base.cons]/1 +// +// ios_base(); +// Effects: Each ios_base member has an indeterminate value after construction. +// The object's members shall be initialized by calling basic_ios::init before +// the object's first use or before it is destroyed, whichever comes first; +// otherwise the behavior is undefined. +// +// [basic.ios.cons]/2 +// +// basic_ios(); +// Effects: Leaves its member objects uninitialized. The object shall be +// initialized by calling basic_ios::init before its first use or before it is +// destroyed, whichever comes first; otherwise the behavior is undefined. +// +// ostream and friends have a basic_ios virtual base. +// [class.base.init]/13 +// In a non-delegating constructor, initialization proceeds in the +// following order: +// - First, and only for the constructor of the most derived class +// ([intro.object]), virtual base classes are initialized ... +// +// So in this example +// struct Foo : AlwaysThrows, std::ostream { +// Foo() : AlwaysThrows{}, std::ostream{nullptr} {} +// }; +// +// Here +// - the ios_base object is constructed +// - the AlwaysThrows object is constructed and throws an exception +// - the AlwaysThrows object is destrodyed +// - the ios_base object is destroyed +// +// The ios_base object is destroyed before it has been initialized and runs +// into undefined behavior. By using __loc_ as a sentinel we can avoid +// accessing uninitialized memory in the destructor. + +#include + +struct AlwaysThrows { + AlwaysThrows() { throw 1; } +}; + +struct Foo : AlwaysThrows, std::ostream { + Foo() : AlwaysThrows(), std::ostream(nullptr) {} +}; + +int main(int, char**) { + try { + Foo foo; + } catch (...) { + }; + return 0; +} -- GitLab From 683a9ac803a56f6dda9b783a6e2d6d92a5d0626c Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Tue, 12 Mar 2024 17:10:16 +0000 Subject: [PATCH 275/953] [X86] combineVectorPack - use APInt::truncSSat for PACKSS constant folding. NFC. Unfortunately PACKUS can't use APInt::truncUSat --- llvm/lib/Target/X86/X86ISelLowering.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index b4d0421c14c0..72b45d462dfe 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -47630,16 +47630,12 @@ static SDValue combineVectorPack(SDNode *N, SelectionDAG &DAG, // PACKSS: Truncate signed value with signed saturation. // Source values less than dst minint are saturated to minint. // Source values greater than dst maxint are saturated to maxint. - if (Val.isSignedIntN(DstBitsPerElt)) - Val = Val.trunc(DstBitsPerElt); - else if (Val.isNegative()) - Val = APInt::getSignedMinValue(DstBitsPerElt); - else - Val = APInt::getSignedMaxValue(DstBitsPerElt); + Val = Val.truncSSat(DstBitsPerElt); } else { // PACKUS: Truncate signed value with unsigned saturation. // Source values less than zero are saturated to zero. // Source values greater than dst maxuint are saturated to maxuint. + // NOTE: This is different from APInt::truncUSat. if (Val.isIntN(DstBitsPerElt)) Val = Val.trunc(DstBitsPerElt); else if (Val.isNegative()) -- GitLab From 7bee91fadf8db90f71b458aaff4de0efa7dc23a0 Mon Sep 17 00:00:00 2001 From: "Diego A. Estrada Rivera" Date: Tue, 12 Mar 2024 13:21:31 -0400 Subject: [PATCH 276/953] [analyzer][NFC] Turn NodeBuilderContext into a class (#84638) From issue #73088. I changed `NodeBuilderContext` into a class. Additionally, there were some other mentions of the former being a struct which I also changed into a class. This is my first time working with an issue so I will be open to hearing any advice or changes that need to be done. --- .../clang/StaticAnalyzer/Core/CheckerManager.h | 2 +- .../StaticAnalyzer/Core/PathSensitive/CoreEngine.h | 12 +++++++++--- .../StaticAnalyzer/Core/PathSensitive/ExprEngine.h | 2 +- clang/lib/StaticAnalyzer/Core/CoreEngine.cpp | 6 +++--- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h index a45ba1bc573e..ad25d18f2807 100644 --- a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -49,7 +49,7 @@ class ExplodedNodeSet; class ExprEngine; struct EvalCallOptions; class MemRegion; -struct NodeBuilderContext; +class NodeBuilderContext; class ObjCMethodCall; class RegionAndSymbolInvalidationTraits; class SVal; diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 8e392421fef9..0ef353bf9731 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -59,7 +59,7 @@ class CoreEngine { friend class ExprEngine; friend class IndirectGotoNodeBuilder; friend class NodeBuilder; - friend struct NodeBuilderContext; + friend class NodeBuilderContext; friend class SwitchNodeBuilder; public: @@ -193,12 +193,12 @@ public: DataTag::Factory &getDataTags() { return DataTags; } }; -// TODO: Turn into a class. -struct NodeBuilderContext { +class NodeBuilderContext { const CoreEngine &Eng; const CFGBlock *Block; const LocationContext *LC; +public: NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, const LocationContext *L) : Eng(E), Block(B), LC(L) { @@ -208,9 +208,15 @@ struct NodeBuilderContext { NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N) : NodeBuilderContext(E, B, N->getLocationContext()) {} + /// Return the CoreEngine associated with this builder. + const CoreEngine &getEngine() const { return Eng; } + /// Return the CFGBlock associated with this builder. const CFGBlock *getBlock() const { return Block; } + /// Return the location context associated with this builder. + const LocationContext *getLocationContext() const { return LC; } + /// Returns the number of times the current basic block has been /// visited on the exploded graph path. unsigned blockCount() const { diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index f7894fb83ce6..859c1497d7e6 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -85,7 +85,7 @@ class ExplodedNodeSet; class ExplodedNode; class IndirectGotoNodeBuilder; class MemRegion; -struct NodeBuilderContext; +class NodeBuilderContext; class NodeBuilderWithSinks; class ProgramState; class ProgramStateManager; diff --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp index 141d0cb320bf..8605fa149e4f 100644 --- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -625,8 +625,8 @@ ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc, bool MarkAsSink) { HasGeneratedNodes = true; bool IsNew; - ExplodedNode *N = C.Eng.G.getNode(Loc, State, MarkAsSink, &IsNew); - N->addPredecessor(FromN, C.Eng.G); + ExplodedNode *N = C.getEngine().G.getNode(Loc, State, MarkAsSink, &IsNew); + N->addPredecessor(FromN, C.getEngine().G); Frontier.erase(FromN); if (!IsNew) @@ -655,7 +655,7 @@ ExplodedNode *BranchNodeBuilder::generateNode(ProgramStateRef State, if (!isFeasible(branch)) return nullptr; - ProgramPoint Loc = BlockEdge(C.Block, branch ? DstT:DstF, + ProgramPoint Loc = BlockEdge(C.getBlock(), branch ? DstT : DstF, NodePred->getLocationContext()); ExplodedNode *Succ = generateNodeImpl(Loc, State, NodePred); return Succ; -- GitLab From 93503aafcdc66837ecf220243aaa530c05c35895 Mon Sep 17 00:00:00 2001 From: Hiroshi Yamauchi <56735936+hjyamauchi@users.noreply.github.com> Date: Tue, 12 Mar 2024 10:26:44 -0700 Subject: [PATCH 277/953] Fix MSVC build issues (#84362) MSVC fails when there is ambiguity (multiple options) around implicit type conversion operators. Make ConstString's conversion operator to string_view explicit to avoid ambiguity with one to StringRef and remove an unused local variable that MSVC also fails on. --- lldb/include/lldb/Utility/ConstString.h | 4 ++-- lldb/source/Core/Mangled.cpp | 12 +++++++----- lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp | 1 - 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/lldb/include/lldb/Utility/ConstString.h b/lldb/include/lldb/Utility/ConstString.h index 470a554ca048..f7f7ec7605eb 100644 --- a/lldb/include/lldb/Utility/ConstString.h +++ b/lldb/include/lldb/Utility/ConstString.h @@ -168,8 +168,8 @@ public: // Implicitly convert \class ConstString instances to \class StringRef. operator llvm::StringRef() const { return GetStringRef(); } - // Implicitly convert \class ConstString instances to \class std::string_view. - operator std::string_view() const { + // Explicitly convert \class ConstString instances to \class std::string_view. + explicit operator std::string_view() const { return std::string_view(m_string, GetLength()); } diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp index 23ae3913093f..b167c51fdce2 100644 --- a/lldb/source/Core/Mangled.cpp +++ b/lldb/source/Core/Mangled.cpp @@ -125,7 +125,7 @@ void Mangled::SetValue(ConstString name) { } // Local helpers for different demangling implementations. -static char *GetMSVCDemangledStr(std::string_view M) { +static char *GetMSVCDemangledStr(llvm::StringRef M) { char *demangled_cstr = llvm::microsoftDemangle( M, nullptr, nullptr, llvm::MSDemangleFlags( @@ -169,27 +169,29 @@ static char *GetItaniumDemangledStr(const char *M) { return demangled_cstr; } -static char *GetRustV0DemangledStr(std::string_view M) { +static char *GetRustV0DemangledStr(llvm::StringRef M) { char *demangled_cstr = llvm::rustDemangle(M); if (Log *log = GetLog(LLDBLog::Demangle)) { if (demangled_cstr && demangled_cstr[0]) LLDB_LOG(log, "demangled rustv0: {0} -> \"{1}\"", M, demangled_cstr); else - LLDB_LOG(log, "demangled rustv0: {0} -> error: failed to demangle", M); + LLDB_LOG(log, "demangled rustv0: {0} -> error: failed to demangle", + static_cast(M)); } return demangled_cstr; } -static char *GetDLangDemangledStr(std::string_view M) { +static char *GetDLangDemangledStr(llvm::StringRef M) { char *demangled_cstr = llvm::dlangDemangle(M); if (Log *log = GetLog(LLDBLog::Demangle)) { if (demangled_cstr && demangled_cstr[0]) LLDB_LOG(log, "demangled dlang: {0} -> \"{1}\"", M, demangled_cstr); else - LLDB_LOG(log, "demangled dlang: {0} -> error: failed to demangle", M); + LLDB_LOG(log, "demangled dlang: {0} -> error: failed to demangle", + static_cast(M)); } return demangled_cstr; diff --git a/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp b/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp index 6a2ea8c4a41b..f237dd63ab1c 100644 --- a/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp +++ b/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp @@ -527,7 +527,6 @@ TEST_F(SymbolFilePDBTests, TestTypedefs) { SymbolFilePDB *symfile = static_cast(module->GetSymbolFile()); llvm::pdb::IPDBSession &session = symfile->GetPDBSession(); - TypeMap results; const char *TypedefsToCheck[] = {"ClassTypedef", "NSClassTypedef", "FuncPointerTypedef", -- GitLab From c4e517f59c086eafe2eb61d23197820f05be799c Mon Sep 17 00:00:00 2001 From: Jun Wang Date: Tue, 12 Mar 2024 10:30:39 -0700 Subject: [PATCH 278/953] [AMDGPU] Adding the amdgpu_num_work_groups function attribute (#79035) A new function attribute named amdgpu_num_work_groups is added. This attribute, which consists of three integers, allows programmers to let the compiler know the number of workgroups to be launched in each of the three dimensions and do optimizations based on that information. --------- Co-authored-by: Jun Wang --- clang/docs/ReleaseNotes.rst | 6 + clang/include/clang/Basic/Attr.td | 7 + clang/include/clang/Basic/AttrDocs.td | 27 ++++ clang/include/clang/Sema/Sema.h | 10 ++ clang/lib/CodeGen/Targets/AMDGPU.cpp | 23 +++ clang/lib/Sema/SemaDeclAttr.cpp | 62 ++++++++ .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 29 ++++ clang/test/CodeGenCUDA/amdgpu-kernel-attrs.cu | 35 +++++ clang/test/CodeGenOpenCL/amdgpu-attrs.cl | 47 +++++++ ...a-attribute-supported-attributes-list.test | 1 + clang/test/SemaCUDA/amdgpu-attrs.cu | 132 ++++++++++++++++++ llvm/docs/AMDGPUUsage.rst | 10 ++ .../AMDGPU/AMDGPUHSAMetadataStreamer.cpp | 8 ++ llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp | 7 +- llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h | 3 + .../Target/AMDGPU/SIMachineFunctionInfo.cpp | 2 + .../lib/Target/AMDGPU/SIMachineFunctionInfo.h | 10 ++ .../Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp | 37 +++++ llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h | 18 +++ .../AMDGPU/attr-amdgpu-num-workgroups.ll | 84 +++++++++++ .../attr-amdgpu-num-workgroups_error_check.ll | 71 ++++++++++ 21 files changed, 628 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/AMDGPU/attr-amdgpu-num-workgroups.ll create mode 100644 llvm/test/CodeGen/AMDGPU/attr-amdgpu-num-workgroups_error_check.ll diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2842b63197ff..e14c92eae0af 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -194,6 +194,12 @@ Removed Compiler Flags Attribute Changes in Clang -------------------------- +- Introduced a new function attribute ``__attribute__((amdgpu_max_num_work_groups(x, y, z)))`` or + ``[[clang::amdgpu_max_num_work_groups(x, y, z)]]`` for the AMDGPU target. This attribute can be + attached to HIP or OpenCL kernel function definitions to provide an optimization hint. The parameters + ``x``, ``y``, and ``z`` specify the maximum number of workgroups for the respective dimensions, + and each must be a positive integer when provided. The parameter ``x`` is required, while ``y`` and + ``z`` are optional with default value of 1. Improvements to Clang's diagnostics ----------------------------------- diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 080340669b60..63efd85dcd4e 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2054,6 +2054,13 @@ def AMDGPUNumVGPR : InheritableAttr { let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; } +def AMDGPUMaxNumWorkGroups : InheritableAttr { + let Spellings = [Clang<"amdgpu_max_num_work_groups", 0>]; + let Args = [ExprArgument<"MaxNumWorkGroupsX">, ExprArgument<"MaxNumWorkGroupsY", 1>, ExprArgument<"MaxNumWorkGroupsZ", 1>]; + let Documentation = [AMDGPUMaxNumWorkGroupsDocs]; + let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; +} + def AMDGPUKernelCall : DeclOrTypeAttr { let Spellings = [Clang<"amdgpu_kernel">]; let Documentation = [Undocumented]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 2c07cd09b0d5..d61f96ade557 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2741,6 +2741,33 @@ An error will be given if: }]; } +def AMDGPUMaxNumWorkGroupsDocs : Documentation { + let Category = DocCatAMDGPUAttributes; + let Content = [{ +This attribute specifies the max number of work groups when the kernel +is dispatched. + +Clang supports the +``__attribute__((amdgpu_max_num_work_groups(, , )))`` or +``[[clang::amdgpu_max_num_work_groups(, , )]]`` attribute for the +AMDGPU target. This attribute may be attached to HIP or OpenCL kernel function +definitions and is an optimization hint. + +The ```` parameter specifies the maximum number of work groups in the x dimension. +Similarly ```` and ```` are for the y and z dimensions respectively. +Each of the three values must be greater than 0 when provided. The ```` parameter +is required, while ```` and ```` are optional with default value of 1. + +If specified, the AMDGPU target backend might be able to produce better machine +code. + +An error will be given if: + - Specified values violate subtarget specifications; + - Specified values are not compatible with values provided through other + attributes. + }]; +} + def DocCatCallingConvs : DocumentationCategory<"Calling Conventions"> { let Content = [{ Clang supports several different calling conventions, depending on the target diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 267c79cc057c..b226851f0303 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3911,6 +3911,16 @@ public: void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI, Expr *Min, Expr *Max); + /// Create an AMDGPUMaxNumWorkGroupsAttr attribute. + AMDGPUMaxNumWorkGroupsAttr * + CreateAMDGPUMaxNumWorkGroupsAttr(const AttributeCommonInfo &CI, Expr *XExpr, + Expr *YExpr, Expr *ZExpr); + + /// addAMDGPUMaxNumWorkGroupsAttr - Adds an amdgpu_max_num_work_groups + /// attribute to a particular declaration. + void addAMDGPUMaxNumWorkGroupsAttr(Decl *D, const AttributeCommonInfo &CI, + Expr *XExpr, Expr *YExpr, Expr *ZExpr); + DLLImportAttr *mergeDLLImportAttr(Decl *D, const AttributeCommonInfo &CI); DLLExportAttr *mergeDLLExportAttr(Decl *D, const AttributeCommonInfo &CI); MSInheritanceAttr *mergeMSInheritanceAttr(Decl *D, diff --git a/clang/lib/CodeGen/Targets/AMDGPU.cpp b/clang/lib/CodeGen/Targets/AMDGPU.cpp index 03ac6b78598f..44e86c0b40f6 100644 --- a/clang/lib/CodeGen/Targets/AMDGPU.cpp +++ b/clang/lib/CodeGen/Targets/AMDGPU.cpp @@ -356,6 +356,29 @@ void AMDGPUTargetCodeGenInfo::setFunctionDeclAttributes( if (NumVGPR != 0) F->addFnAttr("amdgpu-num-vgpr", llvm::utostr(NumVGPR)); } + + if (const auto *Attr = FD->getAttr()) { + uint32_t X = Attr->getMaxNumWorkGroupsX() + ->EvaluateKnownConstInt(M.getContext()) + .getExtValue(); + // Y and Z dimensions default to 1 if not specified + uint32_t Y = Attr->getMaxNumWorkGroupsY() + ? Attr->getMaxNumWorkGroupsY() + ->EvaluateKnownConstInt(M.getContext()) + .getExtValue() + : 1; + uint32_t Z = Attr->getMaxNumWorkGroupsZ() + ? Attr->getMaxNumWorkGroupsZ() + ->EvaluateKnownConstInt(M.getContext()) + .getExtValue() + : 1; + + llvm::SmallString<32> AttrVal; + llvm::raw_svector_ostream OS(AttrVal); + OS << X << ',' << Y << ',' << Z; + + F->addFnAttr("amdgpu-max-num-workgroups", AttrVal.str()); + } } /// Emits control constants used to change per-architecture behaviour in the diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c00120b59d39..e3da3e606435 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -8079,6 +8079,65 @@ static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) AMDGPUNumVGPRAttr(S.Context, AL, NumVGPR)); } +static bool +checkAMDGPUMaxNumWorkGroupsArguments(Sema &S, Expr *XExpr, Expr *YExpr, + Expr *ZExpr, + const AMDGPUMaxNumWorkGroupsAttr &Attr) { + if (S.DiagnoseUnexpandedParameterPack(XExpr) || + (YExpr && S.DiagnoseUnexpandedParameterPack(YExpr)) || + (ZExpr && S.DiagnoseUnexpandedParameterPack(ZExpr))) + return true; + + // Accept template arguments for now as they depend on something else. + // We'll get to check them when they eventually get instantiated. + if (XExpr->isValueDependent() || (YExpr && YExpr->isValueDependent()) || + (ZExpr && ZExpr->isValueDependent())) + return false; + + uint32_t NumWG = 0; + Expr *Exprs[3] = {XExpr, YExpr, ZExpr}; + for (int i = 0; i < 3; i++) { + if (Exprs[i]) { + if (!checkUInt32Argument(S, Attr, Exprs[i], NumWG, i, + /*StrictlyUnsigned=*/true)) + return true; + if (NumWG == 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero) + << &Attr << Exprs[i]->getSourceRange(); + return true; + } + } + } + + return false; +} + +AMDGPUMaxNumWorkGroupsAttr * +Sema::CreateAMDGPUMaxNumWorkGroupsAttr(const AttributeCommonInfo &CI, + Expr *XExpr, Expr *YExpr, Expr *ZExpr) { + AMDGPUMaxNumWorkGroupsAttr TmpAttr(Context, CI, XExpr, YExpr, ZExpr); + + if (checkAMDGPUMaxNumWorkGroupsArguments(*this, XExpr, YExpr, ZExpr, TmpAttr)) + return nullptr; + + return ::new (Context) + AMDGPUMaxNumWorkGroupsAttr(Context, CI, XExpr, YExpr, ZExpr); +} + +void Sema::addAMDGPUMaxNumWorkGroupsAttr(Decl *D, const AttributeCommonInfo &CI, + Expr *XExpr, Expr *YExpr, + Expr *ZExpr) { + if (auto *Attr = CreateAMDGPUMaxNumWorkGroupsAttr(CI, XExpr, YExpr, ZExpr)) + D->addAttr(Attr); +} + +static void handleAMDGPUMaxNumWorkGroupsAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + Expr *YExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr; + Expr *ZExpr = (AL.getNumArgs() > 2) ? AL.getArgAsExpr(2) : nullptr; + S.addAMDGPUMaxNumWorkGroupsAttr(D, AL, AL.getArgAsExpr(0), YExpr, ZExpr); +} + static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // If we try to apply it to a function pointer, don't warn, but don't @@ -9183,6 +9242,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_AMDGPUNumVGPR: handleAMDGPUNumVGPRAttr(S, D, AL); break; + case ParsedAttr::AT_AMDGPUMaxNumWorkGroups: + handleAMDGPUMaxNumWorkGroupsAttr(S, D, AL); + break; case ParsedAttr::AT_AVRSignal: handleAVRSignalAttr(S, D, AL); break; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 20c2c93ac9c7..8ef8bfdf2a7b 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -607,6 +607,29 @@ static void instantiateDependentAMDGPUWavesPerEUAttr( S.addAMDGPUWavesPerEUAttr(New, Attr, MinExpr, MaxExpr); } +static void instantiateDependentAMDGPUMaxNumWorkGroupsAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const AMDGPUMaxNumWorkGroupsAttr &Attr, Decl *New) { + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::ConstantEvaluated); + + ExprResult ResultX = S.SubstExpr(Attr.getMaxNumWorkGroupsX(), TemplateArgs); + if (!ResultX.isUsable()) + return; + ExprResult ResultY = S.SubstExpr(Attr.getMaxNumWorkGroupsY(), TemplateArgs); + if (!ResultY.isUsable()) + return; + ExprResult ResultZ = S.SubstExpr(Attr.getMaxNumWorkGroupsZ(), TemplateArgs); + if (!ResultZ.isUsable()) + return; + + Expr *XExpr = ResultX.getAs(); + Expr *YExpr = ResultY.getAs(); + Expr *ZExpr = ResultZ.getAs(); + + S.addAMDGPUMaxNumWorkGroupsAttr(New, Attr, XExpr, YExpr, ZExpr); +} + // This doesn't take any template parameters, but we have a custom action that // needs to happen when the kernel itself is instantiated. We need to run the // ItaniumMangler to mark the names required to name this kernel. @@ -792,6 +815,12 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, *AMDGPUFlatWorkGroupSize, New); } + if (const auto *AMDGPUMaxNumWorkGroups = + dyn_cast(TmplAttr)) { + instantiateDependentAMDGPUMaxNumWorkGroupsAttr( + *this, TemplateArgs, *AMDGPUMaxNumWorkGroups, New); + } + if (const auto *ParamAttr = dyn_cast(TmplAttr)) { instantiateDependentHLSLParamModifierAttr(*this, TemplateArgs, ParamAttr, New); diff --git a/clang/test/CodeGenCUDA/amdgpu-kernel-attrs.cu b/clang/test/CodeGenCUDA/amdgpu-kernel-attrs.cu index a1642421af2c..11a133fd1351 100644 --- a/clang/test/CodeGenCUDA/amdgpu-kernel-attrs.cu +++ b/clang/test/CodeGenCUDA/amdgpu-kernel-attrs.cu @@ -40,12 +40,45 @@ __attribute__((amdgpu_num_vgpr(64))) // expected-no-diagnostics __global__ void num_vgpr_64() { // CHECK: define{{.*}} amdgpu_kernel void @_Z11num_vgpr_64v() [[NUM_VGPR_64:#[0-9]+]] } +__attribute__((amdgpu_max_num_work_groups(32, 4, 2))) // expected-no-diagnostics +__global__ void max_num_work_groups_32_4_2() { +// CHECK: define{{.*}} amdgpu_kernel void @_Z26max_num_work_groups_32_4_2v() [[MAX_NUM_WORK_GROUPS_32_4_2:#[0-9]+]] +} +__attribute__((amdgpu_max_num_work_groups(32))) // expected-no-diagnostics +__global__ void max_num_work_groups_32() { +// CHECK: define{{.*}} amdgpu_kernel void @_Z22max_num_work_groups_32v() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]] +} +__attribute__((amdgpu_max_num_work_groups(32,1))) // expected-no-diagnostics +__global__ void max_num_work_groups_32_1() { +// CHECK: define{{.*}} amdgpu_kernel void @_Z24max_num_work_groups_32_1v() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]] +} + + + +template +__attribute__((amdgpu_max_num_work_groups(a, 4, 2))) +__global__ void template_a_4_2_max_num_work_groups() {} +template __global__ void template_a_4_2_max_num_work_groups<32>(); +// CHECK: define{{.*}} amdgpu_kernel void @_Z34template_a_4_2_max_num_work_groupsILj32EEvv() [[MAX_NUM_WORK_GROUPS_32_4_2:#[0-9]+]] + +template +__attribute__((amdgpu_max_num_work_groups(32, a, 2))) +__global__ void template_32_a_2_max_num_work_groups() {} +template __global__ void template_32_a_2_max_num_work_groups<4>(); +// CHECK: define{{.*}} amdgpu_kernel void @_Z35template_32_a_2_max_num_work_groupsILj4EEvv() [[MAX_NUM_WORK_GROUPS_32_4_2:#[0-9]+]] + +template +__attribute__((amdgpu_max_num_work_groups(32, 4, a))) +__global__ void template_32_4_a_max_num_work_groups() {} +template __global__ void template_32_4_a_max_num_work_groups<2>(); +// CHECK: define{{.*}} amdgpu_kernel void @_Z35template_32_4_a_max_num_work_groupsILj2EEvv() [[MAX_NUM_WORK_GROUPS_32_4_2:#[0-9]+]] // Make sure this is silently accepted on other targets. // NAMD-NOT: "amdgpu-flat-work-group-size" // NAMD-NOT: "amdgpu-waves-per-eu" // NAMD-NOT: "amdgpu-num-vgpr" // NAMD-NOT: "amdgpu-num-sgpr" +// NAMD-NOT: "amdgpu-max-num-work-groups" // DEFAULT-DAG: attributes [[FLAT_WORK_GROUP_SIZE_DEFAULT]] = {{.*}}"amdgpu-flat-work-group-size"="1,1024"{{.*}}"uniform-work-group-size"="true" // MAX1024-DAG: attributes [[FLAT_WORK_GROUP_SIZE_DEFAULT]] = {{.*}}"amdgpu-flat-work-group-size"="1,1024" @@ -53,5 +86,7 @@ __global__ void num_vgpr_64() { // CHECK-DAG: attributes [[WAVES_PER_EU_2]] = {{.*}}"amdgpu-waves-per-eu"="2" // CHECK-DAG: attributes [[NUM_SGPR_32]] = {{.*}}"amdgpu-num-sgpr"="32" // CHECK-DAG: attributes [[NUM_VGPR_64]] = {{.*}}"amdgpu-num-vgpr"="64" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_32_4_2]] = {{.*}}"amdgpu-max-num-workgroups"="32,4,2" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_32_1_1]] = {{.*}}"amdgpu-max-num-workgroups"="32,1,1" // NOUB-NOT: "uniform-work-group-size"="true" diff --git a/clang/test/CodeGenOpenCL/amdgpu-attrs.cl b/clang/test/CodeGenOpenCL/amdgpu-attrs.cl index b0dfc97b53b2..5648bc13458e 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-attrs.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-attrs.cl @@ -139,6 +139,46 @@ kernel void reqd_work_group_size_32_2_1_flat_work_group_size_16_128() { // CHECK: define{{.*}} amdgpu_kernel void @reqd_work_group_size_32_2_1_flat_work_group_size_16_128() [[FLAT_WORK_GROUP_SIZE_16_128:#[0-9]+]] } +__attribute__((amdgpu_max_num_work_groups(1, 1, 1))) // expected-no-diagnostics +kernel void max_num_work_groups_1_1_1() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_1_1_1() [[MAX_NUM_WORK_GROUPS_1_1_1:#[0-9]+]] +} + +__attribute__((amdgpu_max_num_work_groups(32, 1, 1))) // expected-no-diagnostics +kernel void max_num_work_groups_32_1_1() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_32_1_1() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]] +} + +__attribute__((amdgpu_max_num_work_groups(32, 8, 1))) // expected-no-diagnostics +kernel void max_num_work_groups_32_8_1() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_32_8_1() [[MAX_NUM_WORK_GROUPS_32_8_1:#[0-9]+]] +} + +__attribute__((amdgpu_max_num_work_groups(1, 1, 32))) // expected-no-diagnostics +kernel void max_num_work_groups_1_1_32() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_1_1_32() [[MAX_NUM_WORK_GROUPS_1_1_32:#[0-9]+]] +} + +__attribute__((amdgpu_max_num_work_groups(1, 8, 32))) // expected-no-diagnostics +kernel void max_num_work_groups_1_8_32() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_1_8_32() [[MAX_NUM_WORK_GROUPS_1_8_32:#[0-9]+]] +} + +__attribute__((amdgpu_max_num_work_groups(4, 8, 32))) // expected-no-diagnostics +kernel void max_num_work_groups_4_8_32() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_4_8_32() [[MAX_NUM_WORK_GROUPS_4_8_32:#[0-9]+]] +} + +__attribute__((amdgpu_max_num_work_groups(32))) // expected-no-diagnostics +kernel void max_num_work_groups_32() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_32() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]] +} + +__attribute__((amdgpu_max_num_work_groups(32,1))) // expected-no-diagnostics +kernel void max_num_work_groups_32_1() { +// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_32_1() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]] +} + void a_function() { // CHECK: define{{.*}} void @a_function() [[A_FUNCTION:#[0-9]+]] } @@ -189,5 +229,12 @@ kernel void default_kernel() { // CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32_NUM_VGPR_64]] = {{.*}} "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2" // CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32_NUM_VGPR_64]] = {{.*}} "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_1_1_1]] = {{.*}} "amdgpu-max-num-workgroups"="1,1,1" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_32_1_1]] = {{.*}} "amdgpu-max-num-workgroups"="32,1,1" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_32_8_1]] = {{.*}} "amdgpu-max-num-workgroups"="32,8,1" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_1_1_32]] = {{.*}} "amdgpu-max-num-workgroups"="1,1,32" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_1_8_32]] = {{.*}} "amdgpu-max-num-workgroups"="1,8,32" +// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_4_8_32]] = {{.*}} "amdgpu-max-num-workgroups"="4,8,32" + // CHECK-DAG: attributes [[A_FUNCTION]] = {{.*}} // CHECK-DAG: attributes [[DEFAULT_KERNEL_ATTRS]] = {{.*}} "amdgpu-flat-work-group-size"="1,256" diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index ec84ebdc6abe..318bfb2df2a7 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -4,6 +4,7 @@ // CHECK: #pragma clang attribute supports the following attributes: // CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function) +// CHECK-NEXT: AMDGPUMaxNumWorkGroups (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUWavesPerEU (SubjectMatchRule_function) diff --git a/clang/test/SemaCUDA/amdgpu-attrs.cu b/clang/test/SemaCUDA/amdgpu-attrs.cu index 4811ef796c66..e04b32d121bc 100644 --- a/clang/test/SemaCUDA/amdgpu-attrs.cu +++ b/clang/test/SemaCUDA/amdgpu-attrs.cu @@ -63,6 +63,16 @@ __global__ void flat_work_group_size_32_64_waves_per_eu_2_num_sgpr_32_num_vgpr_6 __attribute__((amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4), amdgpu_num_sgpr(32), amdgpu_num_vgpr(64))) __global__ void flat_work_group_size_32_64_waves_per_eu_2_4_num_sgpr_32_num_vgpr_64() {} +__attribute__((amdgpu_max_num_work_groups(32, 1, 1))) +__global__ void max_num_work_groups_32_1_1() {} + +__attribute__((amdgpu_max_num_work_groups(32, 1, 1), amdgpu_flat_work_group_size(32, 64))) +__global__ void max_num_work_groups_32_1_1_flat_work_group_size_32_64() {} + +__attribute__((amdgpu_max_num_work_groups(32, 1, 1), amdgpu_flat_work_group_size(32, 64), amdgpu_waves_per_eu(2, 4), amdgpu_num_sgpr(32), amdgpu_num_vgpr(64))) +__global__ void max_num_work_groups_32_1_1_flat_work_group_size_32_64_waves_per_eu_2_4_num_sgpr_32_num_vgpr_64() {} + + // expected-error@+2{{attribute 'reqd_work_group_size' can only be applied to an OpenCL kernel function}} __attribute__((reqd_work_group_size(32, 64, 64))) __global__ void reqd_work_group_size_32_64_64() {} @@ -194,3 +204,125 @@ __global__ void non_cexpr_waves_per_eu_2() {} // expected-error@+1{{'amdgpu_waves_per_eu' attribute requires parameter 1 to be an integer constant}} __attribute__((amdgpu_waves_per_eu(2, ipow2(2)))) __global__ void non_cexpr_waves_per_eu_2_4() {} + +__attribute__((amdgpu_max_num_work_groups(32))) +__global__ void max_num_work_groups_32() {} + +__attribute__((amdgpu_max_num_work_groups(32, 1))) +__global__ void max_num_work_groups_32_1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute takes no more than 3 arguments}} +__attribute__((amdgpu_max_num_work_groups(32, 1, 1, 1))) +__global__ void max_num_work_groups_32_1_1_1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute takes at least 1 argument}} +__attribute__((amdgpu_max_num_work_groups())) +__global__ void max_num_work_groups_no_arg() {} + +// expected-error@+1{{expected expression}} +__attribute__((amdgpu_max_num_work_groups(,1,1))) +__global__ void max_num_work_groups_empty_1_1() {} + +// expected-error@+1{{expected expression}} +__attribute__((amdgpu_max_num_work_groups(32,,1))) +__global__ void max_num_work_groups_32_empty_1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires parameter 0 to be an integer constant}} +__attribute__((amdgpu_max_num_work_groups(ipow2(5), 1, 1))) +__global__ void max_num_work_groups_32_1_1_non_int_arg0() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires parameter 1 to be an integer constant}} +__attribute__((amdgpu_max_num_work_groups(32, "1", 1))) +__global__ void max_num_work_groups_32_1_1_non_int_arg1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires a non-negative integral compile time constant expression}} +__attribute__((amdgpu_max_num_work_groups(-32, 1, 1))) +__global__ void max_num_work_groups_32_1_1_neg_int_arg0() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires a non-negative integral compile time constant expression}} +__attribute__((amdgpu_max_num_work_groups(32, -1, 1))) +__global__ void max_num_work_groups_32_1_1_neg_int_arg1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires a non-negative integral compile time constant expression}} +__attribute__((amdgpu_max_num_work_groups(32, 1, -1))) +__global__ void max_num_work_groups_32_1_1_neg_int_arg2() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute must be greater than 0}} +__attribute__((amdgpu_max_num_work_groups(0, 1, 1))) +__global__ void max_num_work_groups_0_1_1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute must be greater than 0}} +__attribute__((amdgpu_max_num_work_groups(32, 0, 1))) +__global__ void max_num_work_groups_32_0_1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute must be greater than 0}} +__attribute__((amdgpu_max_num_work_groups(32, 1, 0))) +__global__ void max_num_work_groups_32_1_0() {} + +__attribute__((amdgpu_max_num_work_groups(4294967295))) +__global__ void max_num_work_groups_max_unsigned_int() {} + +// expected-error@+1{{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}} +__attribute__((amdgpu_max_num_work_groups(4294967296))) +__global__ void max_num_work_groups_max_unsigned_int_plus1() {} + +// expected-error@+1{{integer constant expression evaluates to value 10000000000 that cannot be represented in a 32-bit unsigned integer type}} +__attribute__((amdgpu_max_num_work_groups(10000000000))) +__global__ void max_num_work_groups_too_large() {} + +int num_wg_x = 32; +int num_wg_y = 1; +int num_wg_z = 1; +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires parameter 0 to be an integer constant}} +__attribute__((amdgpu_max_num_work_groups(num_wg_x, 1, 1))) +__global__ void max_num_work_groups_32_1_1_non_const_arg0() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires parameter 1 to be an integer constant}} +__attribute__((amdgpu_max_num_work_groups(32, num_wg_y, 1))) +__global__ void max_num_work_groups_32_1_1_non_const_arg1() {} + +// expected-error@+1{{'amdgpu_max_num_work_groups' attribute requires parameter 2 to be an integer constant}} +__attribute__((amdgpu_max_num_work_groups(32, 1, num_wg_z))) +__global__ void max_num_work_groups_32_1_1_non_const_arg2() {} + +const int c_num_wg_x = 32; +__attribute__((amdgpu_max_num_work_groups(c_num_wg_x, 1, 1))) +__global__ void max_num_work_groups_32_1_1_const_arg0() {} + +template +__attribute__((amdgpu_max_num_work_groups(a, 1, 1))) +__global__ void template_a_1_1_max_num_work_groups() {} +template __global__ void template_a_1_1_max_num_work_groups<32>(); + +template +__attribute__((amdgpu_max_num_work_groups(32, a, 1))) +__global__ void template_32_a_1_max_num_work_groups() {} +template __global__ void template_32_a_1_max_num_work_groups<1>(); + +template +__attribute__((amdgpu_max_num_work_groups(32, 1, a))) +__global__ void template_32_1_a_max_num_work_groups() {} +template __global__ void template_32_1_a_max_num_work_groups<1>(); + +// expected-error@+3{{'amdgpu_max_num_work_groups' attribute must be greater than 0}} +// expected-note@+4{{in instantiation of}} +template +__attribute__((amdgpu_max_num_work_groups(b, 1, 1))) +__global__ void template_b_1_1_max_num_work_groups() {} +template __global__ void template_b_1_1_max_num_work_groups<0>(); + +// expected-error@+3{{'amdgpu_max_num_work_groups' attribute must be greater than 0}} +// expected-note@+4{{in instantiation of}} +template +__attribute__((amdgpu_max_num_work_groups(32, b, 1))) +__global__ void template_32_b_1_max_num_work_groups() {} +template __global__ void template_32_b_1_max_num_work_groups<0>(); + +// expected-error@+3{{'amdgpu_max_num_work_groups' attribute must be greater than 0}} +// expected-note@+4{{in instantiation of}} +template +__attribute__((amdgpu_max_num_work_groups(32, 1, b))) +__global__ void template_32_1_b_max_num_work_groups() {} +template __global__ void template_32_1_b_max_num_work_groups<0>(); + + diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst index f5f37d9e8a3b..99d7a482710f 100644 --- a/llvm/docs/AMDGPUUsage.rst +++ b/llvm/docs/AMDGPUUsage.rst @@ -1442,6 +1442,11 @@ The AMDGPU backend supports the following LLVM IR attributes. the frame. This is an internal detail of how LDS variables are lowered, language front ends should not set this attribute. + "amdgpu-max-num-workgroups"="x,y,z" Specify the maximum number of work groups for the kernel dispatch in the + X, Y, and Z dimensions. Generated by the ``amdgpu_max_num_work_groups`` + CLANG attribute [CLANG-ATTR]_. Clang only emits this attribute when all + the three numbers are >= 1. + ======================================= ========================================================== Calling Conventions @@ -3917,6 +3922,11 @@ same *vendor-name*. If omitted, "normal" is assumed. + ".max_num_work_groups_{x,y,z}" integer The max number of + launched work-groups + in the X, Y, and Z + dimensions. Each number + must be >=1. =================================== ============== ========= ================================ .. diff --git a/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp b/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp index c20fdd51607a..9e288ab50e17 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp @@ -494,6 +494,14 @@ MetadataStreamerMsgPackV4::getHSAKernelProps(const MachineFunction &MF, Kern[".max_flat_workgroup_size"] = Kern.getDocument()->getNode(MFI.getMaxFlatWorkGroupSize()); + unsigned NumWGX = MFI.getMaxNumWorkGroupsX(); + unsigned NumWGY = MFI.getMaxNumWorkGroupsY(); + unsigned NumWGZ = MFI.getMaxNumWorkGroupsZ(); + if (NumWGX != 0 && NumWGY != 0 && NumWGZ != 0) { + Kern[".max_num_workgroups_x"] = Kern.getDocument()->getNode(NumWGX); + Kern[".max_num_workgroups_y"] = Kern.getDocument()->getNode(NumWGY); + Kern[".max_num_workgroups_z"] = Kern.getDocument()->getNode(NumWGZ); + } Kern[".sgpr_spill_count"] = Kern.getDocument()->getNode(MFI.getNumSpilledSGPRs()); Kern[".vgpr_spill_count"] = diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp index bcc7dedf3229..fa77b94fc22d 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp @@ -432,7 +432,7 @@ std::pair AMDGPUSubtarget::getEffectiveWavesPerEU( std::pair Default(1, getMaxWavesPerEU()); // If minimum/maximum flat work group sizes were explicitly requested using - // "amdgpu-flat-work-group-size" attribute, then set default minimum/maximum + // "amdgpu-flat-workgroup-size" attribute, then set default minimum/maximum // number of waves per execution unit to values implied by requested // minimum/maximum flat work group sizes. unsigned MinImpliedByFlatWorkGroupSize = @@ -1108,3 +1108,8 @@ void GCNUserSGPRUsageInfo::allocKernargPreloadSGPRs(unsigned NumSGPRs) { unsigned GCNUserSGPRUsageInfo::getNumFreeUserSGPRs() { return AMDGPU::getMaxNumUserSGPRs(ST) - NumUsedUserSGPRs; } + +SmallVector +AMDGPUSubtarget::getMaxNumWorkGroups(const Function &F) const { + return AMDGPU::getIntegerVecAttribute(F, "amdgpu-max-num-workgroups", 3); +} diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h index b72697973be7..e2d8b5d1ce97 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h @@ -288,6 +288,9 @@ public: /// 2) dimension. unsigned getMaxWorkitemID(const Function &Kernel, unsigned Dimension) const; + /// Return the number of work groups for the function. + SmallVector getMaxNumWorkGroups(const Function &F) const; + /// Return true if only a single workitem can be active in a wave. bool isSingleLaneExecution(const Function &Kernel) const; diff --git a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp index 52d6fe6c7ba5..2569f40fec0e 100644 --- a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp +++ b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp @@ -46,6 +46,8 @@ SIMachineFunctionInfo::SIMachineFunctionInfo(const Function &F, const GCNSubtarget &ST = *static_cast(STI); FlatWorkGroupSizes = ST.getFlatWorkGroupSizes(F); WavesPerEU = ST.getWavesPerEU(F); + MaxNumWorkGroups = ST.getMaxNumWorkGroups(F); + assert(MaxNumWorkGroups.size() == 3); Occupancy = ST.computeOccupancy(F, getLDSSize()); CallingConv::ID CC = F.getCallingConv(); diff --git a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h index 0336ec4985ea..7d0c1ba8448e 100644 --- a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h +++ b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h @@ -426,6 +426,9 @@ class SIMachineFunctionInfo final : public AMDGPUMachineFunction, const AMDGPUGWSResourcePseudoSourceValue GWSResourcePSV; + // Default/requested number of work groups for the function. + SmallVector MaxNumWorkGroups = {0, 0, 0}; + private: unsigned NumUserSGPRs = 0; unsigned NumSystemSGPRs = 0; @@ -1072,6 +1075,13 @@ public: // \returns true if a function needs or may need AGPRs. bool usesAGPRs(const MachineFunction &MF) const; + + /// \returns Default/requested number of work groups for this function. + SmallVector getMaxNumWorkGroups() const { return MaxNumWorkGroups; } + + unsigned getMaxNumWorkGroupsX() const { return MaxNumWorkGroups[0]; } + unsigned getMaxNumWorkGroupsY() const { return MaxNumWorkGroups[1]; } + unsigned getMaxNumWorkGroupsZ() const { return MaxNumWorkGroups[2]; } }; } // end namespace llvm diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp index edb0e50da289..aa47dccf2dd2 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -11,6 +11,7 @@ #include "AMDGPUAsmUtils.h" #include "AMDKernelCodeT.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Constants.h" @@ -1298,6 +1299,42 @@ getIntegerPairAttribute(const Function &F, StringRef Name, return Ints; } +SmallVector getIntegerVecAttribute(const Function &F, StringRef Name, + unsigned Size) { + assert(Size > 2); + SmallVector Default(Size, 0); + + Attribute A = F.getFnAttribute(Name); + if (!A.isStringAttribute()) + return Default; + + SmallVector Vals(Size, 0); + + LLVMContext &Ctx = F.getContext(); + + StringRef S = A.getValueAsString(); + unsigned i = 0; + for (; !S.empty() && i < Size; i++) { + std::pair Strs = S.split(','); + unsigned IntVal; + if (Strs.first.trim().getAsInteger(0, IntVal)) { + Ctx.emitError("can't parse integer attribute " + Strs.first + " in " + + Name); + return Default; + } + Vals[i] = IntVal; + S = Strs.second; + } + + if (!S.empty() || i < Size) { + Ctx.emitError("attribute " + Name + + " has incorrect number of integers; expected " + + llvm::utostr(Size)); + return Default; + } + return Vals; +} + unsigned getVmcntBitMask(const IsaVersion &Version) { return (1 << (getVmcntBitWidthLo(Version.Major) + getVmcntBitWidthHi(Version.Major))) - diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h index d7ea2a3eff4b..f8521cba077c 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -863,6 +863,14 @@ bool isReadOnlySegment(const GlobalValue *GV); /// target triple \p TT, false otherwise. bool shouldEmitConstantsToTextSection(const Triple &TT); +/// \returns Integer value requested using \p F's \p Name attribute. +/// +/// \returns \p Default if attribute is not present. +/// +/// \returns \p Default and emits error if requested value cannot be converted +/// to integer. +int getIntegerAttribute(const Function &F, StringRef Name, int Default); + /// \returns A pair of integer values requested using \p F's \p Name attribute /// in "first[,second]" format ("second" is optional unless \p OnlyFirstRequired /// is false). @@ -877,6 +885,16 @@ getIntegerPairAttribute(const Function &F, StringRef Name, std::pair Default, bool OnlyFirstRequired = false); +/// \returns Generate a vector of integer values requested using \p F's \p Name +/// attribute. +/// +/// \returns true if exactly Size (>2) number of integers are found in the +/// attribute. +/// +/// \returns false if any error occurs. +SmallVector getIntegerVecAttribute(const Function &F, StringRef Name, + unsigned Size); + /// Represents the counter values to wait for in an s_waitcnt instruction. /// /// Large values (including the maximum possible integer) can be used to diff --git a/llvm/test/CodeGen/AMDGPU/attr-amdgpu-num-workgroups.ll b/llvm/test/CodeGen/AMDGPU/attr-amdgpu-num-workgroups.ll new file mode 100644 index 000000000000..bc58222076ac --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/attr-amdgpu-num-workgroups.ll @@ -0,0 +1,84 @@ +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s | FileCheck %s + +; Attribute not specified. +; CHECK-LABEL: {{^}}empty_no_attribute: +define amdgpu_kernel void @empty_no_attribute() { +entry: + ret void +} + +; Ignore if number of work groups for x dimension is 0. +; CHECK-LABEL: {{^}}empty_max_num_workgroups_x0: +define amdgpu_kernel void @empty_max_num_workgroups_x0() #0 { +entry: + ret void +} +attributes #0 = {"amdgpu-max-num-workgroups"="0,2,3"} + +; Ignore if number of work groups for y dimension is 0. +; CHECK-LABEL: {{^}}empty_max_num_workgroups_y0: +define amdgpu_kernel void @empty_max_num_workgroups_y0() #1 { +entry: + ret void +} +attributes #1 = {"amdgpu-max-num-workgroups"="1,0,3"} + +; Ignore if number of work groups for z dimension is 0. +; CHECK-LABEL: {{^}}empty_max_num_workgroups_z0: +define amdgpu_kernel void @empty_max_num_workgroups_z0() #2 { +entry: + ret void +} +attributes #2 = {"amdgpu-max-num-workgroups"="1,2,0"} + +; CHECK-LABEL: {{^}}empty_max_num_workgroups_1_2_3: +define amdgpu_kernel void @empty_max_num_workgroups_1_2_3() #3 { +entry: + ret void +} +attributes #3 = {"amdgpu-max-num-workgroups"="1,2,3"} + +; CHECK-LABEL: {{^}}empty_max_num_workgroups_1024_1024_1024: +define amdgpu_kernel void @empty_max_num_workgroups_1024_1024_1024() #4 { +entry: + ret void +} +attributes #4 = {"amdgpu-max-num-workgroups"="1024,1024,1024"} + + +; CHECK: .amdgpu_metadata +; CHECK: - .args: +; CHECK: .max_flat_workgroup_size: 1024 +; CHECK-NEXT: .name: empty_no_attribute +; CHECK-NEXT: .private_segment_fixed_size: 0 + +; CHECK: - .args: +; CHECK: .max_flat_workgroup_size: 1024 +; CHECK-NEXT: .name: empty_max_num_workgroups_x0 +; CHECK-NEXT: .private_segment_fixed_size: 0 + +; CHECK: - .args: +; CHECK: .max_flat_workgroup_size: 1024 +; CHECK-NEXT: .name: empty_max_num_workgroups_y0 +; CHECK-NEXT: .private_segment_fixed_size: 0 + +; CHECK: - .args: +; CHECK: .max_flat_workgroup_size: 1024 +; CHECK-NEXT: .name: empty_max_num_workgroups_z0 +; CHECK-NEXT: .private_segment_fixed_size: 0 + +; CHECK: - .args: +; CHECK: .max_flat_workgroup_size: 1024 +; CHECK-NEXT: .max_num_workgroups_x: 1 +; CHECK-NEXT: .max_num_workgroups_y: 2 +; CHECK-NEXT: .max_num_workgroups_z: 3 +; CHECK-NEXT: .name: empty_max_num_workgroups_1_2_3 +; CHECK-NEXT: .private_segment_fixed_size: 0 + +; CHECK: - .args: +; CHECK: .max_flat_workgroup_size: 1024 +; CHECK-NEXT: .max_num_workgroups_x: 1024 +; CHECK-NEXT: .max_num_workgroups_y: 1024 +; CHECK-NEXT: .max_num_workgroups_z: 1024 +; CHECK-NEXT: .name: empty_max_num_workgroups_1024_1024_1024 +; CHECK-NEXT: .private_segment_fixed_size: 0 diff --git a/llvm/test/CodeGen/AMDGPU/attr-amdgpu-num-workgroups_error_check.ll b/llvm/test/CodeGen/AMDGPU/attr-amdgpu-num-workgroups_error_check.ll new file mode 100644 index 000000000000..6d86d2d7c1a3 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/attr-amdgpu-num-workgroups_error_check.ll @@ -0,0 +1,71 @@ +; RUN: not llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s 2>&1 | FileCheck --check-prefix=ERROR %s + +; ERROR: error: can't parse integer attribute -1 in amdgpu-max-num-workgroups +define amdgpu_kernel void @empty_max_num_workgroups_neg_num1() #21 { +entry: + ret void +} +attributes #21 = {"amdgpu-max-num-workgroups"="-1,2,3"} + +; ERROR: error: can't parse integer attribute -2 in amdgpu-max-num-workgroups +define amdgpu_kernel void @empty_max_num_workgroups_neg_num2() #22 { +entry: + ret void +} +attributes #22 = {"amdgpu-max-num-workgroups"="1,-2,3"} + +; ERROR: error: can't parse integer attribute -3 in amdgpu-max-num-workgroups +define amdgpu_kernel void @empty_max_num_workgroups_neg_num3() #23 { +entry: + ret void +} +attributes #23 = {"amdgpu-max-num-workgroups"="1,2,-3"} + +; ERROR: error: can't parse integer attribute 1.0 in amdgpu-max-num-workgroups +define amdgpu_kernel void @empty_max_num_workgroups_non_int1() #31 { +entry: + ret void +} +attributes #31 = {"amdgpu-max-num-workgroups"="1.0,2,3"} + +; ERROR: error: can't parse integer attribute 2.0 in amdgpu-max-num-workgroups +define amdgpu_kernel void @empty_max_num_workgroups_non_int2() #32 { +entry: + ret void +} +attributes #32 = {"amdgpu-max-num-workgroups"="1,2.0,3"} + +; ERROR: error: can't parse integer attribute 3.0 in amdgpu-max-num-workgroups +define amdgpu_kernel void @empty_max_num_workgroups_non_int3() #33 { +entry: + ret void +} +attributes #33 = {"amdgpu-max-num-workgroups"="1,2,3.0"} + +; ERROR: error: can't parse integer attribute 10000000000 in amdgpu-max-num-workgroups +define amdgpu_kernel void @empty_max_num_workgroups_too_large() #41 { +entry: + ret void +} +attributes #41 = {"amdgpu-max-num-workgroups"="10000000000,2,3"} + +; ERROR: error: attribute amdgpu-max-num-workgroups has incorrect number of integers; expected 3 +define amdgpu_kernel void @empty_max_num_workgroups_1_arg() #51 { +entry: + ret void +} +attributes #51 = {"amdgpu-max-num-workgroups"="1"} + +; ERROR: error: attribute amdgpu-max-num-workgroups has incorrect number of integers; expected 3 +define amdgpu_kernel void @empty_max_num_workgroups_2_args() #52 { +entry: + ret void +} +attributes #52 = {"amdgpu-max-num-workgroups"="1,2"} + +; ERROR: error: attribute amdgpu-max-num-workgroups has incorrect number of integers; expected 3 +define amdgpu_kernel void @empty_max_num_workgroups_4_args() #53 { +entry: + ret void +} +attributes #53 = {"amdgpu-max-num-workgroups"="1,2,3,4"} -- GitLab From c1af6ab505a83bfb4fc8752591ad333190bc9389 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Tue, 12 Mar 2024 17:29:30 +0000 Subject: [PATCH 279/953] [X86] getFauxShuffleMask - recognise CONCAT(SUB0, SUB1) style patterns Handles the INSERT_SUBVECTOR(INSERT_SUBVECTOR(UNDEF,SUB0,0),SUB1,N) pattern Currently limited to v8i64/v8f64 cases as only AVX512 has decent cross lane 2-input shuffles, the plan is to relax this as I deal with some regressions --- llvm/lib/Target/X86/X86ISelLowering.cpp | 17 ++ .../vector-interleaved-store-i16-stride-7.ll | 10 +- .../vector-interleaved-store-i16-stride-8.ll | 28 +- .../vector-interleaved-store-i32-stride-7.ll | 20 +- .../vector-interleaved-store-i32-stride-8.ll | 280 +++++++++--------- .../vector-interleaved-store-i64-stride-4.ll | 120 ++++---- 6 files changed, 233 insertions(+), 242 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 72b45d462dfe..2b5e3c0379a1 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -5858,6 +5858,23 @@ static bool getFauxShuffleMask(SDValue N, const APInt &DemandedElts, Ops.push_back(SubBCSrc); return true; } + // Handle CONCAT(SUB0, SUB1). + // Limit this to vXi64 512-bit vector cases to make the most of AVX512 + // cross lane shuffles. + if (Depth > 0 && InsertIdx == NumSubElts && NumElts == (2 * NumSubElts) && + NumBitsPerElt == 64 && NumSizeInBits == 512 && + Src.getOpcode() == ISD::INSERT_SUBVECTOR && + Src.getOperand(0).isUndef() && + Src.getOperand(1).getValueType() == SubVT && + Src.getConstantOperandVal(2) == 0) { + for (int i = 0; i != (int)NumSubElts; ++i) + Mask.push_back(i); + for (int i = 0; i != (int)NumSubElts; ++i) + Mask.push_back(i + NumElts); + Ops.push_back(Src.getOperand(1)); + Ops.push_back(Sub); + return true; + } // Handle INSERT_SUBVECTOR(SRC0, SHUFFLE(SRC1)). SmallVector SubMask; SmallVector SubInputs; diff --git a/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-7.ll b/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-7.ll index 79cc8e49f1fd..9e70aef86885 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-7.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-7.ll @@ -821,9 +821,8 @@ define void @store_i16_stride7_vf4(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 ; AVX512BW-FCP-NEXT: vpmovsxbq {{.*#+}} ymm1 = [0,2,4,0] ; AVX512BW-FCP-NEXT: vpermi2q %ymm3, %ymm0, %ymm1 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm0 -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,16,20,24,1,5,9,13,17,21,25,2,6,10,14,18,22,26,3,7,11,15,19,23,27,0,0,0,0] -; AVX512BW-FCP-NEXT: vpermw %zmm0, %zmm1, %zmm0 +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm0 = [0,4,8,12,32,36,40,1,5,9,13,33,37,41,2,6,10,14,34,38,42,3,7,11,15,35,39,43,0,0,0,0] +; AVX512BW-FCP-NEXT: vpermi2w %zmm1, %zmm2, %zmm0 ; AVX512BW-FCP-NEXT: vextracti32x4 $2, %zmm0, 32(%rax) ; AVX512BW-FCP-NEXT: vextracti32x4 $3, %zmm0, %xmm1 ; AVX512BW-FCP-NEXT: vmovq %xmm1, 48(%rax) @@ -873,9 +872,8 @@ define void @store_i16_stride7_vf4(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 ; AVX512DQ-BW-FCP-NEXT: vpmovsxbq {{.*#+}} ymm1 = [0,2,4,0] ; AVX512DQ-BW-FCP-NEXT: vpermi2q %ymm3, %ymm0, %ymm1 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,16,20,24,1,5,9,13,17,21,25,2,6,10,14,18,22,26,3,7,11,15,19,23,27,0,0,0,0] -; AVX512DQ-BW-FCP-NEXT: vpermw %zmm0, %zmm1, %zmm0 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm0 = [0,4,8,12,32,36,40,1,5,9,13,33,37,41,2,6,10,14,34,38,42,3,7,11,15,35,39,43,0,0,0,0] +; AVX512DQ-BW-FCP-NEXT: vpermi2w %zmm1, %zmm2, %zmm0 ; AVX512DQ-BW-FCP-NEXT: vextracti32x4 $2, %zmm0, 32(%rax) ; AVX512DQ-BW-FCP-NEXT: vextracti32x4 $3, %zmm0, %xmm1 ; AVX512DQ-BW-FCP-NEXT: vmovq %xmm1, 48(%rax) diff --git a/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-8.ll b/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-8.ll index 194b715b6594..32825f291e98 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-8.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-store-i16-stride-8.ll @@ -762,10 +762,9 @@ define void @store_i16_stride8_vf4(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] ; AVX512BW-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 ; AVX512BW-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,16,20,24,28,1,5,9,13,17,21,25,29,2,6,10,14,18,22,26,30,3,7,11,15,19,23,27,31] -; AVX512BW-NEXT: vpermw %zmm0, %zmm1, %zmm0 -; AVX512BW-NEXT: vmovdqa64 %zmm0, (%rax) +; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,32,36,40,44,1,5,9,13,33,37,41,45,2,6,10,14,34,38,42,46,3,7,11,15,35,39,43,47] +; AVX512BW-NEXT: vpermi2w %zmm2, %zmm0, %zmm1 +; AVX512BW-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512BW-NEXT: vzeroupper ; AVX512BW-NEXT: retq ; @@ -788,10 +787,9 @@ define void @store_i16_stride8_vf4(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] ; AVX512BW-FCP-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 ; AVX512BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,16,20,24,28,1,5,9,13,17,21,25,29,2,6,10,14,18,22,26,30,3,7,11,15,19,23,27,31] -; AVX512BW-FCP-NEXT: vpermw %zmm0, %zmm1, %zmm0 -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm0, (%rax) +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,32,36,40,44,1,5,9,13,33,37,41,45,2,6,10,14,34,38,42,46,3,7,11,15,35,39,43,47] +; AVX512BW-FCP-NEXT: vpermi2w %zmm2, %zmm0, %zmm1 +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512BW-FCP-NEXT: vzeroupper ; AVX512BW-FCP-NEXT: retq ; @@ -814,10 +812,9 @@ define void @store_i16_stride8_vf4(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] ; AVX512DQ-BW-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 ; AVX512DQ-BW-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,16,20,24,28,1,5,9,13,17,21,25,29,2,6,10,14,18,22,26,30,3,7,11,15,19,23,27,31] -; AVX512DQ-BW-NEXT: vpermw %zmm0, %zmm1, %zmm0 -; AVX512DQ-BW-NEXT: vmovdqa64 %zmm0, (%rax) +; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,32,36,40,44,1,5,9,13,33,37,41,45,2,6,10,14,34,38,42,46,3,7,11,15,35,39,43,47] +; AVX512DQ-BW-NEXT: vpermi2w %zmm2, %zmm0, %zmm1 +; AVX512DQ-BW-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512DQ-BW-NEXT: vzeroupper ; AVX512DQ-BW-NEXT: retq ; @@ -840,10 +837,9 @@ define void @store_i16_stride8_vf4(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] ; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 ; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,16,20,24,28,1,5,9,13,17,21,25,29,2,6,10,14,18,22,26,30,3,7,11,15,19,23,27,31] -; AVX512DQ-BW-FCP-NEXT: vpermw %zmm0, %zmm1, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm0, (%rax) +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [0,4,8,12,32,36,40,44,1,5,9,13,33,37,41,45,2,6,10,14,34,38,42,46,3,7,11,15,35,39,43,47] +; AVX512DQ-BW-FCP-NEXT: vpermi2w %zmm2, %zmm0, %zmm1 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512DQ-BW-FCP-NEXT: vzeroupper ; AVX512DQ-BW-FCP-NEXT: retq %in.vec0 = load <4 x i16>, ptr %in.vecptr0, align 64 diff --git a/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-7.ll b/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-7.ll index 837d990596a5..45a76599d3e9 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-7.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-7.ll @@ -227,9 +227,8 @@ define void @store_i32_stride7_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 ; AVX512-FCP-NEXT: vpmovsxbq {{.*#+}} ymm1 = [0,2,4,0] ; AVX512-FCP-NEXT: vpermi2q %ymm3, %ymm0, %ymm1 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm0 -; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,8,10,12,1,3,5,7,9,11,13,0,0] -; AVX512-FCP-NEXT: vpermd %zmm0, %zmm1, %zmm0 +; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} zmm0 = [0,2,4,6,16,18,20,1,3,5,7,17,19,21,0,0] +; AVX512-FCP-NEXT: vpermi2d %zmm1, %zmm2, %zmm0 ; AVX512-FCP-NEXT: vextracti32x4 $2, %zmm0, 32(%rax) ; AVX512-FCP-NEXT: vextracti32x4 $3, %zmm0, %xmm1 ; AVX512-FCP-NEXT: vmovq %xmm1, 48(%rax) @@ -279,9 +278,8 @@ define void @store_i32_stride7_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 ; AVX512DQ-FCP-NEXT: vpmovsxbq {{.*#+}} ymm1 = [0,2,4,0] ; AVX512DQ-FCP-NEXT: vpermi2q %ymm3, %ymm0, %ymm1 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm0 -; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,8,10,12,1,3,5,7,9,11,13,0,0] -; AVX512DQ-FCP-NEXT: vpermd %zmm0, %zmm1, %zmm0 +; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} zmm0 = [0,2,4,6,16,18,20,1,3,5,7,17,19,21,0,0] +; AVX512DQ-FCP-NEXT: vpermi2d %zmm1, %zmm2, %zmm0 ; AVX512DQ-FCP-NEXT: vextracti32x4 $2, %zmm0, 32(%rax) ; AVX512DQ-FCP-NEXT: vextracti32x4 $3, %zmm0, %xmm1 ; AVX512DQ-FCP-NEXT: vmovq %xmm1, 48(%rax) @@ -331,9 +329,8 @@ define void @store_i32_stride7_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 ; AVX512BW-FCP-NEXT: vpmovsxbq {{.*#+}} ymm1 = [0,2,4,0] ; AVX512BW-FCP-NEXT: vpermi2q %ymm3, %ymm0, %ymm1 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm0 -; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,8,10,12,1,3,5,7,9,11,13,0,0] -; AVX512BW-FCP-NEXT: vpermd %zmm0, %zmm1, %zmm0 +; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm0 = [0,2,4,6,16,18,20,1,3,5,7,17,19,21,0,0] +; AVX512BW-FCP-NEXT: vpermi2d %zmm1, %zmm2, %zmm0 ; AVX512BW-FCP-NEXT: vextracti32x4 $2, %zmm0, 32(%rax) ; AVX512BW-FCP-NEXT: vextracti32x4 $3, %zmm0, %xmm1 ; AVX512BW-FCP-NEXT: vmovq %xmm1, 48(%rax) @@ -383,9 +380,8 @@ define void @store_i32_stride7_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 ; AVX512DQ-BW-FCP-NEXT: vpmovsxbq {{.*#+}} ymm1 = [0,2,4,0] ; AVX512DQ-BW-FCP-NEXT: vpermi2q %ymm3, %ymm0, %ymm1 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,8,10,12,1,3,5,7,9,11,13,0,0] -; AVX512DQ-BW-FCP-NEXT: vpermd %zmm0, %zmm1, %zmm0 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm0 = [0,2,4,6,16,18,20,1,3,5,7,17,19,21,0,0] +; AVX512DQ-BW-FCP-NEXT: vpermi2d %zmm1, %zmm2, %zmm0 ; AVX512DQ-BW-FCP-NEXT: vextracti32x4 $2, %zmm0, 32(%rax) ; AVX512DQ-BW-FCP-NEXT: vextracti32x4 $3, %zmm0, %xmm1 ; AVX512DQ-BW-FCP-NEXT: vmovq %xmm1, 48(%rax) diff --git a/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-8.ll b/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-8.ll index 955927eb7691..265f6daeb200 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-8.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-store-i32-stride-8.ll @@ -160,24 +160,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512-NEXT: vmovaps %zmm0, (%rax) +; AVX512-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512-NEXT: vzeroupper ; AVX512-NEXT: retq ; @@ -186,24 +185,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512-FCP-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512-FCP-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512-FCP-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512-FCP-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512-FCP-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512-FCP-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512-FCP-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512-FCP-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512-FCP-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512-FCP-NEXT: vmovaps %zmm0, (%rax) +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512-FCP-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512-FCP-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512-FCP-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512-FCP-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512-FCP-NEXT: vzeroupper ; AVX512-FCP-NEXT: retq ; @@ -212,24 +210,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512DQ-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512DQ-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512DQ-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512DQ-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512DQ-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512DQ-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512DQ-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512DQ-NEXT: vmovaps %zmm0, (%rax) +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512DQ-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512DQ-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512DQ-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512DQ-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512DQ-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512DQ-NEXT: vzeroupper ; AVX512DQ-NEXT: retq ; @@ -238,24 +235,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512DQ-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512DQ-FCP-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512DQ-FCP-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512DQ-FCP-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512DQ-FCP-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512DQ-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512DQ-FCP-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512DQ-FCP-NEXT: vmovaps %zmm0, (%rax) +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-FCP-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512DQ-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512DQ-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512DQ-FCP-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512DQ-FCP-NEXT: vzeroupper ; AVX512DQ-FCP-NEXT: retq ; @@ -264,24 +260,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512BW-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512BW-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512BW-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512BW-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512BW-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512BW-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512BW-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512BW-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512BW-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512BW-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512BW-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512BW-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512BW-NEXT: vmovaps %zmm0, (%rax) +; AVX512BW-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512BW-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512BW-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512BW-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512BW-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512BW-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512BW-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512BW-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512BW-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512BW-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512BW-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512BW-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512BW-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512BW-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512BW-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512BW-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512BW-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512BW-NEXT: vzeroupper ; AVX512BW-NEXT: retq ; @@ -290,24 +285,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512BW-FCP-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512BW-FCP-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512BW-FCP-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512BW-FCP-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512BW-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512BW-FCP-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512BW-FCP-NEXT: vmovaps %zmm0, (%rax) +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512BW-FCP-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512BW-FCP-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512BW-FCP-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512BW-FCP-NEXT: vzeroupper ; AVX512BW-FCP-NEXT: retq ; @@ -316,24 +310,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-BW-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512DQ-BW-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512DQ-BW-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512DQ-BW-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512DQ-BW-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512DQ-BW-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512DQ-BW-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512DQ-BW-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512DQ-BW-NEXT: vmovaps %zmm0, (%rax) +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-BW-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-BW-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-BW-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-BW-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512DQ-BW-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512DQ-BW-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512DQ-BW-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512DQ-BW-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512DQ-BW-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512DQ-BW-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512DQ-BW-NEXT: vzeroupper ; AVX512DQ-BW-NEXT: retq ; @@ -342,24 +335,23 @@ define void @store_i32_stride8_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r10 ; AVX512DQ-BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r11 -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovlhps {{.*#+}} xmm0 = xmm1[0],xmm0[0] -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovlhps {{.*#+}} xmm1 = xmm2[0],xmm1[0] -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovlhps {{.*#+}} xmm2 = xmm3[0],xmm2[0] -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm3 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovsd {{.*#+}} xmm4 = mem[0],zero -; AVX512DQ-BW-FCP-NEXT: vmovlhps {{.*#+}} xmm3 = xmm4[0],xmm3[0] -; AVX512DQ-BW-FCP-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 -; AVX512DQ-BW-FCP-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 -; AVX512DQ-BW-FCP-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15] -; AVX512DQ-BW-FCP-NEXT: vpermps %zmm0, %zmm1, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vmovaps %zmm0, (%rax) +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm2 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm3[0],xmm2[0] +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm3 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vmovq {{.*#+}} xmm4 = mem[0],zero +; AVX512DQ-BW-FCP-NEXT: vpunpcklqdq {{.*#+}} xmm3 = xmm4[0],xmm3[0] +; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, %xmm3, %ymm2, %ymm2 +; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, %xmm1, %ymm0, %ymm0 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,2,4,6,16,18,20,22,1,3,5,7,17,19,21,23] +; AVX512DQ-BW-FCP-NEXT: vpermi2d %zmm2, %zmm0, %zmm1 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm1, (%rax) ; AVX512DQ-BW-FCP-NEXT: vzeroupper ; AVX512DQ-BW-FCP-NEXT: retq %in.vec0 = load <2 x i32>, ptr %in.vecptr0, align 64 diff --git a/llvm/test/CodeGen/X86/vector-interleaved-store-i64-stride-4.ll b/llvm/test/CodeGen/X86/vector-interleaved-store-i64-stride-4.ll index 38623c6ce0cb..ded7c002c873 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-store-i64-stride-4.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-store-i64-stride-4.ll @@ -94,105 +94,97 @@ define void @store_i64_stride4_vf2(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; ; AVX512-LABEL: store_i64_stride4_vf2: ; AVX512: # %bb.0: -; AVX512-NEXT: vmovaps (%rdi), %xmm0 -; AVX512-NEXT: vmovaps (%rdx), %xmm1 -; AVX512-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512-NEXT: vmovaps %zmm0, (%r8) +; AVX512-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512-NEXT: vzeroupper ; AVX512-NEXT: retq ; ; AVX512-FCP-LABEL: store_i64_stride4_vf2: ; AVX512-FCP: # %bb.0: -; AVX512-FCP-NEXT: vmovaps (%rdi), %xmm0 -; AVX512-FCP-NEXT: vmovaps (%rdx), %xmm1 -; AVX512-FCP-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512-FCP-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512-FCP-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512-FCP-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512-FCP-NEXT: vmovaps %zmm0, (%r8) +; AVX512-FCP-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512-FCP-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512-FCP-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512-FCP-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512-FCP-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512-FCP-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512-FCP-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512-FCP-NEXT: vzeroupper ; AVX512-FCP-NEXT: retq ; ; AVX512DQ-LABEL: store_i64_stride4_vf2: ; AVX512DQ: # %bb.0: -; AVX512DQ-NEXT: vmovaps (%rdi), %xmm0 -; AVX512DQ-NEXT: vmovaps (%rdx), %xmm1 -; AVX512DQ-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512DQ-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512DQ-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512DQ-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512DQ-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512DQ-NEXT: vmovaps %zmm0, (%r8) +; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512DQ-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512DQ-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512DQ-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512DQ-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512DQ-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512DQ-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512DQ-NEXT: vzeroupper ; AVX512DQ-NEXT: retq ; ; AVX512DQ-FCP-LABEL: store_i64_stride4_vf2: ; AVX512DQ-FCP: # %bb.0: -; AVX512DQ-FCP-NEXT: vmovaps (%rdi), %xmm0 -; AVX512DQ-FCP-NEXT: vmovaps (%rdx), %xmm1 -; AVX512DQ-FCP-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512DQ-FCP-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512DQ-FCP-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512DQ-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512DQ-FCP-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512DQ-FCP-NEXT: vmovaps %zmm0, (%r8) +; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512DQ-FCP-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512DQ-FCP-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512DQ-FCP-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512DQ-FCP-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512DQ-FCP-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512DQ-FCP-NEXT: vzeroupper ; AVX512DQ-FCP-NEXT: retq ; ; AVX512BW-LABEL: store_i64_stride4_vf2: ; AVX512BW: # %bb.0: -; AVX512BW-NEXT: vmovaps (%rdi), %xmm0 -; AVX512BW-NEXT: vmovaps (%rdx), %xmm1 -; AVX512BW-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512BW-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512BW-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512BW-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512BW-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512BW-NEXT: vmovaps %zmm0, (%r8) +; AVX512BW-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512BW-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512BW-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512BW-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512BW-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512BW-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512BW-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512BW-NEXT: vzeroupper ; AVX512BW-NEXT: retq ; ; AVX512BW-FCP-LABEL: store_i64_stride4_vf2: ; AVX512BW-FCP: # %bb.0: -; AVX512BW-FCP-NEXT: vmovaps (%rdi), %xmm0 -; AVX512BW-FCP-NEXT: vmovaps (%rdx), %xmm1 -; AVX512BW-FCP-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512BW-FCP-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512BW-FCP-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512BW-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512BW-FCP-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512BW-FCP-NEXT: vmovaps %zmm0, (%r8) +; AVX512BW-FCP-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512BW-FCP-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512BW-FCP-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512BW-FCP-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512BW-FCP-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512BW-FCP-NEXT: vzeroupper ; AVX512BW-FCP-NEXT: retq ; ; AVX512DQ-BW-LABEL: store_i64_stride4_vf2: ; AVX512DQ-BW: # %bb.0: -; AVX512DQ-BW-NEXT: vmovaps (%rdi), %xmm0 -; AVX512DQ-BW-NEXT: vmovaps (%rdx), %xmm1 -; AVX512DQ-BW-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512DQ-BW-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512DQ-BW-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512DQ-BW-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512DQ-BW-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512DQ-BW-NEXT: vmovaps %zmm0, (%r8) +; AVX512DQ-BW-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512DQ-BW-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512DQ-BW-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512DQ-BW-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512DQ-BW-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512DQ-BW-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512DQ-BW-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512DQ-BW-NEXT: vzeroupper ; AVX512DQ-BW-NEXT: retq ; ; AVX512DQ-BW-FCP-LABEL: store_i64_stride4_vf2: ; AVX512DQ-BW-FCP: # %bb.0: -; AVX512DQ-BW-FCP-NEXT: vmovaps (%rdi), %xmm0 -; AVX512DQ-BW-FCP-NEXT: vmovaps (%rdx), %xmm1 -; AVX512DQ-BW-FCP-NEXT: vinsertf128 $1, (%rcx), %ymm1, %ymm1 -; AVX512DQ-BW-FCP-NEXT: vinsertf128 $1, (%rsi), %ymm0, %ymm0 -; AVX512DQ-BW-FCP-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vmovaps {{.*#+}} zmm1 = [0,2,4,6,1,3,5,7] -; AVX512DQ-BW-FCP-NEXT: vpermpd %zmm0, %zmm1, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vmovaps %zmm0, (%r8) +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %xmm1 +; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, (%rcx), %ymm1, %ymm1 +; AVX512DQ-BW-FCP-NEXT: vinserti128 $1, (%rsi), %ymm0, %ymm0 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbq {{.*#+}} zmm2 = [0,2,8,10,1,3,9,11] +; AVX512DQ-BW-FCP-NEXT: vpermi2q %zmm1, %zmm0, %zmm2 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm2, (%r8) ; AVX512DQ-BW-FCP-NEXT: vzeroupper ; AVX512DQ-BW-FCP-NEXT: retq %in.vec0 = load <2 x i64>, ptr %in.vecptr0, align 64 -- GitLab From f1ca2a09671e4d4acc2bea362b39268ed7883b6d Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 12 Mar 2024 10:56:14 -0700 Subject: [PATCH 280/953] [ELF] Add --compress-section to compress matched non-SHF_ALLOC sections --compress-sections =[none|zlib|zstd] is similar to --compress-debug-sections but applies to broader sections without the SHF_ALLOC flag. lld will report an error if a SHF_ALLOC section is matched. An interesting use case is to compress `.strtab`/`.symtab`, which consume a significant portion of the file size (15.1% for a release build of Clang). An older revision is available at https://reviews.llvm.org/D154641 . This patch focuses on non-allocated sections for safety. Moving `maybeCompress` as D154641 does not handle STT_SECTION symbols for `-r --compress-debug-sections=zlib` (see `relocatable-section-symbol.s` from #66804). Since different output sections may use different compression algorithms, we need CompressedData::type to generalize config->compressDebugSections. GNU ld feature request: https://sourceware.org/bugzilla/show_bug.cgi?id=27452 Link: https://discourse.llvm.org/t/rfc-compress-arbitrary-sections-with-ld-lld-compress-sections/71674 Pull Request: https://github.com/llvm/llvm-project/pull/84855 --- lld/ELF/Config.h | 4 +- lld/ELF/Driver.cpp | 24 ++++- lld/ELF/Options.td | 4 + lld/ELF/OutputSections.cpp | 43 ++++++--- lld/ELF/OutputSections.h | 8 +- lld/docs/ReleaseNotes.rst | 4 + lld/docs/ld.lld.1 | 4 + lld/test/ELF/compress-sections-err.s | 3 + lld/test/ELF/compress-sections-special.s | 31 +++++++ lld/test/ELF/compress-sections.s | 91 +++++++++++++++++++ lld/test/ELF/linkerscript/compress-sections.s | 62 +++++++++++++ 11 files changed, 259 insertions(+), 19 deletions(-) create mode 100644 lld/test/ELF/compress-sections-special.s create mode 100644 lld/test/ELF/compress-sections.s create mode 100644 lld/test/ELF/linkerscript/compress-sections.s diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 691ebfc07432..9ae01eb90fa4 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -222,7 +222,9 @@ struct Config { CGProfileSortKind callGraphProfileSort; bool checkSections; bool checkDynamicRelocs; - llvm::DebugCompressionType compressDebugSections; + std::optional compressDebugSections; + llvm::SmallVector, 0> + compressSections; bool cref; llvm::SmallVector, 0> deadRelocInNonAlloc; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index de4b2e345ac9..2439d141fb66 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1224,9 +1224,10 @@ static void readConfigs(opt::InputArgList &args) { config->checkSections = args.hasFlag(OPT_check_sections, OPT_no_check_sections, true); config->chroot = args.getLastArgValue(OPT_chroot); - config->compressDebugSections = getCompressionType( - args.getLastArgValue(OPT_compress_debug_sections, "none"), - "--compress-debug-sections"); + if (auto *arg = args.getLastArg(OPT_compress_debug_sections)) { + config->compressDebugSections = + getCompressionType(arg->getValue(), "--compress-debug-sections"); + } config->cref = args.hasArg(OPT_cref); config->optimizeBBJumps = args.hasFlag(OPT_optimize_bb_jumps, OPT_no_optimize_bb_jumps, false); @@ -1516,6 +1517,23 @@ static void readConfigs(opt::InputArgList &args) { } } + for (opt::Arg *arg : args.filtered(OPT_compress_sections)) { + SmallVector fields; + StringRef(arg->getValue()).split(fields, '='); + if (fields.size() != 2 || fields[1].empty()) { + error(arg->getSpelling() + + ": parse error, not 'section-glob=[none|zlib|zstd]'"); + continue; + } + auto type = getCompressionType(fields[1], arg->getSpelling()); + if (Expected pat = GlobPattern::create(fields[0])) { + config->compressSections.emplace_back(std::move(*pat), type); + } else { + error(arg->getSpelling() + ": " + toString(pat.takeError())); + continue; + } + } + for (opt::Arg *arg : args.filtered(OPT_z)) { std::pair option = StringRef(arg->getValue()).split('='); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index c10a73e2d9c3..3819b86238ea 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -67,6 +67,10 @@ defm compress_debug_sections: Eq<"compress-debug-sections", "Compress DWARF debug sections">, MetaVarName<"[none,zlib,zstd]">; +defm compress_sections: EEq<"compress-sections", + "Compress non-SHF_ALLOC output sections matching ">, + MetaVarName<"=[none|zlib|zstd]">; + defm defsym: Eq<"defsym", "Define a symbol alias">, MetaVarName<"=">; defm optimize_bb_jumps: BB<"optimize-bb-jumps", diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index ee9374186787..55e6a14f103e 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -326,17 +326,30 @@ static SmallVector deflateShard(ArrayRef in, int level, } #endif -// Compress section contents if this section contains debug info. +// Compress certain non-SHF_ALLOC sections: +// +// * (if --compress-debug-sections is specified) non-empty .debug_* sections +// * (if --compress-sections is specified) matched sections template void OutputSection::maybeCompress() { using Elf_Chdr = typename ELFT::Chdr; (void)sizeof(Elf_Chdr); - // Compress only DWARF debug sections. - if (config->compressDebugSections == DebugCompressionType::None || - (flags & SHF_ALLOC) || !name.starts_with(".debug_") || size == 0) + DebugCompressionType ctype = DebugCompressionType::None; + for (auto &[glob, t] : config->compressSections) + if (glob.match(name)) + ctype = t; + if (!(flags & SHF_ALLOC) && config->compressDebugSections && + name.starts_with(".debug_") && size) + ctype = *config->compressDebugSections; + if (ctype == DebugCompressionType::None) + return; + if (flags & SHF_ALLOC) { + errorOrWarn("--compress-sections: section '" + name + + "' with the SHF_ALLOC flag cannot be compressed"); return; + } - llvm::TimeTraceScope timeScope("Compress debug sections"); + llvm::TimeTraceScope timeScope("Compress sections"); compressed.uncompressedSize = size; auto buf = std::make_unique(size); // Write uncompressed data to a temporary zero-initialized buffer. @@ -344,14 +357,21 @@ template void OutputSection::maybeCompress() { parallel::TaskGroup tg; writeTo(buf.get(), tg); } + // The generic ABI specifies "The sh_size and sh_addralign fields of the + // section header for a compressed section reflect the requirements of the + // compressed section." However, 1-byte alignment has been wildly accepted + // and utilized for a long time. Removing alignment padding is particularly + // useful when there are many compressed output sections. + addralign = 1; #if LLVM_ENABLE_ZSTD // Use ZSTD's streaming compression API which permits parallel workers working // on the stream. See http://facebook.github.io/zstd/zstd_manual.html // "Streaming compression - HowTo". - if (config->compressDebugSections == DebugCompressionType::Zstd) { + if (ctype == DebugCompressionType::Zstd) { // Allocate a buffer of half of the input size, and grow it by 1.5x if // insufficient. + compressed.type = ELFCOMPRESS_ZSTD; compressed.shards = std::make_unique[]>(1); SmallVector &out = compressed.shards[0]; out.resize_for_overwrite(std::max(size / 2, 32)); @@ -424,6 +444,7 @@ template void OutputSection::maybeCompress() { } size += 4; // checksum + compressed.type = ELFCOMPRESS_ZLIB; compressed.shards = std::move(shardsOut); compressed.numShards = numShards; compressed.checksum = checksum; @@ -450,20 +471,18 @@ void OutputSection::writeTo(uint8_t *buf, parallel::TaskGroup &tg) { if (type == SHT_NOBITS) return; - // If --compress-debug-section is specified and if this is a debug section, - // we've already compressed section contents. If that's the case, - // just write it down. + // If the section is compressed due to + // --compress-debug-section/--compress-sections, the content is already known. if (compressed.shards) { auto *chdr = reinterpret_cast(buf); + chdr->ch_type = compressed.type; chdr->ch_size = compressed.uncompressedSize; chdr->ch_addralign = addralign; buf += sizeof(*chdr); - if (config->compressDebugSections == DebugCompressionType::Zstd) { - chdr->ch_type = ELFCOMPRESS_ZSTD; + if (compressed.type == ELFCOMPRESS_ZSTD) { memcpy(buf, compressed.shards[0].data(), compressed.shards[0].size()); return; } - chdr->ch_type = ELFCOMPRESS_ZLIB; // Compute shard offsets. auto offsets = std::make_unique(compressed.numShards); diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index c7931471a6ed..421a0181feb5 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -23,6 +23,7 @@ struct PhdrEntry; struct CompressedData { std::unique_ptr[]> shards; + uint32_t type = 0; uint32_t numShards = 0; uint32_t checksum = 0; uint64_t uncompressedSize; @@ -116,12 +117,13 @@ public: void sortInitFini(); void sortCtorsDtors(); + // Used for implementation of --compress-debug-sections and + // --compress-sections. + CompressedData compressed; + private: SmallVector storage; - // Used for implementation of --compress-debug-sections option. - CompressedData compressed; - std::array getFiller(); }; diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index 6f60efd87c97..97ed06048910 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -26,6 +26,10 @@ Non-comprehensive list of changes in this release ELF Improvements ---------------- +* ``--compress-sections =[none|zlib|zstd]`` is added to compress + matched output sections without the ``SHF_ALLOC`` flag. + (`#84855 `_) + Breaking changes ---------------- diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 index e4d39e47f5c5..e759776c8d55 100644 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -164,6 +164,10 @@ to set the compression level to 6. The compression level is 5. .El .Pp +.It Fl -compress-sections Ns = Ns Ar section-glob=[none|zlib|zstd] +Compress output sections that match the glob and do not have the SHF_ALLOC flag. +This is like a generalized +.Cm --compress-debug-sections. .It Fl -cref Output cross reference table. If .Fl Map diff --git a/lld/test/ELF/compress-sections-err.s b/lld/test/ELF/compress-sections-err.s index 097803807083..1b46aea12e9c 100644 --- a/lld/test/ELF/compress-sections-err.s +++ b/lld/test/ELF/compress-sections-err.s @@ -5,8 +5,11 @@ # RUN: ld.lld %t.o --compress-debug-sections=zlib --compress-debug-sections=none -o /dev/null 2>&1 | count 0 # RUN: not ld.lld %t.o --compress-debug-sections=zlib -o /dev/null 2>&1 | \ # RUN: FileCheck %s --implicit-check-not=error: +# RUN: not ld.lld %t.o --compress-sections=foo=zlib -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=CHECK2 --implicit-check-not=error: # CHECK: error: --compress-debug-sections: LLVM was not built with LLVM_ENABLE_ZLIB or did not find zlib at build time +# CHECK2: error: --compress-sections: LLVM was not built with LLVM_ENABLE_ZLIB or did not find zlib at build time .globl _start _start: diff --git a/lld/test/ELF/compress-sections-special.s b/lld/test/ELF/compress-sections-special.s new file mode 100644 index 000000000000..80c61fe626a4 --- /dev/null +++ b/lld/test/ELF/compress-sections-special.s @@ -0,0 +1,31 @@ +# REQUIRES: x86, zlib + +# RUN: rm -rf %t && mkdir %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o a.o +# RUN: ld.lld -pie a.o --compress-sections .strtab=zlib --compress-sections .symtab=zlib -o out +# RUN: llvm-readelf -Ss -x .strtab out 2>&1 | FileCheck %s + +# CHECK: nonalloc0 PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 1 +# CHECK: .symtab SYMTAB 0000000000000000 [[#%x,]] [[#%x,]] 18 C 12 3 1 +# CHECK-NEXT: .shstrtab STRTAB 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 1 +# CHECK-NEXT: .strtab STRTAB 0000000000000000 [[#%x,]] [[#%x,]] 00 C 0 0 1 + +## TODO Add compressed SHT_STRTAB/SHT_SYMTAB support to llvm-readelf +# CHECK: warning: {{.*}}: unable to get the string table for the SHT_SYMTAB section: SHT_STRTAB string table section + +# CHECK: Hex dump of section '.strtab': +# CHECK-NEXT: 01000000 00000000 1a000000 00000000 +# CHECK-NEXT: 01000000 00000000 {{.*}} + +# RUN: not ld.lld -shared a.o --compress-sections .dynstr=zlib 2>&1 | FileCheck %s --check-prefix=ERR-ALLOC +# ERR-ALLOC: error: --compress-sections: section '.dynstr' with the SHF_ALLOC flag cannot be compressed + +.globl _start, g0, g1 +_start: +l0: +g0: +g1: + +.section nonalloc0,"" +.quad .text+1 +.quad .text+2 diff --git a/lld/test/ELF/compress-sections.s b/lld/test/ELF/compress-sections.s new file mode 100644 index 000000000000..59b5408c9624 --- /dev/null +++ b/lld/test/ELF/compress-sections.s @@ -0,0 +1,91 @@ +# REQUIRES: x86, zlib, zstd + +# RUN: rm -rf %t && mkdir %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o a.o +# RUN: ld.lld -pie a.o -o out --compress-sections '*0=zlib' --compress-sections '*0=none' --compress-sections 'nomatch=none' +# RUN: llvm-readelf -SrsX out | FileCheck %s --check-prefix=CHECK1 + +# CHECK1: Name Type Address Off Size ES Flg Lk Inf Al +# CHECK1: foo0 PROGBITS [[#%x,FOO0:]] [[#%x,]] [[#%x,]] 00 A 0 0 8 +# CHECK1-NEXT: foo1 PROGBITS [[#%x,FOO1:]] [[#%x,]] [[#%x,]] 00 A 0 0 8 +# CHECK1-NEXT: .text PROGBITS [[#%x,TEXT:]] [[#%x,]] [[#%x,]] 00 AX 0 0 4 +# CHECK1: nonalloc0 PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 8 +# CHECK1-NEXT: nonalloc1 PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 8 +# CHECK1-NEXT: .debug_str PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 01 MS 0 0 1 + +# CHECK1: 0000000000000010 0 NOTYPE LOCAL DEFAULT [[#]] (nonalloc0) sym0 +# CHECK1: 0000000000000008 0 NOTYPE LOCAL DEFAULT [[#]] (nonalloc1) sym1 + +# RUN: ld.lld -pie a.o --compress-sections '*c0=zlib' --compress-sections .debug_str=zstd -o out2 +# RUN: llvm-readelf -SrsX -x nonalloc0 -x .debug_str out2 | FileCheck %s --check-prefix=CHECK2 + +# CHECK2: Name Type Address Off Size ES Flg Lk Inf Al +# CHECK2: foo0 PROGBITS [[#%x,FOO0:]] [[#%x,]] [[#%x,]] 00 A 0 0 8 +# CHECK2-NEXT: foo1 PROGBITS [[#%x,FOO1:]] [[#%x,]] [[#%x,]] 00 A 0 0 8 +# CHECK2-NEXT: .text PROGBITS [[#%x,TEXT:]] [[#%x,]] [[#%x,]] 00 AX 0 0 4 +# CHECK2: nonalloc0 PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 C 0 0 1 +# CHECK2-NEXT: nonalloc1 PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 8 +# CHECK2-NEXT: .debug_str PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 01 MSC 0 0 1 + +# CHECK2: 0000000000000010 0 NOTYPE LOCAL DEFAULT [[#]] (nonalloc0) sym0 +# CHECK2: 0000000000000008 0 NOTYPE LOCAL DEFAULT [[#]] (nonalloc1) sym1 + +# CHECK2: Hex dump of section 'nonalloc0': +## zlib with ch_size=0x10 +# CHECK2-NEXT: 01000000 00000000 10000000 00000000 +# CHECK2-NEXT: 01000000 00000000 {{.*}} +# CHECK2: Hex dump of section '.debug_str': +## zstd with ch_size=0x38 +# CHECK2-NEXT: 02000000 00000000 38000000 00000000 +# CHECK2-NEXT: 01000000 00000000 {{.*}} + +## --compress-debug-sections=none takes precedence. +# RUN: ld.lld a.o --compress-debug-sections=none --compress-sections .debug_str=zstd -o out3 +# RUN: llvm-readelf -S out3 | FileCheck %s --check-prefix=CHECK3 + +# CHECK3: .debug_str PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 01 MS 0 0 1 + +# RUN: not ld.lld a.o --compress-sections '*0=zlib' 2>&1 | \ +# RUN: FileCheck %s --check-prefix=ERR-ALLOC --implicit-check-not=error: +# ERR-ALLOC: error: --compress-sections: section 'foo0' with the SHF_ALLOC flag cannot be compressed + +# RUN: not ld.lld --compress-sections=foo a.o 2>&1 | \ +# RUN: FileCheck %s --check-prefix=ERR1 --implicit-check-not=error: +# ERR1: error: --compress-sections: parse error, not 'section-glob=[none|zlib|zstd]' + +# RUN: not ld.lld --compress-sections 'a[=zlib' a.o 2>&1 | \ +# RUN: FileCheck %s --check-prefix=ERR2 --implicit-check-not=error: +# ERR2: error: --compress-sections: invalid glob pattern, unmatched '[' + +# RUN: not ld.lld a.o --compress-sections='.debug*=zlib-gabi' --compress-sections='.debug*=' 2>&1 | \ +# RUN: FileCheck -check-prefix=ERR3 %s +# ERR3: unknown --compress-sections value: zlib-gabi +# ERR3-NEXT: --compress-sections: parse error, not 'section-glob=[none|zlib|zstd]' + +.globl _start +_start: + ret + +.section foo0,"a" +.balign 8 +.quad .text-. +.quad .text-. +.section foo1,"a" +.balign 8 +.quad .text-. +.quad .text-. +.section nonalloc0,"" +.balign 8 +.quad .text+1 +.quad .text+2 +sym0: +.section nonalloc1,"" +.balign 8 +.quad 42 +sym1: + +.section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "AAAAAAAAAAAAAAAAAAAAAAAAAAA" +.Linfo_string1: + .asciz "BBBBBBBBBBBBBBBBBBBBBBBBBBB" diff --git a/lld/test/ELF/linkerscript/compress-sections.s b/lld/test/ELF/linkerscript/compress-sections.s new file mode 100644 index 000000000000..9b4574a1778c --- /dev/null +++ b/lld/test/ELF/linkerscript/compress-sections.s @@ -0,0 +1,62 @@ +# REQUIRES: x86, zlib + +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o +# RUN: ld.lld -T a.lds a.o --compress-sections nonalloc=zlib --compress-sections str=zlib -o out +# RUN: llvm-readelf -SsXz -p str out | FileCheck %s + +# CHECK: Name Type Address Off Size ES Flg Lk Inf Al +# CHECK: nonalloc PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 C 0 0 1 +# CHECK-NEXT: str PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 01 MSC 0 0 1 + +# CHECK: 0000000000000000 0 NOTYPE GLOBAL DEFAULT [[#]] (nonalloc) nonalloc_start +# CHECK: 0000000000000023 0 NOTYPE GLOBAL DEFAULT [[#]] (nonalloc) nonalloc_end +# CHECK: String dump of section 'str': +# CHECK-NEXT: [ 0] AAA +# CHECK-NEXT: [ 4] BBB + +## TODO The uncompressed size of 'nonalloc' is dependent on linker script +## commands, which is not handled. We should report an error. +# RUN: ld.lld -T b.lds a.o --compress-sections nonalloc=zlib + +#--- a.s +.globl _start +_start: + ret + +.section nonalloc0,"" +.balign 8 +.quad .text +.quad .text +.section nonalloc1,"" +.balign 8 +.quad 42 + +.section str,"MS",@progbits,1 + .asciz "AAA" + .asciz "BBB" + +#--- a.lds +SECTIONS { + .text : { *(.text) } + c = SIZEOF(.text); + b = c+1; + a = b+1; + nonalloc : { + nonalloc_start = .; +## In general, using data commands is error-prone. This case is correct, though. + *(nonalloc*) QUAD(SIZEOF(.text)) + . += a; + nonalloc_end = .; + } + str : { *(str) } +} + +#--- b.lds +SECTIONS { + nonalloc : { *(nonalloc*) . += a; } + .text : { *(.text) } + a = b+1; + b = c+1; + c = SIZEOF(.text); +} -- GitLab From 536e0ebaaa842471ae91bbda4f8cc1821690861e Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Tue, 12 Mar 2024 11:06:23 -0700 Subject: [PATCH 281/953] Remove XFAIL from tests passing on green dragon --- .../debuginfo-tests/llgdb-tests/static-member-2.cpp | 1 - .../debuginfo-tests/llgdb-tests/static-member.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp index 3f11ae018fc8..5b6647c0631c 100644 --- a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp +++ b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp @@ -2,7 +2,6 @@ // RUN: %clangxx %target_itanium_abi_host_triple %t -o %t.out // RUN: %test_debuginfo %s %t.out // XFAIL: gdb-clang-incompatibility -// XFAIL: system-darwin // DEBUGGER: delete breakpoints // DEBUGGER: break static-member.cpp:33 diff --git a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp index 57316dfd6404..29dd84dc8325 100644 --- a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp +++ b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp @@ -2,7 +2,6 @@ // RUN: %clangxx %target_itanium_abi_host_triple %t -o %t.out // RUN: %test_debuginfo %s %t.out // XFAIL: !system-darwin && gdb-clang-incompatibility -// XFAIL: system-darwin // DEBUGGER: delete breakpoints // DEBUGGER: break static-member.cpp:33 // DEBUGGER: r -- GitLab From 42ecccfe346daf342b6c46a6a471ba5ed99b1139 Mon Sep 17 00:00:00 2001 From: amilendra Date: Tue, 12 Mar 2024 18:17:13 +0000 Subject: [PATCH 282/953] [libcxx] Fix incorrect type in the has-1024-bit-atomics feature test (#84904) --- libcxx/utils/libcxx/test/features.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py index 4fd8798b794a..872bff372b3d 100644 --- a/libcxx/utils/libcxx/test/features.py +++ b/libcxx/utils/libcxx/test/features.py @@ -176,7 +176,7 @@ DEFAULT_FEATURES = [ cfg, """ #include - struct Large { int storage[1024/8]; }; + struct Large { char storage[1024/8]; }; std::atomic x; int main(int, char**) { (void)x.load(); (void)x.is_lock_free(); return 0; } """, -- GitLab From a843f26a77dee7900891b6748d43cf8d4e423bfe Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Tue, 12 Mar 2024 11:25:12 -0700 Subject: [PATCH 283/953] [NFC] SLVectorizer comparator refactoring that preserves behavior (#84966) Spinning off from #79321 / 35f4592 - looked like the comparator could be simplified & made more clear/less risk of leaving hidden bugs. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 87 +++++++++---------- 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 7b99c3ac8c55..6ef46e3c5258 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -16614,36 +16614,11 @@ bool SLPVectorizerPass::vectorizeChainsInBlock(BasicBlock *BB, BoUpSLP &R) { if (Opcodes1.size() > Opcodes2.size()) return false; for (int I = 0, E = Opcodes1.size(); I < E; ++I) { - // Undefs are compatible with any other value. - if (isa(Opcodes1[I]) || isa(Opcodes2[I])) { - if (isa(Opcodes1[I]) && isa(Opcodes2[I])) - continue; - if (isa(Opcodes1[I])) { - assert(isa(Opcodes2[I]) && "Expected 2nd undef value"); - return true; - } - if (isa(Opcodes2[I])) { - assert(isa(Opcodes1[I]) && "Expected 1st undef value"); - return false; - } - if (isa(Opcodes1[I]) && !isa(Opcodes1[I])) { - assert(isa(Opcodes2[I]) && "Expected 2nd undef value"); - return true; - } - if (isa(Opcodes2[I]) && !isa(Opcodes2[I])) { - assert(isa(Opcodes1[I]) && "Expected 1st undef value"); - return false; - } - if (!isa(Opcodes2[I])) { - assert(isa(Opcodes1[I]) && "Expected 1st undef value"); - return false; - } - assert(!isa(Opcodes1[I]) && isa(Opcodes2[I]) && - "Expected 1st non-undef and 2nd undef value"); - return true; - } - if (auto *I1 = dyn_cast(Opcodes1[I])) - if (auto *I2 = dyn_cast(Opcodes2[I])) { + { + // Instructions come first. + auto *I1 = dyn_cast(Opcodes1[I]); + auto *I2 = dyn_cast(Opcodes2[I]); + if (I1 && I2) { DomTreeNodeBase *NodeI1 = DT->getNode(I1->getParent()); DomTreeNodeBase *NodeI2 = DT->getNode(I2->getParent()); if (!NodeI1) @@ -16660,20 +16635,44 @@ bool SLPVectorizerPass::vectorizeChainsInBlock(BasicBlock *BB, BoUpSLP &R) { continue; return I1->getOpcode() < I2->getOpcode(); } - if (isa(Opcodes1[I]) && isa(Opcodes2[I])) - continue; - if (isa(Opcodes1[I]) && !isa(Opcodes2[I])) - return true; - if (!isa(Opcodes1[I]) && isa(Opcodes2[I])) - return false; - if (isa(Opcodes1[I]) && !isa(Opcodes2[I])) - return true; - if (!isa(Opcodes1[I]) && isa(Opcodes2[I])) - return false; - if (Opcodes1[I]->getValueID() < Opcodes2[I]->getValueID()) - return true; - if (Opcodes1[I]->getValueID() > Opcodes2[I]->getValueID()) - return false; + if (I1) + return true; + if (I2) + return false; + } + { + // Non-undef constants come next. + bool C1 = isa(Opcodes1[I]) && !isa(Opcodes1[I]); + bool C2 = isa(Opcodes2[I]) && !isa(Opcodes2[I]); + if (C1 && C2) + continue; + if (C1) + return true; + if (C2) + return false; + } + bool U1 = isa(Opcodes1[I]); + bool U2 = isa(Opcodes2[I]); + { + // Non-constant non-instructions come next. + if (!U1 && !U2) { + auto ValID1 = Opcodes1[I]->getValueID(); + auto ValID2 = Opcodes2[I]->getValueID(); + if (ValID1 == ValID2) + continue; + if (ValID1 < ValID2) + return true; + if (ValID1 > ValID2) + return false; + } + if (!U1) + return true; + if (!U2) + return false; + } + // Undefs come last. + assert(U1 && U2); + continue; } return false; }; -- GitLab From 377da51546b2f514c3e90fca351004a2cf3f1eed Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Mon, 11 Mar 2024 22:52:20 -0500 Subject: [PATCH 284/953] [InstCombine] Add test for detecting `(x ^ -x)` as a ~Mask; NFC --- .../InstCombine/icmp-and-lowbit-mask.ll | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll index 640a95b05616..903d70685ab5 100644 --- a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll +++ b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll @@ -453,6 +453,25 @@ define i1 @src_is_notmask_shl(i8 %x_in, i8 %y, i1 %cond) { ret i1 %r } +define i1 @src_is_notmask_x_xor_neg_x(i8 %x_in, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_is_notmask_x_xor_neg_x( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[NEG_Y:%.*]] = sub i8 0, [[Y:%.*]] +; CHECK-NEXT: [[NOTMASK0:%.*]] = xor i8 [[NEG_Y]], [[Y]] +; CHECK-NEXT: [[NOTMASK:%.*]] = select i1 [[COND:%.*]], i8 [[NOTMASK0]], i8 -8 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %neg_y = sub i8 0, %y + %nmask0 = xor i8 %y, %neg_y + %notmask = select i1 %cond, i8 %nmask0, i8 -8 + %and = and i8 %x, %notmask + %r = icmp eq i8 %and, 0 + ret i1 %r +} + define i1 @src_is_notmask_shl_fail_multiuse_invert(i8 %x_in, i8 %y, i1 %cond) { ; CHECK-LABEL: @src_is_notmask_shl_fail_multiuse_invert( ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 122 -- GitLab From 5ca325e49cedee2aa5e80581ba95dcab56292c32 Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Mon, 11 Mar 2024 22:52:29 -0500 Subject: [PATCH 285/953] [InstCombine] Detect `(x ^ -x)` as a ~Mask Proof: https://alive2.llvm.org/ce/z/TAFmPw This is a lemma for clearing up some of the regressions that #84688 causes. Closes #84868 --- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 7 +++++-- llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll | 7 +++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index e71f3e113b96..0dce0077bf15 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4113,9 +4113,12 @@ static bool isMaskOrZero(const Value *V, bool Not, const SimplifyQuery &Q, if (match(V, m_Not(m_Value(X)))) return isMaskOrZero(X, !Not, Q, Depth); + // (X ^ -X) is a ~Mask + if (Not) + return match(V, m_c_Xor(m_Value(X), m_Neg(m_Deferred(X)))); // (X ^ (X - 1)) is a Mask - return !Not && - match(V, m_c_Xor(m_Value(X), m_Add(m_Deferred(X), m_AllOnes()))); + else + return match(V, m_c_Xor(m_Value(X), m_Add(m_Deferred(X), m_AllOnes()))); case Instruction::Select: // c ? Mask0 : Mask1 is a Mask. return isMaskOrZero(I->getOperand(1), Not, Q, Depth) && diff --git a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll index 903d70685ab5..070609228958 100644 --- a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll +++ b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll @@ -456,11 +456,10 @@ define i1 @src_is_notmask_shl(i8 %x_in, i8 %y, i1 %cond) { define i1 @src_is_notmask_x_xor_neg_x(i8 %x_in, i8 %y, i1 %cond) { ; CHECK-LABEL: @src_is_notmask_x_xor_neg_x( ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 -; CHECK-NEXT: [[NEG_Y:%.*]] = sub i8 0, [[Y:%.*]] +; CHECK-NEXT: [[NEG_Y:%.*]] = add i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[NOTMASK0:%.*]] = xor i8 [[NEG_Y]], [[Y]] -; CHECK-NEXT: [[NOTMASK:%.*]] = select i1 [[COND:%.*]], i8 [[NOTMASK0]], i8 -8 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[COND:%.*]], i8 [[NOTMASK0]], i8 7 +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[TMP3]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 -- GitLab From 9ac03158987802706110ef465c4b6a7553cc4b86 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Tue, 12 Mar 2024 18:28:30 +0000 Subject: [PATCH 286/953] Add comment to assert from a843f26 --- llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 6ef46e3c5258..b8b67609d755 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -16671,7 +16671,7 @@ bool SLPVectorizerPass::vectorizeChainsInBlock(BasicBlock *BB, BoUpSLP &R) { return false; } // Undefs come last. - assert(U1 && U2); + assert(U1 && U2 && "The only thing left should be undef & undef."); continue; } return false; -- GitLab From f5334f5da5166ac26fb24ca44669b3d425f0d131 Mon Sep 17 00:00:00 2001 From: Jonathan Peyton Date: Tue, 12 Mar 2024 11:36:19 -0700 Subject: [PATCH 287/953] [OpenMP] Add debug checks for divide by zero (#83300) --- openmp/runtime/src/kmp_affinity.cpp | 2 ++ openmp/runtime/src/kmp_sched.cpp | 23 ++++++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/openmp/runtime/src/kmp_affinity.cpp b/openmp/runtime/src/kmp_affinity.cpp index b79b57eafd6a..c3ee4de75a23 100644 --- a/openmp/runtime/src/kmp_affinity.cpp +++ b/openmp/runtime/src/kmp_affinity.cpp @@ -1777,6 +1777,8 @@ static bool __kmp_affinity_create_hwloc_map(kmp_i18n_id_t *const msg_id) { __kmp_nThreadsPerCore = __kmp_hwloc_get_nobjs_under_obj(o, HWLOC_OBJ_PU); else __kmp_nThreadsPerCore = 1; // no CORE found + if (__kmp_nThreadsPerCore == 0) + __kmp_nThreadsPerCore = 1; __kmp_ncores = __kmp_xproc / __kmp_nThreadsPerCore; if (nCoresPerPkg == 0) nCoresPerPkg = 1; // to prevent possible division by 0 diff --git a/openmp/runtime/src/kmp_sched.cpp b/openmp/runtime/src/kmp_sched.cpp index 53182bef5873..4d764e441f28 100644 --- a/openmp/runtime/src/kmp_sched.cpp +++ b/openmp/runtime/src/kmp_sched.cpp @@ -52,6 +52,7 @@ char const *traits_t::spec = "ld"; } else if (i > 0) { \ t = (u - l) / i + 1; \ } else { \ + KMP_DEBUG_ASSERT(i != 0); \ t = (l - u) / (-i) + 1; \ } \ KMP_COUNT_VALUE(stat, t); \ @@ -284,6 +285,7 @@ static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid, // upper-lower can exceed the limit of signed type trip_count = (UT)(*pupper - *plower) / incr + 1; } else { + KMP_DEBUG_ASSERT(incr != 0); trip_count = (UT)(*plower - *pupper) / (-incr) + 1; } @@ -318,6 +320,7 @@ static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid, if (plastiter != NULL) *plastiter = (tid == trip_count - 1); } else { + KMP_DEBUG_ASSERT(nth != 0); if (__kmp_static == kmp_sch_static_balanced) { UT small_chunk = trip_count / nth; UT extras = trip_count % nth; @@ -358,6 +361,7 @@ static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid, case kmp_sch_static_chunked: { ST span; UT nchunks; + KMP_DEBUG_ASSERT(chunk != 0); if (chunk < 1) chunk = 1; else if ((UT)chunk > trip_count) @@ -383,6 +387,7 @@ static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid, } case kmp_sch_static_balanced_chunked: { T old_upper = *pupper; + KMP_DEBUG_ASSERT(nth != 0); // round up to make sure the chunk is enough to cover all iterations UT span = (trip_count + nth - 1) / nth; @@ -398,8 +403,10 @@ static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid, } else if (*pupper < old_upper) *pupper = old_upper; - if (plastiter != NULL) + if (plastiter != NULL) { + KMP_DEBUG_ASSERT(chunk != 0); *plastiter = (tid == ((trip_count - 1) / (UT)chunk)); + } break; } default: @@ -417,6 +424,7 @@ static void __kmp_for_static_init(ident_t *loc, kmp_int32 global_tid, // Calculate chunk in case it was not specified; it is specified for // kmp_sch_static_chunked if (schedtype == kmp_sch_static) { + KMP_DEBUG_ASSERT(nth != 0); cur_chunk = trip_count / nth + ((trip_count % nth) ? 1 : 0); } // 0 - "static" schedule @@ -547,6 +555,7 @@ static void __kmp_dist_for_static_init(ident_t *loc, kmp_int32 gtid, // upper-lower can exceed the limit of signed type trip_count = (UT)(*pupper - *plower) / incr + 1; } else { + KMP_DEBUG_ASSERT(incr != 0); trip_count = (UT)(*plower - *pupper) / (-incr) + 1; } @@ -568,6 +577,7 @@ static void __kmp_dist_for_static_init(ident_t *loc, kmp_int32 gtid, *plastiter = (tid == 0 && team_id == trip_count - 1); } else { // Get the team's chunk first (each team gets at most one chunk) + KMP_DEBUG_ASSERT(nteams != 0); if (__kmp_static == kmp_sch_static_balanced) { UT chunkD = trip_count / nteams; UT extras = trip_count % nteams; @@ -619,6 +629,7 @@ static void __kmp_dist_for_static_init(ident_t *loc, kmp_int32 gtid, // upper-lower can exceed the limit of signed type trip_count = (UT)(*pupperDist - *plower) / incr + 1; } else { + KMP_DEBUG_ASSERT(incr != 0); trip_count = (UT)(*plower - *pupperDist) / (-incr) + 1; } KMP_DEBUG_ASSERT(trip_count); @@ -637,6 +648,7 @@ static void __kmp_dist_for_static_init(ident_t *loc, kmp_int32 gtid, if (*plastiter != 0 && !(tid == trip_count - 1)) *plastiter = 0; } else { + KMP_DEBUG_ASSERT(nth != 0); if (__kmp_static == kmp_sch_static_balanced) { UT chunkL = trip_count / nth; UT extras = trip_count % nth; @@ -684,9 +696,11 @@ static void __kmp_dist_for_static_init(ident_t *loc, kmp_int32 gtid, *pstride = span * nth; *plower = *plower + (span * tid); *pupper = *plower + span - incr; - if (plastiter != NULL) + if (plastiter != NULL) { + KMP_DEBUG_ASSERT(chunk != 0); if (*plastiter != 0 && !(tid == ((trip_count - 1) / (UT)chunk) % nth)) *plastiter = 0; + } break; } default: @@ -809,6 +823,7 @@ static void __kmp_team_static_init(ident_t *loc, kmp_int32 gtid, // upper-lower can exceed the limit of signed type trip_count = (UT)(upper - lower) / incr + 1; } else { + KMP_DEBUG_ASSERT(incr != 0); trip_count = (UT)(lower - upper) / (-incr) + 1; } if (chunk < 1) @@ -817,8 +832,10 @@ static void __kmp_team_static_init(ident_t *loc, kmp_int32 gtid, *p_st = span * nteams; *p_lb = lower + (span * team_id); *p_ub = *p_lb + span - incr; - if (p_last != NULL) + if (p_last != NULL) { + KMP_DEBUG_ASSERT(chunk != 0); *p_last = (team_id == ((trip_count - 1) / (UT)chunk) % nteams); + } // Correct upper bound if needed if (incr > 0) { if (*p_ub < *p_lb) // overflow? -- GitLab From 3303be63fc2ac196568b03f58c146655e19183f6 Mon Sep 17 00:00:00 2001 From: Jonathan Peyton Date: Tue, 12 Mar 2024 11:36:43 -0700 Subject: [PATCH 288/953] [OpenMP] Make sure mask is set to nullptr (#83299) --- openmp/runtime/src/kmp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index 48d7124e56c5..de758d37269d 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -825,7 +825,7 @@ class kmp_affinity_raii_t { public: kmp_affinity_raii_t(const kmp_affin_mask_t *new_mask = nullptr) - : restored(false) { + : mask(nullptr), restored(false) { if (KMP_AFFINITY_CAPABLE()) { KMP_CPU_ALLOC(mask); KMP_ASSERT(mask != NULL); @@ -835,7 +835,7 @@ public: } } void restore() { - if (!restored && KMP_AFFINITY_CAPABLE()) { + if (mask && KMP_AFFINITY_CAPABLE() && !restored) { __kmp_set_system_affinity(mask, /*abort_on_error=*/true); KMP_CPU_FREE(mask); } -- GitLab From 6272500e0b1456a87256f0c8659fdc86cfe3ef9a Mon Sep 17 00:00:00 2001 From: Jonathan Peyton Date: Tue, 12 Mar 2024 11:37:01 -0700 Subject: [PATCH 289/953] [OpenMP] Remove unused logical/physical CPUID information (#83298) --- openmp/runtime/src/kmp.h | 2 - openmp/runtime/src/kmp_utility.cpp | 68 +----------------------------- 2 files changed, 1 insertion(+), 69 deletions(-) diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index de758d37269d..569a1ab9b477 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -1392,8 +1392,6 @@ typedef struct kmp_cpuinfo { int stepping; // CPUID(1).EAX[3:0] ( Stepping ) kmp_cpuinfo_flags_t flags; int apic_id; - int physical_id; - int logical_id; kmp_uint64 frequency; // Nominal CPU frequency in Hz. char name[3 * sizeof(kmp_cpuid_t)]; // CPUID(0x80000002,0x80000003,0x80000004) } kmp_cpuinfo_t; diff --git a/openmp/runtime/src/kmp_utility.cpp b/openmp/runtime/src/kmp_utility.cpp index f901eaca92f4..bfa450c9ced2 100644 --- a/openmp/runtime/src/kmp_utility.cpp +++ b/openmp/runtime/src/kmp_utility.cpp @@ -28,68 +28,6 @@ static const char *unknown = "unknown"; static int trace_level = 5; #endif -/* LOG_ID_BITS = ( 1 + floor( log_2( max( log_per_phy - 1, 1 )))) - * APIC_ID = (PHY_ID << LOG_ID_BITS) | LOG_ID - * PHY_ID = APIC_ID >> LOG_ID_BITS - */ -int __kmp_get_physical_id(int log_per_phy, int apic_id) { - int index_lsb, index_msb, temp; - - if (log_per_phy > 1) { - index_lsb = 0; - index_msb = 31; - - temp = log_per_phy; - while ((temp & 1) == 0) { - temp >>= 1; - index_lsb++; - } - - temp = log_per_phy; - while ((temp & 0x80000000) == 0) { - temp <<= 1; - index_msb--; - } - - /* If >1 bits were set in log_per_phy, choose next higher power of 2 */ - if (index_lsb != index_msb) - index_msb++; - - return ((int)(apic_id >> index_msb)); - } - - return apic_id; -} - -/* - * LOG_ID_BITS = ( 1 + floor( log_2( max( log_per_phy - 1, 1 )))) - * APIC_ID = (PHY_ID << LOG_ID_BITS) | LOG_ID - * LOG_ID = APIC_ID & (( 1 << LOG_ID_BITS ) - 1 ) - */ -int __kmp_get_logical_id(int log_per_phy, int apic_id) { - unsigned current_bit; - int bits_seen; - - if (log_per_phy <= 1) - return (0); - - bits_seen = 0; - - for (current_bit = 1; log_per_phy != 0; current_bit <<= 1) { - if (log_per_phy & current_bit) { - log_per_phy &= ~current_bit; - bits_seen++; - } - } - - /* If exactly 1 bit was set in log_per_phy, choose next lower power of 2 */ - if (bits_seen == 1) { - current_bit >>= 1; - } - - return ((int)((current_bit - 1) & apic_id)); -} - static kmp_uint64 __kmp_parse_frequency( // R: Frequency in Hz. char const *frequency // I: Float number and unit: MHz, GHz, or TGz. ) { @@ -122,7 +60,6 @@ static kmp_uint64 __kmp_parse_frequency( // R: Frequency in Hz. void __kmp_query_cpuid(kmp_cpuinfo_t *p) { struct kmp_cpuid buf; int max_arg; - int log_per_phy; #ifdef KMP_DEBUG int cflush_size; #endif @@ -227,11 +164,8 @@ void __kmp_query_cpuid(kmp_cpuinfo_t *p) { if ((buf.edx >> 28) & 1) { /* Bits 23-16: Logical Processors per Physical Processor (1 for P4) */ - log_per_phy = data[2]; p->apic_id = data[3]; /* Bits 31-24: Processor Initial APIC ID (X) */ - KA_TRACE(trace_level, (" HT(%d TPUs)", log_per_phy)); - p->physical_id = __kmp_get_physical_id(log_per_phy, p->apic_id); - p->logical_id = __kmp_get_logical_id(log_per_phy, p->apic_id); + KA_TRACE(trace_level, (" HT(%d TPUs)", data[2])); } #ifdef KMP_DEBUG if ((buf.edx >> 29) & 1) { -- GitLab From 7c83d1bd612783634aae33baf8765ecfdcc5cd0d Mon Sep 17 00:00:00 2001 From: Han-Chung Wang Date: Tue, 12 Mar 2024 11:46:05 -0700 Subject: [PATCH 290/953] [mlir][vector] Use inferRankReducedResultType for subview type inference. (#84395) Fixes https://github.com/openxla/iree/issues/16475 --- .../Vector/Transforms/VectorTransforms.cpp | 48 ++++--------------- ...tor-transfer-collapse-inner-most-dims.mlir | 35 ++++++++------ 2 files changed, 28 insertions(+), 55 deletions(-) diff --git a/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp index a2d4e2166331..6f6b6dcdad20 100644 --- a/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp @@ -1255,42 +1255,6 @@ getTransferFoldableInnerUnitDims(MemRefType srcType, VectorType vectorType) { return result; } -/// Returns a MemRef type that drops inner `dimsToDrop` dimensions from -/// `srcType`. E.g., if `srcType` is memref<512x16x1x1xf32> and `dimsToDrop` is -/// two, it returns memref<512x16x16> type. -static MemRefType getMemRefTypeWithDroppingInnerDims(OpBuilder &builder, - MemRefType srcType, - size_t dimsToDrop) { - MemRefLayoutAttrInterface layout = srcType.getLayout(); - if (isa(layout) && layout.isIdentity()) { - return MemRefType::get(srcType.getShape().drop_back(dimsToDrop), - srcType.getElementType(), nullptr, - srcType.getMemorySpace()); - } - MemRefLayoutAttrInterface updatedLayout; - if (auto strided = dyn_cast(layout)) { - auto strides = llvm::to_vector(strided.getStrides().drop_back(dimsToDrop)); - updatedLayout = StridedLayoutAttr::get(strided.getContext(), - strided.getOffset(), strides); - return MemRefType::get(srcType.getShape().drop_back(dimsToDrop), - srcType.getElementType(), updatedLayout, - srcType.getMemorySpace()); - } - - // Non-strided layout case. - AffineMap map = srcType.getLayout().getAffineMap(); - int numSymbols = map.getNumSymbols(); - for (size_t i = 0; i < dimsToDrop; ++i) { - int dim = srcType.getRank() - i - 1; - map = map.replace(builder.getAffineDimExpr(dim), - builder.getAffineConstantExpr(0), map.getNumDims() - 1, - numSymbols); - } - return MemRefType::get(srcType.getShape().drop_back(dimsToDrop), - srcType.getElementType(), updatedLayout, - srcType.getMemorySpace()); -} - /// Drop inner most contiguous unit dimensions from transfer_read operand. class DropInnerMostUnitDimsTransferRead : public OpRewritePattern { @@ -1337,8 +1301,10 @@ class DropInnerMostUnitDimsTransferRead rewriter.getIndexAttr(0)); SmallVector strides(srcType.getRank(), rewriter.getIndexAttr(1)); - MemRefType resultMemrefType = - getMemRefTypeWithDroppingInnerDims(rewriter, srcType, dimsToDrop); + auto resultMemrefType = + cast(memref::SubViewOp::inferRankReducedResultType( + srcType.getShape().drop_back(dimsToDrop), srcType, offsets, sizes, + strides)); ArrayAttr inBoundsAttr = readOp.getInBounds() ? rewriter.getArrayAttr( @@ -1421,8 +1387,10 @@ class DropInnerMostUnitDimsTransferWrite rewriter.getIndexAttr(0)); SmallVector strides(srcType.getRank(), rewriter.getIndexAttr(1)); - MemRefType resultMemrefType = - getMemRefTypeWithDroppingInnerDims(rewriter, srcType, dimsToDrop); + auto resultMemrefType = + cast(memref::SubViewOp::inferRankReducedResultType( + srcType.getShape().drop_back(dimsToDrop), srcType, offsets, sizes, + strides)); ArrayAttr inBoundsAttr = writeOp.getInBounds() ? rewriter.getArrayAttr( diff --git a/mlir/test/Dialect/Vector/vector-transfer-collapse-inner-most-dims.mlir b/mlir/test/Dialect/Vector/vector-transfer-collapse-inner-most-dims.mlir index 3984f17f9e8c..477755b66c02 100644 --- a/mlir/test/Dialect/Vector/vector-transfer-collapse-inner-most-dims.mlir +++ b/mlir/test/Dialect/Vector/vector-transfer-collapse-inner-most-dims.mlir @@ -16,22 +16,27 @@ func.func @contiguous_inner_most_view(%in: memref<1x1x8x1xf32, strided<[3072, 8, // ----- -func.func @contiguous_outer_dyn_inner_most_view(%in: memref>) -> vector<1x8x1xf32>{ +func.func @contiguous_outer_dyn_inner_most_view(%a: index, %b: index, %memref: memref) -> vector<8x1xf32> { %c0 = arith.constant 0 : index - %cst = arith.constant 0.0 : f32 - %0 = vector.transfer_read %in[%c0, %c0, %c0, %c0], %cst {in_bounds = [true, true, true]} : memref>, vector<1x8x1xf32> - return %0 : vector<1x8x1xf32> + %pad = arith.constant 0.0 : f32 + %v = vector.transfer_read %memref[%a, %b, %c0, %c0], %pad {in_bounds = [true, true]} : memref, vector<8x1xf32> + return %v : vector<8x1xf32> } -// CHECK: func @contiguous_outer_dyn_inner_most_view( +// CHECK: func.func @contiguous_outer_dyn_inner_most_view( +// CHECK-SAME: %[[IDX0:[a-zA-Z0-9]+]] +// CHECK-SAME: %[[IDX1:[a-zA-Z0-9]+]] // CHECK-SAME: %[[SRC:[a-zA-Z0-9]+]] -// CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index -// CHECK-DAG: %[[D0:.+]] = memref.dim %[[SRC]], %[[C0]] -// CHECK: %[[SRC_0:.+]] = memref.subview %[[SRC]][0, 0, 0, 0] [%[[D0]], 1, 8, 1] [1, 1, 1, 1] -// CHECK-SAME: memref> to memref> -// CHECK: %[[VEC:.+]] = vector.transfer_read %[[SRC_0]] -// CHECK-SAME: memref>, vector<1x8xf32> -// CHECK: %[[RESULT:.+]] = vector.shape_cast %[[VEC]] -// CHECK: return %[[RESULT]] +// CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index +// CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index +// CHECK-DAG: %[[PAD:.+]] = arith.constant 0.000000e+00 : f32 +// CHECK: %[[D0:.+]] = memref.dim %[[SRC]], %[[C0]] +// CHECK: %[[D1:.+]] = memref.dim %[[SRC]], %[[C1]] +// CHECK: %[[VIEW:.+]] = memref.subview %[[SRC]][0, 0, 0, 0] [%[[D0]], %[[D1]], 8, 1] [1, 1, 1, 1] +// CHECK-SAME: memref to memref> +// CHECK: %[[VEC:.+]] = vector.transfer_read %[[VIEW]] +// CHECK-SAME: memref>, vector<8xf32> +// CHECK: %[[RESULT:.+]] = vector.shape_cast %[[VEC]] +// CHECK: return %[[RESULT]] // ----- @@ -43,7 +48,7 @@ func.func @contiguous_inner_most_dim(%A: memref<16x1xf32>, %i:index, %j:index) - } // CHECK: func @contiguous_inner_most_dim(%[[SRC:.+]]: memref<16x1xf32>, %[[I:.+]]: index, %[[J:.+]]: index) -> vector<8x1xf32> // CHECK: %[[SRC_0:.+]] = memref.subview %[[SRC]] -// CHECK-SAME: memref<16x1xf32> to memref<16xf32> +// CHECK-SAME: memref<16x1xf32> to memref<16xf32, strided<[1]>> // CHECK: %[[V:.+]] = vector.transfer_read %[[SRC_0]] // CHECK: %[[RESULT]] = vector.shape_cast %[[V]] : vector<8xf32> to vector<8x1xf32> // CHECK: return %[[RESULT]] @@ -111,7 +116,7 @@ func.func @drop_two_inner_most_dim_for_transfer_write(%arg0: memref<1x512x16x1x1 // CHECK-SAME: %[[IDX:[a-zA-Z0-9]+]] // CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index // CHECK: %[[SUBVIEW:.+]] = memref.subview %[[DEST]] -// CHECK-SAME: memref<1x512x16x1x1xf32> to memref<1x512x16xf32> +// CHECK-SAME: memref<1x512x16x1x1xf32> to memref<1x512x16xf32, strided<[8192, 16, 1]>> // CHECK: %[[CAST:.+]] = vector.shape_cast %[[VEC]] : vector<1x16x16x1x1xf32> to vector<1x16x16xf32> // CHECK: vector.transfer_write %[[CAST]], %[[SUBVIEW]] // CHECK-SAME: [%[[C0]], %[[IDX]], %[[C0]]] -- GitLab From 45219702e77f6f834ea2dfe2a68b140e59f7e0e2 Mon Sep 17 00:00:00 2001 From: Arthur Eubanks Date: Tue, 12 Mar 2024 19:07:37 +0000 Subject: [PATCH 291/953] [test][X86] Precommit test for large data threshold and i1 global --- llvm/test/CodeGen/X86/code-model-elf.ll | 181 ++++++++++++++++-------- 1 file changed, 121 insertions(+), 60 deletions(-) diff --git a/llvm/test/CodeGen/X86/code-model-elf.ll b/llvm/test/CodeGen/X86/code-model-elf.ll index 71a6a310906e..4e96d39d153f 100644 --- a/llvm/test/CodeGen/X86/code-model-elf.ll +++ b/llvm/test/CodeGen/X86/code-model-elf.ll @@ -54,6 +54,7 @@ target triple = "x86_64--linux" @extern_data = external global [10 x i32], align 16 @thread_data = external thread_local global i32, align 4 @unknown_size_data = dso_local global [0 x i32] zeroinitializer, align 16 +@bool = dso_local global i1 false @opaque = external dso_local global %t @forced_small_data = dso_local global [10 x i32] zeroinitializer, code_model "small", align 16 @forced_large_data = dso_local global [10 x i32] zeroinitializer, code_model "large", align 16 @@ -746,6 +747,66 @@ define dso_local i32 @load_unknown_size_data() #0 { ret i32 %rv } +define dso_local i1 @load_bool() #0 { +; SMALL-STATIC-LABEL: load_bool: +; SMALL-STATIC: # %bb.0: +; SMALL-STATIC-NEXT: movzbl bool(%rip), %eax +; SMALL-STATIC-NEXT: retq +; +; MEDIUM-STATIC-LABEL: load_bool: +; MEDIUM-STATIC: # %bb.0: +; MEDIUM-STATIC-NEXT: movabsq $bool, %rax +; MEDIUM-STATIC-NEXT: movzbl (%rax), %eax +; MEDIUM-STATIC-NEXT: retq +; +; LARGE-STATIC-LABEL: load_bool: +; LARGE-STATIC: # %bb.0: +; LARGE-STATIC-NEXT: movabsq $bool, %rax +; LARGE-STATIC-NEXT: movzbl (%rax), %eax +; LARGE-STATIC-NEXT: retq +; +; SMALL-PIC-LABEL: load_bool: +; SMALL-PIC: # %bb.0: +; SMALL-PIC-NEXT: movzbl bool(%rip), %eax +; SMALL-PIC-NEXT: retq +; +; MEDIUM-SMALL-DATA-PIC-LABEL: load_bool: +; MEDIUM-SMALL-DATA-PIC: # %bb.0: +; MEDIUM-SMALL-DATA-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax +; MEDIUM-SMALL-DATA-PIC-NEXT: movabsq $bool@GOTOFF, %rcx +; MEDIUM-SMALL-DATA-PIC-NEXT: movzbl (%rax,%rcx), %eax +; MEDIUM-SMALL-DATA-PIC-NEXT: retq +; +; MEDIUM-PIC-LABEL: load_bool: +; MEDIUM-PIC: # %bb.0: +; MEDIUM-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax +; MEDIUM-PIC-NEXT: movabsq $bool@GOTOFF, %rcx +; MEDIUM-PIC-NEXT: movzbl (%rax,%rcx), %eax +; MEDIUM-PIC-NEXT: retq +; +; LARGE-PIC-LABEL: load_bool: +; LARGE-PIC: # %bb.0: +; LARGE-PIC-NEXT: .L12$pb: +; LARGE-PIC-NEXT: leaq .L12$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L12$pb, %rcx +; LARGE-PIC-NEXT: addq %rax, %rcx +; LARGE-PIC-NEXT: movabsq $bool@GOTOFF, %rax +; LARGE-PIC-NEXT: movzbl (%rcx,%rax), %eax +; LARGE-PIC-NEXT: retq +; +; LARGE-SMALL-DATA-PIC-LABEL: load_bool: +; LARGE-SMALL-DATA-PIC: # %bb.0: +; LARGE-SMALL-DATA-PIC-NEXT: .L12$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L12$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L12$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $bool@GOTOFF, %rax +; LARGE-SMALL-DATA-PIC-NEXT: movzbl (%rcx,%rax), %eax +; LARGE-SMALL-DATA-PIC-NEXT: retq + %rv = load i1, ptr @bool + ret i1 %rv +} + define dso_local ptr @lea_opaque() #0 { ; SMALL-STATIC-LABEL: lea_opaque: ; SMALL-STATIC: # %bb.0: @@ -783,9 +844,9 @@ define dso_local ptr @lea_opaque() #0 { ; ; LARGE-PIC-LABEL: lea_opaque: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L12$pb: -; LARGE-PIC-NEXT: leaq .L12$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L12$pb, %rcx +; LARGE-PIC-NEXT: .L13$pb: +; LARGE-PIC-NEXT: leaq .L13$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L13$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $opaque@GOTOFF, %rax ; LARGE-PIC-NEXT: addq %rcx, %rax @@ -793,9 +854,9 @@ define dso_local ptr @lea_opaque() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_opaque: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L12$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L12$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L12$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L13$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L13$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L13$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $opaque@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax @@ -840,9 +901,9 @@ define dso_local ptr @lea_ehdr_start() #0 { ; ; LARGE-PIC-LABEL: lea_ehdr_start: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L13$pb: -; LARGE-PIC-NEXT: leaq .L13$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L13$pb, %rcx +; LARGE-PIC-NEXT: .L14$pb: +; LARGE-PIC-NEXT: leaq .L14$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L14$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $__ehdr_start@GOTOFF, %rax ; LARGE-PIC-NEXT: addq %rcx, %rax @@ -850,9 +911,9 @@ define dso_local ptr @lea_ehdr_start() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_ehdr_start: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L13$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L13$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L13$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L14$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L14$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L14$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $__ehdr_start@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax @@ -897,9 +958,9 @@ define dso_local ptr @lea_start_foo() #0 { ; ; LARGE-PIC-LABEL: lea_start_foo: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L14$pb: -; LARGE-PIC-NEXT: leaq .L14$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L14$pb, %rcx +; LARGE-PIC-NEXT: .L15$pb: +; LARGE-PIC-NEXT: leaq .L15$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L15$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $__start_foo@GOTOFF, %rax ; LARGE-PIC-NEXT: addq %rcx, %rax @@ -907,9 +968,9 @@ define dso_local ptr @lea_start_foo() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_start_foo: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L14$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L14$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L14$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L15$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L15$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L15$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $__start_foo@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax @@ -954,9 +1015,9 @@ define dso_local ptr @lea_stop_foo() #0 { ; ; LARGE-PIC-LABEL: lea_stop_foo: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L15$pb: -; LARGE-PIC-NEXT: leaq .L15$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L15$pb, %rcx +; LARGE-PIC-NEXT: .L16$pb: +; LARGE-PIC-NEXT: leaq .L16$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L16$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $__stop_foo@GOTOFF, %rax ; LARGE-PIC-NEXT: addq %rcx, %rax @@ -964,9 +1025,9 @@ define dso_local ptr @lea_stop_foo() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_stop_foo: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L15$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L15$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L15$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L16$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L16$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L16$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $__stop_foo@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax @@ -1035,9 +1096,9 @@ define dso_local ptr @lea_static_fn() #0 { ; ; LARGE-PIC-LABEL: lea_static_fn: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L19$pb: -; LARGE-PIC-NEXT: leaq .L19$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L19$pb, %rcx +; LARGE-PIC-NEXT: .L20$pb: +; LARGE-PIC-NEXT: leaq .L20$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L20$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $static_fn@GOTOFF, %rax ; LARGE-PIC-NEXT: addq %rcx, %rax @@ -1045,9 +1106,9 @@ define dso_local ptr @lea_static_fn() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_static_fn: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L19$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L19$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L19$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L20$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L20$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L20$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $static_fn@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax @@ -1088,9 +1149,9 @@ define dso_local ptr @lea_global_fn() #0 { ; ; LARGE-PIC-LABEL: lea_global_fn: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L20$pb: -; LARGE-PIC-NEXT: leaq .L20$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L20$pb, %rcx +; LARGE-PIC-NEXT: .L21$pb: +; LARGE-PIC-NEXT: leaq .L21$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L21$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $global_fn@GOTOFF, %rax ; LARGE-PIC-NEXT: addq %rcx, %rax @@ -1098,9 +1159,9 @@ define dso_local ptr @lea_global_fn() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_global_fn: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L20$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L20$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L20$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L21$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L21$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L21$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $global_fn@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax @@ -1141,9 +1202,9 @@ define dso_local ptr @lea_extern_fn() #0 { ; ; LARGE-PIC-LABEL: lea_extern_fn: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L21$pb: -; LARGE-PIC-NEXT: leaq .L21$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L21$pb, %rcx +; LARGE-PIC-NEXT: .L22$pb: +; LARGE-PIC-NEXT: leaq .L22$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L22$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $extern_fn@GOT, %rax ; LARGE-PIC-NEXT: movq (%rcx,%rax), %rax @@ -1151,9 +1212,9 @@ define dso_local ptr @lea_extern_fn() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_extern_fn: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L21$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L21$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L21$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L22$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L22$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L22$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $extern_fn@GOT, %rax ; LARGE-SMALL-DATA-PIC-NEXT: movq (%rcx,%rax), %rax @@ -1194,9 +1255,9 @@ define dso_local ptr @lea_ifunc() #0 { ; ; LARGE-PIC-LABEL: lea_ifunc: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L22$pb: -; LARGE-PIC-NEXT: leaq .L22$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L22$pb, %rcx +; LARGE-PIC-NEXT: .L23$pb: +; LARGE-PIC-NEXT: leaq .L23$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L23$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $ifunc_func@GOT, %rax ; LARGE-PIC-NEXT: movq (%rcx,%rax), %rax @@ -1204,9 +1265,9 @@ define dso_local ptr @lea_ifunc() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_ifunc: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L22$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L22$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L22$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L23$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L23$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L23$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $ifunc_func@GOT, %rax ; LARGE-SMALL-DATA-PIC-NEXT: movq (%rcx,%rax), %rax @@ -1247,9 +1308,9 @@ define dso_local ptr @lea_dso_local_ifunc() #0 { ; ; LARGE-PIC-LABEL: lea_dso_local_ifunc: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L23$pb: -; LARGE-PIC-NEXT: leaq .L23$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L23$pb, %rcx +; LARGE-PIC-NEXT: .L24$pb: +; LARGE-PIC-NEXT: leaq .L24$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L24$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq $dso_local_ifunc_func@GOTOFF, %rax ; LARGE-PIC-NEXT: addq %rcx, %rax @@ -1257,9 +1318,9 @@ define dso_local ptr @lea_dso_local_ifunc() #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: lea_dso_local_ifunc: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L23$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L23$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L23$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L24$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L24$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L24$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq $dso_local_ifunc_func@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addq %rcx, %rax @@ -1334,9 +1395,9 @@ define dso_local float @load_constant_pool(float %x) #0 { ; ; LARGE-PIC-LABEL: load_constant_pool: ; LARGE-PIC: # %bb.0: -; LARGE-PIC-NEXT: .L25$pb: -; LARGE-PIC-NEXT: leaq .L25$pb(%rip), %rax -; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L25$pb, %rcx +; LARGE-PIC-NEXT: .L26$pb: +; LARGE-PIC-NEXT: leaq .L26$pb(%rip), %rax +; LARGE-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L26$pb, %rcx ; LARGE-PIC-NEXT: addq %rax, %rcx ; LARGE-PIC-NEXT: movabsq ${{\.?LCPI[0-9]+_[0-9]+}}@GOTOFF, %rax ; LARGE-PIC-NEXT: addss (%rcx,%rax), %xmm0 @@ -1344,9 +1405,9 @@ define dso_local float @load_constant_pool(float %x) #0 { ; ; LARGE-SMALL-DATA-PIC-LABEL: load_constant_pool: ; LARGE-SMALL-DATA-PIC: # %bb.0: -; LARGE-SMALL-DATA-PIC-NEXT: .L25$pb: -; LARGE-SMALL-DATA-PIC-NEXT: leaq .L25$pb(%rip), %rax -; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L25$pb, %rcx +; LARGE-SMALL-DATA-PIC-NEXT: .L26$pb: +; LARGE-SMALL-DATA-PIC-NEXT: leaq .L26$pb(%rip), %rax +; LARGE-SMALL-DATA-PIC-NEXT: movabsq $_GLOBAL_OFFSET_TABLE_-.L26$pb, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: addq %rax, %rcx ; LARGE-SMALL-DATA-PIC-NEXT: movabsq ${{\.?LCPI[0-9]+_[0-9]+}}@GOTOFF, %rax ; LARGE-SMALL-DATA-PIC-NEXT: addss (%rcx,%rax), %xmm0 -- GitLab From a38b7a432d3cbb093af9310eba5b4982dc0a0243 Mon Sep 17 00:00:00 2001 From: Cyndy Ishida Date: Tue, 12 Mar 2024 12:37:17 -0700 Subject: [PATCH 292/953] [InstallAPI] Break up headers and add common header for TextAPI types (#84960) Before it gets too unwieldy, add a common header for all MachO types that are used across InstallAPI. Also, break up the types in `InstallAPI/Frontend`. This both avoids circular dependencies and is logically easier to maintain as more functionality gets added. --- clang/include/clang/InstallAPI/Context.h | 6 +- clang/include/clang/InstallAPI/Frontend.h | 94 --------------- .../clang/InstallAPI/FrontendRecords.h | 108 ++++++++++++++++++ clang/include/clang/InstallAPI/MachO.h | 40 +++++++ clang/lib/InstallAPI/Frontend.cpp | 1 + clang/lib/InstallAPI/Visitor.cpp | 2 +- .../clang-installapi/ClangInstallAPI.cpp | 6 +- clang/tools/clang-installapi/Options.h | 12 +- 8 files changed, 159 insertions(+), 110 deletions(-) create mode 100644 clang/include/clang/InstallAPI/FrontendRecords.h create mode 100644 clang/include/clang/InstallAPI/MachO.h diff --git a/clang/include/clang/InstallAPI/Context.h b/clang/include/clang/InstallAPI/Context.h index 4e9e90e5d2db..bdb576d7d85f 100644 --- a/clang/include/clang/InstallAPI/Context.h +++ b/clang/include/clang/InstallAPI/Context.h @@ -12,8 +12,8 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/InstallAPI/HeaderFile.h" +#include "clang/InstallAPI/MachO.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/TextAPI/InterfaceFile.h" namespace clang { namespace installapi { @@ -25,7 +25,7 @@ class FrontendRecordsSlice; struct InstallAPIContext { /// Library attributes that are typically passed as linker inputs. - llvm::MachO::RecordsSlice::BinaryAttrs BA; + BinaryAttrs BA; /// All headers that represent a library. HeaderSeq InputHeaders; @@ -49,7 +49,7 @@ struct InstallAPIContext { llvm::StringRef OutputLoc{}; /// What encoding to write output as. - llvm::MachO::FileType FT = llvm::MachO::FileType::TBD_V5; + FileType FT = FileType::TBD_V5; /// Populate entries of headers that should be included for TextAPI /// generation. diff --git a/clang/include/clang/InstallAPI/Frontend.h b/clang/include/clang/InstallAPI/Frontend.h index cbc2b159ebd1..873cb50d60a5 100644 --- a/clang/include/clang/InstallAPI/Frontend.h +++ b/clang/include/clang/InstallAPI/Frontend.h @@ -25,100 +25,6 @@ namespace clang { namespace installapi { -using SymbolFlags = llvm::MachO::SymbolFlags; -using RecordLinkage = llvm::MachO::RecordLinkage; -using GlobalRecord = llvm::MachO::GlobalRecord; -using ObjCContainerRecord = llvm::MachO::ObjCContainerRecord; -using ObjCInterfaceRecord = llvm::MachO::ObjCInterfaceRecord; -using ObjCCategoryRecord = llvm::MachO::ObjCCategoryRecord; -using ObjCIVarRecord = llvm::MachO::ObjCIVarRecord; - -// Represents a collection of frontend records for a library that are tied to a -// darwin target triple. -class FrontendRecordsSlice : public llvm::MachO::RecordsSlice { -public: - FrontendRecordsSlice(const llvm::Triple &T) - : llvm::MachO::RecordsSlice({T}) {} - - /// Add non-ObjC global record with attributes from AST. - /// - /// \param Name The name of symbol. - /// \param Linkage The linkage of symbol. - /// \param GV The kind of global. - /// \param Avail The availability information tied to the active target - /// triple. - /// \param D The pointer to the declaration from traversing AST. - /// \param Access The intended access level of symbol. - /// \param Flags The flags that describe attributes of the symbol. - /// \param Inlined Whether declaration is inlined, only applicable to - /// functions. - /// \return The non-owning pointer to added record in slice. - GlobalRecord *addGlobal(StringRef Name, RecordLinkage Linkage, - GlobalRecord::Kind GV, - const clang::AvailabilityInfo Avail, const Decl *D, - const HeaderType Access, - SymbolFlags Flags = SymbolFlags::None, - bool Inlined = false); - - /// Add ObjC Class record with attributes from AST. - /// - /// \param Name The name of class, not symbol. - /// \param Linkage The linkage of symbol. - /// \param Avail The availability information tied to the active target - /// triple. - /// \param D The pointer to the declaration from traversing AST. - /// \param Access The intended access level of symbol. - /// \param IsEHType Whether declaration has an exception attribute. - /// \return The non-owning pointer to added record in slice. - ObjCInterfaceRecord *addObjCInterface(StringRef Name, RecordLinkage Linkage, - const clang::AvailabilityInfo Avail, - const Decl *D, HeaderType Access, - bool IsEHType); - - /// Add ObjC Category record with attributes from AST. - /// - /// \param ClassToExtend The name of class that is extended by category, not - /// symbol. - /// \param CategoryName The name of category, not symbol. - /// \param Avail The availability information tied - /// to the active target triple. - /// \param D The pointer to the declaration from traversing AST. - /// \param Access The intended access level of symbol. - /// \return The non-owning pointer to added record in slice. - ObjCCategoryRecord *addObjCCategory(StringRef ClassToExtend, - StringRef CategoryName, - const clang::AvailabilityInfo Avail, - const Decl *D, HeaderType Access); - - /// Add ObjC IVar record with attributes from AST. - /// - /// \param Container The owning pointer for instance variable. - /// \param Name The name of ivar, not symbol. - /// \param Linkage The linkage of symbol. - /// \param Avail The availability information tied to the active target - /// triple. - /// \param D The pointer to the declaration from traversing AST. - /// \param Access The intended access level of symbol. - /// \param AC The access control tied to the ivar declaration. - /// \return The non-owning pointer to added record in slice. - ObjCIVarRecord *addObjCIVar(ObjCContainerRecord *Container, - StringRef IvarName, RecordLinkage Linkage, - const clang::AvailabilityInfo Avail, - const Decl *D, HeaderType Access, - const clang::ObjCIvarDecl::AccessControl AC); - -private: - /// Frontend information captured about records. - struct FrontendAttrs { - const AvailabilityInfo Avail; - const Decl *D; - const HeaderType Access; - }; - - /// Mapping of records stored in slice to their frontend attributes. - llvm::DenseMap FrontendRecords; -}; - /// Create a buffer that contains all headers to scan /// for global symbols with. std::unique_ptr createInputBuffer(InstallAPIContext &Ctx); diff --git a/clang/include/clang/InstallAPI/FrontendRecords.h b/clang/include/clang/InstallAPI/FrontendRecords.h new file mode 100644 index 000000000000..333015b6a113 --- /dev/null +++ b/clang/include/clang/InstallAPI/FrontendRecords.h @@ -0,0 +1,108 @@ +//===- InstallAPI/FrontendRecords.h ------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INSTALLAPI_FRONTENDRECORDS_H +#define LLVM_CLANG_INSTALLAPI_FRONTENDRECORDS_H + +#include "clang/AST/Availability.h" +#include "clang/AST/DeclObjC.h" +#include "clang/InstallAPI/MachO.h" + +namespace clang { +namespace installapi { + +/// Frontend information captured about records. +struct FrontendAttrs { + const AvailabilityInfo Avail; + const Decl *D; + const HeaderType Access; +}; + +// Represents a collection of frontend records for a library that are tied to a +// darwin target triple. +class FrontendRecordsSlice : public llvm::MachO::RecordsSlice { +public: + FrontendRecordsSlice(const llvm::Triple &T) + : llvm::MachO::RecordsSlice({T}) {} + + /// Add non-ObjC global record with attributes from AST. + /// + /// \param Name The name of symbol. + /// \param Linkage The linkage of symbol. + /// \param GV The kind of global. + /// \param Avail The availability information tied to the active target + /// triple. + /// \param D The pointer to the declaration from traversing AST. + /// \param Access The intended access level of symbol. + /// \param Flags The flags that describe attributes of the symbol. + /// \param Inlined Whether declaration is inlined, only applicable to + /// functions. + /// \return The non-owning pointer to added record in slice. + GlobalRecord *addGlobal(StringRef Name, RecordLinkage Linkage, + GlobalRecord::Kind GV, + const clang::AvailabilityInfo Avail, const Decl *D, + const HeaderType Access, + SymbolFlags Flags = SymbolFlags::None, + bool Inlined = false); + + /// Add ObjC Class record with attributes from AST. + /// + /// \param Name The name of class, not symbol. + /// \param Linkage The linkage of symbol. + /// \param Avail The availability information tied to the active target + /// triple. + /// \param D The pointer to the declaration from traversing AST. + /// \param Access The intended access level of symbol. + /// \param IsEHType Whether declaration has an exception attribute. + /// \return The non-owning pointer to added record in slice. + ObjCInterfaceRecord *addObjCInterface(StringRef Name, RecordLinkage Linkage, + const clang::AvailabilityInfo Avail, + const Decl *D, HeaderType Access, + bool IsEHType); + + /// Add ObjC Category record with attributes from AST. + /// + /// \param ClassToExtend The name of class that is extended by category, not + /// symbol. + /// \param CategoryName The name of category, not symbol. + /// \param Avail The availability information tied + /// to the active target triple. + /// \param D The pointer to the declaration from traversing AST. + /// \param Access The intended access level of symbol. + /// \return The non-owning pointer to added record in slice. + ObjCCategoryRecord *addObjCCategory(StringRef ClassToExtend, + StringRef CategoryName, + const clang::AvailabilityInfo Avail, + const Decl *D, HeaderType Access); + + /// Add ObjC IVar record with attributes from AST. + /// + /// \param Container The owning pointer for instance variable. + /// \param Name The name of ivar, not symbol. + /// \param Linkage The linkage of symbol. + /// \param Avail The availability information tied to the active target + /// triple. + /// \param D The pointer to the declaration from traversing AST. + /// \param Access The intended access level of symbol. + /// \param AC The access control tied to the ivar declaration. + /// \return The non-owning pointer to added record in slice. + ObjCIVarRecord *addObjCIVar(ObjCContainerRecord *Container, + StringRef IvarName, RecordLinkage Linkage, + const clang::AvailabilityInfo Avail, + const Decl *D, HeaderType Access, + const clang::ObjCIvarDecl::AccessControl AC); + +private: + /// Mapping of records stored in slice to their frontend attributes. + llvm::DenseMap FrontendRecords; +}; + +} // namespace installapi +} // namespace clang + +#endif // LLVM_CLANG_INSTALLAPI_FRONTENDRECORDS_H diff --git a/clang/include/clang/InstallAPI/MachO.h b/clang/include/clang/InstallAPI/MachO.h new file mode 100644 index 000000000000..55e5591389ce --- /dev/null +++ b/clang/include/clang/InstallAPI/MachO.h @@ -0,0 +1,40 @@ +//===- InstallAPI/MachO.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Imports and forward declarations for llvm::MachO types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INSTALLAPI_MACHO_H +#define LLVM_CLANG_INSTALLAPI_MACHO_H + +#include "llvm/TextAPI/Architecture.h" +#include "llvm/TextAPI/InterfaceFile.h" +#include "llvm/TextAPI/PackedVersion.h" +#include "llvm/TextAPI/Platform.h" +#include "llvm/TextAPI/RecordVisitor.h" +#include "llvm/TextAPI/Target.h" +#include "llvm/TextAPI/TextAPIWriter.h" +#include "llvm/TextAPI/Utils.h" + +using SymbolFlags = llvm::MachO::SymbolFlags; +using RecordLinkage = llvm::MachO::RecordLinkage; +using Record = llvm::MachO::Record; +using GlobalRecord = llvm::MachO::GlobalRecord; +using ObjCContainerRecord = llvm::MachO::ObjCContainerRecord; +using ObjCInterfaceRecord = llvm::MachO::ObjCInterfaceRecord; +using ObjCCategoryRecord = llvm::MachO::ObjCCategoryRecord; +using ObjCIVarRecord = llvm::MachO::ObjCIVarRecord; +using Records = llvm::MachO::Records; +using BinaryAttrs = llvm::MachO::RecordsSlice::BinaryAttrs; +using SymbolSet = llvm::MachO::SymbolSet; +using FileType = llvm::MachO::FileType; +using PackedVersion = llvm::MachO::PackedVersion; +using Target = llvm::MachO::Target; + +#endif // LLVM_CLANG_INSTALLAPI_MACHO_H diff --git a/clang/lib/InstallAPI/Frontend.cpp b/clang/lib/InstallAPI/Frontend.cpp index 0d526fe1da66..707aeb17dc89 100644 --- a/clang/lib/InstallAPI/Frontend.cpp +++ b/clang/lib/InstallAPI/Frontend.cpp @@ -8,6 +8,7 @@ #include "clang/InstallAPI/Frontend.h" #include "clang/AST/Availability.h" +#include "clang/InstallAPI/FrontendRecords.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" diff --git a/clang/lib/InstallAPI/Visitor.cpp b/clang/lib/InstallAPI/Visitor.cpp index aded94f7a94a..b4ed5974a057 100644 --- a/clang/lib/InstallAPI/Visitor.cpp +++ b/clang/lib/InstallAPI/Visitor.cpp @@ -11,7 +11,7 @@ #include "clang/AST/ParentMapContext.h" #include "clang/AST/VTableBuilder.h" #include "clang/Basic/Linkage.h" -#include "clang/InstallAPI/Frontend.h" +#include "clang/InstallAPI/FrontendRecords.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/DataLayout.h" diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp index c6da1c80a673..15b0baee88bc 100644 --- a/clang/tools/clang-installapi/ClangInstallAPI.cpp +++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp @@ -19,6 +19,8 @@ #include "clang/Driver/Tool.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/InstallAPI/Frontend.h" +#include "clang/InstallAPI/FrontendRecords.h" +#include "clang/InstallAPI/MachO.h" #include "clang/Tooling/Tooling.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Option/Option.h" @@ -29,8 +31,6 @@ #include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include "llvm/TargetParser/Host.h" -#include "llvm/TextAPI/RecordVisitor.h" -#include "llvm/TextAPI/TextAPIWriter.h" #include using namespace clang; @@ -125,7 +125,7 @@ static bool run(ArrayRef Args, const char *ProgName) { // Execute and gather AST results. // An invocation is ran for each unique target triple and for each header // access level. - llvm::MachO::Records FrontendResults; + Records FrontendResults; for (const auto &[Targ, Trip] : Opts.DriverOpts.Targets) { for (const HeaderType Type : {HeaderType::Public, HeaderType::Private, HeaderType::Project}) { diff --git a/clang/tools/clang-installapi/Options.h b/clang/tools/clang-installapi/Options.h index 9d4d841284fd..06f79b62c531 100644 --- a/clang/tools/clang-installapi/Options.h +++ b/clang/tools/clang-installapi/Options.h @@ -13,23 +13,17 @@ #include "clang/Basic/FileManager.h" #include "clang/Frontend/FrontendOptions.h" #include "clang/InstallAPI/Context.h" +#include "clang/InstallAPI/MachO.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Support/Program.h" #include "llvm/TargetParser/Triple.h" -#include "llvm/TextAPI/Architecture.h" -#include "llvm/TextAPI/InterfaceFile.h" -#include "llvm/TextAPI/PackedVersion.h" -#include "llvm/TextAPI/Platform.h" -#include "llvm/TextAPI/Target.h" -#include "llvm/TextAPI/Utils.h" #include #include #include namespace clang { namespace installapi { -using Macro = std::pair; struct DriverOptions { /// \brief Path to input file lists (JSON). @@ -42,7 +36,7 @@ struct DriverOptions { std::string OutputPath; /// \brief File encoding to print. - llvm::MachO::FileType OutFT = llvm::MachO::FileType::TBD_V5; + FileType OutFT = FileType::TBD_V5; /// \brief Print verbose output. bool Verbose = false; @@ -53,7 +47,7 @@ struct LinkerOptions { std::string InstallName; /// \brief The current version to use for the dynamic library. - llvm::MachO::PackedVersion CurrentVersion; + PackedVersion CurrentVersion; /// \brief Is application extension safe. bool AppExtensionSafe = false; -- GitLab From 6bbb73b4cbc89b7291a8088aaa635814a216fbf6 Mon Sep 17 00:00:00 2001 From: Arthur Eubanks Date: Tue, 12 Mar 2024 13:43:29 -0600 Subject: [PATCH 293/953] [X86] Fix determining if globals with size <8 bits are large (#84975) Previously any global under 8 bits would accidentally be considered 0 sized, which is considered a large global. --- llvm/lib/Target/TargetMachine.cpp | 2 +- llvm/test/CodeGen/X86/code-model-elf.ll | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp index 8b177a89c919..a7fe329b064e 100644 --- a/llvm/lib/Target/TargetMachine.cpp +++ b/llvm/lib/Target/TargetMachine.cpp @@ -92,7 +92,7 @@ bool TargetMachine::isLargeGlobalValue(const GlobalValue *GVal) const { GV->getName().starts_with("__stop_"))) return true; const DataLayout &DL = GV->getParent()->getDataLayout(); - uint64_t Size = DL.getTypeSizeInBits(GV->getValueType()) / 8; + uint64_t Size = DL.getTypeAllocSize(GV->getValueType()); return Size == 0 || Size > LargeDataThreshold; } diff --git a/llvm/test/CodeGen/X86/code-model-elf.ll b/llvm/test/CodeGen/X86/code-model-elf.ll index 4e96d39d153f..0da62e3e7a65 100644 --- a/llvm/test/CodeGen/X86/code-model-elf.ll +++ b/llvm/test/CodeGen/X86/code-model-elf.ll @@ -772,9 +772,7 @@ define dso_local i1 @load_bool() #0 { ; ; MEDIUM-SMALL-DATA-PIC-LABEL: load_bool: ; MEDIUM-SMALL-DATA-PIC: # %bb.0: -; MEDIUM-SMALL-DATA-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax -; MEDIUM-SMALL-DATA-PIC-NEXT: movabsq $bool@GOTOFF, %rcx -; MEDIUM-SMALL-DATA-PIC-NEXT: movzbl (%rax,%rcx), %eax +; MEDIUM-SMALL-DATA-PIC-NEXT: movzbl bool(%rip), %eax ; MEDIUM-SMALL-DATA-PIC-NEXT: retq ; ; MEDIUM-PIC-LABEL: load_bool: -- GitLab From 6095f8bbc410d2f8b926a32ba969d507f7343949 Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Tue, 12 Mar 2024 12:52:31 -0700 Subject: [PATCH 294/953] Get rid of noisy debug log in verifyOpAndAdjustFlags. (#84677) This debug log adds noise to a large fraction of *other* debug logs when you run with -debug, because it prints "Verifying operation: blah blah\n" whenever those other debug logs dump an op. You can use -debug-only to get around this, but sometimes -debug really is what's called for! --- mlir/lib/IR/AsmPrinter.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/mlir/lib/IR/AsmPrinter.cpp b/mlir/lib/IR/AsmPrinter.cpp index 8d75349f8eed..456cf6a2c277 100644 --- a/mlir/lib/IR/AsmPrinter.cpp +++ b/mlir/lib/IR/AsmPrinter.cpp @@ -1895,9 +1895,6 @@ static OpPrintingFlags verifyOpAndAdjustFlags(Operation *op, printerFlags.shouldAssumeVerified()) return printerFlags; - LLVM_DEBUG(llvm::dbgs() << DEBUG_TYPE << ": Verifying operation: " - << op->getName() << "\n"); - // Ignore errors emitted by the verifier. We check the thread id to avoid // consuming other threads' errors. auto parentThreadId = llvm::get_threadid(); -- GitLab From 97fb91ee665660036f8beffd064b44c6fbbf1b73 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Tue, 12 Mar 2024 12:55:47 -0700 Subject: [PATCH 295/953] [SLP][NFC]Add a test with non-profitable alternate vectorized instructions. --- .../SLPVectorizer/alternate-non-profitable.ll | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 llvm/test/Transforms/SLPVectorizer/alternate-non-profitable.ll diff --git a/llvm/test/Transforms/SLPVectorizer/alternate-non-profitable.ll b/llvm/test/Transforms/SLPVectorizer/alternate-non-profitable.ll new file mode 100644 index 000000000000..c6e2cf5543e1 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/alternate-non-profitable.ll @@ -0,0 +1,190 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -passes=slp-vectorizer -slp-threshold=-10000 < %s | FileCheck %s + +define <2 x float> @test_fdiv(float %a, i1 %cmp) { +; CHECK-LABEL: define <2 x float> @test_fdiv( +; CHECK-SAME: float [[A:%.*]], i1 [[CMP:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[A]], 3.000000e+00 +; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x float> poison, float [[TMP1]], i64 1 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[CMP]], <2 x float> , <2 x float> [[TMP2]] +; CHECK-NEXT: ret <2 x float> [[TMP3]] +; + %1 = fdiv float %a, 3.000000e+00 + %2 = insertelement <2 x float> poison, float %1, i64 1 + %3 = select i1 %cmp, <2 x float> , <2 x float> %2 + ret <2 x float> %3 +} + +define <2 x float> @test_frem(float %a, i1 %cmp) { +; CHECK-LABEL: define <2 x float> @test_frem( +; CHECK-SAME: float [[A:%.*]], i1 [[CMP:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = frem float [[A]], 3.000000e+00 +; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x float> poison, float [[TMP1]], i64 1 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[CMP]], <2 x float> , <2 x float> [[TMP2]] +; CHECK-NEXT: ret <2 x float> [[TMP3]] +; + %1 = frem float %a, 3.000000e+00 + %2 = insertelement <2 x float> poison, float %1, i64 1 + %3 = select i1 %cmp, <2 x float> , <2 x float> %2 + ret <2 x float> %3 +} + +define <2 x float> @replace_through_casts(i16 %inp) { +; CHECK-LABEL: define <2 x float> @replace_through_casts( +; CHECK-SAME: i16 [[INP:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[INP]], -10 +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i16> poison, i16 [[INP]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i16> [[TMP1]], i16 [[ADD]], i32 1 +; CHECK-NEXT: [[TMP3:%.*]] = uitofp <2 x i16> [[TMP2]] to <2 x float> +; CHECK-NEXT: [[TMP4:%.*]] = sitofp <2 x i16> [[TMP2]] to <2 x float> +; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP3]], <2 x float> [[TMP4]], <2 x i32> +; CHECK-NEXT: ret <2 x float> [[R]] +; + %add = add nsw i16 %inp, -10 + %1 = uitofp i16 %inp to float + %2 = sitofp i16 %add to float + %3 = insertelement <2 x float> poison, float %1, i64 0 + %r = insertelement <2 x float> %3, float %2, i64 1 + ret <2 x float> %r +} + +define <2 x float> @replace_through_casts_and_binop(i16 %inp) { +; CHECK-LABEL: define <2 x float> @replace_through_casts_and_binop( +; CHECK-SAME: i16 [[INP:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[INP]], -10 +; CHECK-NEXT: [[MUL:%.*]] = mul nsw i16 [[INP]], 5 +; CHECK-NEXT: [[TMP1:%.*]] = uitofp i16 [[MUL]] to float +; CHECK-NEXT: [[TMP2:%.*]] = fadd float [[TMP1]], 2.000000e+00 +; CHECK-NEXT: [[TMP3:%.*]] = sitofp i16 [[ADD]] to float +; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x float> poison, float [[TMP2]], i64 0 +; CHECK-NEXT: [[R:%.*]] = insertelement <2 x float> [[TMP4]], float [[TMP3]], i64 1 +; CHECK-NEXT: ret <2 x float> [[R]] +; + %add = add nsw i16 %inp, -10 + %mul = mul nsw i16 %inp, 5 + %1 = uitofp i16 %mul to float + %2 = fadd float %1, 2.000000e+00 + %3 = sitofp i16 %add to float + %4 = insertelement <2 x float> poison, float %2, i64 0 + %r = insertelement <2 x float> %4, float %3, i64 1 + ret <2 x float> %r +} + +define <2 x float> @replace_through_casts_and_binop_and_unop(i16 %inp) { +; CHECK-LABEL: define <2 x float> @replace_through_casts_and_binop_and_unop( +; CHECK-SAME: i16 [[INP:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[INP]], -10 +; CHECK-NEXT: [[TMP1:%.*]] = sitofp i16 [[ADD]] to float +; CHECK-NEXT: [[TMP2:%.*]] = fneg float [[TMP1]] +; CHECK-NEXT: [[TMP3:%.*]] = uitofp i16 [[ADD]] to float +; CHECK-NEXT: [[TMP4:%.*]] = fadd float [[TMP3]], 2.000000e+00 +; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x float> poison, float [[TMP4]], i64 0 +; CHECK-NEXT: [[R:%.*]] = insertelement <2 x float> [[TMP5]], float [[TMP2]], i64 1 +; CHECK-NEXT: ret <2 x float> [[R]] +; + %add = add nsw i16 %inp, -10 + %1 = sitofp i16 %add to float + %2 = fneg float %1 + %3 = uitofp i16 %add to float + %4 = fadd float %3, 2.000000e+00 + %5 = insertelement <2 x float> poison, float %4, i64 0 + %r = insertelement <2 x float> %5, float %2, i64 1 + ret <2 x float> %r +} + +define <2 x float> @replace_through_casts_through_splat(i16 %inp) { +; CHECK-LABEL: define <2 x float> @replace_through_casts_through_splat( +; CHECK-SAME: i16 [[INP:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[INP]], -10 +; CHECK-NEXT: [[TMP1:%.*]] = uitofp i16 [[ADD]] to float +; CHECK-NEXT: [[TMP2:%.*]] = fadd float [[TMP1]], 2.000000e+00 +; CHECK-NEXT: [[TMP3:%.*]] = sitofp i16 [[ADD]] to float +; CHECK-NEXT: [[TMP4:%.*]] = fneg float [[TMP3]] +; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x float> poison, float [[TMP2]], i64 0 +; CHECK-NEXT: [[R:%.*]] = insertelement <2 x float> [[TMP5]], float [[TMP4]], i64 1 +; CHECK-NEXT: ret <2 x float> [[R]] +; + %add = add nsw i16 %inp, -10 + %1 = uitofp i16 %add to float + %2 = fadd float %1, 2.000000e+00 + %3 = sitofp i16 %add to float + %4 = fneg float %3 + %5 = insertelement <2 x float> poison, float %2, i64 0 + %r = insertelement <2 x float> %5, float %4, i64 1 + ret <2 x float> %r +} + +define <2 x i32> @replace_through_int_casts(i16 %inp, <2 x i16> %dead) { +; CHECK-LABEL: define <2 x i32> @replace_through_int_casts( +; CHECK-SAME: i16 [[INP:%.*]], <2 x i16> [[DEAD:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[INP]], -10 +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i16> poison, i16 [[INP]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i16> [[TMP1]], i16 [[ADD]], i32 1 +; CHECK-NEXT: [[TMP3:%.*]] = zext <2 x i16> [[TMP2]] to <2 x i32> +; CHECK-NEXT: [[TMP4:%.*]] = sext <2 x i16> [[TMP2]] to <2 x i32> +; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[R]] +; + %add = add nsw i16 %inp, -10 + %1 = zext i16 %inp to i32 + %2 = sext i16 %add to i32 + %3 = insertelement <2 x i32> poison, i32 %1, i64 0 + %r = insertelement <2 x i32> %3, i32 %2, i64 1 + ret <2 x i32> %r +} + +define <2 x i32> @replace_through_int_casts_ele0_only(i16 %inp, <2 x i16> %dead) { +; CHECK-LABEL: define <2 x i32> @replace_through_int_casts_ele0_only( +; CHECK-SAME: i16 [[INP:%.*]], <2 x i16> [[DEAD:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i16> poison, i16 [[INP]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x i16> [[TMP1]], <2 x i16> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = zext <2 x i16> [[TMP2]] to <2 x i32> +; CHECK-NEXT: [[TMP4:%.*]] = sext <2 x i16> [[TMP2]] to <2 x i32> +; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[R]] +; + %2 = sext i16 %inp to i32 + %4 = zext i16 %inp to i32 + %5 = insertelement <2 x i32> poison, i32 %4, i64 0 + %r = insertelement <2 x i32> %5, i32 %2, i64 1 + ret <2 x i32> %r +} + +define <2 x i8> @replace_through_binop_fail_cant_speculate(i8 %inp, <2 x i8> %d, <2 x i8> %any) { +; CHECK-LABEL: define <2 x i8> @replace_through_binop_fail_cant_speculate( +; CHECK-SAME: i8 [[INP:%.*]], <2 x i8> [[D:%.*]], <2 x i8> [[ANY:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[INP]], 5 +; CHECK-NEXT: [[V0:%.*]] = insertelement <2 x i8> poison, i8 [[INP]], i64 0 +; CHECK-NEXT: [[V:%.*]] = insertelement <2 x i8> [[V0]], i8 [[ADD]], i64 1 +; CHECK-NEXT: [[DIV0:%.*]] = sdiv <2 x i8> , [[V]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[INP]], 123 +; CHECK-NEXT: [[R:%.*]] = insertelement <2 x i8> [[DIV0]], i8 [[TMP1]], i64 0 +; CHECK-NEXT: ret <2 x i8> [[R]] +; + %add = add i8 %inp, 5 + %v0 = insertelement <2 x i8> poison, i8 %inp, i64 0 + %v = insertelement <2 x i8> %v0, i8 %add, i64 1 + %div0 = sdiv <2 x i8> , %v + %1 = xor i8 %inp, 123 + %r = insertelement <2 x i8> %div0, i8 %1, i64 0 + ret <2 x i8> %r +} + +define <2 x i8> @replace_through_binop_preserve_flags(i8 %inp, <2 x i8> %d, <2 x i8> %any) { +; CHECK-LABEL: define <2 x i8> @replace_through_binop_preserve_flags( +; CHECK-SAME: i8 [[INP:%.*]], <2 x i8> [[D:%.*]], <2 x i8> [[ANY:%.*]]) { +; CHECK-NEXT: [[ADD:%.*]] = xor i8 [[INP]], 5 +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> poison, i8 [[INP]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x i8> [[TMP1]], i8 [[ADD]], i32 1 +; CHECK-NEXT: [[TMP3:%.*]] = xor <2 x i8> [[TMP2]], +; CHECK-NEXT: [[TMP4:%.*]] = add nsw <2 x i8> [[TMP2]], +; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x i8> [[TMP3]], <2 x i8> [[TMP4]], <2 x i32> +; CHECK-NEXT: ret <2 x i8> [[R]] +; + %add = xor i8 %inp, 5 + %1 = xor i8 %inp, 123 + %2 = add nsw i8 %add, 1 + %3 = insertelement <2 x i8> poison, i8 %1, i64 0 + %r = insertelement <2 x i8> %3, i8 %2, i64 1 + ret <2 x i8> %r +} -- GitLab From 2377beba8d10ce1092db7f8ddd5b10a2c0d3bfd1 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Tue, 12 Mar 2024 13:33:12 -0700 Subject: [PATCH 296/953] [Fuchsia] Add LLDB_TEST_USE_VENDOR_PACKAGES to boostrap passthrough --- clang/cmake/caches/Fuchsia.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/cmake/caches/Fuchsia.cmake b/clang/cmake/caches/Fuchsia.cmake index fe925901eb3d..1209fd935986 100644 --- a/clang/cmake/caches/Fuchsia.cmake +++ b/clang/cmake/caches/Fuchsia.cmake @@ -65,6 +65,7 @@ set(_FUCHSIA_BOOTSTRAP_PASSTHROUGH LLDB_EMBED_PYTHON_HOME LLDB_PYTHON_HOME LLDB_PYTHON_RELATIVE_PATH + LLDB_TEST_USE_VENDOR_PACKAGES Python3_EXECUTABLE Python3_LIBRARIES Python3_INCLUDE_DIRS -- GitLab From 54f631d11640732af0dc9c2aa53af4e118d9fe36 Mon Sep 17 00:00:00 2001 From: "S. Bharadwaj Yadavalli" Date: Tue, 12 Mar 2024 16:51:18 -0400 Subject: [PATCH 297/953] [DirectX][NFC] Model precise overload type specification of DXIL Ops (#83917) Implement an abstraction to specify precise overload types supported by DXIL ops. These overload types are typically a subset of LLVM intrinsics. Implement the corresponding changes in DXILEmitter backend. Add tests to verify expected errors for unsupported overload types at code generation time. Add tests to check for correct overload error output. --- llvm/lib/Target/DirectX/DXIL.td | 55 ++++++++- llvm/lib/Target/DirectX/DXILOpBuilder.cpp | 4 +- llvm/test/CodeGen/DirectX/exp2_error.ll | 13 ++ llvm/test/CodeGen/DirectX/frac.ll | 3 - llvm/test/CodeGen/DirectX/frac_error.ll | 14 +++ llvm/test/CodeGen/DirectX/round_error.ll | 13 ++ llvm/test/CodeGen/DirectX/sin.ll | 22 +--- llvm/test/CodeGen/DirectX/sin_error.ll | 14 +++ llvm/utils/TableGen/DXILEmitter.cpp | 140 +++++++++++++++------- 9 files changed, 203 insertions(+), 75 deletions(-) create mode 100644 llvm/test/CodeGen/DirectX/exp2_error.ll create mode 100644 llvm/test/CodeGen/DirectX/frac_error.ll create mode 100644 llvm/test/CodeGen/DirectX/round_error.ll create mode 100644 llvm/test/CodeGen/DirectX/sin_error.ll diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index 9536a01e125b..66b0ef24332c 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -205,28 +205,71 @@ defset list OpClasses = { def writeSamplerFeedbackBias : DXILOpClass; def writeSamplerFeedbackGrad : DXILOpClass; def writeSamplerFeedbackLevel: DXILOpClass; + + // This is a sentinel definition. Hence placed at the end of the list + // and not as part of the above alphabetically sorted valid definitions. + // Additionally it is capitalized unlike all the others. + def UnknownOpClass: DXILOpClass; +} + +// Several of the overloaded DXIL Operations support for data types +// that are a subset of the overloaded LLVM intrinsics that they map to. +// For e.g., llvm.sin.* intrinsic operates on any floating-point type and +// maps for lowering to DXIL Op Sin. However, valid overloads of DXIL Sin +// operation overloads are half (f16) and float (f32) only. +// +// The following abstracts overload types specific to DXIL operations. + +class DXILType : LLVMType { + let isAny = 1; + int isI16OrI32 = 0; + int isHalfOrFloat = 0; } +// Concrete records for various overload types supported specifically by +// DXIL Operations. +let isI16OrI32 = 1 in + def llvm_i16ori32_ty : DXILType; + +let isHalfOrFloat = 1 in + def llvm_halforfloat_ty : DXILType; + // Abstraction DXIL Operation to LLVM intrinsic -class DXILOpMapping { +class DXILOpMappingBase { + int OpCode = 0; // Opcode of DXIL Operation + DXILOpClass OpClass = UnknownOpClass;// Class of DXIL Operation. + Intrinsic LLVMIntrinsic = ?; // LLVM Intrinsic DXIL Operation maps to + string Doc = ""; // A short description of the operation + list OpTypes = ?; // Valid types of DXIL Operation in the + // format [returnTy, param1ty, ...] +} + +class DXILOpMapping opTys = []> : DXILOpMappingBase { int OpCode = opCode; // Opcode corresponding to DXIL Operation - DXILOpClass OpClass = opClass; // Class of DXIL Operation. + DXILOpClass OpClass = opClass; // Class of DXIL Operation. Intrinsic LLVMIntrinsic = intrinsic; // LLVM Intrinsic the DXIL Operation maps string Doc = doc; // to a short description of the operation + list OpTypes = !if(!eq(!size(opTys), 0), LLVMIntrinsic.Types, opTys); } // Concrete definition of DXIL Operation mapping to corresponding LLVM intrinsic def Sin : DXILOpMapping<13, unary, int_sin, - "Returns sine(theta) for theta in radians.">; + "Returns sine(theta) for theta in radians.", + [llvm_halforfloat_ty, LLVMMatchType<0>]>; def Exp2 : DXILOpMapping<21, unary, int_exp2, "Returns the base 2 exponential, or 2**x, of the specified value." - "exp2(x) = 2**x.">; + "exp2(x) = 2**x.", + [llvm_halforfloat_ty, LLVMMatchType<0>]>; def Frac : DXILOpMapping<22, unary, int_dx_frac, "Returns a fraction from 0 to 1 that represents the " - "decimal part of the input.">; + "decimal part of the input.", + [llvm_halforfloat_ty, LLVMMatchType<0>]>; def Round : DXILOpMapping<26, unary, int_round, "Returns the input rounded to the nearest integer" - "within a floating-point type.">; + "within a floating-point type.", + [llvm_halforfloat_ty, LLVMMatchType<0>]>; def UMax : DXILOpMapping<39, binary, int_umax, "Unsigned integer maximum. UMax(a,b) = a > b ? a : b">; def FMad : DXILOpMapping<46, tertiary, int_fmuladd, diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp index 21a20d45b922..11b24d044923 100644 --- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp +++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp @@ -254,10 +254,8 @@ static FunctionCallee getOrCreateDXILOpFunction(dxil::OpCode DXILOp, const OpCodeProperty *Prop = getOpCodeProperty(DXILOp); OverloadKind Kind = getOverloadKind(OverloadTy); - // FIXME: find the issue and report error in clang instead of check it in - // backend. if ((Prop->OverloadTys & (uint16_t)Kind) == 0) { - llvm_unreachable("invalid overload"); + report_fatal_error("Invalid Overload Type", /* gen_crash_diag=*/false); } std::string FnName = constructOverloadName(Kind, OverloadTy, *Prop); diff --git a/llvm/test/CodeGen/DirectX/exp2_error.ll b/llvm/test/CodeGen/DirectX/exp2_error.ll new file mode 100644 index 000000000000..6b9126785fd4 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/exp2_error.ll @@ -0,0 +1,13 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation exp2 does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload + +define noundef double @exp2_double(double noundef %a) #0 { +entry: + %a.addr = alloca double, align 8 + store double %a, ptr %a.addr, align 8 + %0 = load double, ptr %a.addr, align 8 + %elt.exp2 = call double @llvm.exp2.f64(double %0) + ret double %elt.exp2 +} diff --git a/llvm/test/CodeGen/DirectX/frac.ll b/llvm/test/CodeGen/DirectX/frac.ll index ab605ed6084a..ae86fe06654d 100644 --- a/llvm/test/CodeGen/DirectX/frac.ll +++ b/llvm/test/CodeGen/DirectX/frac.ll @@ -29,6 +29,3 @@ entry: %dx.frac = call half @llvm.dx.frac.f16(half %0) ret half %dx.frac } - -; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn -declare half @llvm.dx.frac.f16(half) #1 diff --git a/llvm/test/CodeGen/DirectX/frac_error.ll b/llvm/test/CodeGen/DirectX/frac_error.ll new file mode 100644 index 000000000000..ebce76105ad4 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/frac_error.ll @@ -0,0 +1,14 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation frac does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload Type + +; Function Attrs: noinline nounwind optnone +define noundef double @frac_double(double noundef %a) #0 { +entry: + %a.addr = alloca double, align 8 + store double %a, ptr %a.addr, align 8 + %0 = load double, ptr %a.addr, align 8 + %dx.frac = call double @llvm.dx.frac.f64(double %0) + ret double %dx.frac +} diff --git a/llvm/test/CodeGen/DirectX/round_error.ll b/llvm/test/CodeGen/DirectX/round_error.ll new file mode 100644 index 000000000000..3bd87b2bbf02 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/round_error.ll @@ -0,0 +1,13 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; This test is expected to fail with the following error +; CHECK: LLVM ERROR: Invalid Overload Type + +define noundef double @round_double(double noundef %a) #0 { +entry: + %a.addr = alloca double, align 8 + store double %a, ptr %a.addr, align 8 + %0 = load double, ptr %a.addr, align 8 + %elt.round = call double @llvm.round.f64(double %0) + ret double %elt.round +} diff --git a/llvm/test/CodeGen/DirectX/sin.ll b/llvm/test/CodeGen/DirectX/sin.ll index bb31d28bfcfe..1f285c433581 100644 --- a/llvm/test/CodeGen/DirectX/sin.ll +++ b/llvm/test/CodeGen/DirectX/sin.ll @@ -4,11 +4,8 @@ ; CHECK:call float @dx.op.unary.f32(i32 13, float %{{.*}}) ; CHECK:call half @dx.op.unary.f16(i32 13, half %{{.*}}) -target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" -target triple = "dxil-pc-shadermodel6.7-library" - ; Function Attrs: noinline nounwind optnone -define noundef float @_Z3foof(float noundef %a) #0 { +define noundef float @sin_float(float noundef %a) #0 { entry: %a.addr = alloca float, align 4 store float %a, ptr %a.addr, align 4 @@ -17,11 +14,8 @@ entry: ret float %1 } -; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn -declare float @llvm.sin.f32(float) #1 - ; Function Attrs: noinline nounwind optnone -define noundef half @_Z3barDh(half noundef %a) #0 { +define noundef half @sin_half(half noundef %a) #0 { entry: %a.addr = alloca half, align 2 store half %a, ptr %a.addr, align 2 @@ -29,15 +23,3 @@ entry: %1 = call half @llvm.sin.f16(half %0) ret half %1 } - -; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn -declare half @llvm.sin.f16(half) #1 - -attributes #0 = { noinline nounwind optnone "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } -attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"wchar_size", i32 4} -!1 = !{!"clang version 15.0.0 (https://github.com/llvm/llvm-project.git 73417c517644db5c419c85c0b3cb6750172fcab5)"} diff --git a/llvm/test/CodeGen/DirectX/sin_error.ll b/llvm/test/CodeGen/DirectX/sin_error.ll new file mode 100644 index 000000000000..ece0e530315b --- /dev/null +++ b/llvm/test/CodeGen/DirectX/sin_error.ll @@ -0,0 +1,14 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation sin does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload + +define noundef double @sin_double(double noundef %a) #0 { +entry: + %a.addr = alloca double, align 8 + store double %a, ptr %a.addr, align 8 + %0 = load double, ptr %a.addr, align 8 + %1 = call double @llvm.sin.f64(double %0) + ret double %1 +} + diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp index fc958f532873..59089929837e 100644 --- a/llvm/utils/TableGen/DXILEmitter.cpp +++ b/llvm/utils/TableGen/DXILEmitter.cpp @@ -22,6 +22,7 @@ #include "llvm/Support/DXILABI.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" +#include using namespace llvm; using namespace llvm::dxil; @@ -38,8 +39,8 @@ struct DXILOperationDesc { int OpCode; // ID of DXIL operation StringRef OpClass; // name of the opcode class StringRef Doc; // the documentation description of this instruction - SmallVector OpTypes; // Vector of operand types - - // return type is at index 0 + SmallVector OpTypes; // Vector of operand type records - + // return type is at index 0 SmallVector OpAttributes; // operation attribute represented as strings StringRef Intrinsic; // The llvm intrinsic map to OpName. Default is "" which @@ -57,20 +58,21 @@ struct DXILOperationDesc { DXILShaderModel ShaderModel; // minimum shader model required DXILShaderModel ShaderModelTranslated; // minimum shader model required with // translation by linker - int OverloadParamIndex; // parameter index which control the overload. - // When < 0, should be only 1 overload type. + int OverloadParamIndex; // Index of parameter with overload type. + // -1 : no overload types SmallVector counters; // counters for this inst. DXILOperationDesc(const Record *); }; } // end anonymous namespace -/// Convert DXIL type name string to dxil::ParameterKind +/// Return dxil::ParameterKind corresponding to input LLVMType record /// -/// \param VT Simple Value Type +/// \param R TableGen def record of class LLVMType /// \return ParameterKind As defined in llvm/Support/DXILABI.h -static ParameterKind getParameterKind(MVT::SimpleValueType VT) { - switch (VT) { +static ParameterKind getParameterKind(const Record *R) { + auto VTRec = R->getValueAsDef("VT"); + switch (getValueType(VTRec)) { case MVT::isVoid: return ParameterKind::VOID; case MVT::f16: @@ -90,6 +92,12 @@ static ParameterKind getParameterKind(MVT::SimpleValueType VT) { case MVT::fAny: case MVT::iAny: return ParameterKind::OVERLOAD; + case MVT::Other: + // Handle DXIL-specific overload types + if (R->getValueAsInt("isHalfOrFloat") || R->getValueAsInt("isI16OrI32")) { + return ParameterKind::OVERLOAD; + } + LLVM_FALLTHROUGH; default: llvm_unreachable("Support for specified DXIL Type not yet implemented"); } @@ -106,45 +114,80 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) { Doc = R->getValueAsString("Doc"); + auto TypeRecs = R->getValueAsListOfDefs("OpTypes"); + unsigned TypeRecsSize = TypeRecs.size(); + // Populate OpTypes with return type and parameter types + + // Parameter indices of overloaded parameters. + // This vector contains overload parameters in the order order used to + // resolve an LLVMMatchType in accordance with convention outlined in + // the comment before the definition of class LLVMMatchType in + // llvm/IR/Intrinsics.td + SmallVector OverloadParamIndices; + for (unsigned i = 0; i < TypeRecsSize; i++) { + auto TR = TypeRecs[i]; + // Track operation parameter indices of any overload types + auto isAny = TR->getValueAsInt("isAny"); + if (isAny == 1) { + // TODO: At present it is expected that all overload types in a DXIL Op + // are of the same type. Hence, OverloadParamIndices will have only one + // element. This implies we do not need a vector. However, until more + // (all?) DXIL Ops are added in DXIL.td, a vector is being used to flag + // cases this assumption would not hold. + if (!OverloadParamIndices.empty()) { + bool knownType = true; + // Ensure that the same overload type registered earlier is being used + for (auto Idx : OverloadParamIndices) { + if (TR != TypeRecs[Idx]) { + knownType = false; + break; + } + } + if (!knownType) { + report_fatal_error("Specification of multiple differing overload " + "parameter types not yet supported", + false); + } + } else { + OverloadParamIndices.push_back(i); + } + } + // Populate OpTypes array according to the type specification + if (TR->isAnonymous()) { + // Check prior overload types exist + assert(!OverloadParamIndices.empty() && + "No prior overloaded parameter found to match."); + // Get the parameter index of anonymous type, TR, references + auto OLParamIndex = TR->getValueAsInt("Number"); + // Resolve and insert the type to that at OLParamIndex + OpTypes.emplace_back(TypeRecs[OLParamIndex]); + } else { + // A non-anonymous type. Just record it in OpTypes + OpTypes.emplace_back(TR); + } + } + + // Set the index of the overload parameter, if any. + OverloadParamIndex = -1; // default; indicating none + if (!OverloadParamIndices.empty()) { + if (OverloadParamIndices.size() > 1) + report_fatal_error("Multiple overload type specification not supported", + false); + OverloadParamIndex = OverloadParamIndices[0]; + } + // Get the operation class + OpClass = R->getValueAsDef("OpClass")->getName(); + if (R->getValue("LLVMIntrinsic")) { auto *IntrinsicDef = R->getValueAsDef("LLVMIntrinsic"); auto DefName = IntrinsicDef->getName(); assert(DefName.starts_with("int_") && "invalid intrinsic name"); // Remove the int_ from intrinsic name. Intrinsic = DefName.substr(4); - // TODO: It is expected that return type and parameter types of - // DXIL Operation are the same as that of the intrinsic. Deviations - // are expected to be encoded in TableGen record specification and - // handled accordingly here. Support to be added later, as needed. - // Get parameter type list of the intrinsic. Types attribute contains - // the list of as [returnType, param1Type,, param2Type, ...] - - OverloadParamIndex = -1; - auto TypeRecs = IntrinsicDef->getValueAsListOfDefs("Types"); - unsigned TypeRecsSize = TypeRecs.size(); - // Populate return type and parameter type names - for (unsigned i = 0; i < TypeRecsSize; i++) { - auto TR = TypeRecs[i]; - OpTypes.emplace_back(getValueType(TR->getValueAsDef("VT"))); - // Get the overload parameter index. - // TODO : Seems hacky. Is it possible that more than one parameter can - // be of overload kind?? - // TODO: Check for any additional constraints specified for DXIL operation - // restricting return type. - if (i > 0) { - auto &CurParam = OpTypes.back(); - if (getParameterKind(CurParam) >= ParameterKind::OVERLOAD) { - OverloadParamIndex = i; - } - } - } - // Get the operation class - OpClass = R->getValueAsDef("OpClass")->getName(); - - // NOTE: For now, assume that attributes of DXIL Operation are the same as + // TODO: For now, assume that attributes of DXIL Operation are the same as // that of the intrinsic. Deviations are expected to be encoded in TableGen // record specification and handled accordingly here. Support to be added - // later. + // as needed. auto IntrPropList = IntrinsicDef->getValueAsListInit("IntrProperties"); auto IntrPropListSize = IntrPropList->size(); for (unsigned i = 0; i < IntrPropListSize; i++) { @@ -191,12 +234,13 @@ static std::string getParameterKindStr(ParameterKind Kind) { } /// Return a string representation of OverloadKind enum that maps to -/// input Simple Value Type enum -/// \param VT Simple Value Type enum +/// input LLVMType record +/// \param R TableGen def record of class LLVMType /// \return std::string string representation of OverloadKind -static std::string getOverloadKindStr(MVT::SimpleValueType VT) { - switch (VT) { +static std::string getOverloadKindStr(const Record *R) { + auto VTRec = R->getValueAsDef("VT"); + switch (getValueType(VTRec)) { case MVT::isVoid: return "OverloadKind::VOID"; case MVT::f16: @@ -219,6 +263,16 @@ static std::string getOverloadKindStr(MVT::SimpleValueType VT) { return "OverloadKind::I16 | OverloadKind::I32 | OverloadKind::I64"; case MVT::fAny: return "OverloadKind::HALF | OverloadKind::FLOAT | OverloadKind::DOUBLE"; + case MVT::Other: + // Handle DXIL-specific overload types + { + if (R->getValueAsInt("isHalfOrFloat")) { + return "OverloadKind::HALF | OverloadKind::FLOAT"; + } else if (R->getValueAsInt("isI16OrI32")) { + return "OverloadKind::I16 | OverloadKind::I32"; + } + } + LLVM_FALLTHROUGH; default: llvm_unreachable( "Support for specified parameter OverloadKind not yet implemented"); -- GitLab From e9492ccae085b5feb850ff17a96fe8211f7f6d7d Mon Sep 17 00:00:00 2001 From: Jason Eckhardt Date: Tue, 12 Mar 2024 16:01:58 -0500 Subject: [PATCH 298/953] [TableGen] DecoderEmitter clean-ups and modernization. (#84832) The decoder emitter is showing some signs of age. This patch makes a few kinds of clean-ups: - Use ranged-for more widely, including using enumerate() for those loops maintaining a loop index along with the items. - Reduce the number of arguments to fieldFromInsn (removes an out reference parameter: CodingStandards). The insn_t argument to insnWithID can/should probably be removed soon too since modern C++ allows us to return a local container without a copy. - Use raw strings for the large emitted code segments. This enhances both readability and modifiability. --- llvm/utils/TableGen/DecoderEmitter.cpp | 653 ++++++++++++------------- 1 file changed, 317 insertions(+), 336 deletions(-) diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp index 88f245238138..dd78dc02159b 100644 --- a/llvm/utils/TableGen/DecoderEmitter.cpp +++ b/llvm/utils/TableGen/DecoderEmitter.cpp @@ -226,7 +226,7 @@ static BitsInit &getBitsField(const Record &def, StringRef str) { VarLenInst VLI = VarLenInst(cast(RV->getValue()), RV); SmallVector Bits; - for (auto &SI : VLI) { + for (const auto &SI : VLI) { if (const BitsInit *BI = dyn_cast(SI.Value)) { for (unsigned Idx = 0U; Idx < BI->getNumBits(); ++Idx) { Bits.push_back(BI->getBit(Idx)); @@ -441,16 +441,15 @@ public: protected: // Populates the insn given the uid. void insnWithID(insn_t &Insn, unsigned Opcode) const { - BitsInit &Bits = getBitsField(*AllInstructions[Opcode].EncodingDef, "Inst"); - Insn.resize(BitWidth > Bits.getNumBits() ? BitWidth : Bits.getNumBits(), - BIT_UNSET); + const Record *EncodingDef = AllInstructions[Opcode].EncodingDef; + BitsInit &Bits = getBitsField(*EncodingDef, "Inst"); + Insn.resize(std::max(BitWidth, Bits.getNumBits()), BIT_UNSET); // We may have a SoftFail bitmask, which specifies a mask where an encoding // may differ from the value in "Inst" and yet still be valid, but the // disassembler should return SoftFail instead of Success. // // This is used for marking UNPREDICTABLE instructions in the ARM world. - const RecordVal *RV = - AllInstructions[Opcode].EncodingDef->getValue("SoftFail"); + const RecordVal *RV = EncodingDef->getValue("SoftFail"); const BitsInit *SFBits = RV ? dyn_cast(RV->getValue()) : nullptr; for (unsigned i = 0; i < Bits.getNumBits(); ++i) { if (SFBits && bitFromBits(*SFBits, i) == BIT_TRUE) @@ -472,10 +471,11 @@ protected: // Populates the field of the insn given the start position and the number of // consecutive bits to scan for. // - // Returns false if there exists any uninitialized bit value in the range. - // Returns true, otherwise. - bool fieldFromInsn(uint64_t &Field, insn_t &Insn, unsigned StartBit, - unsigned NumBits) const; + // Returns a pair of values (indicator, field), where the indicator is false + // if there exists any uninitialized bit value in the range and true if all + // bits are well-known. The second value is the potentially populated field. + std::pair fieldFromInsn(const insn_t &Insn, unsigned StartBit, + unsigned NumBits) const; /// dumpFilterArray - dumpFilterArray prints out debugging info for the given /// filter array as a series of chars. @@ -581,26 +581,25 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, NumFiltered = 0; LastOpcFiltered = {0, 0}; - for (unsigned i = 0, e = Owner->Opcodes.size(); i != e; ++i) { + for (const auto &OpcPair : Owner->Opcodes) { insn_t Insn; // Populates the insn given the uid. - Owner->insnWithID(Insn, Owner->Opcodes[i].EncodingID); + Owner->insnWithID(Insn, OpcPair.EncodingID); - uint64_t Field; // Scans the segment for possibly well-specified encoding bits. - bool ok = Owner->fieldFromInsn(Field, Insn, StartBit, NumBits); + auto [Ok, Field] = Owner->fieldFromInsn(Insn, StartBit, NumBits); - if (ok) { + if (Ok) { // The encoding bits are well-known. Lets add the uid of the // instruction into the bucket keyed off the constant field value. - LastOpcFiltered = Owner->Opcodes[i]; + LastOpcFiltered = OpcPair; FilteredInstructions[Field].push_back(LastOpcFiltered); ++NumFiltered; } else { // Some of the encoding bit(s) are unspecified. This contributes to // one additional member of "Variable" instructions. - VariableInstructions.push_back(Owner->Opcodes[i]); + VariableInstructions.push_back(OpcPair); } } @@ -699,7 +698,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { size_t PrevFilter = 0; bool HasFallthrough = false; - for (auto &Filter : FilterChooserMap) { + for (const auto &Filter : FilterChooserMap) { // Field value -1 implies a non-empty set of variable instructions. // See also recurse(). if (Filter.first == NO_FIXED_SEGMENTS_SENTINEL) { @@ -784,7 +783,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, // is used below to index into NumberedEncodings. DenseMap OpcodeToEncodingID; OpcodeToEncodingID.reserve(EncodingIDs.size()); - for (auto &EI : EncodingIDs) + for (const auto &EI : EncodingIDs) OpcodeToEncodingID[EI.Opcode] = EI.EncodingID; OS.indent(Indentation) << "static const uint8_t DecoderTable" << Namespace @@ -1038,27 +1037,29 @@ void DecoderEmitter::emitDecoderFunction(formatted_raw_ostream &OS, } OS.indent(Indentation) << "}\n"; Indentation -= 2; - OS.indent(Indentation) << "}\n\n"; + OS.indent(Indentation) << "}\n"; } // Populates the field of the insn given the start position and the number of // consecutive bits to scan for. // -// Returns false if and on the first uninitialized bit value encountered. -// Returns true, otherwise. -bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn, - unsigned StartBit, unsigned NumBits) const { - Field = 0; +// Returns a pair of values (indicator, field), where the indicator is false +// if there exists any uninitialized bit value in the range and true if all +// bits are well-known. The second value is the potentially populated field. +std::pair FilterChooser::fieldFromInsn(const insn_t &Insn, + unsigned StartBit, + unsigned NumBits) const { + uint64_t Field = 0; for (unsigned i = 0; i < NumBits; ++i) { if (Insn[StartBit + i] == BIT_UNSET) - return false; + return {false, Field}; if (Insn[StartBit + i] == BIT_TRUE) Field = Field | (1ULL << i); } - return true; + return {true, Field}; } /// dumpFilterArray - dumpFilterArray prints out debugging info for the given @@ -1246,14 +1247,14 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders, unsigned Opc, // If ParenIfBinOp is true, print a surrounding () if Val uses && or ||. bool FilterChooser::emitPredicateMatchAux(const Init &Val, bool ParenIfBinOp, raw_ostream &OS) const { - if (auto *D = dyn_cast(&Val)) { + if (const auto *D = dyn_cast(&Val)) { if (!D->getDef()->isSubClassOf("SubtargetFeature")) return true; OS << "Bits[" << Emitter->PredicateNamespace << "::" << D->getAsString() << "]"; return false; } - if (auto *D = dyn_cast(&Val)) { + if (const auto *D = dyn_cast(&Val)) { std::string Op = D->getOperator()->getAsString(); if (Op == "not" && D->getNumArgs() == 1) { OS << '!'; @@ -1350,9 +1351,9 @@ void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo, encodeULEB128(PIdx, S); TableInfo.Table.push_back(MCD::OPC_CheckPredicate); - // Predicate index - for (unsigned i = 0, e = PBytes.size(); i != e; ++i) - TableInfo.Table.push_back(PBytes[i]); + // Predicate index. + for (const auto PB : PBytes) + TableInfo.Table.push_back(PB); // Push location for NumToSkip backpatching. TableInfo.FixupStack.back().push_back(TableInfo.Table.size()); TableInfo.Table.push_back(0); @@ -1362,13 +1363,13 @@ void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo, void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo, unsigned Opc) const { - const RecordVal *RV = AllInstructions[Opc].EncodingDef->getValue("SoftFail"); + const Record *EncodingDef = AllInstructions[Opc].EncodingDef; + const RecordVal *RV = EncodingDef->getValue("SoftFail"); BitsInit *SFBits = RV ? dyn_cast(RV->getValue()) : nullptr; if (!SFBits) return; - BitsInit *InstBits = - AllInstructions[Opc].EncodingDef->getValueAsBitsInit("Inst"); + BitsInit *InstBits = EncodingDef->getValueAsBitsInit("Inst"); APInt PositiveMask(BitWidth, 0ULL); APInt NegativeMask(BitWidth, 0ULL); @@ -1495,9 +1496,9 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, raw_svector_ostream S(Bytes); encodeULEB128(DIdx, S); - // Decoder index - for (unsigned i = 0, e = Bytes.size(); i != e; ++i) - TableInfo.Table.push_back(Bytes[i]); + // Decoder index. + for (const auto B : Bytes) + TableInfo.Table.push_back(B); if (!HasCompleteDecoder) { // Push location for NumToSkip backpatching. @@ -1566,7 +1567,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { if (AllowMixed && !Greedy) { assert(numInstructions == 3); - for (auto Opcode : Opcodes) { + for (const auto &Opcode : Opcodes) { std::vector StartBits; std::vector EndBits; std::vector FieldVals; @@ -1613,10 +1614,10 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { else bitAttrs.push_back(ATTR_NONE); - for (unsigned InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) { + for (const auto &OpcPair : Opcodes) { insn_t insn; - insnWithID(insn, Opcodes[InsnIndex].EncodingID); + insnWithID(insn, OpcPair.EncodingID); for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) { switch (bitAttrs[BitIndex]) { @@ -1760,14 +1761,14 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { bool AllUseless = true; unsigned BestScore = 0; - for (unsigned i = 0, e = Filters.size(); i != e; ++i) { - unsigned Usefulness = Filters[i].usefulness(); + for (const auto &[Idx, Filter] : enumerate(Filters)) { + unsigned Usefulness = Filter.usefulness(); if (Usefulness) AllUseless = false; if (Usefulness > BestScore) { - BestIndex = i; + BestIndex = Idx; BestScore = Usefulness; } } @@ -1892,8 +1893,7 @@ void parseVarLenInstOperand(const Record &Def, VarLenInst VLI(cast(RV->getValue()), RV); SmallVector TiedTo; - for (unsigned Idx = 0; Idx < CGI.Operands.size(); ++Idx) { - auto &Op = CGI.Operands[Idx]; + for (const auto &[Idx, Op] : enumerate(CGI.Operands)) { if (Op.MIOperandInfo && Op.MIOperandInfo->getNumArgs() > 0) for (auto *Arg : Op.MIOperandInfo->getArgs()) Operands.push_back(getOpInfo(cast(Arg)->getDef())); @@ -1909,7 +1909,7 @@ void parseVarLenInstOperand(const Record &Def, } unsigned CurrBitPos = 0; - for (auto &EncodingSegment : VLI) { + for (const auto &EncodingSegment : VLI) { unsigned Offset = 0; StringRef OpName; @@ -2028,26 +2028,23 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef, std::vector> InOutOperands; DagInit *Out = Def.getValueAsDag("OutOperandList"); DagInit *In = Def.getValueAsDag("InOperandList"); - for (unsigned i = 0; i < Out->getNumArgs(); ++i) - InOutOperands.push_back(std::pair(Out->getArg(i), Out->getArgNameStr(i))); - for (unsigned i = 0; i < In->getNumArgs(); ++i) - InOutOperands.push_back(std::pair(In->getArg(i), In->getArgNameStr(i))); + for (const auto &[Idx, Arg] : enumerate(Out->getArgs())) + InOutOperands.push_back(std::pair(Arg, Out->getArgNameStr(Idx))); + for (const auto &[Idx, Arg] : enumerate(In->getArgs())) + InOutOperands.push_back(std::pair(Arg, In->getArgNameStr(Idx))); // Search for tied operands, so that we can correctly instantiate // operands that are not explicitly represented in the encoding. std::map TiedNames; - for (unsigned i = 0; i < CGI.Operands.size(); ++i) { - auto &Op = CGI.Operands[i]; - for (unsigned j = 0; j < Op.Constraints.size(); ++j) { - const CGIOperandList::ConstraintInfo &CI = Op.Constraints[j]; + for (const auto &[I, Op] : enumerate(CGI.Operands)) { + for (const auto &[J, CI] : enumerate(Op.Constraints)) { if (CI.isTied()) { - int tiedTo = CI.getTiedOperand(); std::pair SO = - CGI.Operands.getSubOperandNumber(tiedTo); + CGI.Operands.getSubOperandNumber(CI.getTiedOperand()); std::string TiedName = CGI.Operands[SO.first].SubOpNames[SO.second]; if (TiedName.empty()) TiedName = CGI.Operands[SO.first].Name; - std::string MyName = Op.SubOpNames[j]; + std::string MyName = Op.SubOpNames[J]; if (MyName.empty()) MyName = Op.Name; @@ -2099,10 +2096,9 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef, // Decode each of the sub-ops separately. assert(SubOps && SubArgDag->getNumArgs() == SubOps->getNumArgs()); - for (unsigned i = 0; i < SubOps->getNumArgs(); ++i) { - StringRef SubOpName = SubArgDag->getArgNameStr(i); - OperandInfo SubOpInfo = - getOpInfo(cast(SubOps->getArg(i))->getDef()); + for (const auto &[I, Arg] : enumerate(SubOps->getArgs())) { + StringRef SubOpName = SubArgDag->getArgNameStr(I); + OperandInfo SubOpInfo = getOpInfo(cast(Arg)->getDef()); addOneOperandFields(EncodingDef, Bits, TiedNames, SubOpName, SubOpInfo); @@ -2169,273 +2165,253 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef, // using the VS compiler. It has a bug which causes the function // to be optimized out in some circumstances. See llvm.org/pr38292 static void emitFieldFromInstruction(formatted_raw_ostream &OS) { - OS << "// Helper functions for extracting fields from encoded instructions.\n" - << "// InsnType must either be integral or an APInt-like object that " - "must:\n" - << "// * be default-constructible and copy-constructible\n" - << "// * be constructible from an APInt (this can be private)\n" - << "// * Support insertBits(bits, startBit, numBits)\n" - << "// * Support extractBitsAsZExtValue(numBits, startBit)\n" - << "// * Support the ~, &, ==, and != operators with other objects of " - "the same type\n" - << "// * Support the != and bitwise & with uint64_t\n" - << "// * Support put (<<) to raw_ostream&\n" - << "template \n" - << "#if defined(_MSC_VER) && !defined(__clang__)\n" - << "__declspec(noinline)\n" - << "#endif\n" - << "static std::enable_if_t::value, InsnType>\n" - << "fieldFromInstruction(const InsnType &insn, unsigned startBit,\n" - << " unsigned numBits) {\n" - << " assert(startBit + numBits <= 64 && \"Cannot support >64-bit " - "extractions!\");\n" - << " assert(startBit + numBits <= (sizeof(InsnType) * 8) &&\n" - << " \"Instruction field out of bounds!\");\n" - << " InsnType fieldMask;\n" - << " if (numBits == sizeof(InsnType) * 8)\n" - << " fieldMask = (InsnType)(-1LL);\n" - << " else\n" - << " fieldMask = (((InsnType)1 << numBits) - 1) << startBit;\n" - << " return (insn & fieldMask) >> startBit;\n" - << "}\n" - << "\n" - << "template \n" - << "static std::enable_if_t::value, " - "uint64_t>\n" - << "fieldFromInstruction(const InsnType &insn, unsigned startBit,\n" - << " unsigned numBits) {\n" - << " return insn.extractBitsAsZExtValue(numBits, startBit);\n" - << "}\n\n"; + OS << R"( +// Helper functions for extracting fields from encoded instructions. +// InsnType must either be integral or an APInt-like object that must: +// * be default-constructible and copy-constructible +// * be constructible from an APInt (this can be private) +// * Support insertBits(bits, startBit, numBits) +// * Support extractBitsAsZExtValue(numBits, startBit) +// * Support the ~, &, ==, and != operators with other objects of the same type +// * Support the != and bitwise & with uint64_t +// * Support put (<<) to raw_ostream& +template +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(noinline) +#endif +static std::enable_if_t::value, InsnType> +fieldFromInstruction(const InsnType &insn, unsigned startBit, + unsigned numBits) { + assert(startBit + numBits <= 64 && "Cannot support >64-bit extractions!"); + assert(startBit + numBits <= (sizeof(InsnType) * 8) && + "Instruction field out of bounds!"); + InsnType fieldMask; + if (numBits == sizeof(InsnType) * 8) + fieldMask = (InsnType)(-1LL); + else + fieldMask = (((InsnType)1 << numBits) - 1) << startBit; + return (insn & fieldMask) >> startBit; +} + +template +static std::enable_if_t::value, uint64_t> +fieldFromInstruction(const InsnType &insn, unsigned startBit, + unsigned numBits) { + return insn.extractBitsAsZExtValue(numBits, startBit); +} +)"; } // emitInsertBits - Emit the templated helper function insertBits(). static void emitInsertBits(formatted_raw_ostream &OS) { - OS << "// Helper function for inserting bits extracted from an encoded " - "instruction into\n" - << "// a field.\n" - << "template \n" - << "static std::enable_if_t::value>\n" - << "insertBits(InsnType &field, InsnType bits, unsigned startBit, " - "unsigned numBits) {\n" - << " assert(startBit + numBits <= sizeof field * 8);\n" - << " field |= (InsnType)bits << startBit;\n" - << "}\n" - << "\n" - << "template \n" - << "static std::enable_if_t::value>\n" - << "insertBits(InsnType &field, uint64_t bits, unsigned startBit, " - "unsigned numBits) {\n" - << " field.insertBits(bits, startBit, numBits);\n" - << "}\n\n"; + OS << R"( +// Helper function for inserting bits extracted from an encoded instruction into +// a field. +template +static std::enable_if_t::value> +insertBits(InsnType &field, InsnType bits, unsigned startBit, unsigned numBits) { + assert(startBit + numBits <= sizeof field * 8); + field |= (InsnType)bits << startBit; +} + +template +static std::enable_if_t::value> +insertBits(InsnType &field, uint64_t bits, unsigned startBit, unsigned numBits) { + field.insertBits(bits, startBit, numBits); +} +)"; } // emitDecodeInstruction - Emit the templated helper function // decodeInstruction(). static void emitDecodeInstruction(formatted_raw_ostream &OS, bool IsVarLenInst) { - OS << "template \n" - << "static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], " - "MCInst &MI,\n" - << " InsnType insn, uint64_t " - "Address,\n" - << " const MCDisassembler *DisAsm,\n" - << " const MCSubtargetInfo &STI"; + OS << R"( +template +static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, + InsnType insn, uint64_t Address, + const MCDisassembler *DisAsm, + const MCSubtargetInfo &STI)"; if (IsVarLenInst) { - OS << ",\n" - << " llvm::function_ref makeUp"; + OS << ",\n " + "llvm::function_ref makeUp"; } - OS << ") {\n" - << " const FeatureBitset &Bits = STI.getFeatureBits();\n" - << "\n" - << " const uint8_t *Ptr = DecodeTable;\n" - << " uint64_t CurFieldValue = 0;\n" - << " DecodeStatus S = MCDisassembler::Success;\n" - << " while (true) {\n" - << " ptrdiff_t Loc = Ptr - DecodeTable;\n" - << " switch (*Ptr) {\n" - << " default:\n" - << " errs() << Loc << \": Unexpected decode table opcode!\\n\";\n" - << " return MCDisassembler::Fail;\n" - << " case MCD::OPC_ExtractField: {\n" - << " // Decode the start value.\n" - << " unsigned DecodedLen;\n" - << " unsigned Start = decodeULEB128(++Ptr, &DecodedLen);\n" - << " Ptr += DecodedLen;\n" - << " unsigned Len = *Ptr++;\n"; + OS << R"() { + const FeatureBitset &Bits = STI.getFeatureBits(); + + const uint8_t *Ptr = DecodeTable; + uint64_t CurFieldValue = 0; + DecodeStatus S = MCDisassembler::Success; + while (true) { + ptrdiff_t Loc = Ptr - DecodeTable; + switch (*Ptr) { + default: + errs() << Loc << ": Unexpected decode table opcode!\n"; + return MCDisassembler::Fail; + case MCD::OPC_ExtractField: { + // Decode the start value. + unsigned DecodedLen; + unsigned Start = decodeULEB128(++Ptr, &DecodedLen); + Ptr += DecodedLen; + unsigned Len = *Ptr++;)"; if (IsVarLenInst) - OS << " makeUp(insn, Start + Len);\n"; - OS << " CurFieldValue = fieldFromInstruction(insn, Start, Len);\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_ExtractField(\" << Start << " - "\", \"\n" - << " << Len << \"): \" << CurFieldValue << \"\\n\");\n" - << " break;\n" - << " }\n" - << " case MCD::OPC_FilterValue: {\n" - << " // Decode the field value.\n" - << " unsigned Len;\n" - << " uint64_t Val = decodeULEB128(++Ptr, &Len);\n" - << " Ptr += Len;\n" - << " // NumToSkip is a plain 24-bit integer.\n" - << " unsigned NumToSkip = *Ptr++;\n" - << " NumToSkip |= (*Ptr++) << 8;\n" - << " NumToSkip |= (*Ptr++) << 16;\n" - << "\n" - << " // Perform the filter operation.\n" - << " if (Val != CurFieldValue)\n" - << " Ptr += NumToSkip;\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_FilterValue(\" << Val << " - "\", \" << NumToSkip\n" - << " << \"): \" << ((Val != CurFieldValue) ? \"FAIL:\" " - ": \"PASS:\")\n" - << " << \" continuing at \" << (Ptr - DecodeTable) << " - "\"\\n\");\n" - << "\n" - << " break;\n" - << " }\n" - << " case MCD::OPC_CheckField: {\n" - << " // Decode the start value.\n" - << " unsigned Len;\n" - << " unsigned Start = decodeULEB128(++Ptr, &Len);\n" - << " Ptr += Len;\n" - << " Len = *Ptr;\n"; + OS << "\n makeUp(insn, Start + Len);"; + OS << R"( + CurFieldValue = fieldFromInstruction(insn, Start, Len); + LLVM_DEBUG(dbgs() << Loc << ": OPC_ExtractField(" << Start << ", " + << Len << "): " << CurFieldValue << "\n"); + break; + } + case MCD::OPC_FilterValue: { + // Decode the field value. + unsigned Len; + uint64_t Val = decodeULEB128(++Ptr, &Len); + Ptr += Len; + // NumToSkip is a plain 24-bit integer. + unsigned NumToSkip = *Ptr++; + NumToSkip |= (*Ptr++) << 8; + NumToSkip |= (*Ptr++) << 16; + + // Perform the filter operation. + if (Val != CurFieldValue) + Ptr += NumToSkip; + LLVM_DEBUG(dbgs() << Loc << ": OPC_FilterValue(" << Val << ", " << NumToSkip + << "): " << ((Val != CurFieldValue) ? "FAIL:" : "PASS:") + << " continuing at " << (Ptr - DecodeTable) << "\n"); + + break; + } + case MCD::OPC_CheckField: { + // Decode the start value. + unsigned Len; + unsigned Start = decodeULEB128(++Ptr, &Len); + Ptr += Len; + Len = *Ptr;)"; if (IsVarLenInst) - OS << " makeUp(insn, Start + Len);\n"; - OS << " uint64_t FieldValue = fieldFromInstruction(insn, Start, Len);\n" - << " // Decode the field value.\n" - << " unsigned PtrLen = 0;\n" - << " uint64_t ExpectedValue = decodeULEB128(++Ptr, &PtrLen);\n" - << " Ptr += PtrLen;\n" - << " // NumToSkip is a plain 24-bit integer.\n" - << " unsigned NumToSkip = *Ptr++;\n" - << " NumToSkip |= (*Ptr++) << 8;\n" - << " NumToSkip |= (*Ptr++) << 16;\n" - << "\n" - << " // If the actual and expected values don't match, skip.\n" - << " if (ExpectedValue != FieldValue)\n" - << " Ptr += NumToSkip;\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_CheckField(\" << Start << " - "\", \"\n" - << " << Len << \", \" << ExpectedValue << \", \" << " - "NumToSkip\n" - << " << \"): FieldValue = \" << FieldValue << \", " - "ExpectedValue = \"\n" - << " << ExpectedValue << \": \"\n" - << " << ((ExpectedValue == FieldValue) ? \"PASS\\n\" : " - "\"FAIL\\n\"));\n" - << " break;\n" - << " }\n" - << " case MCD::OPC_CheckPredicate: {\n" - << " unsigned Len;\n" - << " // Decode the Predicate Index value.\n" - << " unsigned PIdx = decodeULEB128(++Ptr, &Len);\n" - << " Ptr += Len;\n" - << " // NumToSkip is a plain 24-bit integer.\n" - << " unsigned NumToSkip = *Ptr++;\n" - << " NumToSkip |= (*Ptr++) << 8;\n" - << " NumToSkip |= (*Ptr++) << 16;\n" - << " // Check the predicate.\n" - << " bool Pred;\n" - << " if (!(Pred = checkDecoderPredicate(PIdx, Bits)))\n" - << " Ptr += NumToSkip;\n" - << " (void)Pred;\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_CheckPredicate(\" << PIdx " - "<< \"): \"\n" - << " << (Pred ? \"PASS\\n\" : \"FAIL\\n\"));\n" - << "\n" - << " break;\n" - << " }\n" - << " case MCD::OPC_Decode: {\n" - << " unsigned Len;\n" - << " // Decode the Opcode value.\n" - << " unsigned Opc = decodeULEB128(++Ptr, &Len);\n" - << " Ptr += Len;\n" - << " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\n" - << " Ptr += Len;\n" - << "\n" - << " MI.clear();\n" - << " MI.setOpcode(Opc);\n" - << " bool DecodeComplete;\n"; + OS << "\n makeUp(insn, Start + Len);"; + OS << R"( + uint64_t FieldValue = fieldFromInstruction(insn, Start, Len); + // Decode the field value. + unsigned PtrLen = 0; + uint64_t ExpectedValue = decodeULEB128(++Ptr, &PtrLen); + Ptr += PtrLen; + // NumToSkip is a plain 24-bit integer. + unsigned NumToSkip = *Ptr++; + NumToSkip |= (*Ptr++) << 8; + NumToSkip |= (*Ptr++) << 16; + + // If the actual and expected values don't match, skip. + if (ExpectedValue != FieldValue) + Ptr += NumToSkip; + LLVM_DEBUG(dbgs() << Loc << ": OPC_CheckField(" << Start << ", " + << Len << ", " << ExpectedValue << ", " << NumToSkip + << "): FieldValue = " << FieldValue << ", ExpectedValue = " + << ExpectedValue << ": " + << ((ExpectedValue == FieldValue) ? "PASS\n" : "FAIL\n")); + break; + } + case MCD::OPC_CheckPredicate: { + unsigned Len; + // Decode the Predicate Index value. + unsigned PIdx = decodeULEB128(++Ptr, &Len); + Ptr += Len; + // NumToSkip is a plain 24-bit integer. + unsigned NumToSkip = *Ptr++; + NumToSkip |= (*Ptr++) << 8; + NumToSkip |= (*Ptr++) << 16; + // Check the predicate. + bool Pred; + if (!(Pred = checkDecoderPredicate(PIdx, Bits))) + Ptr += NumToSkip; + (void)Pred; + LLVM_DEBUG(dbgs() << Loc << ": OPC_CheckPredicate(" << PIdx << "): " + << (Pred ? "PASS\n" : "FAIL\n")); + + break; + } + case MCD::OPC_Decode: { + unsigned Len; + // Decode the Opcode value. + unsigned Opc = decodeULEB128(++Ptr, &Len); + Ptr += Len; + unsigned DecodeIdx = decodeULEB128(Ptr, &Len); + Ptr += Len; + + MI.clear(); + MI.setOpcode(Opc); + bool DecodeComplete;)"; if (IsVarLenInst) { - OS << " Len = InstrLenTable[Opc];\n" - << " makeUp(insn, Len);\n"; + OS << "\n Len = InstrLenTable[Opc];\n" + << " makeUp(insn, Len);"; + } + OS << R"( + S = decodeToMCInst(S, DecodeIdx, insn, MI, Address, DisAsm, DecodeComplete); + assert(DecodeComplete); + + LLVM_DEBUG(dbgs() << Loc << ": OPC_Decode: opcode " << Opc + << ", using decoder " << DecodeIdx << ": " + << (S != MCDisassembler::Fail ? "PASS" : "FAIL") << "\n"); + return S; + } + case MCD::OPC_TryDecode: { + unsigned Len; + // Decode the Opcode value. + unsigned Opc = decodeULEB128(++Ptr, &Len); + Ptr += Len; + unsigned DecodeIdx = decodeULEB128(Ptr, &Len); + Ptr += Len; + // NumToSkip is a plain 24-bit integer. + unsigned NumToSkip = *Ptr++; + NumToSkip |= (*Ptr++) << 8; + NumToSkip |= (*Ptr++) << 16; + + // Perform the decode operation. + MCInst TmpMI; + TmpMI.setOpcode(Opc); + bool DecodeComplete; + S = decodeToMCInst(S, DecodeIdx, insn, TmpMI, Address, DisAsm, DecodeComplete); + LLVM_DEBUG(dbgs() << Loc << ": OPC_TryDecode: opcode " << Opc + << ", using decoder " << DecodeIdx << ": "); + + if (DecodeComplete) { + // Decoding complete. + LLVM_DEBUG(dbgs() << (S != MCDisassembler::Fail ? "PASS" : "FAIL") << "\n"); + MI = TmpMI; + return S; + } else { + assert(S == MCDisassembler::Fail); + // If the decoding was incomplete, skip. + Ptr += NumToSkip; + LLVM_DEBUG(dbgs() << "FAIL: continuing at " << (Ptr - DecodeTable) << "\n"); + // Reset decode status. This also drops a SoftFail status that could be + // set before the decode attempt. + S = MCDisassembler::Success; + } + break; + } + case MCD::OPC_SoftFail: { + // Decode the mask values. + unsigned Len; + uint64_t PositiveMask = decodeULEB128(++Ptr, &Len); + Ptr += Len; + uint64_t NegativeMask = decodeULEB128(Ptr, &Len); + Ptr += Len; + bool Fail = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0; + if (Fail) + S = MCDisassembler::SoftFail; + LLVM_DEBUG(dbgs() << Loc << ": OPC_SoftFail: " << (Fail ? "FAIL\n" : "PASS\n")); + break; + } + case MCD::OPC_Fail: { + LLVM_DEBUG(dbgs() << Loc << ": OPC_Fail\n"); + return MCDisassembler::Fail; + } + } } - OS << " S = decodeToMCInst(S, DecodeIdx, insn, MI, Address, DisAsm, " - "DecodeComplete);\n" - << " assert(DecodeComplete);\n" - << "\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_Decode: opcode \" << Opc\n" - << " << \", using decoder \" << DecodeIdx << \": \"\n" - << " << (S != MCDisassembler::Fail ? \"PASS\" : " - "\"FAIL\") << \"\\n\");\n" - << " return S;\n" - << " }\n" - << " case MCD::OPC_TryDecode: {\n" - << " unsigned Len;\n" - << " // Decode the Opcode value.\n" - << " unsigned Opc = decodeULEB128(++Ptr, &Len);\n" - << " Ptr += Len;\n" - << " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\n" - << " Ptr += Len;\n" - << " // NumToSkip is a plain 24-bit integer.\n" - << " unsigned NumToSkip = *Ptr++;\n" - << " NumToSkip |= (*Ptr++) << 8;\n" - << " NumToSkip |= (*Ptr++) << 16;\n" - << "\n" - << " // Perform the decode operation.\n" - << " MCInst TmpMI;\n" - << " TmpMI.setOpcode(Opc);\n" - << " bool DecodeComplete;\n" - << " S = decodeToMCInst(S, DecodeIdx, insn, TmpMI, Address, DisAsm, " - "DecodeComplete);\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_TryDecode: opcode \" << " - "Opc\n" - << " << \", using decoder \" << DecodeIdx << \": \");\n" - << "\n" - << " if (DecodeComplete) {\n" - << " // Decoding complete.\n" - << " LLVM_DEBUG(dbgs() << (S != MCDisassembler::Fail ? \"PASS\" : " - "\"FAIL\") << \"\\n\");\n" - << " MI = TmpMI;\n" - << " return S;\n" - << " } else {\n" - << " assert(S == MCDisassembler::Fail);\n" - << " // If the decoding was incomplete, skip.\n" - << " Ptr += NumToSkip;\n" - << " LLVM_DEBUG(dbgs() << \"FAIL: continuing at \" << (Ptr - " - "DecodeTable) << \"\\n\");\n" - << " // Reset decode status. This also drops a SoftFail status " - "that could be\n" - << " // set before the decode attempt.\n" - << " S = MCDisassembler::Success;\n" - << " }\n" - << " break;\n" - << " }\n" - << " case MCD::OPC_SoftFail: {\n" - << " // Decode the mask values.\n" - << " unsigned Len;\n" - << " uint64_t PositiveMask = decodeULEB128(++Ptr, &Len);\n" - << " Ptr += Len;\n" - << " uint64_t NegativeMask = decodeULEB128(Ptr, &Len);\n" - << " Ptr += Len;\n" - << " bool Fail = (insn & PositiveMask) != 0 || (~insn & " - "NegativeMask) != 0;\n" - << " if (Fail)\n" - << " S = MCDisassembler::SoftFail;\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_SoftFail: \" << (Fail ? " - "\"FAIL\\n\" : \"PASS\\n\"));\n" - << " break;\n" - << " }\n" - << " case MCD::OPC_Fail: {\n" - << " LLVM_DEBUG(dbgs() << Loc << \": OPC_Fail\\n\");\n" - << " return MCDisassembler::Fail;\n" - << " }\n" - << " }\n" - << " }\n" - << " llvm_unreachable(\"bogosity detected in disassembler state " - "machine!\");\n" - << "}\n\n"; + llvm_unreachable("bogosity detected in disassembler state machine!"); +} + +)"; } // Helper to propagate SoftFail status. Returns false if the status is Fail; @@ -2443,10 +2419,13 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS, // is correct to propagate the values of this enum; see comment on 'enum // DecodeStatus'.) static void emitCheck(formatted_raw_ostream &OS) { - OS << "static bool Check(DecodeStatus &Out, DecodeStatus In) {\n" - << " Out = static_cast(Out & In);\n" - << " return Out != MCDisassembler::Fail;\n" - << "}\n\n"; + OS << R"( +static bool Check(DecodeStatus &Out, DecodeStatus In) { + Out = static_cast(Out & In); + return Out != MCDisassembler::Fail; +} + +)"; } // Collect all HwModes referenced by the target for encoding purposes, @@ -2469,16 +2448,18 @@ collectHwModesReferencedForEncodings(const CodeGenHwModes &HWM, // Emits disassembler code for instruction decoding. void DecoderEmitter::run(raw_ostream &o) { formatted_raw_ostream OS(o); - OS << "#include \"llvm/MC/MCInst.h\"\n"; - OS << "#include \"llvm/MC/MCSubtargetInfo.h\"\n"; - OS << "#include \"llvm/Support/DataTypes.h\"\n"; - OS << "#include \"llvm/Support/Debug.h\"\n"; - OS << "#include \"llvm/Support/LEB128.h\"\n"; - OS << "#include \"llvm/Support/raw_ostream.h\"\n"; - OS << "#include \"llvm/TargetParser/SubtargetFeature.h\"\n"; - OS << "#include \n"; - OS << '\n'; - OS << "namespace llvm {\n\n"; + OS << R"( +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/LEB128.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/SubtargetFeature.h" +#include + +namespace llvm { +)"; emitFieldFromInstruction(OS); emitInsertBits(OS); @@ -2533,9 +2514,9 @@ void DecoderEmitter::run(raw_ostream &o) { bool IsVarLenInst = Target.hasVariableLengthEncodings(); unsigned MaxInstLen = 0; - for (unsigned i = 0; i < NumberedEncodings.size(); ++i) { - const Record *EncodingDef = NumberedEncodings[i].EncodingDef; - const CodeGenInstruction *Inst = NumberedEncodings[i].Inst; + for (const auto &[NEI, NumberedEncoding] : enumerate(NumberedEncodings)) { + const Record *EncodingDef = NumberedEncoding.EncodingDef; + const CodeGenInstruction *Inst = NumberedEncoding.Inst; const Record *Def = Inst->TheDef; unsigned Size = EncodingDef->getValueAsInt("Size"); if (Def->getValueAsString("Namespace") == "TargetOpcode" || @@ -2546,7 +2527,7 @@ void DecoderEmitter::run(raw_ostream &o) { continue; } - if (i < NumberedInstructions.size()) + if (NEI < NumberedInstructions.size()) NumInstructions++; NumEncodings++; @@ -2556,19 +2537,19 @@ void DecoderEmitter::run(raw_ostream &o) { if (IsVarLenInst) InstrLen.resize(NumberedInstructions.size(), 0); - if (unsigned Len = populateInstruction(Target, *EncodingDef, *Inst, i, + if (unsigned Len = populateInstruction(Target, *EncodingDef, *Inst, NEI, Operands, IsVarLenInst)) { if (IsVarLenInst) { MaxInstLen = std::max(MaxInstLen, Len); - InstrLen[i] = Len; + InstrLen[NEI] = Len; } std::string DecoderNamespace = std::string(EncodingDef->getValueAsString("DecoderNamespace")); - if (!NumberedEncodings[i].HwModeName.empty()) + if (!NumberedEncoding.HwModeName.empty()) DecoderNamespace += - std::string("_") + NumberedEncodings[i].HwModeName.str(); + std::string("_") + NumberedEncoding.HwModeName.str(); OpcMap[std::pair(DecoderNamespace, Size)].emplace_back( - i, Target.getInstrIntValue(Def)); + NEI, Target.getInstrIntValue(Def)); } else { NumEncodingsOmitted++; } -- GitLab From 498b7d2f86b4bceb381e66b093670c7ec4bc6cc4 Mon Sep 17 00:00:00 2001 From: Changpeng Fang Date: Tue, 12 Mar 2024 14:02:20 -0700 Subject: [PATCH 299/953] AMDGPU: Copy TSFlags from Pseudo to DS_Real (#84977) We need TSFalgs from pseudo to real. --- llvm/lib/Target/AMDGPU/DSInstructions.td | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/lib/Target/AMDGPU/DSInstructions.td b/llvm/lib/Target/AMDGPU/DSInstructions.td index cc763df5a476..87ace01a6d0e 100644 --- a/llvm/lib/Target/AMDGPU/DSInstructions.td +++ b/llvm/lib/Target/AMDGPU/DSInstructions.td @@ -65,6 +65,7 @@ class DS_Real : let SubtargetPredicate = ps.SubtargetPredicate; let WaveSizePredicate = ps.WaveSizePredicate; let OtherPredicates = ps.OtherPredicates; + let TSFlags = ps.TSFlags; let SchedRW = ps.SchedRW; let mayLoad = ps.mayLoad; let mayStore = ps.mayStore; -- GitLab From 1a6ec906fb3781c2fc98979ec37a2a76479b0b08 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Tue, 12 Mar 2024 14:10:49 -0700 Subject: [PATCH 300/953] [Arm64EC] Copy import descriptors to the EC Map (#84834) As noted in , MSVC places import descriptors in both the EC and regular map - that PR moved the descriptors to ONLY the regular map, however this causes linking errors when linking as Arm64EC: ``` bcryptprimitives.lib(bcryptprimitives.dll) : error LNK2001: unresolved external symbol __IMPORT_DESCRIPTOR_bcryptprimitives (EC Symbol) ``` This change copies import descriptors from the regular map to the EC map, which fixes this linking error. --- llvm/include/llvm/Object/COFFImportFile.h | 6 ++++++ llvm/lib/Object/ArchiveWriter.cpp | 11 +++++++++++ llvm/lib/Object/COFFImportFile.cpp | 10 ++++------ llvm/test/tools/llvm-dlltool/arm64ec.test | 6 ++++++ llvm/test/tools/llvm-lib/arm64ec-implib.test | 12 ++++++++++++ 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/llvm/include/llvm/Object/COFFImportFile.h b/llvm/include/llvm/Object/COFFImportFile.h index 402ded0d64fe..7268faa87eb7 100644 --- a/llvm/include/llvm/Object/COFFImportFile.h +++ b/llvm/include/llvm/Object/COFFImportFile.h @@ -26,6 +26,12 @@ namespace llvm { namespace object { +constexpr std::string_view ImportDescriptorPrefix = "__IMPORT_DESCRIPTOR_"; +constexpr std::string_view NullImportDescriptorSymbolName = + "__NULL_IMPORT_DESCRIPTOR"; +constexpr std::string_view NullThunkDataPrefix = "\x7f"; +constexpr std::string_view NullThunkDataSuffix = "_NULL_THUNK_DATA"; + class COFFImportFile : public SymbolicFile { private: enum SymbolIndex { ImpSymbol, ThunkSymbol, ECAuxSymbol, ECThunkSymbol }; diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp index be51093933a8..e0629747b40c 100644 --- a/llvm/lib/Object/ArchiveWriter.cpp +++ b/llvm/lib/Object/ArchiveWriter.cpp @@ -677,6 +677,13 @@ static bool isECObject(object::SymbolicFile &Obj) { return false; } +bool isImportDescriptor(StringRef Name) { + return Name.starts_with(ImportDescriptorPrefix) || + Name == StringRef{NullImportDescriptorSymbolName} || + (Name.starts_with(NullThunkDataPrefix) && + Name.ends_with(NullThunkDataSuffix)); +} + static Expected> getSymbols(SymbolicFile *Obj, uint16_t Index, raw_ostream &SymNames, @@ -704,6 +711,10 @@ static Expected> getSymbols(SymbolicFile *Obj, if (Map == &SymMap->Map) { Ret.push_back(SymNames.tell()); SymNames << Name << '\0'; + // If EC is enabled, then the import descriptors are NOT put into EC + // objects so we need to copy them to the EC map manually. + if (SymMap->UseECMap && isImportDescriptor(Name)) + SymMap->ECMap[Name] = Index; } } else { Ret.push_back(SymNames.tell()); diff --git a/llvm/lib/Object/COFFImportFile.cpp b/llvm/lib/Object/COFFImportFile.cpp index 376dd126baf6..46c8e702581e 100644 --- a/llvm/lib/Object/COFFImportFile.cpp +++ b/llvm/lib/Object/COFFImportFile.cpp @@ -108,7 +108,7 @@ template static void append(std::vector &B, const T &Data) { } static void writeStringTable(std::vector &B, - ArrayRef Strings) { + ArrayRef Strings) { // The COFF string table consists of a 4-byte value which is the size of the // table, including the length field itself. This value is followed by the // string content itself, which is an array of null-terminated C-style @@ -171,9 +171,6 @@ static Expected replace(StringRef S, StringRef From, return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str(); } -static const std::string NullImportDescriptorSymbolName = - "__NULL_IMPORT_DESCRIPTOR"; - namespace { // This class constructs various small object files necessary to support linking // symbols imported from a DLL. The contents are pretty strictly defined and @@ -192,8 +189,9 @@ class ObjectFactory { public: ObjectFactory(StringRef S, MachineTypes M) : NativeMachine(M), ImportName(S), Library(llvm::sys::path::stem(S)), - ImportDescriptorSymbolName(("__IMPORT_DESCRIPTOR_" + Library).str()), - NullThunkSymbolName(("\x7f" + Library + "_NULL_THUNK_DATA").str()) {} + ImportDescriptorSymbolName((ImportDescriptorPrefix + Library).str()), + NullThunkSymbolName( + (NullThunkDataPrefix + Library + NullThunkDataSuffix).str()) {} // Creates an Import Descriptor. This is a small object file which contains a // reference to the terminators and contains the library name (entry) for the diff --git a/llvm/test/tools/llvm-dlltool/arm64ec.test b/llvm/test/tools/llvm-dlltool/arm64ec.test index e742a77ff78a..b03b4eaf7b2d 100644 --- a/llvm/test/tools/llvm-dlltool/arm64ec.test +++ b/llvm/test/tools/llvm-dlltool/arm64ec.test @@ -12,9 +12,12 @@ ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll ARMAP-EMPTY: ARMAP-NEXT: Archive EC map ARMAP-NEXT: #func in test.dll +ARMAP-NEXT: __IMPORT_DESCRIPTOR_test in test.dll +ARMAP-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll ARMAP-NEXT: __imp_aux_func in test.dll ARMAP-NEXT: __imp_func in test.dll ARMAP-NEXT: func in test.dll +ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll RUN: llvm-dlltool -m arm64ec -d test.def -N test2.def -l test2.lib RUN: llvm-nm --print-armap test2.lib | FileCheck --check-prefix=ARMAP2 %s @@ -28,9 +31,12 @@ ARMAP2-NEXT: test_NULL_THUNK_DATA in test.dll ARMAP2-EMPTY: ARMAP2-NEXT: Archive EC map ARMAP2-NEXT: #func in test.dll +ARMAP2-NEXT: __IMPORT_DESCRIPTOR_test in test.dll +ARMAP2-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll ARMAP2-NEXT: __imp_aux_func in test.dll ARMAP2-NEXT: __imp_func in test.dll ARMAP2-NEXT: func in test.dll +ARMAP2-NEXT: test_NULL_THUNK_DATA in test.dll RUN: llvm-dlltool -m arm64ec -d test.def --input-native-def test2.def -l test3.lib RUN: llvm-nm --print-armap test3.lib | FileCheck --check-prefix=ARMAP2 %s diff --git a/llvm/test/tools/llvm-lib/arm64ec-implib.test b/llvm/test/tools/llvm-lib/arm64ec-implib.test index 77bdc23589fd..00eddd2a4752 100644 --- a/llvm/test/tools/llvm-lib/arm64ec-implib.test +++ b/llvm/test/tools/llvm-lib/arm64ec-implib.test @@ -16,6 +16,8 @@ ARMAP-NEXT: #funcexp in test.dll ARMAP-NEXT: #mangledfunc in test.dll ARMAP-NEXT: ?test_cpp_func@@$$hYAHPEAX@Z in test.dll ARMAP-NEXT: ?test_cpp_func@@YAHPEAX@Z in test.dll +ARMAP-NEXT: __IMPORT_DESCRIPTOR_test in test.dll +ARMAP-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll ARMAP-NEXT: __imp_?test_cpp_func@@YAHPEAX@Z in test.dll ARMAP-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test.dll ARMAP-NEXT: __imp_aux_expname in test.dll @@ -28,6 +30,7 @@ ARMAP-NEXT: __imp_mangledfunc in test.dll ARMAP-NEXT: expname in test.dll ARMAP-NEXT: funcexp in test.dll ARMAP-NEXT: mangledfunc in test.dll +ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll RUN: llvm-readobj test.lib | FileCheck -check-prefix=READOBJ %s @@ -122,6 +125,8 @@ ARMAPX-NEXT: #funcexp in test.dll ARMAPX-NEXT: #mangledfunc in test.dll ARMAPX-NEXT: ?test_cpp_func@@$$hYAHPEAX@Z in test.dll ARMAPX-NEXT: ?test_cpp_func@@YAHPEAX@Z in test.dll +ARMAPX-NEXT: __IMPORT_DESCRIPTOR_test in test.dll +ARMAPX-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll ARMAPX-NEXT: __imp_?test_cpp_func@@YAHPEAX@Z in test.dll ARMAPX-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test.dll ARMAPX-NEXT: __imp_aux_expname in test.dll @@ -134,6 +139,7 @@ ARMAPX-NEXT: __imp_mangledfunc in test.dll ARMAPX-NEXT: expname in test.dll ARMAPX-NEXT: funcexp in test.dll ARMAPX-NEXT: mangledfunc in test.dll +ARMAPX-NEXT: test_NULL_THUNK_DATA in test.dll RUN: llvm-readobj testx.lib | FileCheck -check-prefix=READOBJX %s @@ -255,6 +261,8 @@ ARMAPX2-NEXT: #funcexp in test2.dll ARMAPX2-NEXT: #mangledfunc in test2.dll ARMAPX2-NEXT: ?test_cpp_func@@$$hYAHPEAX@Z in test2.dll ARMAPX2-NEXT: ?test_cpp_func@@YAHPEAX@Z in test2.dll +ARMAPX2-NEXT: __IMPORT_DESCRIPTOR_test2 in test2.dll +ARMAPX2-NEXT: __NULL_IMPORT_DESCRIPTOR in test2.dll ARMAPX2-NEXT: __imp_?test_cpp_func@@YAHPEAX@Z in test2.dll ARMAPX2-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test2.dll ARMAPX2-NEXT: __imp_aux_expname in test2.dll @@ -267,6 +275,7 @@ ARMAPX2-NEXT: __imp_mangledfunc in test2.dll ARMAPX2-NEXT: expname in test2.dll ARMAPX2-NEXT: funcexp in test2.dll ARMAPX2-NEXT: mangledfunc in test2.dll +ARMAPX2-NEXT: test2_NULL_THUNK_DATA in test2.dll ARMAPX2: test2.dll: ARMAPX2: 00000000 T #funcexp @@ -309,6 +318,8 @@ EXPAS-ARMAP-NEXT: #func1 in test.dll EXPAS-ARMAP-NEXT: #func2 in test.dll EXPAS-ARMAP-NEXT: #func3 in test.dll EXPAS-ARMAP-NEXT: #func4 in test.dll +EXPAS-ARMAP-NEXT: __IMPORT_DESCRIPTOR_test in test.dll +EXPAS-ARMAP-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll EXPAS-ARMAP-NEXT: __imp_aux_func1 in test.dll EXPAS-ARMAP-NEXT: __imp_aux_func2 in test.dll EXPAS-ARMAP-NEXT: __imp_aux_func3 in test.dll @@ -323,6 +334,7 @@ EXPAS-ARMAP-NEXT: func1 in test.dll EXPAS-ARMAP-NEXT: func2 in test.dll EXPAS-ARMAP-NEXT: func3 in test.dll EXPAS-ARMAP-NEXT: func4 in test.dll +EXPAS-ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll EXPAS-READOBJ: File: test.dll EXPAS-READOBJ-NEXT: Format: COFF-import-file-ARM64EC -- GitLab From d73c2d5df21735805a1f46a85790db64c0615e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= Date: Tue, 12 Mar 2024 23:12:46 +0100 Subject: [PATCH 301/953] Fix unittest after #84460: only applicable if the platform supports JIT --- .../Interpreter/InterpreterExtensionsTest.cpp | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp index f1c3d65ab0a9..77fd1b4e1981 100644 --- a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp +++ b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp @@ -17,7 +17,9 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/Sema.h" +#include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/Support/Error.h" +#include "llvm/Support/TargetSelect.h" #include "llvm/Testing/Support/Error.h" #include "gmock/gmock.h" @@ -27,6 +29,22 @@ using namespace clang; namespace { +static bool HostSupportsJit() { + auto J = llvm::orc::LLJITBuilder().create(); + if (J) + return true; + LLVMConsumeError(llvm::wrap(J.takeError())); + return false; +} + +struct LLVMInitRAII { + LLVMInitRAII() { + llvm::InitializeNativeTarget(); + llvm::InitializeNativeTargetAsmPrinter(); + } + ~LLVMInitRAII() { llvm::llvm_shutdown(); } +} LLVMInit; + class TestCreateResetExecutor : public Interpreter { public: TestCreateResetExecutor(std::unique_ptr CI, @@ -39,6 +57,10 @@ public: }; TEST(InterpreterExtensionsTest, ExecutorCreateReset) { + // Make sure we can create the executer on the platform. + if (!HostSupportsJit()) + GTEST_SKIP(); + clang::IncrementalCompilerBuilder CB; llvm::Error ErrOut = llvm::Error::success(); TestCreateResetExecutor Interp(cantFail(CB.CreateCpp()), ErrOut); -- GitLab From 76f3a084e77991cffbb8108959457ffd75f8e9c8 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Tue, 12 Mar 2024 15:18:47 -0700 Subject: [PATCH 302/953] Update GettingStarted.rst doc with negative refspec to filter user branches (#75015) This allows to keep fetching release branches as well. --- llvm/docs/GettingStarted.rst | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/llvm/docs/GettingStarted.rst b/llvm/docs/GettingStarted.rst index 705f6427d9ed..7ecef78c405b 100644 --- a/llvm/docs/GettingStarted.rst +++ b/llvm/docs/GettingStarted.rst @@ -42,10 +42,14 @@ Getting the Source Code and Building LLVM ``git clone --depth 1 https://github.com/llvm/llvm-project.git`` - * You are likely only interested in the main branch moving forward, if - you don't want `git fetch` (or `git pull`) to download user branches, use: + * You are likely not interested in the user branches in the repo (used for + stacked pull-requests and reverts), you can filter them from your + `git fetch` (or `git pull`) with this configuration: - ``sed 's#fetch = +refs/heads/\*:refs/remotes/origin/\*#fetch = +refs/heads/main:refs/remotes/origin/main#' -i llvm-project/.git/config`` +.. code-block:: console + + git config --add remote.origin.fetch '^refs/heads/users/*' + git config --add remote.origin.fetch '^refs/heads/revert-*' #. Configure and build LLVM and Clang: -- GitLab From beb47e78be6a819b6501f99302c1c4c1ae84b90e Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 12 Mar 2024 22:19:09 +0000 Subject: [PATCH 303/953] [clang][CodeCompletion] Allow debuggers to code-complete reserved identifiers (#84891) --- clang/lib/Sema/SemaCodeComplete.cpp | 4 ++++ clang/test/CodeCompletion/ordinary-name.c | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 8d7523900940..73e6baa52782 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -764,6 +764,10 @@ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext, // Filter out names reserved for the implementation if they come from a // system header. static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) { + // Debuggers want access to all identifiers, including reserved ones. + if (SemaRef.getLangOpts().DebuggerSupport) + return false; + ReservedIdentifierStatus Status = ND->isReserved(SemaRef.getLangOpts()); // Ignore reserved names for compiler provided decls. if (isReservedInAllContexts(Status) && ND->getLocation().isInvalid()) diff --git a/clang/test/CodeCompletion/ordinary-name.c b/clang/test/CodeCompletion/ordinary-name.c index c8181a248daa..939856192061 100644 --- a/clang/test/CodeCompletion/ordinary-name.c +++ b/clang/test/CodeCompletion/ordinary-name.c @@ -5,6 +5,7 @@ typedef struct t _TYPEDEF; void foo() { int y; // RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -code-completion-at=%s:%(line-1):9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s + // CHECK-CC1-NOT: __builtin_va_list // CHECK-CC1-NOT: __INTEGER_TYPE // CHECK-CC1: _Imaginary // CHECK-CC1: _MyPrivateType @@ -15,4 +16,8 @@ void foo() { // CHECK-CC1: y // PR8744 - // RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -code-completion-at=%s:%(line-17):11 %s + // RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -code-completion-at=%s:%(line-18):11 %s + + // RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -fdebugger-support -code-completion-at=%s:%(line-15):9 %s -o - | FileCheck -check-prefix=CHECK-DBG %s + // CHECK-DBG: __builtin_va_list + // CHECK-DBG: __INTEGER_TYPE -- GitLab From 88bf64097e453deca73c91ec7de1af7eebe296a9 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 12 Mar 2024 22:19:27 +0000 Subject: [PATCH 304/953] [lldb][test] TestExprCompletion.py: add tests for completion of reserved identifiers (#84890) --- lldb/test/API/commands/expression/completion/Makefile | 1 + .../commands/expression/completion/TestExprCompletion.py | 5 +++++ lldb/test/API/commands/expression/completion/main.cpp | 5 +++++ .../API/commands/expression/completion/sys/reserved.h | 8 ++++++++ 4 files changed, 19 insertions(+) create mode 100644 lldb/test/API/commands/expression/completion/sys/reserved.h diff --git a/lldb/test/API/commands/expression/completion/Makefile b/lldb/test/API/commands/expression/completion/Makefile index 020dce7c31d1..9882622b2189 100644 --- a/lldb/test/API/commands/expression/completion/Makefile +++ b/lldb/test/API/commands/expression/completion/Makefile @@ -1,3 +1,4 @@ CXX_SOURCES := main.cpp other.cpp +CXXFLAGS += -isystem $(SRCDIR)/sys include Makefile.rules diff --git a/lldb/test/API/commands/expression/completion/TestExprCompletion.py b/lldb/test/API/commands/expression/completion/TestExprCompletion.py index c6a1e3c0f422..022b9436ee8e 100644 --- a/lldb/test/API/commands/expression/completion/TestExprCompletion.py +++ b/lldb/test/API/commands/expression/completion/TestExprCompletion.py @@ -246,6 +246,11 @@ class CommandLineExprCompletionTestCase(TestBase): "expr some_expr.Self(). FooNoArgs", "expr some_expr.Self(). FooNoArgsBar()" ) + self.complete_from_to("expr myVec.__f", "expr myVec.__func()") + self.complete_from_to("expr myVec._F", "expr myVec._Func()") + self.complete_from_to("expr myVec.__m", "expr myVec.__mem") + self.complete_from_to("expr myVec._M", "expr myVec._Mem") + def test_expr_completion_with_descriptions(self): self.build() self.main_source = "main.cpp" diff --git a/lldb/test/API/commands/expression/completion/main.cpp b/lldb/test/API/commands/expression/completion/main.cpp index 908bebbebff5..5e03805a7a4d 100644 --- a/lldb/test/API/commands/expression/completion/main.cpp +++ b/lldb/test/API/commands/expression/completion/main.cpp @@ -1,3 +1,5 @@ +#include + namespace LongNamespaceName { class NestedClass { long m; }; } // Defined in other.cpp, we only have a forward declaration here. @@ -31,5 +33,8 @@ int main() some_expr.FooNumbersBar1(); Expr::StaticMemberMethodBar(); ForwardDecl *fwd_decl_ptr = &fwd_decl; + MyVec myVec; + myVec.__func(); + myVec._Func(); return 0; // Break here } diff --git a/lldb/test/API/commands/expression/completion/sys/reserved.h b/lldb/test/API/commands/expression/completion/sys/reserved.h new file mode 100644 index 000000000000..0ce10ebec62b --- /dev/null +++ b/lldb/test/API/commands/expression/completion/sys/reserved.h @@ -0,0 +1,8 @@ +class MyVec { + int __mem; + int _Mem; + +public: + void __func() {} + void _Func() {} +}; -- GitLab From 47625e47db1d8fef6936ef48103e9aeb1fa3d328 Mon Sep 17 00:00:00 2001 From: Dave Clausen Date: Tue, 12 Mar 2024 18:36:48 -0400 Subject: [PATCH 305/953] Fix race in the implementation of __tsan_acquire() (#84923) `__tsan::Acquire()`, which is called by `__tsan_acquire()`, has a performance optimization which attempts to avoid acquiring the atomic variable's mutex if the variable has no associated memory model state. However, if the atomic variable was recently written to by a `compare_exchange_weak/strong` on another thread, the memory model state may be created *after* the atomic variable is updated. This is a data race, and can cause the thread calling `Acquire()` to not realize that the atomic variable was previously written to by another thread. Specifically, if you have code that writes to an atomic variable using `compare_exchange_weak/strong`, and then in another thread you read the value using a relaxed load, followed by an `atomic_thread_fence(memory_order_acquire)`, followed by a call to `__tsan_acquire()`, TSAN may not realize that the store happened before the fence, and so it will complain about any other variables you access from both threads if the thread-safety of those accesses depended on the happens-before relationship between the store and the fence. This change eliminates the unsafe optimization in `Acquire()`. Now, `Acquire()` acquires the mutex before checking for the existence of the memory model state. --- compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp | 2 +- .../tsan/compare_exchange_acquire_fence.cpp | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp index 2e978852ea7d..2a8aa1915c9a 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp @@ -446,9 +446,9 @@ void Acquire(ThreadState *thr, uptr pc, uptr addr) { if (!s) return; SlotLocker locker(thr); + ReadLock lock(&s->mtx); if (!s->clock) return; - ReadLock lock(&s->mtx); thr->clock.Acquire(s->clock); } diff --git a/compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp b/compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp new file mode 100644 index 000000000000..b9fd0c5ad21f --- /dev/null +++ b/compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp @@ -0,0 +1,43 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 +// This is a correct program and tsan should not report a race. +// +// Verify that there is a happens-before relationship between a +// memory_order_release store that happens as part of a successful +// compare_exchange_strong(), and an atomic_thread_fence(memory_order_acquire) +// that happens after a relaxed load. + +#include +#include +#include +#include +#include + +std::atomic a; +unsigned int b; +constexpr int loops = 100000; + +void Thread1() { + for (int i = 0; i < loops; ++i) { + while (a.load(std::memory_order_acquire)) { + } + b = i; + bool expected = false; + a.compare_exchange_strong(expected, true, std::memory_order_acq_rel); + } +} + +int main() { + std::thread t(Thread1); + unsigned int sum = 0; + for (int i = 0; i < loops; ++i) { + while (!a.load(std::memory_order_relaxed)) { + } + std::atomic_thread_fence(std::memory_order_acquire); + __tsan_acquire(&a); + sum += b; + a.store(false, std::memory_order_release); + } + t.join(); + fprintf(stderr, "DONE: %u\n", sum); + return 0; +} -- GitLab From fd32e744a58fe61b4bd6acfa1d501bc1d6c1d96f Mon Sep 17 00:00:00 2001 From: Maksim Panchenko Date: Tue, 12 Mar 2024 15:52:27 -0700 Subject: [PATCH 306/953] [BOLT] Add support for Linux kernel PCI fixup section (#84982) .pci_fixup section contains a table with entries allowing to invoke a fixup hook whenever a problem is encountered with a PCI device. The hookup code typically points to the start of a function. As we are not relocating functions in the kernel (at least not yet), verify this assumption while reading the table and ignore any functions with a fixup code in the middle. --- bolt/lib/Rewrite/LinuxKernelRewriter.cpp | 126 +++++++++++++++++------ bolt/test/X86/linux-pci-fixup.s | 41 ++++++++ 2 files changed, 134 insertions(+), 33 deletions(-) create mode 100644 bolt/test/X86/linux-pci-fixup.s diff --git a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp index 331a61e7c3c2..a2bfd45a64e3 100644 --- a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp +++ b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp @@ -55,6 +55,11 @@ static cl::opt DumpParavirtualPatchSites( "dump-para-sites", cl::desc("dump Linux kernel paravitual patch sites"), cl::init(false), cl::Hidden, cl::cat(BoltCategory)); +static cl::opt + DumpPCIFixups("dump-pci-fixups", + cl::desc("dump Linux kernel PCI fixup table"), + cl::init(false), cl::Hidden, cl::cat(BoltCategory)); + static cl::opt DumpStaticCalls("dump-static-calls", cl::desc("dump Linux kernel static calls"), cl::init(false), cl::Hidden, @@ -181,6 +186,10 @@ class LinuxKernelRewriter final : public MetadataRewriter { /// Size of bug_entry struct. static constexpr size_t BUG_TABLE_ENTRY_SIZE = 12; + /// .pci_fixup section. + ErrorOr PCIFixupSection = std::errc::bad_address; + static constexpr size_t PCI_FIXUP_ENTRY_SIZE = 16; + /// Insert an LKMarker for a given code pointer \p PC from a non-code section /// \p SectionName. void insertLKMarker(uint64_t PC, uint64_t SectionOffset, @@ -190,9 +199,6 @@ class LinuxKernelRewriter final : public MetadataRewriter { /// Process linux kernel special sections and their relocations. void processLKSections(); - /// Process special linux kernel section, .pci_fixup. - void processLKPCIFixup(); - /// Process __ksymtab and __ksymtab_gpl. void processLKKSymtab(bool IsGPL = false); @@ -226,6 +232,9 @@ class LinuxKernelRewriter final : public MetadataRewriter { /// Read alternative instruction info from .altinstructions. Error readAltInstructions(); + /// Read .pci_fixup + Error readPCIFixupTable(); + /// Mark instructions referenced by kernel metadata. Error markInstructions(); @@ -256,6 +265,9 @@ public: if (Error E = readAltInstructions()) return E; + if (Error E = readPCIFixupTable()) + return E; + return Error::success(); } @@ -318,41 +330,11 @@ void LinuxKernelRewriter::insertLKMarker(uint64_t PC, uint64_t SectionOffset, } void LinuxKernelRewriter::processLKSections() { - processLKPCIFixup(); processLKKSymtab(); processLKKSymtab(true); processLKSMPLocks(); } -/// Process .pci_fixup section of Linux Kernel. -/// This section contains a list of entries for different PCI devices and their -/// corresponding hook handler (code pointer where the fixup -/// code resides, usually on x86_64 it is an entry PC relative 32 bit offset). -/// Documentation is in include/linux/pci.h. -void LinuxKernelRewriter::processLKPCIFixup() { - ErrorOr SectionOrError = - BC.getUniqueSectionByName(".pci_fixup"); - if (!SectionOrError) - return; - - const uint64_t SectionSize = SectionOrError->getSize(); - const uint64_t SectionAddress = SectionOrError->getAddress(); - assert((SectionSize % 16) == 0 && ".pci_fixup size is not a multiple of 16"); - - for (uint64_t I = 12; I + 4 <= SectionSize; I += 16) { - const uint64_t PC = SectionAddress + I; - ErrorOr Offset = BC.getSignedValueAtAddress(PC, 4); - assert(Offset && "cannot read value from .pci_fixup"); - const int32_t SignedOffset = *Offset; - const uint64_t HookupAddress = PC + SignedOffset; - BinaryFunction *HookupFunction = - BC.getBinaryFunctionAtAddress(HookupAddress); - assert(HookupFunction && "expected function for entry in .pci_fixup"); - BC.addRelocation(PC, HookupFunction->getSymbol(), Relocation::getPC32(), 0, - *Offset); - } -} - /// Process __ksymtab[_gpl] sections of Linux Kernel. /// This section lists all the vmlinux symbols that kernel modules can access. /// @@ -1283,6 +1265,84 @@ Error LinuxKernelRewriter::readAltInstructions() { return Error::success(); } +/// When the Linux kernel needs to handle an error associated with a given PCI +/// device, it uses a table stored in .pci_fixup section to locate a fixup code +/// specific to the vendor and the problematic device. The section contains a +/// list of the following structures defined in include/linux/pci.h: +/// +/// struct pci_fixup { +/// u16 vendor; /* Or PCI_ANY_ID */ +/// u16 device; /* Or PCI_ANY_ID */ +/// u32 class; /* Or PCI_ANY_ID */ +/// unsigned int class_shift; /* should be 0, 8, 16 */ +/// int hook_offset; +/// }; +/// +/// Normally, the hook will point to a function start and we don't have to +/// update the pointer if we are not relocating functions. Hence, while reading +/// the table we validate this assumption. If a function has a fixup code in the +/// middle of its body, we issue a warning and ignore it. +Error LinuxKernelRewriter::readPCIFixupTable() { + PCIFixupSection = BC.getUniqueSectionByName(".pci_fixup"); + if (!PCIFixupSection) + return Error::success(); + + if (PCIFixupSection->getSize() % PCI_FIXUP_ENTRY_SIZE) + return createStringError(errc::executable_format_error, + "PCI fixup table size error"); + + const uint64_t Address = PCIFixupSection->getAddress(); + DataExtractor DE = DataExtractor(PCIFixupSection->getContents(), + BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + uint64_t EntryID = 0; + DataExtractor::Cursor Cursor(0); + while (Cursor && !DE.eof(Cursor)) { + const uint16_t Vendor = DE.getU16(Cursor); + const uint16_t Device = DE.getU16(Cursor); + const uint32_t Class = DE.getU32(Cursor); + const uint32_t ClassShift = DE.getU32(Cursor); + const uint64_t HookAddress = + Address + Cursor.tell() + (int32_t)DE.getU32(Cursor); + + if (!Cursor) + return createStringError(errc::executable_format_error, + "out of bounds while reading .pci_fixup: %s", + toString(Cursor.takeError()).c_str()); + + ++EntryID; + + if (opts::DumpPCIFixups) { + BC.outs() << "PCI fixup entry: " << EntryID << "\n\tVendor 0x" + << Twine::utohexstr(Vendor) << "\n\tDevice: 0x" + << Twine::utohexstr(Device) << "\n\tClass: 0x" + << Twine::utohexstr(Class) << "\n\tClassShift: 0x" + << Twine::utohexstr(ClassShift) << "\n\tHookAddress: 0x" + << Twine::utohexstr(HookAddress) << '\n'; + } + + BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(HookAddress); + if (!BF && opts::Verbosity) { + BC.outs() << "BOLT-INFO: no function matches address 0x" + << Twine::utohexstr(HookAddress) + << " of hook from .pci_fixup\n"; + } + + if (!BF || !BC.shouldEmit(*BF)) + continue; + + if (const uint64_t Offset = HookAddress - BF->getAddress()) { + BC.errs() << "BOLT-WARNING: PCI fixup detected in the middle of function " + << *BF << " at offset 0x" << Twine::utohexstr(Offset) << '\n'; + BF->setSimple(false); + } + } + + BC.outs() << "BOLT-INFO: parsed " << EntryID << " PCI fixup entries\n"; + + return Error::success(); +} + } // namespace std::unique_ptr diff --git a/bolt/test/X86/linux-pci-fixup.s b/bolt/test/X86/linux-pci-fixup.s new file mode 100644 index 000000000000..a574ba84c4df --- /dev/null +++ b/bolt/test/X86/linux-pci-fixup.s @@ -0,0 +1,41 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ +# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie +# RUN: llvm-bolt %t.exe --print-normalized -o %t.out |& FileCheck %s + +## Check that BOLT correctly parses the Linux kernel .pci_fixup section and +## verify that PCI fixup hook in the middle of a function is detected. + +# CHECK: BOLT-INFO: Linux kernel binary detected +# CHECK: BOLT-WARNING: PCI fixup detected in the middle of function _start +# CHECK: BOLT-INFO: parsed 2 PCI fixup entries + + .text + .globl _start + .type _start, %function +_start: + nop +.L0: + ret + .size _start, .-_start + +## PCI fixup table. + .section .pci_fixup,"a",@progbits + + .short 0x8086 # vendor + .short 0xbeef # device + .long 0xffffffff # class + .long 0x0 # class shift + .long _start - . # fixup + + .short 0x8086 # vendor + .short 0xbad # device + .long 0xffffffff # class + .long 0x0 # class shift + .long .L0 - . # fixup + +## Fake Linux Kernel sections. + .section __ksymtab,"a",@progbits + .section __ksymtab_gpl,"a",@progbits -- GitLab From 422d240dc9b4b36f505c43e6fe650af4f4cf4f98 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Tue, 12 Mar 2024 16:10:38 -0700 Subject: [PATCH 307/953] Relax tests to also work with newer versions of lldb. - result variables are optional - static members may print their values - public/protected shows up in ptype output --- .../debuginfo-tests/llgdb-tests/static-member-2.cpp | 10 +++++----- .../debuginfo-tests/llgdb-tests/static-member.cpp | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp index 5b6647c0631c..c9b416dace92 100644 --- a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp +++ b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp @@ -4,19 +4,19 @@ // XFAIL: gdb-clang-incompatibility // DEBUGGER: delete breakpoints -// DEBUGGER: break static-member.cpp:33 +// DEBUGGER: break static-member-2.cpp:36 // DEBUGGER: r // DEBUGGER: ptype C // CHECK: {{struct|class}} C { -// CHECK: static const int a; +// CHECK: static const int a // CHECK-NEXT: static int b; // CHECK-NEXT: static int c; -// CHECK-NEXT: int d; +// CHECK: int d; // CHECK-NEXT: } // DEBUGGER: p C::a -// CHECK: ${{[0-9]}} = 4 +// CHECK: 4 // DEBUGGER: p C::c -// CHECK: ${{[0-9]}} = 15 +// CHECK: 15 // PR14471, PR14734 diff --git a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp index 29dd84dc8325..492e0ca08420 100644 --- a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp +++ b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp @@ -3,14 +3,14 @@ // RUN: %test_debuginfo %s %t.out // XFAIL: !system-darwin && gdb-clang-incompatibility // DEBUGGER: delete breakpoints -// DEBUGGER: break static-member.cpp:33 +// DEBUGGER: break static-member.cpp:35 // DEBUGGER: r // DEBUGGER: ptype MyClass // CHECK: {{struct|class}} MyClass { -// CHECK: static const int a; +// CHECK: static const int a // CHECK-NEXT: static int b; // CHECK-NEXT: static int c; -// CHECK-NEXT: int d; +// CHECK: int d; // CHECK-NEXT: } // DEBUGGER: p MyClass::a // CHECK: ${{[0-9]}} = 4 -- GitLab From 418f0066ebfcde8cd72d33cc103fc1c3e36a1205 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Tue, 12 Mar 2024 16:11:45 -0700 Subject: [PATCH 308/953] Modernize llgdb script and make it easier to debug. --- .../debuginfo-tests/llgdb-tests/test_debuginfo.pl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/cross-project-tests/debuginfo-tests/llgdb-tests/test_debuginfo.pl b/cross-project-tests/debuginfo-tests/llgdb-tests/test_debuginfo.pl index 6dbc3b9b8632..fa52a5037c21 100755 --- a/cross-project-tests/debuginfo-tests/llgdb-tests/test_debuginfo.pl +++ b/cross-project-tests/debuginfo-tests/llgdb-tests/test_debuginfo.pl @@ -56,7 +56,7 @@ my $my_debugger = $ENV{'DEBUGGER'}; if (!$my_debugger) { if ($use_lldb) { my $path = dirname(Cwd::abs_path($0)); - $my_debugger = "/usr/bin/env python3 $path/llgdb.py"; + $my_debugger = "/usr/bin/xcrun python3 $path/llgdb.py"; } else { $my_debugger = "gdb"; } @@ -66,12 +66,18 @@ if (!$my_debugger) { my $debugger_options = "-q -batch -n -x"; # run debugger and capture output. +print("Running debugger\n"); system("$my_debugger $debugger_options $debugger_script_file $executable_file > $output_file 2>&1"); - +if ($?) { + print("Debugger output was:\n"); + system("cat", "$output_file"); + exit 1; +} # validate output. +print("Running FileCheck\n"); system("FileCheck", "-input-file", "$output_file", "$testcase_file"); -if ($?>>8 == 1) { - print "Debugger output was:\n"; +if ($?) { + print("Debugger output was:\n"); system("cat", "$output_file"); exit 1; } -- GitLab From 65f07b804c2c05cf49bd043f2a6e9a0020198165 Mon Sep 17 00:00:00 2001 From: anbbna <117081688+anbbna@users.noreply.github.com> Date: Wed, 13 Mar 2024 07:27:18 +0800 Subject: [PATCH 309/953] [MIPS] Introduce NAL instruction support for Mipsr6 and prer6 (#84429) NAL is an assembly idiom on Pre-R6 instruction sets (which is implemented in binutils), or an actual instruction on Release 6 instruction set, and is used to read the PC, due to the nature of the MIPS architecture. Since we can't read the PC directly, on pre-R6 we use a always-not-taken Branch and Link operation to the address of the next instruction, which effectively writes the address to $31, thus PC is read with offset +8. MIPS Release 6 removed the conventional Branch and Link instructions, but kept NAL as an actual instruction for compatibility on the assembly level. The instruction has the same encoding of the pre-R6 ones, and with the same behavior: PC + 8 -> $31. --- llvm/lib/Target/Mips/Mips32r6InstrFormats.td | 11 ++++++++++ llvm/lib/Target/Mips/Mips32r6InstrInfo.td | 16 ++++++++++++++- llvm/lib/Target/Mips/MipsInstrInfo.td | 3 +++ llvm/lib/Target/Mips/MipsScheduleGeneric.td | 2 +- llvm/test/MC/Mips/mips32/nal.s | 14 +++++++++++++ llvm/test/MC/Mips/mips32r6/nal.s | 21 ++++++++++++++++++++ 6 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 llvm/test/MC/Mips/mips32/nal.s create mode 100644 llvm/test/MC/Mips/mips32r6/nal.s diff --git a/llvm/lib/Target/Mips/Mips32r6InstrFormats.td b/llvm/lib/Target/Mips/Mips32r6InstrFormats.td index ccb6d1df777a..8536c52028c3 100644 --- a/llvm/lib/Target/Mips/Mips32r6InstrFormats.td +++ b/llvm/lib/Target/Mips/Mips32r6InstrFormats.td @@ -86,6 +86,7 @@ def OPCODE5_BC1NEZ : OPCODE5<0b01101>; def OPCODE5_BC2EQZ : OPCODE5<0b01001>; def OPCODE5_BC2NEZ : OPCODE5<0b01101>; def OPCODE5_BGEZAL : OPCODE5<0b10001>; +def OPCODE5_NAL : OPCODE5<0b10000>; def OPCODE5_SIGRIE : OPCODE5<0b10111>; // The next four constants are unnamed in the spec. These names are taken from // the OPGROUP names they are used with. @@ -201,6 +202,16 @@ class BAL_FM : MipsR6Inst { let Inst{15-0} = offset; } +// NAL for Release 6 +class NAL_FM : MipsR6Inst { + bits<32> Inst; + + let Inst{31-26} = OPGROUP_REGIMM.Value; + let Inst{25-21} = 0b00000; + let Inst{20-16} = OPCODE5_NAL.Value; + let Inst{15-0} = 0x00; +} + class COP0_EVP_DVP_FM sc> : MipsR6Inst { bits<5> rt; diff --git a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td index 854563ab32bd..9c29acbd0d8a 100644 --- a/llvm/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips32r6InstrInfo.td @@ -73,6 +73,7 @@ class AUI_ENC : AUI_FM; class AUIPC_ENC : PCREL16_FM; class BAL_ENC : BAL_FM; +class NAL_ENC : NAL_FM; class BALC_ENC : BRANCH_OFF26_FM<0b111010>; class BC_ENC : BRANCH_OFF26_FM<0b110010>; class BEQC_ENC : CMP_BRANCH_2R_OFF16_FM, @@ -381,6 +382,12 @@ class BC_DESC_BASE : BRANCH_DESC_BASE, bit isCTI = 1; } +class NAL_DESC_BASE : BRANCH_DESC_BASE, + MipsR6Arch { + string AsmString = instr_asm; + bit isCTI = 1; +} + class CMP_BC_DESC_BASE : BRANCH_DESC_BASE, MipsR6Arch { @@ -424,6 +431,12 @@ class BAL_DESC : BC_DESC_BASE<"bal", brtarget> { bit isCTI = 1; } +class NAL_DESC : NAL_DESC_BASE<"nal"> { + bit hasDelaySlot = 1; + list Defs = [RA]; + bit isCTI = 1; +} + class BALC_DESC : BC_DESC_BASE<"balc", brtarget26> { bit isCall = 1; list Defs = [RA]; @@ -868,6 +881,8 @@ def AUI : R6MMR6Rel, AUI_ENC, AUI_DESC, ISA_MIPS32R6; def AUIPC : R6MMR6Rel, AUIPC_ENC, AUIPC_DESC, ISA_MIPS32R6; def BAL : BAL_ENC, BAL_DESC, ISA_MIPS32R6; def BALC : R6MMR6Rel, BALC_ENC, BALC_DESC, ISA_MIPS32R6; +def NAL : NAL_ENC, NAL_DESC, ISA_MIPS32R6; + let AdditionalPredicates = [NotInMicroMips] in { def BC1EQZ : BC1EQZ_ENC, BC1EQZ_DESC, ISA_MIPS32R6, HARDFLOAT; def BC1NEZ : BC1NEZ_ENC, BC1NEZ_DESC, ISA_MIPS32R6, HARDFLOAT; @@ -948,7 +963,6 @@ let AdditionalPredicates = [NotInMicroMips] in { def MUL_R6 : R6MMR6Rel, MUL_R6_ENC, MUL_R6_DESC, ISA_MIPS32R6; def MULU : R6MMR6Rel, MULU_ENC, MULU_DESC, ISA_MIPS32R6; } -def NAL; // BAL with rd=0 let AdditionalPredicates = [NotInMicroMips] in { def PREF_R6 : R6MMR6Rel, PREF_ENC, PREF_DESC, ISA_MIPS32R6; def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6, HARDFLOAT; diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index 4b6f4b22e71b..23e04c442bf6 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -3049,6 +3049,9 @@ def : MipsInstAlias<"divu $rd, $imm", (UDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, simm32:$imm), 0>, ISA_MIPS1_NOT_32R6_64R6; + +def : MipsInstAlias<"nal", (BLTZAL ZERO, 0), 1>, ISA_MIPS1_NOT_32R6_64R6; + def SRemMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), "rem\t$rd, $rs, $rt">, diff --git a/llvm/lib/Target/Mips/MipsScheduleGeneric.td b/llvm/lib/Target/Mips/MipsScheduleGeneric.td index a3df88a93cfb..6771a897eea7 100644 --- a/llvm/lib/Target/Mips/MipsScheduleGeneric.td +++ b/llvm/lib/Target/Mips/MipsScheduleGeneric.td @@ -285,7 +285,7 @@ def GenericWriteJumpAndLink : SchedWriteRes<[GenericIssueCTISTD]> { // jalr, jr.hb, jr, jalr.hb, jarlc, jialc def : InstRW<[GenericWriteJump], (instrs B, BAL, BAL_BR, BEQ, BNE, BGTZ, BGEZ, BLEZ, BLTZ, BLTZAL, J, JALX, JR, JR_HB, ERET, - ERet, ERETNC, DERET)>; + ERet, ERETNC, DERET, NAL)>; def : InstRW<[GenericWriteJump], (instrs BEQL, BNEL, BGEZL, BGTZL, BLEZL, BLTZL)>; diff --git a/llvm/test/MC/Mips/mips32/nal.s b/llvm/test/MC/Mips/mips32/nal.s new file mode 100644 index 000000000000..72c723108586 --- /dev/null +++ b/llvm/test/MC/Mips/mips32/nal.s @@ -0,0 +1,14 @@ +# RUN: llvm-mc %s -triple=mipsel-linux-gnu -filetype=obj -o - | \ +# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32-EL +# RUN: llvm-mc %s -triple=mips-linux-gnu -filetype=obj -o - | \ +# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32-EB + +# Whether it is a macro or an actual instruction, it always has a delay slot. +# Ensure the delay slot is filled correctly. +# MIPS32-EL: 00 00 10 04 bltzal $zero, 0x4 +# MIPS32-EL-NEXT: 00 00 00 00 nop +# MIPS32-EB: 04 10 00 00 bltzal $zero, 0x4 +# MIPS32-EB-NEXT: 00 00 00 00 nop + +nal_test: + nal diff --git a/llvm/test/MC/Mips/mips32r6/nal.s b/llvm/test/MC/Mips/mips32r6/nal.s new file mode 100644 index 000000000000..94c1a774f47e --- /dev/null +++ b/llvm/test/MC/Mips/mips32r6/nal.s @@ -0,0 +1,21 @@ +# RUN: llvm-mc %s -triple=mipsisa32r6el-linux-gnu -filetype=obj -o - | \ +# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32R6-EL +# RUN: llvm-mc %s -triple=mipsisa32r6-linux-gnu -filetype=obj -o - | \ +# RUN: llvm-objdump --no-print-imm-hex -d - | FileCheck %s --check-prefix=MIPS32R6-EB + +# Whether it is a macro or an actual instruction, it always has a delay slot. +# Ensure the delay slot is filled correctly. +# Also ensure that NAL does not reside in a forbidden slot. +# MIPS32R6-EL: 00 00 80 f8 bnezc $4, 0x4 +# MIPS32R6-EL-NEXT: 00 00 00 00 nop +# MIPS32R6-EL: 00 00 10 04 nal +# MIPS32R6-EL-NEXT: 00 00 00 00 nop +# MIPS32R6-EB: f8 80 00 00 bnezc $4, 0x4 +# MIPS32R6-EB-NEXT: 00 00 00 00 nop +# MIPS32R6-EB: 04 10 00 00 nal +# MIPS32R6-EB-NEXT: 00 00 00 00 nop + +nal_test: + # We generate a fobidden solt just for testing. + bnezc $a0, 0 + nal -- GitLab From 8003f553a01a9a2a7eb09fe07e88f1ba9ee7d3a7 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Tue, 12 Mar 2024 16:29:34 -0700 Subject: [PATCH 310/953] Reland "[llvm-exegesis] Add thread IDs to subprocess memory names (#84451)" This reverts commit aefad27096bba513f06162fac2763089578f3de4. This relands commit 6bbe8a296ee91754d423c59c35727eaa624f7140. This patch was casuing build failures on non-Linux platforms due to the default implementations for the functions not being updated. This ended up causing out-of-line definition errors. Fixed for the relanding. --- .../llvm-exegesis/lib/BenchmarkRunner.cpp | 9 +++--- .../llvm-exegesis/lib/SubprocessMemory.cpp | 30 +++++++++++++------ .../llvm-exegesis/lib/SubprocessMemory.h | 5 +++- .../X86/SubprocessMemoryTest.cpp | 5 +++- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp index 5c9848f3c688..4e97d188d172 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -301,6 +301,7 @@ private: if (AddMemDefError) return AddMemDefError; + long ParentTID = SubprocessMemory::getCurrentTID(); pid_t ParentOrChildPID = fork(); if (ParentOrChildPID == -1) { @@ -314,7 +315,7 @@ private: // Unregister handlers, signal handling is now handled through ptrace in // the host process. sys::unregisterHandlers(); - prepareAndRunBenchmark(PipeFiles[0], Key); + prepareAndRunBenchmark(PipeFiles[0], Key, ParentTID); // The child process terminates in the above function, so we should never // get to this point. llvm_unreachable("Child process didn't exit when expected."); @@ -415,8 +416,8 @@ private: setrlimit(RLIMIT_CORE, &rlim); } - [[noreturn]] void prepareAndRunBenchmark(int Pipe, - const BenchmarkKey &Key) const { + [[noreturn]] void prepareAndRunBenchmark(int Pipe, const BenchmarkKey &Key, + long ParentTID) const { // Disable core dumps in the child process as otherwise everytime we // encounter an execution failure like a segmentation fault, we will create // a core dump. We report the information directly rather than require the @@ -473,7 +474,7 @@ private: Expected AuxMemFDOrError = SubprocessMemory::setupAuxiliaryMemoryInSubprocess( - Key.MemoryValues, ParentPID, CounterFileDescriptor); + Key.MemoryValues, ParentPID, ParentTID, CounterFileDescriptor); if (!AuxMemFDOrError) exit(ChildProcessExitCodeE::AuxiliaryMemorySetupFailed); diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp index a49fa077257d..1fd81bd407be 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp @@ -9,11 +9,13 @@ #include "SubprocessMemory.h" #include "Error.h" #include "llvm/Support/Error.h" +#include "llvm/Support/FormatVariadic.h" #include #ifdef __linux__ #include #include +#include #include #endif @@ -22,12 +24,21 @@ namespace exegesis { #if defined(__linux__) && !defined(__ANDROID__) +long SubprocessMemory::getCurrentTID() { + // We're using the raw syscall here rather than the gettid() function provided + // by most libcs for compatibility as gettid() was only added to glibc in + // version 2.30. + return syscall(SYS_gettid); +} + Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessID) { // Add the PID to the shared memory name so that if we're running multiple // processes at the same time, they won't interfere with each other. // This comes up particularly often when running the exegesis tests with - // llvm-lit - std::string AuxiliaryMemoryName = "/auxmem" + std::to_string(ProcessID); + // llvm-lit. Additionally add the TID so that downstream consumers + // using multiple threads don't run into conflicts. + std::string AuxiliaryMemoryName = + formatv("/{0}auxmem{1}", getCurrentTID(), ProcessID); int AuxiliaryMemoryFD = shm_open(AuxiliaryMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryFD == -1) @@ -47,8 +58,8 @@ Error SubprocessMemory::addMemoryDefinition( pid_t ProcessPID) { SharedMemoryNames.reserve(MemoryDefinitions.size()); for (auto &[Name, MemVal] : MemoryDefinitions) { - std::string SharedMemoryName = "/" + std::to_string(ProcessPID) + "memdef" + - std::to_string(MemVal.Index); + std::string SharedMemoryName = + formatv("/{0}t{1}memdef{2}", ProcessPID, getCurrentTID(), MemVal.Index); SharedMemoryNames.push_back(SharedMemoryName); int SharedMemoryFD = shm_open(SharedMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); @@ -82,8 +93,9 @@ Error SubprocessMemory::addMemoryDefinition( Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, int CounterFileDescriptor) { - std::string AuxiliaryMemoryName = "/auxmem" + std::to_string(ParentPID); + pid_t ParentPID, long ParentTID, int CounterFileDescriptor) { + std::string AuxiliaryMemoryName = + formatv("/{0}auxmem{1}", ParentTID, ParentPID); int AuxiliaryMemoryFileDescriptor = shm_open(AuxiliaryMemoryName.c_str(), O_RDWR, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryFileDescriptor == -1) @@ -97,8 +109,8 @@ Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( return make_error("Mapping auxiliary memory failed"); AuxiliaryMemoryMapping[0] = CounterFileDescriptor; for (auto &[Name, MemVal] : MemoryDefinitions) { - std::string MemoryValueName = "/" + std::to_string(ParentPID) + "memdef" + - std::to_string(MemVal.Index); + std::string MemoryValueName = + formatv("/{0}t{1}memdef{2}", ParentPID, ParentTID, MemVal.Index); AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] = shm_open(MemoryValueName.c_str(), O_RDWR, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] == -1) @@ -133,7 +145,7 @@ Error SubprocessMemory::addMemoryDefinition( Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, int CounterFileDescriptor) { + pid_t ParentPID, long ParentTID, int CounterFileDescriptor) { return make_error( "setupAuxiliaryMemoryInSubprocess is only supported on Linux"); } diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h index e20b50cdc811..572d1085d9cf 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h @@ -35,6 +35,9 @@ public: static constexpr const size_t AuxiliaryMemoryOffset = 1; static constexpr const size_t AuxiliaryMemorySize = 4096; + // Gets the thread ID for the calling thread. + static long getCurrentTID(); + Error initializeSubprocessMemory(pid_t ProcessID); // The following function sets up memory definitions. It creates shared @@ -54,7 +57,7 @@ public: // section. static Expected setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, int CounterFileDescriptor); + pid_t ParentPID, long ParentTID, int CounterFileDescriptor); ~SubprocessMemory(); diff --git a/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp index c07ec188a602..7c23e7b7e9c5 100644 --- a/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #endif // __linux__ @@ -49,7 +50,9 @@ protected: std::string getSharedMemoryName(const unsigned TestNumber, const unsigned DefinitionNumber) { - return "/" + std::to_string(getSharedMemoryNumber(TestNumber)) + "memdef" + + long CurrentTID = syscall(SYS_gettid); + return "/" + std::to_string(getSharedMemoryNumber(TestNumber)) + "t" + + std::to_string(CurrentTID) + "memdef" + std::to_string(DefinitionNumber); } -- GitLab From 1c3b15e9f5bc671e40bcf5d3475f5425466754ce Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Tue, 12 Mar 2024 16:55:01 -0700 Subject: [PATCH 311/953] [llvm-exegesis] Use LLVM Support to get thread ID This patch switches from manually using the Linux syscall to get the current thread ID to using the relevant LLVM Support libraries that abstract over the low level system details. --- llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp | 2 +- .../tools/llvm-exegesis/lib/SubprocessMemory.cpp | 16 +++++----------- llvm/tools/llvm-exegesis/lib/SubprocessMemory.h | 5 +---- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp index 4e97d188d172..17ce0355ef4f 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -301,7 +301,7 @@ private: if (AddMemDefError) return AddMemDefError; - long ParentTID = SubprocessMemory::getCurrentTID(); + long ParentTID = get_threadid(); pid_t ParentOrChildPID = fork(); if (ParentOrChildPID == -1) { diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp index 1fd81bd407be..28b341c46180 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp @@ -10,6 +10,7 @@ #include "Error.h" #include "llvm/Support/Error.h" #include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/Threading.h" #include #ifdef __linux__ @@ -24,13 +25,6 @@ namespace exegesis { #if defined(__linux__) && !defined(__ANDROID__) -long SubprocessMemory::getCurrentTID() { - // We're using the raw syscall here rather than the gettid() function provided - // by most libcs for compatibility as gettid() was only added to glibc in - // version 2.30. - return syscall(SYS_gettid); -} - Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessID) { // Add the PID to the shared memory name so that if we're running multiple // processes at the same time, they won't interfere with each other. @@ -38,7 +32,7 @@ Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessID) { // llvm-lit. Additionally add the TID so that downstream consumers // using multiple threads don't run into conflicts. std::string AuxiliaryMemoryName = - formatv("/{0}auxmem{1}", getCurrentTID(), ProcessID); + formatv("/{0}auxmem{1}", get_threadid(), ProcessID); int AuxiliaryMemoryFD = shm_open(AuxiliaryMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryFD == -1) @@ -59,7 +53,7 @@ Error SubprocessMemory::addMemoryDefinition( SharedMemoryNames.reserve(MemoryDefinitions.size()); for (auto &[Name, MemVal] : MemoryDefinitions) { std::string SharedMemoryName = - formatv("/{0}t{1}memdef{2}", ProcessPID, getCurrentTID(), MemVal.Index); + formatv("/{0}t{1}memdef{2}", ProcessPID, get_threadid(), MemVal.Index); SharedMemoryNames.push_back(SharedMemoryName); int SharedMemoryFD = shm_open(SharedMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); @@ -93,7 +87,7 @@ Error SubprocessMemory::addMemoryDefinition( Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, long ParentTID, int CounterFileDescriptor) { + pid_t ParentPID, uint64_t ParentTID, int CounterFileDescriptor) { std::string AuxiliaryMemoryName = formatv("/{0}auxmem{1}", ParentTID, ParentPID); int AuxiliaryMemoryFileDescriptor = @@ -145,7 +139,7 @@ Error SubprocessMemory::addMemoryDefinition( Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, long ParentTID, int CounterFileDescriptor) { + pid_t ParentPID, uint64_t ParentTID, int CounterFileDescriptor) { return make_error( "setupAuxiliaryMemoryInSubprocess is only supported on Linux"); } diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h index 572d1085d9cf..807046e38ce6 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h @@ -35,9 +35,6 @@ public: static constexpr const size_t AuxiliaryMemoryOffset = 1; static constexpr const size_t AuxiliaryMemorySize = 4096; - // Gets the thread ID for the calling thread. - static long getCurrentTID(); - Error initializeSubprocessMemory(pid_t ProcessID); // The following function sets up memory definitions. It creates shared @@ -57,7 +54,7 @@ public: // section. static Expected setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, long ParentTID, int CounterFileDescriptor); + pid_t ParentPID, uint64_t ParentTID, int CounterFileDescriptor); ~SubprocessMemory(); -- GitLab From 94e27c265a9aeb3659175ecee81a68d1763e0180 Mon Sep 17 00:00:00 2001 From: Peiming Liu Date: Tue, 12 Mar 2024 16:59:17 -0700 Subject: [PATCH 312/953] =?UTF-8?q?[mlir][sparse]=20reuse=20tensor.insert?= =?UTF-8?q?=20operation=20to=20insert=20elements=20into=20=E2=80=A6=20(#84?= =?UTF-8?q?987)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …a sparse tensor. --- .../SparseTensor/IR/SparseTensorOps.td | 42 ------------------- .../SparseTensor/IR/SparseTensorDialect.cpp | 9 ---- .../BufferizableOpInterfaceImpl.cpp | 22 ---------- .../Transforms/SparseReinterpretMap.cpp | 4 +- .../Transforms/SparseTensorCodegen.cpp | 19 +++++---- .../Transforms/SparseTensorConversion.cpp | 21 ++++++---- .../Transforms/SparseTensorRewriting.cpp | 6 ++- .../Transforms/Sparsification.cpp | 5 ++- mlir/test/Dialect/SparseTensor/codegen.mlir | 6 +-- .../SparseTensor/constant_index_map.mlir | 2 +- .../test/Dialect/SparseTensor/conversion.mlir | 2 +- mlir/test/Dialect/SparseTensor/invalid.mlir | 18 -------- mlir/test/Dialect/SparseTensor/roundtrip.mlir | 4 +- mlir/test/Dialect/SparseTensor/sparse_2d.mlir | 10 ++--- .../SparseTensor/sparse_broadcast.mlir | 2 +- .../sparse_conv_2d_slice_based.mlir | 2 +- .../Dialect/SparseTensor/sparse_fp_ops.mlir | 4 +- .../Dialect/SparseTensor/sparse_index.mlir | 2 +- .../test/Dialect/SparseTensor/sparse_out.mlir | 4 +- .../SparseTensor/sparse_reinterpret_map.mlir | 2 +- .../Dialect/SparseTensor/sparse_reshape.mlir | 8 ++-- .../SparseTensor/sparse_tensor_reshape.mlir | 2 +- .../SparseTensor/sparse_transpose.mlir | 2 +- .../SparseTensor/CPU/sparse_insert_1d.mlir | 10 ++--- .../SparseTensor/CPU/sparse_insert_2d.mlir | 40 +++++++++--------- .../SparseTensor/CPU/sparse_insert_3d.mlir | 40 +++++++++--------- 26 files changed, 106 insertions(+), 182 deletions(-) diff --git a/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td b/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td index feed15d6af05..0498576fcffc 100644 --- a/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td +++ b/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td @@ -668,48 +668,6 @@ def SparseTensor_CrdTranslateOp : SparseTensor_Op<"crd_translate", [Pure]>, // refined over time as our sparse abstractions evolve. //===----------------------------------------------------------------------===// -def SparseTensor_InsertOp : SparseTensor_Op<"insert", - [TypesMatchWith<"value type matches element type of tensor", - "tensor", "value", - "::llvm::cast($_self).getElementType()">, - AllTypesMatch<["tensor", "result"]>]>, - Arguments<(ins AnyType:$value, - AnySparseTensor:$tensor, - Variadic:$lvlCoords)>, - Results<(outs AnySparseTensor:$result)> { - string summary = "Inserts a value into the sparse tensor"; - string description = [{ - Inserts the value into the underlying storage of the tensor at the - given level-coordinates. The arity of `lvlCoords` must match the - level-rank of the tensor. This operation can only be applied when - the tensor materializes unintialized from a `tensor.empty` operation - and the final tensor is constructed with a `load` operation which - has the `hasInserts` attribute set. - - The level-properties of the sparse tensor type fully describe what - kind of insertion order is allowed. When all levels have "unique" - and "ordered" properties, for example, insertions should occur in - strict lexicographical level-coordinate order. Other properties - define different insertion regimens. Inserting in a way contrary - to these properties results in undefined behavior. - - Note that this operation is "impure" in the sense that even though - the result is modeled through an SSA value, the insertion is eventually - done "in place", and referencing the old SSA value is undefined behavior. - This operation is scheduled to be unified with the dense counterpart - `tensor.insert` that has pure SSA semantics. - - Example: - - ```mlir - %result = sparse_tensor.insert %val into %tensor[%i,%j] : tensor<1024x1024xf64, #CSR> - ``` - }]; - let assemblyFormat = "$value `into` $tensor `[` $lvlCoords `]` attr-dict" - "`:` type($tensor)"; - let hasVerifier = 1; -} - def SparseTensor_PushBackOp : SparseTensor_Op<"push_back", [TypesMatchWith<"value type matches element type of inBuffer", "inBuffer", "value", diff --git a/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp b/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp index c19907a945d3..7750efdd9add 100644 --- a/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp +++ b/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp @@ -1741,15 +1741,6 @@ LogicalResult ConcatenateOp::verify() { return success(); } -LogicalResult InsertOp::verify() { - const auto stt = getSparseTensorType(getTensor()); - if (stt.getEncoding().getBatchLvlRank() > 0) - return emitOpError("batched sparse tensor insertion not implemented"); - if (stt.getLvlRank() != static_cast(getLvlCoords().size())) - return emitOpError("incorrect number of coordinates"); - return success(); -} - void PushBackOp::build(OpBuilder &builder, OperationState &result, Value curSize, Value inBuffer, Value value) { build(builder, result, curSize, inBuffer, value, Value()); diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp index 3f4ae1f67de1..a942a721e218 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp @@ -187,27 +187,6 @@ struct DisassembleOpInterface } }; -struct InsertOpInterface : public SparseBufferizableOpInterfaceExternalModel< - InsertOpInterface, sparse_tensor::InsertOp> { - bool bufferizesToMemoryRead(Operation *op, OpOperand &opOperand, - const AnalysisState &state) const { - return true; - } - - bool bufferizesToMemoryWrite(Operation *op, OpOperand &opOperand, - const AnalysisState &state) const { - // InsertOp writes to memory. - return true; - } - - AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand, - const AnalysisState &state) const { - // InsertOp returns an alias of its operand. - assert(op->getNumResults() == 1); - return {{op->getOpResult(0), BufferRelation::Equivalent}}; - } -}; - struct NumberOfEntriesOpInterface : public SparseBufferizableOpInterfaceExternalModel< NumberOfEntriesOpInterface, sparse_tensor::NumberOfEntriesOp> { @@ -324,7 +303,6 @@ void mlir::sparse_tensor::registerBufferizableOpInterfaceExternalModels( sparse_tensor::ConvertOp::attachInterface(*ctx); sparse_tensor::LoadOp::attachInterface(*ctx); sparse_tensor::NewOp::attachInterface(*ctx); - sparse_tensor::InsertOp::attachInterface(*ctx); sparse_tensor::NumberOfEntriesOp::attachInterface< NumberOfEntriesOpInterface>(*ctx); sparse_tensor::AssembleOp::attachInterface(*ctx); diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseReinterpretMap.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseReinterpretMap.cpp index fbe2fc31ab8b..f93b59de29e5 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseReinterpretMap.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseReinterpretMap.cpp @@ -640,14 +640,14 @@ struct TensorInsertDemapper using DemapInsRewriter::DemapInsRewriter; LogicalResult rewriteOp(tensor::InsertOp op, OpAdaptor adaptor, PatternRewriter &rewriter) const { - if (!hasAnySparseResult(op)) + if (!hasAnySparseResult(op) || !hasAnyNonIdentityOperandsOrResults(op)) return failure(); Location loc = op.getLoc(); auto stt = getSparseTensorType(op.getResult()); ValueRange lvlCrd = stt.translateCrds(rewriter, loc, op.getIndices(), CrdTransDirectionKind::dim2lvl); - auto insertOp = rewriter.create( + auto insertOp = rewriter.create( loc, op.getScalar(), adaptor.getDest(), lvlCrd); Value out = genRemap(rewriter, stt.getEncoding(), insertOp.getResult()); diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp index 44c5d4dbe485..7ff2fc25328a 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp @@ -1014,24 +1014,29 @@ public: }; /// Sparse codegen rule for the insert operator. -class SparseInsertConverter : public OpConversionPattern { +class SparseInsertConverter : public OpConversionPattern { public: using OpConversionPattern::OpConversionPattern; LogicalResult - matchAndRewrite(InsertOp op, OpAdaptor adaptor, + matchAndRewrite(tensor::InsertOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { + auto stt = getSparseTensorType(adaptor.getDest()); + if (!stt.hasEncoding()) + return failure(); + assert(stt.isIdentity() && "Run reinterpret-map before conversion."); + Location loc = op.getLoc(); - auto desc = getDescriptorFromTensorTuple(adaptor.getTensor()); + auto desc = getDescriptorFromTensorTuple(adaptor.getDest()); TypeRange flatSpTensorTps = desc.getFields().getTypes(); SmallVector params = llvm::to_vector(desc.getFields()); - params.append(adaptor.getLvlCoords().begin(), adaptor.getLvlCoords().end()); - params.push_back(adaptor.getValue()); - SparseInsertGenerator insertGen(op.getTensor().getType(), flatSpTensorTps, + params.append(adaptor.getIndices().begin(), adaptor.getIndices().end()); + params.push_back(adaptor.getScalar()); + SparseInsertGenerator insertGen(op.getDest().getType(), flatSpTensorTps, params, /*genCall=*/true); SmallVector ret = insertGen.genCallOrInline(rewriter, loc); // Replace operation with resulting memrefs. rewriter.replaceOp(op, - genTuple(rewriter, loc, op.getTensor().getType(), ret)); + genTuple(rewriter, loc, op.getDest().getType(), ret)); return success(); } }; diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp index 010c3aa58b72..0937c10f2572 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp @@ -580,17 +580,24 @@ public: }; /// Sparse conversion rule for the insertion operator. -class SparseTensorInsertConverter : public OpConversionPattern { +class SparseTensorInsertConverter + : public OpConversionPattern { public: using OpConversionPattern::OpConversionPattern; LogicalResult - matchAndRewrite(InsertOp op, OpAdaptor adaptor, + matchAndRewrite(tensor::InsertOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { // Note that the current regime only allows for strict lexicographic // coordinate order. All values are passed by reference through stack // allocated memrefs. Location loc = op->getLoc(); - const auto stt = getSparseTensorType(op.getTensor()); + const auto stt = getSparseTensorType(op.getDest()); + + // Dense tensor insertion. + if (!stt.hasEncoding()) + return failure(); + + assert(stt.isIdentity() && "Run reinterpret-map before conversion."); const auto elemTp = stt.getElementType(); const Level lvlRank = stt.getLvlRank(); Value lvlCoords, vref; @@ -608,12 +615,12 @@ public: lvlCoords = genAlloca(rewriter, loc, lvlRank, rewriter.getIndexType()); vref = genAllocaScalar(rewriter, loc, elemTp); } - storeAll(rewriter, loc, lvlCoords, adaptor.getLvlCoords()); - rewriter.create(loc, adaptor.getValue(), vref); + storeAll(rewriter, loc, lvlCoords, adaptor.getIndices()); + rewriter.create(loc, adaptor.getScalar(), vref); SmallString<12> name{"lexInsert", primaryTypeFunctionSuffix(elemTp)}; createFuncCall(rewriter, loc, name, {}, - {adaptor.getTensor(), lvlCoords, vref}, EmitCInterface::On); - rewriter.replaceOp(op, adaptor.getTensor()); + {adaptor.getDest(), lvlCoords, vref}, EmitCInterface::On); + rewriter.replaceOp(op, adaptor.getDest()); return success(); } }; diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp index a65bce78d095..17f70d0796cc 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp @@ -817,7 +817,8 @@ public: reshapeCvs(builder, loc, expandReass, collapsedSizes, collapsedDcvs, dstSizes, dstDcvs); - auto t = builder.create(loc, v, reduc.front(), dstDcvs); + auto t = + builder.create(loc, v, reduc.front(), dstDcvs); builder.create(loc, t); }); @@ -901,7 +902,8 @@ public: SmallVector dstDcvs; reshapeCvs(builder, loc, op.getReassociationIndices(), srcSizes, srcDcvs, dstSizes, dstDcvs); - auto t = builder.create(loc, v, reduc.front(), dstDcvs); + auto t = + builder.create(loc, v, reduc.front(), dstDcvs); builder.create(loc, t); }); diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp index 1fb70ed5035c..cd046b670d9a 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp @@ -428,7 +428,7 @@ static void genInsertionStore(CodegenEnv &env, OpBuilder &builder, OpOperand *t, /*else=*/true); // True branch. builder.setInsertionPointToStart(ifValidLexInsert.thenBlock()); - Value res = builder.create(loc, rhs, chain, ivs); + Value res = builder.create(loc, rhs, chain, ivs); builder.create(loc, res); // False branch. builder.setInsertionPointToStart(ifValidLexInsert.elseBlock()); @@ -438,7 +438,8 @@ static void genInsertionStore(CodegenEnv &env, OpBuilder &builder, OpOperand *t, env.updateInsertionChain(ifValidLexInsert.getResult(0)); } else { // Generates regular insertion chain. - env.updateInsertionChain(builder.create(loc, rhs, chain, ivs)); + env.updateInsertionChain( + builder.create(loc, rhs, chain, ivs)); } return; } diff --git a/mlir/test/Dialect/SparseTensor/codegen.mlir b/mlir/test/Dialect/SparseTensor/codegen.mlir index b63762485c96..40bfa1e4e2a5 100644 --- a/mlir/test/Dialect/SparseTensor/codegen.mlir +++ b/mlir/test/Dialect/SparseTensor/codegen.mlir @@ -643,7 +643,7 @@ func.func @sparse_compression_unordered(%tensor: tensor<8x8xf64, #UCSR>, // CHECK: %[[R:.*]]:4 = call @_insert_compressed_128_f64_0_0(%[[A1]], %[[A2]], %[[A3]], %[[A4]], %[[A5]], %[[A6]]) // CHECK: return %[[R]]#0, %[[R]]#1, %[[R]]#2, %[[R]]#3 func.func @sparse_insert(%arg0: tensor<128xf64, #SV>, %arg1: index, %arg2: f64) -> tensor<128xf64, #SV> { - %0 = sparse_tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf64, #SV> + %0 = tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf64, #SV> %1 = sparse_tensor.load %0 hasInserts : tensor<128xf64, #SV> return %1 : tensor<128xf64, #SV> } @@ -666,7 +666,7 @@ func.func @sparse_insert(%arg0: tensor<128xf64, #SV>, %arg1: index, %arg2: f64) // CHECK: %[[R:.*]]:4 = call @_insert_compressed_128_f64_64_32(%[[A1]], %[[A2]], %[[A3]], %[[A4]], %[[A5]], %[[A6]]) // CHECK: return %[[R]]#0, %[[R]]#1, %[[R]]#2, %[[R]]#3 func.func @sparse_insert_typed(%arg0: tensor<128xf64, #SparseVector>, %arg1: index, %arg2: f64) -> tensor<128xf64, #SparseVector> { - %0 = sparse_tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf64, #SparseVector> + %0 = tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf64, #SparseVector> %1 = sparse_tensor.load %0 hasInserts : tensor<128xf64, #SparseVector> return %1 : tensor<128xf64, #SparseVector> } @@ -690,7 +690,7 @@ func.func @sparse_insert_typed(%arg0: tensor<128xf64, #SparseVector>, %arg1: ind // CHECK: %[[R:.*]]:4 = call @_insert_compressed_nonunique_singleton_5_6_f64_0_0(%[[A0]], %[[A1]], %[[A2]], %[[A3]], %[[A4]], %[[A4]], %[[A5]]) // CHECK: return %[[R]]#0, %[[R]]#1, %[[R]]#2, %[[R]]#3 func.func @sparse_insert_coo(%arg0: tensor<5x6xf64, #Coo>, %arg1: index, %arg2: f64) -> tensor<5x6xf64, #Coo> { - %0 = sparse_tensor.insert %arg2 into %arg0[%arg1, %arg1] : tensor<5x6xf64, #Coo> + %0 = tensor.insert %arg2 into %arg0[%arg1, %arg1] : tensor<5x6xf64, #Coo> %1 = sparse_tensor.load %0 hasInserts : tensor<5x6xf64, #Coo> return %1 : tensor<5x6xf64, #Coo> } diff --git a/mlir/test/Dialect/SparseTensor/constant_index_map.mlir b/mlir/test/Dialect/SparseTensor/constant_index_map.mlir index eaef6a315852..f9559ce648c7 100644 --- a/mlir/test/Dialect/SparseTensor/constant_index_map.mlir +++ b/mlir/test/Dialect/SparseTensor/constant_index_map.mlir @@ -20,7 +20,7 @@ // CHECK: %[[VAL_11:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_3]], %[[VAL_9]]] : memref<1x77xi1> // CHECK: %[[VAL_12:.*]] = memref.load %[[VAL_7]]{{\[}}%[[VAL_3]], %[[VAL_9]]] : memref<1x77xi1> // CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_11]], %[[VAL_12]] : i1 -// CHECK: %[[VAL_14:.*]] = sparse_tensor.insert %[[VAL_13]] into %[[VAL_10]]{{\[}}%[[VAL_9]]] : tensor<77xi1, #{{.*}}> +// CHECK: %[[VAL_14:.*]] = tensor.insert %[[VAL_13]] into %[[VAL_10]]{{\[}}%[[VAL_9]]] : tensor<77xi1, #{{.*}}> // CHECK: scf.yield %[[VAL_14]] : tensor<77xi1, #{{.*}}> // CHECK: } // CHECK: %[[VAL_15:.*]] = sparse_tensor.load %[[VAL_16:.*]] hasInserts : tensor<77xi1, #{{.*}}> diff --git a/mlir/test/Dialect/SparseTensor/conversion.mlir b/mlir/test/Dialect/SparseTensor/conversion.mlir index 465f21086266..f23f6ac4f181 100644 --- a/mlir/test/Dialect/SparseTensor/conversion.mlir +++ b/mlir/test/Dialect/SparseTensor/conversion.mlir @@ -318,7 +318,7 @@ func.func @sparse_reconstruct_ins(%arg0: tensor<128xf32, #SparseVector>) -> tens func.func @sparse_insert(%arg0: tensor<128xf32, #SparseVector>, %arg1: index, %arg2: f32) -> tensor<128xf32, #SparseVector> { - %0 = sparse_tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf32, #SparseVector> + %0 = tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf32, #SparseVector> return %0 : tensor<128xf32, #SparseVector> } diff --git a/mlir/test/Dialect/SparseTensor/invalid.mlir b/mlir/test/Dialect/SparseTensor/invalid.mlir index eac97f702f58..48f28ef390ed 100644 --- a/mlir/test/Dialect/SparseTensor/invalid.mlir +++ b/mlir/test/Dialect/SparseTensor/invalid.mlir @@ -290,24 +290,6 @@ func.func @sparse_unannotated_load(%arg0: tensor<16x32xf64>) -> tensor<16x32xf64 // ----- -func.func @sparse_unannotated_insert(%arg0: tensor<128xf64>, %arg1: index, %arg2: f64) { - // expected-error@+1 {{'sparse_tensor.insert' 'tensor' must be sparse tensor of any type values, but got 'tensor<128xf64>'}} - sparse_tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf64> - return -} - -// ----- - -#CSR = #sparse_tensor.encoding<{map = (d0, d1) -> (d0 : dense, d1 : compressed)}> - -func.func @sparse_wrong_arity_insert(%arg0: tensor<128x64xf64, #CSR>, %arg1: index, %arg2: f64) { - // expected-error@+1 {{'sparse_tensor.insert' op incorrect number of coordinates}} - sparse_tensor.insert %arg2 into %arg0[%arg1] : tensor<128x64xf64, #CSR> - return -} - -// ----- - func.func @sparse_push_back(%arg0: index, %arg1: memref, %arg2: f32) -> (memref, index) { // expected-error@+1 {{'sparse_tensor.push_back' op failed to verify that value type matches element type of inBuffer}} %0:2 = sparse_tensor.push_back %arg0, %arg1, %arg2 : index, memref, f32 diff --git a/mlir/test/Dialect/SparseTensor/roundtrip.mlir b/mlir/test/Dialect/SparseTensor/roundtrip.mlir index 41094fbad921..e9e458e805ba 100644 --- a/mlir/test/Dialect/SparseTensor/roundtrip.mlir +++ b/mlir/test/Dialect/SparseTensor/roundtrip.mlir @@ -311,10 +311,10 @@ func.func @sparse_load_ins(%arg0: tensor<16x32xf64, #DenseMatrix>) -> tensor<16x // CHECK-SAME: %[[A:.*]]: tensor<128xf64, #sparse{{[0-9]*}}>, // CHECK-SAME: %[[B:.*]]: index, // CHECK-SAME: %[[C:.*]]: f64) -// CHECK: %[[T:.*]] = sparse_tensor.insert %[[C]] into %[[A]][%[[B]]] : tensor<128xf64, #{{.*}}> +// CHECK: %[[T:.*]] = tensor.insert %[[C]] into %[[A]][%[[B]]] : tensor<128xf64, #{{.*}}> // CHECK: return %[[T]] : tensor<128xf64, #{{.*}}> func.func @sparse_insert(%arg0: tensor<128xf64, #SparseVector>, %arg1: index, %arg2: f64) -> tensor<128xf64, #SparseVector> { - %0 = sparse_tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf64, #SparseVector> + %0 = tensor.insert %arg2 into %arg0[%arg1] : tensor<128xf64, #SparseVector> return %0 : tensor<128xf64, #SparseVector> } diff --git a/mlir/test/Dialect/SparseTensor/sparse_2d.mlir b/mlir/test/Dialect/SparseTensor/sparse_2d.mlir index 85ae0db91689..4afa0a8ceccd 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_2d.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_2d.mlir @@ -1090,20 +1090,20 @@ func.func @cmp_ss_ss(%arga: tensor<32x16xf32, #Tss>, %argb: tensor<32x16xf32, #T // CHECK: %[[VAL_41:.*]] = memref.load %[[VAL_8]]{{\[}}%[[VAL_30]]] : memref // CHECK: %[[VAL_42:.*]] = memref.load %[[VAL_11]]{{\[}}%[[VAL_31]]] : memref // CHECK: %[[VAL_43:.*]] = arith.subf %[[VAL_41]], %[[VAL_42]] : f64 -// CHECK: %[[VAL_44:.*]] = sparse_tensor.insert %[[VAL_43]] into %[[VAL_32]]{{\[}}%[[VAL_13]], %[[VAL_36]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_44:.*]] = tensor.insert %[[VAL_43]] into %[[VAL_32]]{{\[}}%[[VAL_13]], %[[VAL_36]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_44]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: } else { // CHECK: %[[VAL_45:.*]] = arith.cmpi eq, %[[VAL_33]], %[[VAL_36]] : index // CHECK: %[[VAL_46:.*]] = scf.if %[[VAL_45]] -> (tensor<2x3xf64, #sparse{{[0-9]*}}>) { // CHECK: %[[VAL_47:.*]] = memref.load %[[VAL_8]]{{\[}}%[[VAL_30]]] : memref -// CHECK: %[[VAL_48:.*]] = sparse_tensor.insert %[[VAL_47]] into %[[VAL_32]]{{\[}}%[[VAL_13]], %[[VAL_36]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_48:.*]] = tensor.insert %[[VAL_47]] into %[[VAL_32]]{{\[}}%[[VAL_13]], %[[VAL_36]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_48]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: } else { // CHECK: %[[VAL_49:.*]] = arith.cmpi eq, %[[VAL_34]], %[[VAL_36]] : index // CHECK: %[[VAL_50:.*]] = scf.if %[[VAL_49]] -> (tensor<2x3xf64, #sparse{{[0-9]*}}>) { // CHECK: %[[VAL_51:.*]] = memref.load %[[VAL_11]]{{\[}}%[[VAL_31]]] : memref // CHECK: %[[VAL_52:.*]] = arith.negf %[[VAL_51]] : f64 -// CHECK: %[[VAL_53:.*]] = sparse_tensor.insert %[[VAL_52]] into %[[VAL_32]]{{\[}}%[[VAL_13]], %[[VAL_36]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_53:.*]] = tensor.insert %[[VAL_52]] into %[[VAL_32]]{{\[}}%[[VAL_13]], %[[VAL_36]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_53]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: } else { // CHECK: scf.yield %[[VAL_32]] : tensor<2x3xf64, #sparse{{[0-9]*}}> @@ -1123,14 +1123,14 @@ func.func @cmp_ss_ss(%arga: tensor<32x16xf32, #Tss>, %argb: tensor<32x16xf32, #T // CHECK: %[[VAL_63:.*]] = scf.for %[[VAL_64:.*]] = %[[VAL_65:.*]]#0 to %[[VAL_18]] step %[[VAL_4]] iter_args(%[[VAL_66:.*]] = %[[VAL_65]]#2) // CHECK: %[[VAL_67:.*]] = memref.load %[[VAL_7]]{{\[}}%[[VAL_64]]] : memref // CHECK: %[[VAL_68:.*]] = memref.load %[[VAL_8]]{{\[}}%[[VAL_64]]] : memref -// CHECK: %[[VAL_69:.*]] = sparse_tensor.insert %[[VAL_68]] into %[[VAL_66]]{{\[}}%[[VAL_13]], %[[VAL_67]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_69:.*]] = tensor.insert %[[VAL_68]] into %[[VAL_66]]{{\[}}%[[VAL_13]], %[[VAL_67]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_69]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: } // CHECK: %[[VAL_70:.*]] = scf.for %[[VAL_71:.*]] = %[[VAL_72:.*]]#1 to %[[VAL_22]] step %[[VAL_4]] iter_args(%[[VAL_73:.*]] = %[[VAL_74:.*]]) // CHECK: %[[VAL_75:.*]] = memref.load %[[VAL_10]]{{\[}}%[[VAL_71]]] : memref // CHECK: %[[VAL_76:.*]] = memref.load %[[VAL_11]]{{\[}}%[[VAL_71]]] : memref // CHECK: %[[VAL_77:.*]] = arith.negf %[[VAL_76]] : f64 -// CHECK: %[[VAL_78:.*]] = sparse_tensor.insert %[[VAL_77]] into %[[VAL_73]]{{\[}}%[[VAL_13]], %[[VAL_75]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_78:.*]] = tensor.insert %[[VAL_77]] into %[[VAL_73]]{{\[}}%[[VAL_13]], %[[VAL_75]]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_78]] : tensor<2x3xf64, #sparse{{[0-9]*}}> // CHECK: } // CHECK: scf.yield %[[VAL_79:.*]] : tensor<2x3xf64, #sparse{{[0-9]*}}> diff --git a/mlir/test/Dialect/SparseTensor/sparse_broadcast.mlir b/mlir/test/Dialect/SparseTensor/sparse_broadcast.mlir index 278450fabd74..a409329700ff 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_broadcast.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_broadcast.mlir @@ -33,7 +33,7 @@ // CHECK: %[[L2:.*]] = scf.for %[[TMP_arg3:.*]] = %[[TMP_10]] to %[[TMP_12]] step %[[TMP_c1]] {{.*}} { // CHECK: %[[TMP_13:.*]] = memref.load %[[TMP_4]][%[[TMP_arg3]]] : memref // CHECK: %[[TMP_14:.*]] = memref.load %[[TMP_5]][%[[TMP_arg3]]] : memref -// CHECK: %[[Y:.*]] = sparse_tensor.insert %[[TMP_14]] into %{{.*}}[%[[TMP_9]], %[[TMP_arg2]], %[[TMP_13]]] +// CHECK: %[[Y:.*]] = tensor.insert %[[TMP_14]] into %{{.*}}[%[[TMP_9]], %[[TMP_arg2]], %[[TMP_13]]] // CHECK: scf.yield %[[Y]] // CHECK: } // CHECK: scf.yield %[[L2]] diff --git a/mlir/test/Dialect/SparseTensor/sparse_conv_2d_slice_based.mlir b/mlir/test/Dialect/SparseTensor/sparse_conv_2d_slice_based.mlir index 6076c1fbe76f..bf3473ead204 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_conv_2d_slice_based.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_conv_2d_slice_based.mlir @@ -41,7 +41,7 @@ // CHECK: scf.yield // CHECK: } // CHECK: scf.if {{.*}} { -// CHECK: sparse_tensor.insert %{{.*}} into %{{.*}}{{\[}}%[[D0]], %[[D1]]] +// CHECK: tensor.insert %{{.*}} into %{{.*}}{{\[}}%[[D0]], %[[D1]]] // CHECK: scf.yield // CHECK: } else { // CHECK: scf.yield diff --git a/mlir/test/Dialect/SparseTensor/sparse_fp_ops.mlir b/mlir/test/Dialect/SparseTensor/sparse_fp_ops.mlir index 8c09523174bd..07b2c3c22995 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_fp_ops.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_fp_ops.mlir @@ -371,7 +371,7 @@ func.func @divbyc(%arga: tensor<32xf64, #SV>, // CHECK: %[[VAL_17:.*]] = math.log1p %[[VAL_16]] : f64 // CHECK: %[[VAL_18:.*]] = math.sin %[[VAL_17]] : f64 // CHECK: %[[VAL_19:.*]] = math.tanh %[[VAL_18]] : f64 -// CHECK: %[[Y:.*]] = sparse_tensor.insert %[[VAL_19]] into %{{.*}}[%[[VAL_10]]] : tensor<32xf64, #sparse{{[0-9]*}}> +// CHECK: %[[Y:.*]] = tensor.insert %[[VAL_19]] into %{{.*}}[%[[VAL_10]]] : tensor<32xf64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[Y]] // CHECK: } // CHECK: %[[VAL_20:.*]] = sparse_tensor.load %[[T]] hasInserts : tensor<32xf64, #sparse{{[0-9]*}}> @@ -412,7 +412,7 @@ func.func @zero_preserving_math(%arga: tensor<32xf64, #SV>) -> tensor<32xf64, #S // CHECK: %[[VAL_11:.*]] = memref.load %[[VAL_6]]{{\[}}%[[VAL_10]]] : memref // CHECK: %[[VAL_12:.*]] = memref.load %[[VAL_7]]{{\[}}%[[VAL_10]]] : memref> // CHECK: %[[VAL_13:.*]] = complex.div %[[VAL_12]], %[[VAL_3]] : complex -// CHECK: %[[Y:.*]] = sparse_tensor.insert %[[VAL_13]] into %{{.*}}[%[[VAL_11]]] : tensor<32xcomplex, #sparse{{[0-9]*}}> +// CHECK: %[[Y:.*]] = tensor.insert %[[VAL_13]] into %{{.*}}[%[[VAL_11]]] : tensor<32xcomplex, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[Y]] // CHECK: } // CHECK: %[[VAL_14:.*]] = sparse_tensor.load %[[T]] hasInserts : tensor<32xcomplex, #sparse{{[0-9]*}}> diff --git a/mlir/test/Dialect/SparseTensor/sparse_index.mlir b/mlir/test/Dialect/SparseTensor/sparse_index.mlir index 3e8b485f63df..7fe662893f4b 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_index.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_index.mlir @@ -95,7 +95,7 @@ func.func @dense_index(%arga: tensor) // CHECK: %[[VAL_22:.*]] = memref.load %[[VAL_10]]{{\[}}%[[VAL_18]]] : memref // CHECK: %[[VAL_23:.*]] = arith.muli %[[VAL_21]], %[[VAL_22]] : i64 // CHECK: %[[VAL_24:.*]] = arith.muli %[[VAL_20]], %[[VAL_23]] : i64 -// CHECK: %[[Y:.*]] = sparse_tensor.insert %[[VAL_24]] into %{{.*}}[%[[VAL_14]], %[[VAL_19]]] : tensor +// CHECK: %[[Y:.*]] = tensor.insert %[[VAL_24]] into %{{.*}}[%[[VAL_14]], %[[VAL_19]]] : tensor // CHECK: scf.yield %[[Y]] // CHECK: } // CHECK: scf.yield %[[L]] diff --git a/mlir/test/Dialect/SparseTensor/sparse_out.mlir b/mlir/test/Dialect/SparseTensor/sparse_out.mlir index b1795ff2e1a2..08b81b54a9e6 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_out.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_out.mlir @@ -114,7 +114,7 @@ func.func @sparse_simply_dynamic2(%argx: tensor<32x16xf32, #DCSR>) -> tensor<32x // CHECK: %[[VAL_18:.*]] = memref.load %[[VAL_7]]{{\[}}%[[VAL_16]]] : memref // CHECK: %[[VAL_19:.*]] = memref.load %[[VAL_8]]{{\[}}%[[VAL_16]]] : memref // CHECK: %[[VAL_20:.*]] = arith.mulf %[[VAL_19]], %[[VAL_4]] : f32 -// CHECK: %[[VAL_21:.*]] = sparse_tensor.insert %[[VAL_20]] into %[[VAL_17]]{{\[}}%[[VAL_10]], %[[VAL_18]]] : tensor<10x20xf32, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_21:.*]] = tensor.insert %[[VAL_20]] into %[[VAL_17]]{{\[}}%[[VAL_10]], %[[VAL_18]]] : tensor<10x20xf32, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_21]] : tensor<10x20xf32, #sparse{{[0-9]*}}> // CHECK: } // CHECK: scf.yield %[[VAL_22:.*]] : tensor<10x20xf32, #sparse{{[0-9]*}}> @@ -248,7 +248,7 @@ func.func @sparse_truly_dynamic(%arga: tensor<10x20xf32, #CSR>) -> tensor<10x20x // CHECK: scf.yield %[[VAL_100]], %[[VAL_103]], %[[VAL_104:.*]]#0, %[[VAL_104]]#1, %[[VAL_104]]#2 : index, index, i32, i1, tensor // CHECK: } // CHECK: %[[VAL_202:.*]] = scf.if %[[VAL_74]]#3 -> (tensor) { -// CHECK: %[[VAL_105:.*]] = sparse_tensor.insert %[[VAL_74]]#2 into %[[VAL_74]]#4{{\[}}%[[VAL_39]], %[[VAL_63]]] : tensor +// CHECK: %[[VAL_105:.*]] = tensor.insert %[[VAL_74]]#2 into %[[VAL_74]]#4{{\[}}%[[VAL_39]], %[[VAL_63]]] : tensor // CHECK: scf.yield %[[VAL_105]] : tensor // CHECK: } else { // CHECK: scf.yield %[[VAL_74]]#4 : tensor diff --git a/mlir/test/Dialect/SparseTensor/sparse_reinterpret_map.mlir b/mlir/test/Dialect/SparseTensor/sparse_reinterpret_map.mlir index aa17261724db..97c668716eec 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_reinterpret_map.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_reinterpret_map.mlir @@ -63,7 +63,7 @@ func.func @mul(%arg0: tensor<32x32xf32>, // CHECK: %[[VAL_2:.*]] = sparse_tensor.reinterpret_map %[[VAL_0]] : tensor<2x4xf64, #[[$remap]]> to tensor<1x2x2x2xf64, #[[$demap]]> // CHECK: %[[VAL_4:.*]] = sparse_tensor.foreach in %[[VAL_2]] init(%[[VAL_1]]) // CHECK: ^bb0(%[[VAL_5:.*]]: index, %[[VAL_6:.*]]: index, %[[VAL_7:.*]]: index, %[[VAL_8:.*]]: index, %[[VAL_9:.*]]: f64, %[[VAL_10:.*]]: tensor<1x2x2x2xf64, #[[$demap]]> -// CHECK: %[[VAL_11:.*]] = sparse_tensor.insert %[[VAL_9]] into %[[VAL_10]]{{\[}}%[[VAL_5]], %[[VAL_6]], %[[VAL_7]], %[[VAL_8]]] : tensor<1x2x2x2xf64, #[[$demap]]> +// CHECK: %[[VAL_11:.*]] = tensor.insert %[[VAL_9]] into %[[VAL_10]]{{\[}}%[[VAL_5]], %[[VAL_6]], %[[VAL_7]], %[[VAL_8]]] : tensor<1x2x2x2xf64, #[[$demap]]> // CHECK: sparse_tensor.yield %[[VAL_11]] : tensor<1x2x2x2xf64, #sparse{{[0-9]*}}> // CHECK: } // CHECK: %[[VAL_12:.*]] = sparse_tensor.reinterpret_map %[[VAL_4]] : tensor<1x2x2x2xf64, #[[$demap]]> to tensor<2x4xf64, #[[$remap]]> diff --git a/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir b/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir index eea77c6e5a6c..edb53fa024c2 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_reshape.mlir @@ -31,7 +31,7 @@ // CHECK: %[[SV:.*]] = memref.load %[[V]]{{\[}}%[[I]]] : memref // CHECK: %[[DI0:.*]] = arith.divui %[[SI]], %[[C10]] : index // CHECK: %[[DI1:.*]] = arith.remui %[[SI]], %[[C10]] : index -// CHECK: %[[NT:.*]] = sparse_tensor.insert %[[SV]] into %[[R]]{{\[}}%[[DI0]], %[[DI1]]] +// CHECK: %[[NT:.*]] = tensor.insert %[[SV]] into %[[R]]{{\[}}%[[DI0]], %[[DI1]]] // CHECK: scf.yield %[[NT:.*]] // CHECK: } // CHECK: %[[NT1:.*]] = sparse_tensor.load %[[RET]] hasInserts @@ -75,7 +75,7 @@ func.func @sparse_expand(%arg0: tensor<100xf64, #SparseVector>) -> tensor<10x10x // CHECK: %[[SV:.*]] = memref.load %[[V]]{{\[}}%[[J]]] : memref // CHECK: %[[T:.*]] = arith.muli %[[SI0]], %[[C10]] : index // CHECK: %[[DI:.*]] = arith.addi %[[T]], %[[SI1]] : index -// CHECK: %[[R1:.*]] = sparse_tensor.insert %[[SV]] into %[[A1]]{{\[}}%[[DI]]] +// CHECK: %[[R1:.*]] = tensor.insert %[[SV]] into %[[A1]]{{\[}}%[[DI]]] // CHECK scf.yield %[[R1]] // CHECK } // CHECK scf.yield %[[RET_1]] @@ -120,7 +120,7 @@ func.func @sparse_collapse(%arg0: tensor<10x10xf64, #SparseMatrix>) -> tensor<10 // CHECK: %[[T3:.*]] = arith.remui %[[SI]], %[[T2]] : index // CHECK: %[[T4:.*]] = arith.divui %[[T2]], %[[C10]] : index // CHECK: %[[DI1:.*]] = arith.divui %[[T3]], %[[T4]] : index -// CHECK: %[[NT:.*]] = sparse_tensor.insert %[[SV]] into %[[R]]{{\[}}%[[DI0]], %[[DI1]]] +// CHECK: %[[NT:.*]] = tensor.insert %[[SV]] into %[[R]]{{\[}}%[[DI0]], %[[DI1]]] // CHECK: scf.yield %[[NT]] // CHECK: } // CHECK: %[[NT1:.*]] = sparse_tensor.load %[[RET]] hasInserts @@ -169,7 +169,7 @@ func.func @dynamic_sparse_expand(%arg0: tensor) -> tensor< // CHECK: %[[T3:.*]] = arith.divui %[[T1]], %[[SD1]] : index // CHECK: %[[T4:.*]] = arith.muli %[[SI1]], %[[T3]] : index // CHECK: %[[DI:.*]] = arith.addi %[[T2]], %[[T4]] : index -// CHECK: %[[NT:.*]] = sparse_tensor.insert %[[SV]] into %[[R1]]{{\[}}%[[DI]]] +// CHECK: %[[NT:.*]] = tensor.insert %[[SV]] into %[[R1]]{{\[}}%[[DI]]] // CHECK scf.yield %[[NT]] // CHECK } // CHECK scf.yield %[[RET_1]] diff --git a/mlir/test/Dialect/SparseTensor/sparse_tensor_reshape.mlir b/mlir/test/Dialect/SparseTensor/sparse_tensor_reshape.mlir index 47d24ebf24fc..89826ebfe14d 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_tensor_reshape.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_tensor_reshape.mlir @@ -29,7 +29,7 @@ // CHECK: %[[DI:.*]] = arith.addi %[[T]], %[[SI1]] : index // CHECK: %[[D:.*]] = arith.divui %[[DI]], %[[C10]] : index // CHECK: %[[R:.*]] = arith.remui %[[DI]], %[[C10]] : index -// CHECK: %[[R1:.*]] = sparse_tensor.insert %[[SV]] into %[[A1]]{{\[}}%[[D]], %[[R]]] +// CHECK: %[[R1:.*]] = tensor.insert %[[SV]] into %[[A1]]{{\[}}%[[D]], %[[R]]] // CHECK: scf.yield %[[R1]] // CHECK: } // CHECK: scf.yield %[[RET_1]] diff --git a/mlir/test/Dialect/SparseTensor/sparse_transpose.mlir b/mlir/test/Dialect/SparseTensor/sparse_transpose.mlir index 80a989d789df..5038e977688d 100644 --- a/mlir/test/Dialect/SparseTensor/sparse_transpose.mlir +++ b/mlir/test/Dialect/SparseTensor/sparse_transpose.mlir @@ -37,7 +37,7 @@ // CHECK: %[[VAL_19:.*]] = scf.for %[[VAL_20:.*]] = %[[VAL_16]] to %[[VAL_18]] step %[[VAL_2]] iter_args(%[[VAL_21:.*]] = %[[VAL_14]]) -> (tensor<4x3xf64, #sparse{{[0-9]*}}>) { // CHECK: %[[VAL_22:.*]] = memref.load %[[VAL_8]]{{\[}}%[[VAL_20]]] : memref // CHECK: %[[VAL_23:.*]] = memref.load %[[VAL_9]]{{\[}}%[[VAL_20]]] : memref -// CHECK: %[[VAL_24:.*]] = sparse_tensor.insert %[[VAL_23]] into %[[VAL_21]]{{\[}}%[[VAL_15]], %[[VAL_22]]] : tensor<4x3xf64, #sparse{{[0-9]*}}> +// CHECK: %[[VAL_24:.*]] = tensor.insert %[[VAL_23]] into %[[VAL_21]]{{\[}}%[[VAL_15]], %[[VAL_22]]] : tensor<4x3xf64, #sparse{{[0-9]*}}> // CHECK: scf.yield %[[VAL_24]] : tensor<4x3xf64, #sparse{{[0-9]*}}> // CHECK: } // CHECK: scf.yield %[[VAL_25:.*]] : tensor<4x3xf64, #sparse{{[0-9]*}}> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_1d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_1d.mlir index 61c68507ea51..12e0d2267a26 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_1d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_1d.mlir @@ -54,10 +54,10 @@ module { // Build the sparse vector from straightline code. %0 = tensor.empty() : tensor<1024xf32, #SparseVector> - %1 = sparse_tensor.insert %f1 into %0[%c0] : tensor<1024xf32, #SparseVector> - %2 = sparse_tensor.insert %f2 into %1[%c1] : tensor<1024xf32, #SparseVector> - %3 = sparse_tensor.insert %f3 into %2[%c3] : tensor<1024xf32, #SparseVector> - %4 = sparse_tensor.insert %f4 into %3[%c1023] : tensor<1024xf32, #SparseVector> + %1 = tensor.insert %f1 into %0[%c0] : tensor<1024xf32, #SparseVector> + %2 = tensor.insert %f2 into %1[%c1] : tensor<1024xf32, #SparseVector> + %3 = tensor.insert %f3 into %2[%c3] : tensor<1024xf32, #SparseVector> + %4 = tensor.insert %f4 into %3[%c1023] : tensor<1024xf32, #SparseVector> %5 = sparse_tensor.load %4 hasInserts : tensor<1024xf32, #SparseVector> // @@ -76,7 +76,7 @@ module { %6 = tensor.empty() : tensor<1024xf32, #SparseVector> %7 = scf.for %i = %c0 to %c8 step %c1 iter_args(%vin = %6) -> tensor<1024xf32, #SparseVector> { %ii = arith.muli %i, %c3 : index - %vout = sparse_tensor.insert %f1 into %vin[%ii] : tensor<1024xf32, #SparseVector> + %vout = tensor.insert %f1 into %vin[%ii] : tensor<1024xf32, #SparseVector> scf.yield %vout : tensor<1024xf32, #SparseVector> } %8 = sparse_tensor.load %7 hasInserts : tensor<1024xf32, #SparseVector> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_2d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_2d.mlir index d51b67792337..883109150653 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_2d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_2d.mlir @@ -72,10 +72,10 @@ module { // CHECK-NEXT: ---- // %densea = tensor.empty() : tensor<4x3xf64, #Dense> - %dense1 = sparse_tensor.insert %f1 into %densea[%c0, %c0] : tensor<4x3xf64, #Dense> - %dense2 = sparse_tensor.insert %f2 into %dense1[%c2, %c2] : tensor<4x3xf64, #Dense> - %dense3 = sparse_tensor.insert %f3 into %dense2[%c3, %c0] : tensor<4x3xf64, #Dense> - %dense4 = sparse_tensor.insert %f4 into %dense3[%c3, %c2] : tensor<4x3xf64, #Dense> + %dense1 = tensor.insert %f1 into %densea[%c0, %c0] : tensor<4x3xf64, #Dense> + %dense2 = tensor.insert %f2 into %dense1[%c2, %c2] : tensor<4x3xf64, #Dense> + %dense3 = tensor.insert %f3 into %dense2[%c3, %c0] : tensor<4x3xf64, #Dense> + %dense4 = tensor.insert %f4 into %dense3[%c3, %c2] : tensor<4x3xf64, #Dense> %densem = sparse_tensor.load %dense4 hasInserts : tensor<4x3xf64, #Dense> sparse_tensor.print %densem : tensor<4x3xf64, #Dense> @@ -93,10 +93,10 @@ module { // CHECK-NEXT: ---- // %cooa = tensor.empty() : tensor<4x3xf64, #SortedCOO> - %coo1 = sparse_tensor.insert %f1 into %cooa[%c0, %c0] : tensor<4x3xf64, #SortedCOO> - %coo2 = sparse_tensor.insert %f2 into %coo1[%c2, %c2] : tensor<4x3xf64, #SortedCOO> - %coo3 = sparse_tensor.insert %f3 into %coo2[%c3, %c0] : tensor<4x3xf64, #SortedCOO> - %coo4 = sparse_tensor.insert %f4 into %coo3[%c3, %c2] : tensor<4x3xf64, #SortedCOO> + %coo1 = tensor.insert %f1 into %cooa[%c0, %c0] : tensor<4x3xf64, #SortedCOO> + %coo2 = tensor.insert %f2 into %coo1[%c2, %c2] : tensor<4x3xf64, #SortedCOO> + %coo3 = tensor.insert %f3 into %coo2[%c3, %c0] : tensor<4x3xf64, #SortedCOO> + %coo4 = tensor.insert %f4 into %coo3[%c3, %c2] : tensor<4x3xf64, #SortedCOO> %coom = sparse_tensor.load %coo4 hasInserts : tensor<4x3xf64, #SortedCOO> sparse_tensor.print %coom : tensor<4x3xf64, #SortedCOO> @@ -113,10 +113,10 @@ module { // CHECK-NEXT: ---- // %csra = tensor.empty() : tensor<4x3xf64, #CSR> - %csr1 = sparse_tensor.insert %f1 into %csra[%c0, %c0] : tensor<4x3xf64, #CSR> - %csr2 = sparse_tensor.insert %f2 into %csr1[%c2, %c2] : tensor<4x3xf64, #CSR> - %csr3 = sparse_tensor.insert %f3 into %csr2[%c3, %c0] : tensor<4x3xf64, #CSR> - %csr4 = sparse_tensor.insert %f4 into %csr3[%c3, %c2] : tensor<4x3xf64, #CSR> + %csr1 = tensor.insert %f1 into %csra[%c0, %c0] : tensor<4x3xf64, #CSR> + %csr2 = tensor.insert %f2 into %csr1[%c2, %c2] : tensor<4x3xf64, #CSR> + %csr3 = tensor.insert %f3 into %csr2[%c3, %c0] : tensor<4x3xf64, #CSR> + %csr4 = tensor.insert %f4 into %csr3[%c3, %c2] : tensor<4x3xf64, #CSR> %csrm = sparse_tensor.load %csr4 hasInserts : tensor<4x3xf64, #CSR> sparse_tensor.print %csrm : tensor<4x3xf64, #CSR> @@ -135,10 +135,10 @@ module { // CHECK-NEXT: ---- // %dcsra = tensor.empty() : tensor<4x3xf64, #DCSR> - %dcsr1 = sparse_tensor.insert %f1 into %dcsra[%c0, %c0] : tensor<4x3xf64, #DCSR> - %dcsr2 = sparse_tensor.insert %f2 into %dcsr1[%c2, %c2] : tensor<4x3xf64, #DCSR> - %dcsr3 = sparse_tensor.insert %f3 into %dcsr2[%c3, %c0] : tensor<4x3xf64, #DCSR> - %dcsr4 = sparse_tensor.insert %f4 into %dcsr3[%c3, %c2] : tensor<4x3xf64, #DCSR> + %dcsr1 = tensor.insert %f1 into %dcsra[%c0, %c0] : tensor<4x3xf64, #DCSR> + %dcsr2 = tensor.insert %f2 into %dcsr1[%c2, %c2] : tensor<4x3xf64, #DCSR> + %dcsr3 = tensor.insert %f3 into %dcsr2[%c3, %c0] : tensor<4x3xf64, #DCSR> + %dcsr4 = tensor.insert %f4 into %dcsr3[%c3, %c2] : tensor<4x3xf64, #DCSR> %dcsrm = sparse_tensor.load %dcsr4 hasInserts : tensor<4x3xf64, #DCSR> sparse_tensor.print %dcsrm : tensor<4x3xf64, #DCSR> @@ -155,10 +155,10 @@ module { // CHECK-NEXT: ---- // %rowa = tensor.empty() : tensor<4x3xf64, #Row> - %row1 = sparse_tensor.insert %f1 into %rowa[%c0, %c0] : tensor<4x3xf64, #Row> - %row2 = sparse_tensor.insert %f2 into %row1[%c2, %c2] : tensor<4x3xf64, #Row> - %row3 = sparse_tensor.insert %f3 into %row2[%c3, %c0] : tensor<4x3xf64, #Row> - %row4 = sparse_tensor.insert %f4 into %row3[%c3, %c2] : tensor<4x3xf64, #Row> + %row1 = tensor.insert %f1 into %rowa[%c0, %c0] : tensor<4x3xf64, #Row> + %row2 = tensor.insert %f2 into %row1[%c2, %c2] : tensor<4x3xf64, #Row> + %row3 = tensor.insert %f3 into %row2[%c3, %c0] : tensor<4x3xf64, #Row> + %row4 = tensor.insert %f4 into %row3[%c3, %c2] : tensor<4x3xf64, #Row> %rowm = sparse_tensor.load %row4 hasInserts : tensor<4x3xf64, #Row> sparse_tensor.print %rowm : tensor<4x3xf64, #Row> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_3d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_3d.mlir index 1917fd987c5d..364a188cf37c 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_3d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_3d.mlir @@ -71,11 +71,11 @@ module { // CHECK-NEXT: values : ( 1.1, 2.2, 3.3, 4.4, 5.5 // CHECK-NEXT: ---- %tensora = tensor.empty() : tensor<5x4x3xf64, #TensorCSR> - %tensor1 = sparse_tensor.insert %f1 into %tensora[%c3, %c0, %c1] : tensor<5x4x3xf64, #TensorCSR> - %tensor2 = sparse_tensor.insert %f2 into %tensor1[%c3, %c0, %c2] : tensor<5x4x3xf64, #TensorCSR> - %tensor3 = sparse_tensor.insert %f3 into %tensor2[%c3, %c3, %c1] : tensor<5x4x3xf64, #TensorCSR> - %tensor4 = sparse_tensor.insert %f4 into %tensor3[%c4, %c2, %c2] : tensor<5x4x3xf64, #TensorCSR> - %tensor5 = sparse_tensor.insert %f5 into %tensor4[%c4, %c3, %c2] : tensor<5x4x3xf64, #TensorCSR> + %tensor1 = tensor.insert %f1 into %tensora[%c3, %c0, %c1] : tensor<5x4x3xf64, #TensorCSR> + %tensor2 = tensor.insert %f2 into %tensor1[%c3, %c0, %c2] : tensor<5x4x3xf64, #TensorCSR> + %tensor3 = tensor.insert %f3 into %tensor2[%c3, %c3, %c1] : tensor<5x4x3xf64, #TensorCSR> + %tensor4 = tensor.insert %f4 into %tensor3[%c4, %c2, %c2] : tensor<5x4x3xf64, #TensorCSR> + %tensor5 = tensor.insert %f5 into %tensor4[%c4, %c3, %c2] : tensor<5x4x3xf64, #TensorCSR> %tensorm = sparse_tensor.load %tensor5 hasInserts : tensor<5x4x3xf64, #TensorCSR> sparse_tensor.print %tensorm : tensor<5x4x3xf64, #TensorCSR> @@ -90,11 +90,11 @@ module { // CHECK-NEXT: values : ( 0, 1.1, 2.2, 0, 3.3, 0, 0, 0, 4.4, 0, 0, 5.5 // CHECK-NEXT: ---- %rowa = tensor.empty() : tensor<5x4x3xf64, #TensorRow> - %row1 = sparse_tensor.insert %f1 into %rowa[%c3, %c0, %c1] : tensor<5x4x3xf64, #TensorRow> - %row2 = sparse_tensor.insert %f2 into %row1[%c3, %c0, %c2] : tensor<5x4x3xf64, #TensorRow> - %row3 = sparse_tensor.insert %f3 into %row2[%c3, %c3, %c1] : tensor<5x4x3xf64, #TensorRow> - %row4 = sparse_tensor.insert %f4 into %row3[%c4, %c2, %c2] : tensor<5x4x3xf64, #TensorRow> - %row5 = sparse_tensor.insert %f5 into %row4[%c4, %c3, %c2] : tensor<5x4x3xf64, #TensorRow> + %row1 = tensor.insert %f1 into %rowa[%c3, %c0, %c1] : tensor<5x4x3xf64, #TensorRow> + %row2 = tensor.insert %f2 into %row1[%c3, %c0, %c2] : tensor<5x4x3xf64, #TensorRow> + %row3 = tensor.insert %f3 into %row2[%c3, %c3, %c1] : tensor<5x4x3xf64, #TensorRow> + %row4 = tensor.insert %f4 into %row3[%c4, %c2, %c2] : tensor<5x4x3xf64, #TensorRow> + %row5 = tensor.insert %f5 into %row4[%c4, %c3, %c2] : tensor<5x4x3xf64, #TensorRow> %rowm = sparse_tensor.load %row5 hasInserts : tensor<5x4x3xf64, #TensorRow> sparse_tensor.print %rowm : tensor<5x4x3xf64, #TensorRow> @@ -109,11 +109,11 @@ module { // CHECK-NEXT: values : ( 1.1, 2.2, 3.3, 4.4, 5.5 // CHECK-NEXT: ---- %ccoo = tensor.empty() : tensor<5x4x3xf64, #CCoo> - %ccoo1 = sparse_tensor.insert %f1 into %ccoo[%c3, %c0, %c1] : tensor<5x4x3xf64, #CCoo> - %ccoo2 = sparse_tensor.insert %f2 into %ccoo1[%c3, %c0, %c2] : tensor<5x4x3xf64, #CCoo> - %ccoo3 = sparse_tensor.insert %f3 into %ccoo2[%c3, %c3, %c1] : tensor<5x4x3xf64, #CCoo> - %ccoo4 = sparse_tensor.insert %f4 into %ccoo3[%c4, %c2, %c2] : tensor<5x4x3xf64, #CCoo> - %ccoo5 = sparse_tensor.insert %f5 into %ccoo4[%c4, %c3, %c2] : tensor<5x4x3xf64, #CCoo> + %ccoo1 = tensor.insert %f1 into %ccoo[%c3, %c0, %c1] : tensor<5x4x3xf64, #CCoo> + %ccoo2 = tensor.insert %f2 into %ccoo1[%c3, %c0, %c2] : tensor<5x4x3xf64, #CCoo> + %ccoo3 = tensor.insert %f3 into %ccoo2[%c3, %c3, %c1] : tensor<5x4x3xf64, #CCoo> + %ccoo4 = tensor.insert %f4 into %ccoo3[%c4, %c2, %c2] : tensor<5x4x3xf64, #CCoo> + %ccoo5 = tensor.insert %f5 into %ccoo4[%c4, %c3, %c2] : tensor<5x4x3xf64, #CCoo> %ccoom = sparse_tensor.load %ccoo5 hasInserts : tensor<5x4x3xf64, #CCoo> sparse_tensor.print %ccoom : tensor<5x4x3xf64, #CCoo> @@ -126,11 +126,11 @@ module { // CHECK-NEXT: values : ( 1.1, 2.2, 3.3, 4.4, 5.5 // CHECK-NEXT: ---- %dcoo = tensor.empty() : tensor<5x4x3xf64, #DCoo> - %dcoo1 = sparse_tensor.insert %f1 into %dcoo[%c3, %c0, %c1] : tensor<5x4x3xf64, #DCoo> - %dcoo2 = sparse_tensor.insert %f2 into %dcoo1[%c3, %c0, %c2] : tensor<5x4x3xf64, #DCoo> - %dcoo3 = sparse_tensor.insert %f3 into %dcoo2[%c3, %c3, %c1] : tensor<5x4x3xf64, #DCoo> - %dcoo4 = sparse_tensor.insert %f4 into %dcoo3[%c4, %c2, %c2] : tensor<5x4x3xf64, #DCoo> - %dcoo5 = sparse_tensor.insert %f5 into %dcoo4[%c4, %c3, %c2] : tensor<5x4x3xf64, #DCoo> + %dcoo1 = tensor.insert %f1 into %dcoo[%c3, %c0, %c1] : tensor<5x4x3xf64, #DCoo> + %dcoo2 = tensor.insert %f2 into %dcoo1[%c3, %c0, %c2] : tensor<5x4x3xf64, #DCoo> + %dcoo3 = tensor.insert %f3 into %dcoo2[%c3, %c3, %c1] : tensor<5x4x3xf64, #DCoo> + %dcoo4 = tensor.insert %f4 into %dcoo3[%c4, %c2, %c2] : tensor<5x4x3xf64, #DCoo> + %dcoo5 = tensor.insert %f5 into %dcoo4[%c4, %c3, %c2] : tensor<5x4x3xf64, #DCoo> %dcoom = sparse_tensor.load %dcoo5 hasInserts : tensor<5x4x3xf64, #DCoo> sparse_tensor.print %dcoom : tensor<5x4x3xf64, #DCoo> -- GitLab From 64111831ed46b9e82b8626356c087ce2202f029b Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Tue, 12 Mar 2024 17:00:51 -0700 Subject: [PATCH 313/953] Relax test to work with newer versions of lldb --- .../debuginfo-tests/llgdb-tests/forward-declare-class.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cross-project-tests/debuginfo-tests/llgdb-tests/forward-declare-class.cpp b/cross-project-tests/debuginfo-tests/llgdb-tests/forward-declare-class.cpp index 132420009bd1..850eed6ad95d 100644 --- a/cross-project-tests/debuginfo-tests/llgdb-tests/forward-declare-class.cpp +++ b/cross-project-tests/debuginfo-tests/llgdb-tests/forward-declare-class.cpp @@ -6,9 +6,8 @@ // Work around a gdb bug where it believes that a class is a // struct if there aren't any methods - even though it's tagged // as a class. -// CHECK: type = {{struct|class}} A { -// CHECK-NEXT: {{(public:){0,1}}} -// CHECK-NEXT: int MyData; +// CHECK: {{struct|class}} A { +// CHECK: int MyData; // CHECK-NEXT: } class A; class B { -- GitLab From bb5921e2a2da4a87016e623deb8c2eaed7f1f5a8 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Tue, 12 Mar 2024 17:01:29 -0700 Subject: [PATCH 314/953] [libc] Include FP_* macros in math.h (#84996) These are used unconditionally by libc++ math.h. This is related to issue #84879. --- libc/include/llvm-libc-macros/math-macros.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libc/include/llvm-libc-macros/math-macros.h b/libc/include/llvm-libc-macros/math-macros.h index e67fe4d11b44..db8a4ea65bd6 100644 --- a/libc/include/llvm-libc-macros/math-macros.h +++ b/libc/include/llvm-libc-macros/math-macros.h @@ -11,6 +11,12 @@ #include "limits-macros.h" +#define FP_NAN 0 +#define FP_INFINITE 1 +#define FP_ZERO 2 +#define FP_SUBNORMAL 3 +#define FP_NORMAL 4 + #define MATH_ERRNO 1 #define MATH_ERREXCEPT 2 -- GitLab From accfbf4e4959957db0993a15bab7316001131df3 Mon Sep 17 00:00:00 2001 From: Zahi Moudallal <128723247+zahimoud@users.noreply.github.com> Date: Tue, 12 Mar 2024 17:07:16 -0700 Subject: [PATCH 315/953] [MLIR][ROCDL] Add BallotOp and lit test (#84856) --- mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td | 10 ++++++++++ mlir/test/Target/LLVMIR/rocdl.mlir | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td b/mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td index 32b5a1c016b6..abb38a3df806 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td @@ -158,6 +158,16 @@ Arguments<(ins I32:$index, }]; } +def ROCDL_BallotOp : + ROCDL_Op<"ballot">, + Results<(outs LLVM_Type:$res)>, + Arguments<(ins I1:$pred)> { + string llvmBuilder = [{ + $res = createIntrinsicCall(builder, + llvm::Intrinsic::amdgcn_ballot, {$pred}, {llvm::Type::getInt32Ty(moduleTranslation.getLLVMContext())}); + }]; + let assemblyFormat = "$pred attr-dict `:` type($res)"; +} //===----------------------------------------------------------------------===// // Thread index and Block index diff --git a/mlir/test/Target/LLVMIR/rocdl.mlir b/mlir/test/Target/LLVMIR/rocdl.mlir index d35acb0475e6..93550f5c7bd5 100644 --- a/mlir/test/Target/LLVMIR/rocdl.mlir +++ b/mlir/test/Target/LLVMIR/rocdl.mlir @@ -88,6 +88,13 @@ llvm.func @rocdl.bpermute(%src : i32) -> i32 { llvm.return %0 : i32 } +llvm.func @rocdl.ballot(%pred : i1) -> i32 { + // CHECK-LABEL: rocdl.ballot + // CHECK: call i32 @llvm.amdgcn.ballot + %0 = rocdl.ballot %pred : i32 + llvm.return %0 : i32 +} + llvm.func @rocdl.waitcnt() { // CHECK-LABEL: rocdl.waitcnt // CHECK-NEXT: call void @llvm.amdgcn.s.waitcnt(i32 0) -- GitLab From e2468bf16a0c1f63a39aa417c15c03ebd77fab9e Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Tue, 12 Mar 2024 17:19:46 -0700 Subject: [PATCH 316/953] [lldb][debugserver] Update flags past to app launch request rdar://117421999 --- lldb/tools/debugserver/source/MacOSX/MachProcess.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.mm b/lldb/tools/debugserver/source/MacOSX/MachProcess.mm index 87bdbf835bfd..70b4564a027b 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.mm +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.mm @@ -472,6 +472,8 @@ FBSCreateOptionsDictionary(const char *app_bundle_path, // And there are some other options at the top level in this dictionary: [options setObject:[NSNumber numberWithBool:YES] forKey:FBSOpenApplicationOptionKeyUnlockDevice]; + [options setObject:[NSNumber numberWithBool:YES] + forKey:FBSOpenApplicationOptionKeyPromptUnlockDevice]; // We have to get the "sequence ID & UUID" for this app bundle path and send // them to FBS: -- GitLab From 2f400a2fd77b44d34281792aca84c42e149095e7 Mon Sep 17 00:00:00 2001 From: Michael Maitland Date: Tue, 12 Mar 2024 20:22:49 -0400 Subject: [PATCH 317/953] [GISEL] Add G_VSCALE instruction (#84542) --- llvm/docs/GlobalISel/GenericOpcode.rst | 11 ++++++++++ .../CodeGen/GlobalISel/MachineIRBuilder.h | 22 +++++++++++++++++++ llvm/include/llvm/Support/TargetOpcodes.def | 3 +++ llvm/include/llvm/Target/GenericOpcodes.td | 9 ++++++++ .../CodeGen/GlobalISel/MachineIRBuilder.cpp | 18 +++++++++++++++ llvm/lib/CodeGen/MachineVerifier.cpp | 11 ++++++++++ .../GlobalISel/legalizer-info-validation.mir | 3 +++ llvm/test/MachineVerifier/test_g_vscale.mir | 15 +++++++++++++ 8 files changed, 92 insertions(+) create mode 100644 llvm/test/MachineVerifier/test_g_vscale.mir diff --git a/llvm/docs/GlobalISel/GenericOpcode.rst b/llvm/docs/GlobalISel/GenericOpcode.rst index f9f9e1186460..bf1b3cb30a52 100644 --- a/llvm/docs/GlobalISel/GenericOpcode.rst +++ b/llvm/docs/GlobalISel/GenericOpcode.rst @@ -607,6 +607,17 @@ See the LLVM LangRef entry on '``llvm.lround.*'`` for details on behaviour. Vector Specific Operations -------------------------- +G_VSCALE +^^^^^^^^ + +Puts the value of the runtime ``vscale`` multiplied by the value in the source +operand into the destination register. This can be useful in determining the +actual runtime number of elements in a vector. + +.. code-block:: + + %0:_(s32) = G_VSCALE 4 + G_INSERT_SUBVECTOR ^^^^^^^^^^^^^^^^^^ diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index 4732eaf4ee27..aaa81342845b 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -1143,6 +1143,28 @@ public: MachineInstrBuilder buildInsert(const DstOp &Res, const SrcOp &Src, const SrcOp &Op, unsigned Index); + /// Build and insert \p Res = G_VSCALE \p MinElts + /// + /// G_VSCALE puts the value of the runtime vscale multiplied by \p MinElts + /// into \p Res. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res must be a generic virtual register with scalar type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildVScale(const DstOp &Res, unsigned MinElts); + + /// Build and insert \p Res = G_VSCALE \p MinElts + /// + /// G_VSCALE puts the value of the runtime vscale multiplied by \p MinElts + /// into \p Res. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res must be a generic virtual register with scalar type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildVScale(const DstOp &Res, const ConstantInt &MinElts); + /// Build and insert a G_INTRINSIC instruction. /// /// There are four different opcodes based on combinations of whether the diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def index 3dade14f043b..899eaad5842a 100644 --- a/llvm/include/llvm/Support/TargetOpcodes.def +++ b/llvm/include/llvm/Support/TargetOpcodes.def @@ -727,6 +727,9 @@ HANDLE_TARGET_OPCODE(G_BR) /// Generic branch to jump table entry. HANDLE_TARGET_OPCODE(G_BRJT) +/// Generic vscale. +HANDLE_TARGET_OPCODE(G_VSCALE) + /// Generic insert subvector. HANDLE_TARGET_OPCODE(G_INSERT_SUBVECTOR) diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td index 8dc84fb0ba05..67d405ba96fa 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -1289,6 +1289,15 @@ def G_MERGE_VALUES : GenericInstruction { let variadicOpsType = type1; } +// Generic vscale. +// Puts the value of the runtime vscale multiplied by the value in the source +// operand into the destination register. +def G_VSCALE : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins unknown:$src); + let hasSideEffects = false; +} + /// Create a vector from multiple scalar registers. No implicit /// conversion is performed (i.e. the result element type must be the /// same as all source operands) diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index 9b12d443c96e..f7aaa0f02efc 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -793,6 +793,24 @@ MachineInstrBuilder MachineIRBuilder::buildInsert(const DstOp &Res, return buildInstr(TargetOpcode::G_INSERT, Res, {Src, Op, uint64_t(Index)}); } +MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res, + unsigned MinElts) { + + auto IntN = IntegerType::get(getMF().getFunction().getContext(), + Res.getLLTTy(*getMRI()).getScalarSizeInBits()); + ConstantInt *CI = ConstantInt::get(IntN, MinElts); + return buildVScale(Res, *CI); +} + +MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res, + const ConstantInt &MinElts) { + auto VScale = buildInstr(TargetOpcode::G_VSCALE); + VScale->setDebugLoc(DebugLoc()); + Res.addDefToMIB(*getMRI(), VScale); + VScale.addCImm(&MinElts); + return VScale; +} + static unsigned getIntrinsicOpcode(bool HasSideEffects, bool IsConvergent) { if (HasSideEffects && IsConvergent) return TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS; diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp index 90cbf097370d..c2d6dd35e1cb 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -1613,6 +1613,17 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { report("G_BSWAP size must be a multiple of 16 bits", MI); break; } + case TargetOpcode::G_VSCALE: { + if (!MI->getOperand(1).isCImm()) { + report("G_VSCALE operand must be cimm", MI); + break; + } + if (MI->getOperand(1).getCImm()->isZero()) { + report("G_VSCALE immediate cannot be zero", MI); + break; + } + break; + } case TargetOpcode::G_INSERT_SUBVECTOR: { const MachineOperand &Src0Op = MI->getOperand(1); if (!Src0Op.isReg()) { diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir index ac330918b430..c9e5f8924f8a 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -616,6 +616,9 @@ # DEBUG-NEXT: G_BRJT (opcode {{[0-9]+}}): 2 type indices # DEBUG-NEXT: .. the first uncovered type index: 2, OK # DEBUG-NEXT: .. the first uncovered imm index: 0, OK +# DEBUG-NEXT: G_VSCALE (opcode {{[0-9]+}}): 1 type index, 0 imm indices +# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined +# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined # DEBUG-NEXT: G_INSERT_SUBVECTOR (opcode {{[0-9]+}}): 2 type indices, 1 imm index # DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined # DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined diff --git a/llvm/test/MachineVerifier/test_g_vscale.mir b/llvm/test/MachineVerifier/test_g_vscale.mir new file mode 100644 index 000000000000..78854620913a --- /dev/null +++ b/llvm/test/MachineVerifier/test_g_vscale.mir @@ -0,0 +1,15 @@ +# RUN: not --crash llc -verify-machineinstrs -run-pass none -o /dev/null %s 2>&1 | FileCheck %s + +--- +name: g_vscale +body: | + bb.0: + + %1:_(s32) = G_CONSTANT i32 4 + + ; CHECK: G_VSCALE operand must be cimm + %2:_(s32) = G_VSCALE %1 + + ; CHECK: G_VSCALE immediate cannot be zero + %3:_(s32) = G_VSCALE i32 0 +... -- GitLab From f467cc9caf37fcf6b3523271f977585c39372d55 Mon Sep 17 00:00:00 2001 From: Dave Clausen Date: Tue, 12 Mar 2024 17:21:00 -0700 Subject: [PATCH 318/953] [tsan] Add missing link option to tsan test after #84923 Pull Request: https://github.com/llvm/llvm-project/pull/85003 --- compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp b/compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp index b9fd0c5ad21f..404fd2fbb3c2 100644 --- a/compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp +++ b/compiler-rt/test/tsan/compare_exchange_acquire_fence.cpp @@ -1,4 +1,4 @@ -// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 +// RUN: %clangxx_tsan -O1 %s %link_libcxx_tsan -o %t && %run %t 2>&1 // This is a correct program and tsan should not report a race. // // Verify that there is a happens-before relationship between a -- GitLab From 2aacb56e8361213c1bd69c2ceafdea3aa0ca9125 Mon Sep 17 00:00:00 2001 From: 4ast Date: Tue, 12 Mar 2024 17:27:25 -0700 Subject: [PATCH 319/953] BPF address space insn (#84410) This commit aims to support BPF arena kernel side [feature](https://lore.kernel.org/bpf/20240209040608.98927-1-alexei.starovoitov@gmail.com/): - arena is a memory region accessible from both BPF program and userspace; - base pointers for this memory region differ between kernel and user spaces; - `dst_reg = addr_space_cast(src_reg, dst_addr_space, src_addr_space)` translates src_reg, a pointer in src_addr_space to dst_reg, equivalent pointer in dst_addr_space, {src,dst}_addr_space are immediate constants; - number 0 is assigned to kernel address space; - number 1 is assigned to user address space. On the LLVM side, the goal is to make load and store operations on arena pointers "transparent" for BPF programs: - assume that pointers with non-zero address space are pointers to arena memory; - assume that arena is identified by address space number; - assume that address space zero corresponds to kernel address space; - assume that every BPF-side load or store from arena is done via pointer in user address space, thus convert base pointers using `addr_space_cast(src_reg, 0, 1)`; Only load, store, cmpxchg and atomicrmw IR instructions are handled by this transformation. For example, the following C code: ```c #define __as __attribute__((address_space(1))) void copy(int __as *from, int __as *to) { *to = *from; } ``` Compiled to the following IR: ```llvm define void @copy(ptr addrspace(1) %from, ptr addrspace(1) %to) { entry: %0 = load i32, ptr addrspace(1) %from, align 4 store i32 %0, ptr addrspace(1) %to, align 4 ret void } ``` Is transformed to: ```llvm %to2 = addrspacecast ptr addrspace(1) %to to ptr ;; ! %from1 = addrspacecast ptr addrspace(1) %from to ptr ;; ! %0 = load i32, ptr %from1, align 4, !tbaa !3 store i32 %0, ptr %to2, align 4, !tbaa !3 ret void ``` And compiled as: ```asm r2 = addr_space_cast(r2, 0, 1) r1 = addr_space_cast(r1, 0, 1) r1 = *(u32 *)(r1 + 0) *(u32 *)(r2 + 0) = r1 exit ``` Co-authored-by: Eduard Zingerman --- clang/lib/Basic/Targets/BPF.cpp | 3 + .../test/Preprocessor/bpf-predefined-macros.c | 8 ++ .../lib/Target/BPF/AsmParser/BPFAsmParser.cpp | 1 + llvm/lib/Target/BPF/BPF.h | 8 ++ .../Target/BPF/BPFASpaceCastSimplifyPass.cpp | 92 ++++++++++++++ llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp | 116 ++++++++++++++++++ llvm/lib/Target/BPF/BPFInstrInfo.td | 29 +++++ llvm/lib/Target/BPF/BPFTargetMachine.cpp | 5 + llvm/lib/Target/BPF/CMakeLists.txt | 1 + .../test/CodeGen/BPF/addr-space-auto-casts.ll | 78 ++++++++++++ llvm/test/CodeGen/BPF/addr-space-cast.ll | 22 ++++ llvm/test/CodeGen/BPF/addr-space-gep-chain.ll | 25 ++++ llvm/test/CodeGen/BPF/addr-space-globals.ll | 30 +++++ llvm/test/CodeGen/BPF/addr-space-globals2.ll | 25 ++++ llvm/test/CodeGen/BPF/addr-space-phi.ll | 53 ++++++++ .../test/CodeGen/BPF/addr-space-simplify-1.ll | 19 +++ .../test/CodeGen/BPF/addr-space-simplify-2.ll | 21 ++++ .../test/CodeGen/BPF/addr-space-simplify-3.ll | 26 ++++ .../test/CodeGen/BPF/addr-space-simplify-4.ll | 21 ++++ .../test/CodeGen/BPF/addr-space-simplify-5.ll | 25 ++++ .../test/CodeGen/BPF/assembler-disassembler.s | 7 ++ 21 files changed, 615 insertions(+) create mode 100644 llvm/lib/Target/BPF/BPFASpaceCastSimplifyPass.cpp create mode 100644 llvm/test/CodeGen/BPF/addr-space-auto-casts.ll create mode 100644 llvm/test/CodeGen/BPF/addr-space-cast.ll create mode 100644 llvm/test/CodeGen/BPF/addr-space-gep-chain.ll create mode 100644 llvm/test/CodeGen/BPF/addr-space-globals.ll create mode 100644 llvm/test/CodeGen/BPF/addr-space-globals2.ll create mode 100644 llvm/test/CodeGen/BPF/addr-space-phi.ll create mode 100644 llvm/test/CodeGen/BPF/addr-space-simplify-1.ll create mode 100644 llvm/test/CodeGen/BPF/addr-space-simplify-2.ll create mode 100644 llvm/test/CodeGen/BPF/addr-space-simplify-3.ll create mode 100644 llvm/test/CodeGen/BPF/addr-space-simplify-4.ll create mode 100644 llvm/test/CodeGen/BPF/addr-space-simplify-5.ll diff --git a/clang/lib/Basic/Targets/BPF.cpp b/clang/lib/Basic/Targets/BPF.cpp index e3fbbb720d06..26a54f631fcf 100644 --- a/clang/lib/Basic/Targets/BPF.cpp +++ b/clang/lib/Basic/Targets/BPF.cpp @@ -35,6 +35,9 @@ void BPFTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__BPF_CPU_VERSION__", "0"); return; } + + Builder.defineMacro("__BPF_FEATURE_ARENA_CAST"); + if (CPU.empty() || CPU == "generic" || CPU == "v1") { Builder.defineMacro("__BPF_CPU_VERSION__", "1"); return; diff --git a/clang/test/Preprocessor/bpf-predefined-macros.c b/clang/test/Preprocessor/bpf-predefined-macros.c index ff4d00ac3bcf..fea24d1ea0ff 100644 --- a/clang/test/Preprocessor/bpf-predefined-macros.c +++ b/clang/test/Preprocessor/bpf-predefined-macros.c @@ -61,6 +61,9 @@ int r; #ifdef __BPF_FEATURE_ST int s; #endif +#ifdef __BPF_FEATURE_ARENA_CAST +int t; +#endif // CHECK: int b; // CHECK: int c; @@ -90,6 +93,11 @@ int s; // CPU_V4: int r; // CPU_V4: int s; +// CPU_V1: int t; +// CPU_V2: int t; +// CPU_V3: int t; +// CPU_V4: int t; + // CPU_GENERIC: int g; // CPU_PROBE: int f; diff --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp index 0d1eef60c3b5..3145bc3d19f5 100644 --- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp +++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp @@ -271,6 +271,7 @@ public: .Case("xchg32_32", true) .Case("cmpxchg_64", true) .Case("cmpxchg32_32", true) + .Case("addr_space_cast", true) .Default(false); } }; diff --git a/llvm/lib/Target/BPF/BPF.h b/llvm/lib/Target/BPF/BPF.h index 5c77d183e1ef..bbdbdbbde532 100644 --- a/llvm/lib/Target/BPF/BPF.h +++ b/llvm/lib/Target/BPF/BPF.h @@ -66,6 +66,14 @@ public: static bool isRequired() { return true; } }; +class BPFASpaceCastSimplifyPass + : public PassInfoMixin { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); + + static bool isRequired() { return true; } +}; + class BPFAdjustOptPass : public PassInfoMixin { public: PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); diff --git a/llvm/lib/Target/BPF/BPFASpaceCastSimplifyPass.cpp b/llvm/lib/Target/BPF/BPFASpaceCastSimplifyPass.cpp new file mode 100644 index 000000000000..f87b299bbba6 --- /dev/null +++ b/llvm/lib/Target/BPF/BPFASpaceCastSimplifyPass.cpp @@ -0,0 +1,92 @@ +//===-- BPFASpaceCastSimplifyPass.cpp - BPF addrspacecast simplications --===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "BPF.h" +#include + +#define DEBUG_TYPE "bpf-aspace-simplify" + +using namespace llvm; + +namespace { + +struct CastGEPCast { + AddrSpaceCastInst *OuterCast; + + // Match chain of instructions: + // %inner = addrspacecast N->M + // %gep = getelementptr %inner, ... + // %outer = addrspacecast M->N %gep + // Where I is %outer. + static std::optional match(Value *I) { + auto *OuterCast = dyn_cast(I); + if (!OuterCast) + return std::nullopt; + auto *GEP = dyn_cast(OuterCast->getPointerOperand()); + if (!GEP) + return std::nullopt; + auto *InnerCast = dyn_cast(GEP->getPointerOperand()); + if (!InnerCast) + return std::nullopt; + if (InnerCast->getSrcAddressSpace() != OuterCast->getDestAddressSpace()) + return std::nullopt; + if (InnerCast->getDestAddressSpace() != OuterCast->getSrcAddressSpace()) + return std::nullopt; + return CastGEPCast{OuterCast}; + } + + static PointerType *changeAddressSpace(PointerType *Ty, unsigned AS) { + return Ty->get(Ty->getContext(), AS); + } + + // Assuming match(this->OuterCast) is true, convert: + // (addrspacecast M->N (getelementptr (addrspacecast N->M ptr) ...)) + // To: + // (getelementptr ptr ...) + GetElementPtrInst *rewrite() { + auto *GEP = cast(OuterCast->getPointerOperand()); + auto *InnerCast = cast(GEP->getPointerOperand()); + unsigned AS = OuterCast->getDestAddressSpace(); + auto *NewGEP = cast(GEP->clone()); + NewGEP->setName(GEP->getName()); + NewGEP->insertAfter(OuterCast); + NewGEP->setOperand(0, InnerCast->getPointerOperand()); + auto *GEPTy = cast(GEP->getType()); + NewGEP->mutateType(changeAddressSpace(GEPTy, AS)); + OuterCast->replaceAllUsesWith(NewGEP); + OuterCast->eraseFromParent(); + if (GEP->use_empty()) + GEP->eraseFromParent(); + if (InnerCast->use_empty()) + InnerCast->eraseFromParent(); + return NewGEP; + } +}; + +} // anonymous namespace + +PreservedAnalyses BPFASpaceCastSimplifyPass::run(Function &F, + FunctionAnalysisManager &AM) { + SmallVector WorkList; + bool Changed = false; + for (BasicBlock &BB : F) { + for (Instruction &I : BB) + if (auto It = CastGEPCast::match(&I)) + WorkList.push_back(It.value()); + Changed |= !WorkList.empty(); + + while (!WorkList.empty()) { + CastGEPCast InsnChain = WorkList.pop_back_val(); + GetElementPtrInst *NewGEP = InsnChain.rewrite(); + for (User *U : NewGEP->users()) + if (auto It = CastGEPCast::match(U)) + WorkList.push_back(It.value()); + } + } + return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); +} diff --git a/llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp b/llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp index 81effc9b1db4..edd59aaa6d01 100644 --- a/llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp +++ b/llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp @@ -14,6 +14,8 @@ // optimizations are done and those builtins can be removed. // - remove llvm.bpf.getelementptr.and.load builtins. // - remove llvm.bpf.getelementptr.and.store builtins. +// - for loads and stores with base addresses from non-zero address space +// cast base address to zero address space (support for BPF arenas). // //===----------------------------------------------------------------------===// @@ -55,6 +57,7 @@ private: bool removeCompareBuiltin(Module &M); bool sinkMinMax(Module &M); bool removeGEPBuiltins(Module &M); + bool insertASpaceCasts(Module &M); }; } // End anonymous namespace @@ -416,11 +419,124 @@ bool BPFCheckAndAdjustIR::removeGEPBuiltins(Module &M) { return Changed; } +// Wrap ToWrap with cast to address space zero: +// - if ToWrap is a getelementptr, +// wrap it's base pointer instead and return a copy; +// - if ToWrap is Instruction, insert address space cast +// immediately after ToWrap; +// - if ToWrap is not an Instruction (function parameter +// or a global value), insert address space cast at the +// beginning of the Function F; +// - use Cache to avoid inserting too many casts; +static Value *aspaceWrapValue(DenseMap &Cache, Function *F, + Value *ToWrap) { + auto It = Cache.find(ToWrap); + if (It != Cache.end()) + return It->getSecond(); + + if (auto *GEP = dyn_cast(ToWrap)) { + Value *Ptr = GEP->getPointerOperand(); + Value *WrappedPtr = aspaceWrapValue(Cache, F, Ptr); + auto *GEPTy = cast(GEP->getType()); + auto *NewGEP = GEP->clone(); + NewGEP->insertAfter(GEP); + NewGEP->mutateType(GEPTy->getPointerTo(0)); + NewGEP->setOperand(GEP->getPointerOperandIndex(), WrappedPtr); + NewGEP->setName(GEP->getName()); + Cache[ToWrap] = NewGEP; + return NewGEP; + } + + IRBuilder IB(F->getContext()); + if (Instruction *InsnPtr = dyn_cast(ToWrap)) + IB.SetInsertPoint(*InsnPtr->getInsertionPointAfterDef()); + else + IB.SetInsertPoint(F->getEntryBlock().getFirstInsertionPt()); + auto *PtrTy = cast(ToWrap->getType()); + auto *ASZeroPtrTy = PtrTy->getPointerTo(0); + auto *ACast = IB.CreateAddrSpaceCast(ToWrap, ASZeroPtrTy, ToWrap->getName()); + Cache[ToWrap] = ACast; + return ACast; +} + +// Wrap a pointer operand OpNum of instruction I +// with cast to address space zero +static void aspaceWrapOperand(DenseMap &Cache, Instruction *I, + unsigned OpNum) { + Value *OldOp = I->getOperand(OpNum); + if (OldOp->getType()->getPointerAddressSpace() == 0) + return; + + Value *NewOp = aspaceWrapValue(Cache, I->getFunction(), OldOp); + I->setOperand(OpNum, NewOp); + // Check if there are any remaining users of old GEP, + // delete those w/o users + for (;;) { + auto *OldGEP = dyn_cast(OldOp); + if (!OldGEP) + break; + if (!OldGEP->use_empty()) + break; + OldOp = OldGEP->getPointerOperand(); + OldGEP->eraseFromParent(); + } +} + +// Support for BPF arenas: +// - for each function in the module M, update pointer operand of +// each memory access instruction (load/store/cmpxchg/atomicrmw) +// by casting it from non-zero address space to zero address space, e.g: +// +// (load (ptr addrspace (N) %p) ...) +// -> (load (addrspacecast ptr addrspace (N) %p to ptr)) +// +// - assign section with name .arena.N for globals defined in +// non-zero address space N +bool BPFCheckAndAdjustIR::insertASpaceCasts(Module &M) { + bool Changed = false; + for (Function &F : M) { + DenseMap CastsCache; + for (BasicBlock &BB : F) { + for (Instruction &I : BB) { + unsigned PtrOpNum; + + if (auto *LD = dyn_cast(&I)) + PtrOpNum = LD->getPointerOperandIndex(); + else if (auto *ST = dyn_cast(&I)) + PtrOpNum = ST->getPointerOperandIndex(); + else if (auto *CmpXchg = dyn_cast(&I)) + PtrOpNum = CmpXchg->getPointerOperandIndex(); + else if (auto *RMW = dyn_cast(&I)) + PtrOpNum = RMW->getPointerOperandIndex(); + else + continue; + + aspaceWrapOperand(CastsCache, &I, PtrOpNum); + } + } + Changed |= !CastsCache.empty(); + } + // Merge all globals within same address space into single + // .arena. section + for (GlobalVariable &G : M.globals()) { + if (G.getAddressSpace() == 0 || G.hasSection()) + continue; + SmallString<16> SecName; + raw_svector_ostream OS(SecName); + OS << ".arena." << G.getAddressSpace(); + G.setSection(SecName); + // Prevent having separate section for constants + G.setConstant(false); + } + return Changed; +} + bool BPFCheckAndAdjustIR::adjustIR(Module &M) { bool Changed = removePassThroughBuiltin(M); Changed = removeCompareBuiltin(M) || Changed; Changed = sinkMinMax(M) || Changed; Changed = removeGEPBuiltins(M) || Changed; + Changed = insertASpaceCasts(M) || Changed; return Changed; } diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td index 82d347023106..7198e9499bc3 100644 --- a/llvm/lib/Target/BPF/BPFInstrInfo.td +++ b/llvm/lib/Target/BPF/BPFInstrInfo.td @@ -420,6 +420,35 @@ let Predicates = [BPFHasMovsx] in { } } +def ADDR_SPACE_CAST + : ALU_RR { + bits<64> dst_as; + bits<64> src_as; + + let Inst{47-32} = 1; + let Inst{31-16} = dst_as{15-0}; + let Inst{15-0} = src_as{15-0}; +} + +def SrcAddrSpace : SDNodeXFormgetTargetConstant( + cast(N)->getSrcAddressSpace(), + SDLoc(N), MVT::i64); +}]>; + +def DstAddrSpace : SDNodeXFormgetTargetConstant( + cast(N)->getDestAddressSpace(), + SDLoc(N), MVT::i64); +}]>; + +def : Pat<(addrspacecast:$this GPR:$src), + (ADDR_SPACE_CAST $src, (DstAddrSpace $this), (SrcAddrSpace $this))>; + def FI_ri : TYPE_LD_ST 42) +; a = magic1(); +; else +; a = magic2(); +; a[5] = 7; +; } +; +; Using the following command: +; +; clang --target=bpf -O2 -S -emit-llvm -o t.ll t.c + +define void @test(i64 noundef %i) { +; CHECK: if.end: +; CHECK-NEXT: [[A_0:%.*]] = phi ptr addrspace(1) +; CHECK-NEXT: [[A_01:%.*]] = addrspacecast ptr addrspace(1) [[A_0]] to ptr +; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[A_01]], i64 5 +; CHECK-NEXT: store i32 7, ptr [[ARRAYIDX2]], align 4 +; CHECK-NEXT: ret void +; +entry: + %cmp = icmp sgt i64 %i, 42 + br i1 %cmp, label %if.then, label %if.else + +if.then: ; preds = %entry + %call = tail call ptr addrspace(1) @magic1() + br label %if.end + +if.else: ; preds = %entry + %call1 = tail call ptr addrspace(1) @magic2() + br label %if.end + +if.end: ; preds = %if.else, %if.then + %a.0 = phi ptr addrspace(1) [ %call, %if.then ], [ %call1, %if.else ] + %arrayidx = getelementptr inbounds i32, ptr addrspace(1) %a.0, i64 5 + store i32 7, ptr addrspace(1) %arrayidx, align 4 + ret void +} + +declare ptr addrspace(1) @magic1(...) +declare ptr addrspace(1) @magic2(...) diff --git a/llvm/test/CodeGen/BPF/addr-space-simplify-1.ll b/llvm/test/CodeGen/BPF/addr-space-simplify-1.ll new file mode 100644 index 000000000000..32d67284d1c1 --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-simplify-1.ll @@ -0,0 +1,19 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -passes=bpf-aspace-simplify -mtriple=bpf-pc-linux -S < %s | FileCheck %s + +; Check that bpf-aspace-simplify pass removes unnecessary (for BPF) +; address space casts for cast M->N -> GEP -> cast N->M chain. + +define dso_local ptr addrspace(1) @test (ptr addrspace(1) %p) { +; CHECK-LABEL: define dso_local ptr addrspace(1) @test( +; CHECK-SAME: ptr addrspace(1) [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[B1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 8 +; CHECK-NEXT: ret ptr addrspace(1) [[B1]] +; + entry: + %a = addrspacecast ptr addrspace(1) %p to ptr + %b = getelementptr inbounds i8, ptr %a, i64 8 + %c = addrspacecast ptr %b to ptr addrspace(1) + ret ptr addrspace(1) %c +} diff --git a/llvm/test/CodeGen/BPF/addr-space-simplify-2.ll b/llvm/test/CodeGen/BPF/addr-space-simplify-2.ll new file mode 100644 index 000000000000..a2965554a973 --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-simplify-2.ll @@ -0,0 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -passes=bpf-aspace-simplify -mtriple=bpf-pc-linux -S < %s | FileCheck %s + +; Check that bpf-aspace-simplify pass does not change +; chain 'cast M->N -> GEP -> cast N->K'. + +define dso_local ptr addrspace(2) @test (ptr addrspace(1) %p) { +; CHECK-LABEL: define dso_local ptr addrspace(2) @test( +; CHECK-SAME: ptr addrspace(1) [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = addrspacecast ptr addrspace(1) [[P]] to ptr +; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 8 +; CHECK-NEXT: [[C:%.*]] = addrspacecast ptr [[B]] to ptr addrspace(2) +; CHECK-NEXT: ret ptr addrspace(2) [[C]] +; + entry: + %a = addrspacecast ptr addrspace(1) %p to ptr + %b = getelementptr inbounds i8, ptr %a, i64 8 + %c = addrspacecast ptr %b to ptr addrspace(2) + ret ptr addrspace(2) %c +} diff --git a/llvm/test/CodeGen/BPF/addr-space-simplify-3.ll b/llvm/test/CodeGen/BPF/addr-space-simplify-3.ll new file mode 100644 index 000000000000..a7736c462b44 --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-simplify-3.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -passes=bpf-aspace-simplify -mtriple=bpf-pc-linux -S < %s | FileCheck %s + +; Check that when bpf-aspace-simplify pass modifies chain +; 'cast M->N -> GEP -> cast N->M' it does not remove GEP, +; when that GEP is used by some other instruction. + +define dso_local ptr addrspace(1) @test (ptr addrspace(1) %p) { +; CHECK-LABEL: define dso_local ptr addrspace(1) @test( +; CHECK-SAME: ptr addrspace(1) [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = addrspacecast ptr addrspace(1) [[P]] to ptr +; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 8 +; CHECK-NEXT: [[B1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 8 +; CHECK-NEXT: call void @sink(ptr [[B]]) +; CHECK-NEXT: ret ptr addrspace(1) [[B1]] +; + entry: + %a = addrspacecast ptr addrspace(1) %p to ptr + %b = getelementptr inbounds i8, ptr %a, i64 8 + %c = addrspacecast ptr %b to ptr addrspace(1) + call void @sink(ptr %b) + ret ptr addrspace(1) %c +} + +declare dso_local void @sink(ptr) diff --git a/llvm/test/CodeGen/BPF/addr-space-simplify-4.ll b/llvm/test/CodeGen/BPF/addr-space-simplify-4.ll new file mode 100644 index 000000000000..b2c384bbb6ab --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-simplify-4.ll @@ -0,0 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -passes=bpf-aspace-simplify -mtriple=bpf-pc-linux -S < %s | FileCheck %s + +; Check that bpf-aspace-simplify pass simplifies chain +; 'cast K->M -> cast M->N -> GEP -> cast N->M -> cast M->K'. + +define dso_local ptr addrspace(2) @test (ptr addrspace(2) %p) { +; CHECK-LABEL: define dso_local ptr addrspace(2) @test( +; CHECK-SAME: ptr addrspace(2) [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C12:%.*]] = getelementptr inbounds i8, ptr addrspace(2) [[P]], i64 8 +; CHECK-NEXT: ret ptr addrspace(2) [[C12]] +; + entry: + %a = addrspacecast ptr addrspace(2) %p to ptr addrspace(1) + %b = addrspacecast ptr addrspace(1) %a to ptr + %c = getelementptr inbounds i8, ptr %b, i64 8 + %d = addrspacecast ptr %c to ptr addrspace(1) + %e = addrspacecast ptr addrspace (1) %d to ptr addrspace(2) + ret ptr addrspace(2) %e +} diff --git a/llvm/test/CodeGen/BPF/addr-space-simplify-5.ll b/llvm/test/CodeGen/BPF/addr-space-simplify-5.ll new file mode 100644 index 000000000000..b62d25384d95 --- /dev/null +++ b/llvm/test/CodeGen/BPF/addr-space-simplify-5.ll @@ -0,0 +1,25 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -passes=bpf-aspace-simplify -mtriple=bpf-pc-linux -S < %s | FileCheck %s + +; Check that bpf-aspace-simplify pass removes unnecessary (for BPF) +; address space casts for cast M->N -> GEP -> cast N->M chain, +; where chain is split between several BBs. + +define dso_local ptr addrspace(1) @test (ptr addrspace(1) %p) { +; CHECK-LABEL: define dso_local ptr addrspace(1) @test( +; CHECK-SAME: ptr addrspace(1) [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: [[B1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[P]], i64 8 +; CHECK-NEXT: ret ptr addrspace(1) [[B1]] +; +entry: + %a = addrspacecast ptr addrspace(1) %p to ptr + %b = getelementptr inbounds i8, ptr %a, i64 8 + br label %exit + +exit: + %c = addrspacecast ptr %b to ptr addrspace(1) + ret ptr addrspace(1) %c +} diff --git a/llvm/test/CodeGen/BPF/assembler-disassembler.s b/llvm/test/CodeGen/BPF/assembler-disassembler.s index 2bc7421c2471..991d6edc683a 100644 --- a/llvm/test/CodeGen/BPF/assembler-disassembler.s +++ b/llvm/test/CodeGen/BPF/assembler-disassembler.s @@ -289,3 +289,10 @@ r0 = *(u32*)skb[42] r0 = *(u8*)skb[r1] r0 = *(u16*)skb[r1] r0 = *(u32*)skb[r1] + +// CHECK: bf 10 01 00 01 00 00 00 r0 = addr_space_cast(r1, 0x0, 0x1) +// CHECK: bf 21 01 00 00 00 01 00 r1 = addr_space_cast(r2, 0x1, 0x0) +// CHECK: bf 43 01 00 2a 00 07 00 r3 = addr_space_cast(r4, 0x7, 0x2a) +r0 = addr_space_cast(r1, 0, 1) +r1 = addr_space_cast(r2, 1, 0) +r3 = addr_space_cast(r4, 7, 42) -- GitLab From d014708a217beaef04f9533d311c68bda71a52f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roger=20Ferrer=20Ib=C3=A1=C3=B1ez?= Date: Wed, 13 Mar 2024 01:30:26 +0100 Subject: [PATCH 320/953] [llvm][Mips] Use a Target ISD opcode for PseudoD_SELECT (#84294) The Mips target uses two TargetOpcode enumerators called `PseudoD_SELECT_I` and `PseudoD_SELECT_I64`. A SDAG node is created using these enumerators which is manually selected in `MipsSEISelDAGToDAG.cpp` and ultimately expanded in `EmitInstrWithCustomInserter` in `MipsISelLowering.cpp`. This is not causing any upstream build to fail at the moment but it is not guaranteed that these enumerators do not clash with Target ISD nodes (i.e. those in the `MipsISD` namespace). We have seen this happening in our downstream builds in which `Mips::PseudoD_SELECT_I` ends having the same integer value as `MipsISD::VEXTRACT_ZEXT_ELT`. This confuses the function `trySelect` in `MipsSEISelDAGToDAG.cpp` and causes a crash in 3 tests. This change adds a new Target ISD opcode for these two cases and uses them for the SDAG nodes. No test is included because this is a potential error in the future not one that can be demonstrated in the current codebase. --- llvm/lib/Target/Mips/MipsISelLowering.cpp | 6 ++++-- llvm/lib/Target/Mips/MipsISelLowering.h | 4 ++++ llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index 97e830cec27c..7e5f148e7bf4 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -239,6 +239,8 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::MAQ_S_W_PHR: return "MipsISD::MAQ_S_W_PHR"; case MipsISD::MAQ_SA_W_PHL: return "MipsISD::MAQ_SA_W_PHL"; case MipsISD::MAQ_SA_W_PHR: return "MipsISD::MAQ_SA_W_PHR"; + case MipsISD::DOUBLE_SELECT_I: return "MipsISD::DOUBLE_SELECT_I"; + case MipsISD::DOUBLE_SELECT_I64: return "MipsISD::DOUBLE_SELECT_I64"; case MipsISD::DPAU_H_QBL: return "MipsISD::DPAU_H_QBL"; case MipsISD::DPAU_H_QBR: return "MipsISD::DPAU_H_QBR"; case MipsISD::DPSU_H_QBL: return "MipsISD::DPSU_H_QBL"; @@ -2652,8 +2654,8 @@ SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, if (!(Subtarget.hasMips4() || Subtarget.hasMips32())) { SDVTList VTList = DAG.getVTList(VT, VT); - return DAG.getNode(Subtarget.isGP64bit() ? Mips::PseudoD_SELECT_I64 - : Mips::PseudoD_SELECT_I, + return DAG.getNode(Subtarget.isGP64bit() ? MipsISD::DOUBLE_SELECT_I64 + : MipsISD::DOUBLE_SELECT_I, DL, VTList, Cond, ShiftRightHi, IsSRA ? Ext : DAG.getConstant(0, DL, VT), Or, ShiftRightHi); diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h index 7d243eeca5c6..84ad40d6bbbe 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/llvm/lib/Target/Mips/MipsISelLowering.h @@ -242,6 +242,10 @@ class TargetRegisterClass; VEXTRACT_SEXT_ELT, VEXTRACT_ZEXT_ELT, + // Double select nodes for machines without conditional-move. + DOUBLE_SELECT_I, + DOUBLE_SELECT_I64, + // Load/Store Left/Right nodes. LWL = ISD::FIRST_TARGET_MEMORY_OPCODE, LWR, diff --git a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index c0e978018919..ab39d1b661ef 100644 --- a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -741,8 +741,8 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) { switch(Opcode) { default: break; - case Mips::PseudoD_SELECT_I: - case Mips::PseudoD_SELECT_I64: { + case MipsISD::DOUBLE_SELECT_I: + case MipsISD::DOUBLE_SELECT_I64: { MVT VT = Subtarget->isGP64bit() ? MVT::i64 : MVT::i32; SDValue cond = Node->getOperand(0); SDValue Hi1 = Node->getOperand(1); -- GitLab From 97c0cad388e5d3f5089a05001149ea7eeabbd777 Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Wed, 13 Mar 2024 00:35:08 +0000 Subject: [PATCH 321/953] [gn build] Port 2aacb56e8361 --- llvm/utils/gn/secondary/llvm/lib/Target/BPF/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/llvm/lib/Target/BPF/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Target/BPF/BUILD.gn index 668512ecba88..aa594df8c164 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Target/BPF/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Target/BPF/BUILD.gn @@ -60,6 +60,7 @@ static_library("LLVMBPFCodeGen") { ] include_dirs = [ "." ] sources = [ + "BPFASpaceCastSimplifyPass.cpp", "BPFAbstractMemberAccess.cpp", "BPFAdjustOpt.cpp", "BPFAsmPrinter.cpp", -- GitLab From 8bda5657332c7a94900d3eb2891d2b86e60b0e68 Mon Sep 17 00:00:00 2001 From: Qizhi Hu <836744285@qq.com> Date: Wed, 13 Mar 2024 08:42:22 +0800 Subject: [PATCH 322/953] [Clang][Sema] Allow access to a public template alias declaration that refers to friend's private nested type (#83847) This patch attempts to fix https://github.com/llvm/llvm-project/issues/25708 Current access check missed qualifier(`NestedNameSpecifier`) in friend class checking. Add it to `Records` of `EffectiveContext` by changing the `DeclContext` makes `MatchesFriend` work. Co-authored-by: huqizhi <836744285@qq.com> --- clang/docs/ReleaseNotes.rst | 2 ++ clang/lib/Sema/SemaTemplate.cpp | 10 +++++++--- clang/test/SemaTemplate/PR25708.cpp | 20 ++++++++++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 clang/test/SemaTemplate/PR25708.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index e14c92eae0af..64a9fe0d8bcc 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -360,6 +360,8 @@ Bug Fixes to C++ Support when one of the function had more specialized templates. Fixes (`#82509 `_) and (`#74494 `_) +- Allow access to a public template alias declaration that refers to friend's + private nested type. (#GH25708). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index d62095558d0f..d8c9a5c09944 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4343,9 +4343,13 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, if (Inst.isInvalid()) return QualType(); - CanonType = SubstType(Pattern->getUnderlyingType(), - TemplateArgLists, AliasTemplate->getLocation(), - AliasTemplate->getDeclName()); + std::optional SavedContext; + if (!AliasTemplate->getDeclContext()->isFileContext()) + SavedContext.emplace(*this, AliasTemplate->getDeclContext()); + + CanonType = + SubstType(Pattern->getUnderlyingType(), TemplateArgLists, + AliasTemplate->getLocation(), AliasTemplate->getDeclName()); if (CanonType.isNull()) { // If this was enable_if and we failed to find the nested type // within enable_if in a SFINAE context, dig out the specific diff --git a/clang/test/SemaTemplate/PR25708.cpp b/clang/test/SemaTemplate/PR25708.cpp new file mode 100644 index 000000000000..6a214fc6b43b --- /dev/null +++ b/clang/test/SemaTemplate/PR25708.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s +// expected-no-diagnostics + +struct FooAccessor +{ + template + using Foo = typename T::Foo; +}; + +class Type +{ + friend struct FooAccessor; + + using Foo = int; +}; + +int main() +{ + FooAccessor::Foo t; +} -- GitLab From 0fae4530e8476328f9a19b3ea4338b3a1e2187a8 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Tue, 12 Mar 2024 17:44:04 -0700 Subject: [PATCH 323/953] [LangRef] Fix mistake in example (#84849) --- llvm/docs/LangRef.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 77ec72f176d6..ecedd3a32c7b 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -27553,12 +27553,12 @@ in example below: .. code-block:: text %cond = call i1 @llvm.experimental.widenable.condition() - br i1 %cond, label %solution_1, label %solution_2 + br i1 %cond, label %fast_path, label %slow_path - label %fast_path: + fast_path: ; Apply memory-consuming but fast solution for a task. - label %slow_path: + slow_path: ; Cheap in memory but slow solution. Whether the result of intrinsic's call is `true` or `false`, -- GitLab From dcd9f49c2214891e3e0faffa70cf1a082434592a Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Tue, 12 Mar 2024 17:45:00 -0700 Subject: [PATCH 324/953] [sanitizer][windows] report symbols in clang_rt. or \compiler-rt\lib\ as internal. (#84971) This is the windows equivalent to the existing filters. Work from https://github.com/llvm/llvm-project/pull/81677 that can be applied separately (and is actually not critical for that PR) --- .../lib/sanitizer_common/sanitizer_symbolizer_report.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp index f6b157c07c65..ffbaf1468ec8 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp @@ -39,8 +39,12 @@ static bool FrameIsInternal(const SymbolizedStack *frame) { internal_strstr(file, "/include/c++/") || internal_strstr(file, "/include/g++"))) return true; + if (file && internal_strstr(file, "\\compiler-rt\\lib\\")) + return true; if (module && (internal_strstr(module, "libclang_rt."))) return true; + if (module && (internal_strstr(module, "clang_rt."))) + return true; return false; } -- GitLab From c1ac9a09d04e9be8f8f4860416528baf3691848d Mon Sep 17 00:00:00 2001 From: Yinying Li Date: Tue, 12 Mar 2024 20:57:21 -0400 Subject: [PATCH 325/953] [mlir][sparse] Finish migrating integration tests to use sparse_tensor.print (#84997) --- .../SparseTensor/CPU/sparse_conversion.mlir | 367 ++++++++---------- .../CPU/sparse_conversion_block.mlir | 70 ++-- .../CPU/sparse_conversion_dyn.mlir | 122 +++--- .../CPU/sparse_conversion_element.mlir | 4 +- .../CPU/sparse_conversion_ptr.mlir | 144 ++++--- .../CPU/sparse_conversion_sparse2dense.mlir | 4 +- .../CPU/sparse_conversion_sparse2sparse.mlir | 4 +- .../SparseTensor/CPU/sparse_coo_test.mlir | 47 ++- .../CPU/sparse_dilated_conv_2d_nhwc_hwcf.mlir | 4 +- .../Dialect/SparseTensor/CPU/sparse_dot.mlir | 38 +- .../SparseTensor/CPU/sparse_expand.mlir | 32 +- .../SparseTensor/CPU/sparse_expand_shape.mlir | 123 ++++-- .../CPU/sparse_filter_conv2d.mlir | 32 +- .../SparseTensor/CPU/sparse_flatten.mlir | 4 +- .../CPU/sparse_foreach_slices.mlir | 4 +- .../SparseTensor/CPU/sparse_generate.mlir | 20 +- .../SparseTensor/CPU/sparse_index.mlir | 176 +++++---- .../SparseTensor/CPU/sparse_index_dense.mlir | 4 +- .../SparseTensor/CPU/sparse_insert_3d.mlir | 4 +- 19 files changed, 670 insertions(+), 533 deletions(-) diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion.mlir index f13c1c66df6d..8024c1281895 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -46,28 +46,10 @@ // Integration test that tests conversions between sparse tensors. // module { - // - // Output utilities. - // - func.func @dumpf64(%arg0: memref) { - %c0 = arith.constant 0 : index - %d0 = arith.constant -1.0 : f64 - %0 = vector.transfer_read %arg0[%c0], %d0: memref, vector<24xf64> - vector.print %0 : vector<24xf64> - return - } - func.func @dumpidx(%arg0: memref) { - %c0 = arith.constant 0 : index - %d0 = arith.constant 0 : index - %0 = vector.transfer_read %arg0[%c0], %d0: memref, vector<25xindex> - vector.print %0 : vector<25xindex> - return - } - // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c2 = arith.constant 2 : index @@ -110,195 +92,176 @@ module { %i = sparse_tensor.convert %3 : tensor<2x3x4xf64, #Tensor3> to tensor<2x3x4xf64, #Tensor3> // - // Check number_of_entries. + // Verify the outputs. // - // CHECK-COUNT-12: 24 - %nv1 = sparse_tensor.number_of_entries %1 : tensor<2x3x4xf64, #Tensor1> - %nv2 = sparse_tensor.number_of_entries %2 : tensor<2x3x4xf64, #Tensor2> - %nv3 = sparse_tensor.number_of_entries %3 : tensor<2x3x4xf64, #Tensor3> - %nav = sparse_tensor.number_of_entries %a : tensor<2x3x4xf64, #Tensor1> - %nbv = sparse_tensor.number_of_entries %b : tensor<2x3x4xf64, #Tensor1> - %ncv = sparse_tensor.number_of_entries %c : tensor<2x3x4xf64, #Tensor1> - %ndv = sparse_tensor.number_of_entries %d : tensor<2x3x4xf64, #Tensor2> - %nev = sparse_tensor.number_of_entries %e : tensor<2x3x4xf64, #Tensor2> - %nfv = sparse_tensor.number_of_entries %f : tensor<2x3x4xf64, #Tensor2> - %ngv = sparse_tensor.number_of_entries %g : tensor<2x3x4xf64, #Tensor3> - %nhv = sparse_tensor.number_of_entries %h : tensor<2x3x4xf64, #Tensor3> - %niv = sparse_tensor.number_of_entries %i : tensor<2x3x4xf64, #Tensor3> - vector.print %nv1 : index - vector.print %nv2 : index - vector.print %nv3 : index - vector.print %nav : index - vector.print %nbv : index - vector.print %ncv : index - vector.print %ndv : index - vector.print %nev : index - vector.print %nfv : index - vector.print %ngv : index - vector.print %nhv : index - vector.print %niv : index - + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 2, 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 0, 1 + // CHECK-NEXT: pos[1] : ( 0, 3, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: pos[2] : ( 0, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 + // CHECK-NEXT: ---- // - // Check values. + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 + // CHECK-NEXT: ---- // - // CHECK: ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 ) - // CHECK-NEXT: ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 ) - // CHECK-NEXT: ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 ) - // CHECK-NEXT: ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 ) - // CHECK-NEXT: ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 ) - // CHECK-NEXT: ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 ) - // CHECK-NEXT: ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 ) - // CHECK-NEXT: ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 ) - // CHECK-NEXT: ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 ) - // CHECK-NEXT: ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 ) - // CHECK-NEXT: ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 ) - // CHECK-NEXT: ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 ) + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 4, 2, 3 ) + // CHECK-NEXT: pos[0] : ( 0, 4 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6, 8 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 3, 6, 9, 12, 15, 18, 21, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: values : ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: ---- // - %v1 = sparse_tensor.values %1 : tensor<2x3x4xf64, #Tensor1> to memref - %v2 = sparse_tensor.values %2 : tensor<2x3x4xf64, #Tensor2> to memref - %v3 = sparse_tensor.values %3 : tensor<2x3x4xf64, #Tensor3> to memref - %av = sparse_tensor.values %a : tensor<2x3x4xf64, #Tensor1> to memref - %bv = sparse_tensor.values %b : tensor<2x3x4xf64, #Tensor1> to memref - %cv = sparse_tensor.values %c : tensor<2x3x4xf64, #Tensor1> to memref - %dv = sparse_tensor.values %d : tensor<2x3x4xf64, #Tensor2> to memref - %ev = sparse_tensor.values %e : tensor<2x3x4xf64, #Tensor2> to memref - %fv = sparse_tensor.values %f : tensor<2x3x4xf64, #Tensor2> to memref - %gv = sparse_tensor.values %g : tensor<2x3x4xf64, #Tensor3> to memref - %hv = sparse_tensor.values %h : tensor<2x3x4xf64, #Tensor3> to memref - %iv = sparse_tensor.values %i : tensor<2x3x4xf64, #Tensor3> to memref - - call @dumpf64(%v1) : (memref) -> () - call @dumpf64(%v2) : (memref) -> () - call @dumpf64(%v3) : (memref) -> () - call @dumpf64(%av) : (memref) -> () - call @dumpf64(%bv) : (memref) -> () - call @dumpf64(%cv) : (memref) -> () - call @dumpf64(%dv) : (memref) -> () - call @dumpf64(%ev) : (memref) -> () - call @dumpf64(%fv) : (memref) -> () - call @dumpf64(%gv) : (memref) -> () - call @dumpf64(%hv) : (memref) -> () - call @dumpf64(%iv) : (memref) -> () - + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 2, 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 0, 1 + // CHECK-NEXT: pos[1] : ( 0, 3, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: pos[2] : ( 0, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 + // CHECK-NEXT: ---- // - // Check coordinates. + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 2, 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 0, 1 + // CHECK-NEXT: pos[1] : ( 0, 3, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: pos[2] : ( 0, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 + // CHECK-NEXT: ---- // - // CHECK-NEXT: ( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 ) + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 2, 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 0, 1 + // CHECK-NEXT: pos[1] : ( 0, 3, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: pos[2] : ( 0, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 + // CHECK-NEXT: ---- // - %v10 = sparse_tensor.coordinates %1 { level = 0 : index } : tensor<2x3x4xf64, #Tensor1> to memref - %v11 = sparse_tensor.coordinates %1 { level = 1 : index } : tensor<2x3x4xf64, #Tensor1> to memref - %v12 = sparse_tensor.coordinates %1 { level = 2 : index } : tensor<2x3x4xf64, #Tensor1> to memref - %v20 = sparse_tensor.coordinates %2 { level = 0 : index } : tensor<2x3x4xf64, #Tensor2> to memref - %v21 = sparse_tensor.coordinates %2 { level = 1 : index } : tensor<2x3x4xf64, #Tensor2> to memref - %v22 = sparse_tensor.coordinates %2 { level = 2 : index } : tensor<2x3x4xf64, #Tensor2> to memref - %v30 = sparse_tensor.coordinates %3 { level = 0 : index } : tensor<2x3x4xf64, #Tensor3> to memref - %v31 = sparse_tensor.coordinates %3 { level = 1 : index } : tensor<2x3x4xf64, #Tensor3> to memref - %v32 = sparse_tensor.coordinates %3 { level = 2 : index } : tensor<2x3x4xf64, #Tensor3> to memref - - %a10 = sparse_tensor.coordinates %a { level = 0 : index } : tensor<2x3x4xf64, #Tensor1> to memref - %a11 = sparse_tensor.coordinates %a { level = 1 : index } : tensor<2x3x4xf64, #Tensor1> to memref - %a12 = sparse_tensor.coordinates %a { level = 2 : index } : tensor<2x3x4xf64, #Tensor1> to memref - %b10 = sparse_tensor.coordinates %b { level = 0 : index } : tensor<2x3x4xf64, #Tensor1> to memref - %b11 = sparse_tensor.coordinates %b { level = 1 : index } : tensor<2x3x4xf64, #Tensor1> to memref - %b12 = sparse_tensor.coordinates %b { level = 2 : index } : tensor<2x3x4xf64, #Tensor1> to memref - %c10 = sparse_tensor.coordinates %c { level = 0 : index } : tensor<2x3x4xf64, #Tensor1> to memref - %c11 = sparse_tensor.coordinates %c { level = 1 : index } : tensor<2x3x4xf64, #Tensor1> to memref - %c12 = sparse_tensor.coordinates %c { level = 2 : index } : tensor<2x3x4xf64, #Tensor1> to memref - - %d20 = sparse_tensor.coordinates %d { level = 0 : index } : tensor<2x3x4xf64, #Tensor2> to memref - %d21 = sparse_tensor.coordinates %d { level = 1 : index } : tensor<2x3x4xf64, #Tensor2> to memref - %d22 = sparse_tensor.coordinates %d { level = 2 : index } : tensor<2x3x4xf64, #Tensor2> to memref - %e20 = sparse_tensor.coordinates %e { level = 0 : index } : tensor<2x3x4xf64, #Tensor2> to memref - %e21 = sparse_tensor.coordinates %e { level = 1 : index } : tensor<2x3x4xf64, #Tensor2> to memref - %e22 = sparse_tensor.coordinates %e { level = 2 : index } : tensor<2x3x4xf64, #Tensor2> to memref - %f20 = sparse_tensor.coordinates %f { level = 0 : index } : tensor<2x3x4xf64, #Tensor2> to memref - %f21 = sparse_tensor.coordinates %f { level = 1 : index } : tensor<2x3x4xf64, #Tensor2> to memref - %f22 = sparse_tensor.coordinates %f { level = 2 : index } : tensor<2x3x4xf64, #Tensor2> to memref - - %g30 = sparse_tensor.coordinates %g { level = 0 : index } : tensor<2x3x4xf64, #Tensor3> to memref - %g31 = sparse_tensor.coordinates %g { level = 1 : index } : tensor<2x3x4xf64, #Tensor3> to memref - %g32 = sparse_tensor.coordinates %g { level = 2 : index } : tensor<2x3x4xf64, #Tensor3> to memref - %h30 = sparse_tensor.coordinates %h { level = 0 : index } : tensor<2x3x4xf64, #Tensor3> to memref - %h31 = sparse_tensor.coordinates %h { level = 1 : index } : tensor<2x3x4xf64, #Tensor3> to memref - %h32 = sparse_tensor.coordinates %h { level = 2 : index } : tensor<2x3x4xf64, #Tensor3> to memref - %i30 = sparse_tensor.coordinates %i { level = 0 : index } : tensor<2x3x4xf64, #Tensor3> to memref - %i31 = sparse_tensor.coordinates %i { level = 1 : index } : tensor<2x3x4xf64, #Tensor3> to memref - %i32 = sparse_tensor.coordinates %i { level = 2 : index } : tensor<2x3x4xf64, #Tensor3> to memref - - call @dumpidx(%v10) : (memref) -> () - call @dumpidx(%v11) : (memref) -> () - call @dumpidx(%v12) : (memref) -> () - call @dumpidx(%v20) : (memref) -> () - call @dumpidx(%v21) : (memref) -> () - call @dumpidx(%v22) : (memref) -> () - call @dumpidx(%v30) : (memref) -> () - call @dumpidx(%v31) : (memref) -> () - call @dumpidx(%v32) : (memref) -> () - - call @dumpidx(%a10) : (memref) -> () - call @dumpidx(%a11) : (memref) -> () - call @dumpidx(%a12) : (memref) -> () - call @dumpidx(%b10) : (memref) -> () - call @dumpidx(%b11) : (memref) -> () - call @dumpidx(%b12) : (memref) -> () - call @dumpidx(%c10) : (memref) -> () - call @dumpidx(%c11) : (memref) -> () - call @dumpidx(%c12) : (memref) -> () - - call @dumpidx(%d20) : (memref) -> () - call @dumpidx(%d21) : (memref) -> () - call @dumpidx(%d22) : (memref) -> () - call @dumpidx(%e20) : (memref) -> () - call @dumpidx(%e21) : (memref) -> () - call @dumpidx(%e22) : (memref) -> () - call @dumpidx(%f20) : (memref) -> () - call @dumpidx(%f21) : (memref) -> () - call @dumpidx(%f22) : (memref) -> () - - call @dumpidx(%g30) : (memref) -> () - call @dumpidx(%g31) : (memref) -> () - call @dumpidx(%g32) : (memref) -> () - call @dumpidx(%h30) : (memref) -> () - call @dumpidx(%h31) : (memref) -> () - call @dumpidx(%h32) : (memref) -> () - call @dumpidx(%i30) : (memref) -> () - call @dumpidx(%i31) : (memref) -> () - call @dumpidx(%i32) : (memref) -> () + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 4, 2, 3 ) + // CHECK-NEXT: pos[0] : ( 0, 4 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6, 8 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 3, 6, 9, 12, 15, 18, 21, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: values : ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 4, 2, 3 ) + // CHECK-NEXT: pos[0] : ( 0, 4 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6, 8 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 3, 6, 9, 12, 15, 18, 21, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: values : ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 4, 2, 3 ) + // CHECK-NEXT: pos[0] : ( 0, 4 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6, 8 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 3, 6, 9, 12, 15, 18, 21, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: values : ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: ---- + // + sparse_tensor.print %1 : tensor<2x3x4xf64, #Tensor1> + sparse_tensor.print %2 : tensor<2x3x4xf64, #Tensor2> + sparse_tensor.print %3 : tensor<2x3x4xf64, #Tensor3> + sparse_tensor.print %a : tensor<2x3x4xf64, #Tensor1> + sparse_tensor.print %b : tensor<2x3x4xf64, #Tensor1> + sparse_tensor.print %c : tensor<2x3x4xf64, #Tensor1> + sparse_tensor.print %d : tensor<2x3x4xf64, #Tensor2> + sparse_tensor.print %e : tensor<2x3x4xf64, #Tensor2> + sparse_tensor.print %f : tensor<2x3x4xf64, #Tensor2> + sparse_tensor.print %g : tensor<2x3x4xf64, #Tensor3> + sparse_tensor.print %h : tensor<2x3x4xf64, #Tensor3> + sparse_tensor.print %i : tensor<2x3x4xf64, #Tensor3> // Release the resources. bufferization.dealloc_tensor %1 : tensor<2x3x4xf64, #Tensor1> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_block.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_block.mlir index 809414ba977d..ff22283f43a7 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_block.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_block.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -52,21 +52,10 @@ // Integration test that tests conversions between sparse tensors. // module { - // - // Output utilities. - // - func.func @dumpf64(%arg0: memref) { - %c0 = arith.constant 0 : index - %d0 = arith.constant -1.0 : f64 - %0 = vector.transfer_read %arg0[%c0], %d0: memref, vector<8xf64> - vector.print %0 : vector<8xf64> - return - } - // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c2 = arith.constant 2 : index @@ -88,20 +77,47 @@ module { %3 = sparse_tensor.convert %1 : tensor<2x4xf64, #BSR> to tensor<2x4xf64, #CSR> %4 = sparse_tensor.convert %1 : tensor<2x4xf64, #BSR> to tensor<2x4xf64, #CSC> - %v1 = sparse_tensor.values %1 : tensor<2x4xf64, #BSR> to memref - %v2 = sparse_tensor.values %2 : tensor<2x4xf64, #BSR> to memref - %v3 = sparse_tensor.values %3 : tensor<2x4xf64, #CSR> to memref - %v4 = sparse_tensor.values %4 : tensor<2x4xf64, #CSC> to memref - - - // CHECK: ( 1, 2, 5, 6, 3, 4, 7, 8 ) - // CHECK-NEXT: ( 1, 2, 5, 6, 3, 4, 7, 8 ) - // CHECK-NEXT: ( 1, 2, 3, 4, 5, 6, 7, 8 ) - // CHECK-NEXT: ( 1, 5, 2, 6, 3, 7, 4, 8 ) - call @dumpf64(%v1) : (memref) -> () - call @dumpf64(%v2) : (memref) -> () - call @dumpf64(%v3) : (memref) -> () - call @dumpf64(%v4) : (memref) -> () + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 2, 4 ) + // CHECK-NEXT: lvl = ( 1, 2, 2, 2 ) + // CHECK-NEXT: pos[1] : ( 0, 2 + // CHECK-NEXT: crd[1] : ( 0, 1 + // CHECK-NEXT: values : ( 1, 2, 5, 6, 3, 4, 7, 8 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 2, 4 ) + // CHECK-NEXT: lvl = ( 1, 2, 2, 2 ) + // CHECK-NEXT: pos[1] : ( 0, 2 + // CHECK-NEXT: crd[1] : ( 0, 1 + // CHECK-NEXT: values : ( 1, 2, 5, 6, 3, 4, 7, 8 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 2, 4 ) + // CHECK-NEXT: lvl = ( 2, 4 ) + // CHECK-NEXT: pos[1] : ( 0, 4, 8 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7, 8 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 2, 4 ) + // CHECK-NEXT: lvl = ( 4, 2 ) + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6, 8 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1, 5, 2, 6, 3, 7, 4, 8 + // CHECK-NEXT: ---- + // + sparse_tensor.print %1 : tensor<2x4xf64, #BSR> + sparse_tensor.print %2 : tensor<2x4xf64, #BSR> + sparse_tensor.print %3 : tensor<2x4xf64, #CSR> + sparse_tensor.print %4 : tensor<2x4xf64, #CSC> // TODO: Fix memory leaks. bufferization.dealloc_tensor %1 : tensor<2x4xf64, #BSR> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_dyn.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_dyn.mlir index f658457fa673..11baf65e6350 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_dyn.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_dyn.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -44,19 +44,7 @@ // may change (the actual underlying sizes obviously never change). // module { - - func.func private @printMemref1dF64(%ptr : memref) attributes { llvm.emit_c_interface } - - // - // Helper method to print values array. The transfer actually - // reads more than required to verify size of buffer as well. - // - func.func @dump(%arg0: memref) { - call @printMemref1dF64(%arg0) : (memref) -> () - return - } - - func.func @entry() { + func.func @main() { %t1 = arith.constant sparse< [ [0,0], [0,1], [0,63], [1,0], [1,1], [31,0], [31,63] ], [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 ]> : tensor<32x64xf64> @@ -72,45 +60,81 @@ module { %5 = sparse_tensor.convert %3 : tensor to tensor %6 = sparse_tensor.convert %4 : tensor to tensor -// - // Check number_of_entries. // - // CHECK-COUNT-6: 7 - %n1 = sparse_tensor.number_of_entries %1 : tensor - %n2 = sparse_tensor.number_of_entries %2 : tensor - %n3 = sparse_tensor.number_of_entries %3 : tensor - %n4 = sparse_tensor.number_of_entries %4 : tensor - %n5 = sparse_tensor.number_of_entries %5 : tensor - %n6 = sparse_tensor.number_of_entries %6 : tensor - vector.print %n1 : index - vector.print %n2 : index - vector.print %n3 : index - vector.print %n4 : index - vector.print %n5 : index - vector.print %n6 : index - + // Verify the outputs. + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 32, 64 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 31 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 63, 0, 1, 0, 63 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 64, 32 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 63 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 31, 0, 1, 0, 31 + // CHECK-NEXT: values : ( 1, 4, 6, 2, 5, 3, 7 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 32, 64 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 31 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 63, 0, 1, 0, 63 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 64, 32 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 63 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 31, 0, 1, 0, 31 + // CHECK-NEXT: values : ( 1, 4, 6, 2, 5, 3, 7 + // CHECK-NEXT: ---- // - // All proper row-/column-wise? + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 64, 32 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 63 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 31, 0, 1, 0, 31 + // CHECK-NEXT: values : ( 1, 4, 6, 2, 5, 3, 7 + // CHECK-NEXT: ---- // - // CHECK: [1, 2, 3, 4, 5, 6, 7 - // CHECK: [1, 4, 6, 2, 5, 3, 7 - // CHECK: [1, 2, 3, 4, 5, 6, 7 - // CHECK: [1, 4, 6, 2, 5, 3, 7 - // CHECK: [1, 4, 6, 2, 5, 3, 7 - // CHECK: [1, 2, 3, 4, 5, 6, 7 + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 32, 64 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 31 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 63, 0, 1, 0, 63 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: ---- // - %m1 = sparse_tensor.values %1 : tensor to memref - %m2 = sparse_tensor.values %2 : tensor to memref - %m3 = sparse_tensor.values %3 : tensor to memref - %m4 = sparse_tensor.values %4 : tensor to memref - %m5 = sparse_tensor.values %5 : tensor to memref - %m6 = sparse_tensor.values %6 : tensor to memref - call @dump(%m1) : (memref) -> () - call @dump(%m2) : (memref) -> () - call @dump(%m3) : (memref) -> () - call @dump(%m4) : (memref) -> () - call @dump(%m5) : (memref) -> () - call @dump(%m6) : (memref) -> () + sparse_tensor.print %1 : tensor + sparse_tensor.print %2 : tensor + sparse_tensor.print %3 : tensor + sparse_tensor.print %4 : tensor + sparse_tensor.print %5 : tensor + sparse_tensor.print %6 : tensor // Release the resources. bufferization.dealloc_tensor %1 : tensor diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_element.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_element.mlir index 81f68366be28..a2ec6df392aa 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_element.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_element.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -55,7 +55,7 @@ module { // // The first test suite (for non-singleton LevelTypes). // - func.func @entry() { + func.func @main() { // // Initialize a 3-dim dense tensor. // diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_ptr.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_ptr.mlir index 3ebe3be757d2..6005aa6cfeae 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_ptr.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_ptr.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -54,41 +54,7 @@ // in addition to layout. // module { - - // - // Helper method to print values and indices arrays. The transfer actually - // reads more than required to verify size of buffer as well. - // - func.func @dumpf64(%arg0: memref) { - %c = arith.constant 0 : index - %d = arith.constant 0.0 : f64 - %0 = vector.transfer_read %arg0[%c], %d: memref, vector<8xf64> - vector.print %0 : vector<8xf64> - return - } - func.func @dumpi08(%arg0: memref) { - %c = arith.constant 0 : index - %d = arith.constant 0 : i8 - %0 = vector.transfer_read %arg0[%c], %d: memref, vector<8xi8> - vector.print %0 : vector<8xi8> - return - } - func.func @dumpi32(%arg0: memref) { - %c = arith.constant 0 : index - %d = arith.constant 0 : i32 - %0 = vector.transfer_read %arg0[%c], %d: memref, vector<8xi32> - vector.print %0 : vector<8xi32> - return - } - func.func @dumpi64(%arg0: memref) { - %c = arith.constant 0 : index - %d = arith.constant 0 : i64 - %0 = vector.transfer_read %arg0[%c], %d: memref, vector<8xi64> - vector.print %0 : vector<8xi64> - return - } - - func.func @entry() { + func.func @main() { %c1 = arith.constant 1 : index %t1 = arith.constant sparse< [ [0,0], [0,1], [0,63], [1,0], [1,1], [31,0], [31,63] ], @@ -106,50 +72,78 @@ module { %6 = sparse_tensor.convert %3 : tensor<32x64xf64, #CSC> to tensor<32x64xf64, #DCSR> // - // All proper row-/column-wise? + // Verify the outputs. // - // CHECK: ( 1, 2, 3, 4, 5, 6, 7, 0 ) - // CHECK-NEXT: ( 1, 4, 6, 2, 5, 3, 7, 0 ) - // CHECK-NEXT: ( 1, 4, 6, 2, 5, 3, 7, 0 ) - // CHECK-NEXT: ( 1, 4, 6, 2, 5, 3, 7, 0 ) - // CHECK-NEXT: ( 1, 2, 3, 4, 5, 6, 7, 0 ) - // CHECK-NEXT: ( 1, 2, 3, 4, 5, 6, 7, 0 ) + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 32, 64 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 31 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 63, 0, 1, 0, 63 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: ---- // - %m1 = sparse_tensor.values %1 : tensor<32x64xf64, #DCSR> to memref - %m2 = sparse_tensor.values %2 : tensor<32x64xf64, #DCSC> to memref - %m3 = sparse_tensor.values %3 : tensor<32x64xf64, #CSC> to memref - %m4 = sparse_tensor.values %4 : tensor<32x64xf64, #DCSC> to memref - %m5 = sparse_tensor.values %5 : tensor<32x64xf64, #DCSR> to memref - %m6 = sparse_tensor.values %6 : tensor<32x64xf64, #DCSR> to memref - call @dumpf64(%m1) : (memref) -> () - call @dumpf64(%m2) : (memref) -> () - call @dumpf64(%m3) : (memref) -> () - call @dumpf64(%m4) : (memref) -> () - call @dumpf64(%m5) : (memref) -> () - call @dumpf64(%m6) : (memref) -> () - + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 64, 32 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 63 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 31, 0, 1, 0, 31 + // CHECK-NEXT: values : ( 1, 4, 6, 2, 5, 3, 7 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 64, 32 ) + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 31, 0, 1, 0, 31 + // CHECK-NEXT: values : ( 1, 4, 6, 2, 5, 3, 7 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 64, 32 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 63 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 31, 0, 1, 0, 31 + // CHECK-NEXT: values : ( 1, 4, 6, 2, 5, 3, 7 + // CHECK-NEXT: ---- // - // Sanity check on indices. + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 32, 64 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 31 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 63, 0, 1, 0, 63 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: ---- // - // CHECK-NEXT: ( 0, 1, 63, 0, 1, 0, 63, 0 ) - // CHECK-NEXT: ( 0, 1, 31, 0, 1, 0, 31, 0 ) - // CHECK-NEXT: ( 0, 1, 31, 0, 1, 0, 31, 0 ) - // CHECK-NEXT: ( 0, 1, 31, 0, 1, 0, 31, 0 ) - // CHECK-NEXT: ( 0, 1, 63, 0, 1, 0, 63, 0 ) - // CHECK-NEXT: ( 0, 1, 63, 0, 1, 0, 63, 0 ) + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 32, 64 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 31 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 63, 0, 1, 0, 63 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: ---- // - %i1 = sparse_tensor.coordinates %1 { level = 1 : index } : tensor<32x64xf64, #DCSR> to memref - %i2 = sparse_tensor.coordinates %2 { level = 1 : index } : tensor<32x64xf64, #DCSC> to memref - %i3 = sparse_tensor.coordinates %3 { level = 1 : index } : tensor<32x64xf64, #CSC> to memref - %i4 = sparse_tensor.coordinates %4 { level = 1 : index } : tensor<32x64xf64, #DCSC> to memref - %i5 = sparse_tensor.coordinates %5 { level = 1 : index } : tensor<32x64xf64, #DCSR> to memref - %i6 = sparse_tensor.coordinates %6 { level = 1 : index } : tensor<32x64xf64, #DCSR> to memref - call @dumpi08(%i1) : (memref) -> () - call @dumpi64(%i2) : (memref) -> () - call @dumpi32(%i3) : (memref) -> () - call @dumpi64(%i4) : (memref) -> () - call @dumpi08(%i5) : (memref) -> () - call @dumpi08(%i6) : (memref) -> () + sparse_tensor.print %1 : tensor<32x64xf64, #DCSR> + sparse_tensor.print %2 : tensor<32x64xf64, #DCSC> + sparse_tensor.print %3 : tensor<32x64xf64, #CSC> + sparse_tensor.print %4 : tensor<32x64xf64, #DCSC> + sparse_tensor.print %5 : tensor<32x64xf64, #DCSR> + sparse_tensor.print %6 : tensor<32x64xf64, #DCSR> // Release the resources. bufferization.dealloc_tensor %1 : tensor<32x64xf64, #DCSR> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2dense.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2dense.mlir index 1655d6a03a62..9b05f9bf3a29 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2dense.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2dense.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -107,7 +107,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { // // Initialize a 3-dim dense tensor. // diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2sparse.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2sparse.mlir index 2ace317554a0..0f9dfb9da720 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2sparse.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2sparse.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -180,7 +180,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { call @testNonSingleton() : () -> () call @testSingleton() : () -> () return diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_coo_test.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_coo_test.mlir index 16252c1005eb..16813e0aa707 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_coo_test.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_coo_test.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -93,17 +93,17 @@ module { func.func @add_coo_coo_out_coo(%arga: tensor<8x8xf32, #SortedCOO>, %argb: tensor<8x8xf32, #SortedCOOSoA>) - -> tensor<8x8xf32, #SortedCOO> { - %init = tensor.empty() : tensor<8x8xf32, #SortedCOO> + -> tensor<8x8xf32, #SortedCOOSoA> { + %init = tensor.empty() : tensor<8x8xf32, #SortedCOOSoA> %0 = linalg.generic #trait ins(%arga, %argb: tensor<8x8xf32, #SortedCOO>, tensor<8x8xf32, #SortedCOOSoA>) - outs(%init: tensor<8x8xf32, #SortedCOO>) { + outs(%init: tensor<8x8xf32, #SortedCOOSoA>) { ^bb(%a: f32, %b: f32, %x: f32): %0 = arith.addf %a, %b : f32 linalg.yield %0 : f32 - } -> tensor<8x8xf32, #SortedCOO> - return %0 : tensor<8x8xf32, #SortedCOO> + } -> tensor<8x8xf32, #SortedCOOSoA> + return %0 : tensor<8x8xf32, #SortedCOOSoA> } @@ -126,7 +126,7 @@ module { return %0 : tensor<8x8xf32> } - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c8 = arith.constant 8 : index @@ -171,8 +171,9 @@ module { -> tensor<8x8xf32> %COO_RET = call @add_coo_coo_out_coo(%COO_A, %COO_B) : (tensor<8x8xf32, #SortedCOO>, tensor<8x8xf32, #SortedCOOSoA>) - -> tensor<8x8xf32, #SortedCOO> - %C4 = sparse_tensor.convert %COO_RET : tensor<8x8xf32, #SortedCOO> to tensor<8x8xf32> + -> tensor<8x8xf32, #SortedCOOSoA> + %C4 = sparse_tensor.convert %COO_RET : tensor<8x8xf32, #SortedCOOSoA> to tensor<8x8xf32> + // // Verify computed matrix C. // @@ -201,6 +202,32 @@ module { vector.print %v4 : vector<8xf32> } + // + // Ensure that COO-SoA output has the same values. + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 64 + // CHECK-NEXT: dim = ( 8, 8 ) + // CHECK-NEXT: lvl = ( 8, 8 ) + // CHECK-NEXT: pos[0] : ( 0, 64 + // CHECK-NEXT: crd[0] : ( 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + // CHECK-SAME: 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + // CHECK-SAME: 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, + // CHECK-SAME: 7, 7, 7, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 6, 7 + // CHECK-NEXT: values : ( 8.8, 4.8, 6.8, 4.8, 8.8, 6.1, 14.8, 16.8, 4.4, 4.4, 4.4, 8.4, + // CHECK-SAME: 8.4, 12.4, 16.4, 16.4, 8.8, 4.8, 6.8, 8.8, 8.8, 12.8, 14.8, + // CHECK-SAME: 15.8, 4.3, 5.3, 6.3, 8.3, 8.3, 12.3, 14.3, 16.3, 4.5, 4.5, + // CHECK-SAME: 6.5, 8.5, 8.5, 12.5, 14.5, 16.5, 9.9, 4.9, 6.9, 8.9, 8.9, + // CHECK-SAME: 12.9, 15.9, 16.9, 12.1, 6.1, 5.1, 9.1, 9.1, 13.1, 15.1, 17.1, + // CHECK-SAME: 15.4, 5.4, 7.4, 5.4, 11.4, 10.4, 11.4, 9.4 + // CHECK-NEXT: ---- + // + sparse_tensor.print %COO_RET : tensor<8x8xf32, #SortedCOOSoA> + // Release resources. bufferization.dealloc_tensor %C1 : tensor<8x8xf32> bufferization.dealloc_tensor %C2 : tensor<8x8xf32> @@ -209,7 +236,7 @@ module { bufferization.dealloc_tensor %CSR_A : tensor<8x8xf32, #CSR> bufferization.dealloc_tensor %COO_A : tensor<8x8xf32, #SortedCOO> bufferization.dealloc_tensor %COO_B : tensor<8x8xf32, #SortedCOOSoA> - bufferization.dealloc_tensor %COO_RET : tensor<8x8xf32, #SortedCOO> + bufferization.dealloc_tensor %COO_RET : tensor<8x8xf32, #SortedCOOSoA> return diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dilated_conv_2d_nhwc_hwcf.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dilated_conv_2d_nhwc_hwcf.mlir index b4d40ae08401..40738a9f7d7f 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dilated_conv_2d_nhwc_hwcf.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dilated_conv_2d_nhwc_hwcf.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -78,7 +78,7 @@ func.func @conv_2d_nhwc_hwcf_dual_CDCC(%arg0: tensor, %arg1: } -func.func @entry() { +func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c3 = arith.constant 3 : index diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dot.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dot.mlir index f7ba4daa2458..5451f2d957ad 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dot.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dot.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -49,7 +49,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { // Setup two sparse vectors. %d1 = arith.constant sparse< [ [0], [1], [22], [23], [1022] ], [1.0, 2.0, 3.0, 4.0, 5.0] @@ -60,6 +60,30 @@ module { %s1 = sparse_tensor.convert %d1 : tensor<1024xf32> to tensor<1024xf32, #SparseVector> %s2 = sparse_tensor.convert %d2 : tensor<1024xf32> to tensor<1024xf32, #SparseVector> + // + // Verify the inputs. + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 5 + // CHECK-NEXT: dim = ( 1024 ) + // CHECK-NEXT: lvl = ( 1024 ) + // CHECK-NEXT: pos[0] : ( 0, 5 + // CHECK-NEXT: crd[0] : ( 0, 1, 22, 23, 1022 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 3 + // CHECK-NEXT: dim = ( 1024 ) + // CHECK-NEXT: lvl = ( 1024 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 22, 1022, 1023 + // CHECK-NEXT: values : ( 6, 7, 8 + // CHECK-NEXT: ---- + // + sparse_tensor.print %s1 : tensor<1024xf32, #SparseVector> + sparse_tensor.print %s2 : tensor<1024xf32, #SparseVector> + // Call the kernel and verify the output. // // CHECK: 53 @@ -73,16 +97,6 @@ module { %1 = tensor.extract %0[] : tensor vector.print %1 : f32 - // Print number of entries in the sparse vectors. - // - // CHECK: 5 - // CHECK: 3 - // - %noe1 = sparse_tensor.number_of_entries %s1 : tensor<1024xf32, #SparseVector> - %noe2 = sparse_tensor.number_of_entries %s2 : tensor<1024xf32, #SparseVector> - vector.print %noe1 : index - vector.print %noe2 : index - // Release the resources. bufferization.dealloc_tensor %0 : tensor bufferization.dealloc_tensor %s1 : tensor<1024xf32, #SparseVector> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand.mlir index 93a7ea51ec9c..451195b2185b 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -35,8 +35,6 @@ }> module { - func.func private @printMemrefF64(%ptr : tensor<*xf64>) - // // Column-wise storage forces the ijk loop to permute into jki // so that access pattern expansion (workspace) needs to be @@ -54,7 +52,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %d1 = arith.constant -1.0 : f64 @@ -83,24 +81,26 @@ module { : (tensor<8x2xf64, #CSC>, tensor<2x4xf64, #CSC>) -> tensor<8x4xf64, #CSC> - // CHECK: {{\[}}[32.53, 35.73, 38.93, 42.13], - // CHECK-NEXT: [34.56, 37.96, 41.36, 44.76], - // CHECK-NEXT: [36.59, 40.19, 43.79, 47.39], - // CHECK-NEXT: [38.62, 42.42, 46.22, 50.02], - // CHECK-NEXT: [40.65, 44.65, 48.65, 52.65], - // CHECK-NEXT: [42.68, 46.88, 51.08, 55.28], - // CHECK-NEXT: [44.71, 49.11, 53.51, 57.91], - // CHECK-NEXT: [46.74, 51.34, 55.94, 60.54]] // - %xc = sparse_tensor.convert %x3 : tensor<8x4xf64, #CSC> to tensor<8x4xf64> - %xu = tensor.cast %xc : tensor<8x4xf64> to tensor<*xf64> - call @printMemrefF64(%xu) : (tensor<*xf64>) -> () + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 32 + // CHECK-NEXT: dim = ( 8, 4 ) + // CHECK-NEXT: lvl = ( 4, 8 ) + // CHECK-NEXT: pos[1] : ( 0, 8, 16, 24, 32 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, + // CHECK-SAME: 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: values : ( 32.53, 34.56, 36.59, 38.62, 40.65, 42.68, 44.71, 46.74, + // CHECK-SAME: 35.73, 37.96, 40.19, 42.42, 44.65, 46.88, 49.11, 51.34, + // CHECK-SAME: 38.93, 41.36, 43.79, 46.22, 48.65, 51.08, 53.51, 55.94, + // CHECK-SAME: 42.13, 44.76, 47.39, 50.02, 52.65, 55.28, 57.91, 60.54 + // CHECK-NEXT: ---- + // + sparse_tensor.print %x3 : tensor<8x4xf64, #CSC> // Release the resources. bufferization.dealloc_tensor %x1 : tensor<8x2xf64, #CSC> bufferization.dealloc_tensor %x2 : tensor<2x4xf64, #CSC> bufferization.dealloc_tensor %x3 : tensor<8x4xf64, #CSC> - bufferization.dealloc_tensor %xc : tensor<8x4xf64> return } diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand_shape.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand_shape.mlir index c784375e0f3e..6679a81c7408 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand_shape.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand_shape.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -115,7 +115,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %df = arith.constant -1.0 : f64 @@ -147,60 +147,111 @@ module { %expand11 = call @expand_sparse2sparse_dyn(%sdm) : (tensor) -> tensor // - // Verify results of expand + // Verify results of expand with dense output. // // CHECK: ( ( 1, 0, 3, 0 ), ( 5, 0, 7, 0 ), ( 9, 0, 11, 0 ) ) // CHECK-NEXT: ( ( 1, 0, 3, 0 ), ( 5, 0, 7, 0 ), ( 9, 0, 11, 0 ) ) - // CHECK-NEXT: ( 1, 3, 5, 7, 9, - // CHECK-NEXT: ( 1, 3, 5, 7, 9, // CHECK-NEXT: ( ( ( 1.1, 1.2 ), ( 1.3, 1.4 ) ), ( ( 2.1, 2.2 ), ( 2.3, 2.4 ) ), ( ( 3.1, 3.2 ), ( 3.3, 3.4 ) ) ) // CHECK-NEXT: ( ( ( 1.1, 1.2 ), ( 1.3, 1.4 ) ), ( ( 2.1, 2.2 ), ( 2.3, 2.4 ) ), ( ( 3.1, 3.2 ), ( 3.3, 3.4 ) ) ) - // CHECK-NEXT: ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 ) - // CHECK-NEXT: ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 ) // CHECK-NEXT: ( ( ( 1.1, 1.2 ), ( 1.3, 1.4 ) ), ( ( 2.1, 2.2 ), ( 2.3, 2.4 ) ), ( ( 3.1, 3.2 ), ( 3.3, 3.4 ) ) ) // CHECK-NEXT: ( ( ( 1.1, 1.2 ), ( 1.3, 1.4 ) ), ( ( 2.1, 2.2 ), ( 2.3, 2.4 ) ), ( ( 3.1, 3.2 ), ( 3.3, 3.4 ) ) ) - // CHECK-NEXT: 12 - // CHECK-NEXT: ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 ) - // CHECK-NEXT: 12 - // CHECK-NEXT: ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 ) // - %m0 = vector.transfer_read %expand0[%c0, %c0], %df: tensor<3x4xf64>, vector<3x4xf64> vector.print %m0 : vector<3x4xf64> %m1 = vector.transfer_read %expand1[%c0, %c0], %df: tensor<3x4xf64>, vector<3x4xf64> vector.print %m1 : vector<3x4xf64> - %a2 = sparse_tensor.values %expand2 : tensor<3x4xf64, #SparseMatrix> to memref - %m2 = vector.transfer_read %a2[%c0], %df: memref, vector<12xf64> - vector.print %m2 : vector<12xf64> - %a3 = sparse_tensor.values %expand3 : tensor<3x4xf64, #SparseMatrix> to memref - %m3 = vector.transfer_read %a3[%c0], %df: memref, vector<12xf64> - vector.print %m3 : vector<12xf64> - %m4 = vector.transfer_read %expand4[%c0, %c0, %c0], %df: tensor<3x2x2xf64>, vector<3x2x2xf64> vector.print %m4 : vector<3x2x2xf64> %m5 = vector.transfer_read %expand5[%c0, %c0, %c0], %df: tensor<3x2x2xf64>, vector<3x2x2xf64> vector.print %m5 : vector<3x2x2xf64> - %a6 = sparse_tensor.values %expand6 : tensor<3x2x2xf64, #Sparse3dTensor> to memref - %m6 = vector.transfer_read %a6[%c0], %df: memref, vector<12xf64> - vector.print %m6 : vector<12xf64> - %a7 = sparse_tensor.values %expand7 : tensor<3x2x2xf64, #Sparse3dTensor> to memref - %m7 = vector.transfer_read %a7[%c0], %df: memref, vector<12xf64> - vector.print %m7 : vector<12xf64> - %m8 = vector.transfer_read %expand8[%c0, %c0, %c0], %df: tensor, vector<3x2x2xf64> vector.print %m8 : vector<3x2x2xf64> %m9 = vector.transfer_read %expand9[%c0, %c0, %c0], %df: tensor, vector<3x2x2xf64> vector.print %m9 : vector<3x2x2xf64> - %n10 = sparse_tensor.number_of_entries %expand10 : tensor - vector.print %n10 : index - %a10 = sparse_tensor.values %expand10 : tensor to memref - %m10 = vector.transfer_read %a10[%c0], %df: memref, vector<12xf64> - vector.print %m10 : vector<12xf64> - %n11 = sparse_tensor.number_of_entries %expand11 : tensor - vector.print %n11 : index - %a11 = sparse_tensor.values %expand11 : tensor to memref - %m11 = vector.transfer_read %a11[%c0], %df: memref, vector<12xf64> - vector.print %m11 : vector<12xf64> + + // + // Verify results of expand with sparse output. + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 6 + // CHECK-NEXT: dim = ( 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6 + // CHECK-NEXT: crd[1] : ( 0, 2, 0, 2, 0, 2 + // CHECK-NEXT: values : ( 1, 3, 5, 7, 9, 11 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 6 + // CHECK-NEXT: dim = ( 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6 + // CHECK-NEXT: crd[1] : ( 0, 2, 0, 2, 0, 2 + // CHECK-NEXT: values : ( 1, 3, 5, 7, 9, 11 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 12 + // CHECK-NEXT: dim = ( 3, 2, 2 ) + // CHECK-NEXT: lvl = ( 3, 2, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 12 + // CHECK-NEXT: dim = ( 3, 2, 2 ) + // CHECK-NEXT: lvl = ( 3, 2, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 12 + // CHECK-NEXT: dim = ( 3, 2, 2 ) + // CHECK-NEXT: lvl = ( 3, 2, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 12 + // CHECK-NEXT: dim = ( 3, 2, 2 ) + // CHECK-NEXT: lvl = ( 3, 2, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 + // CHECK-NEXT: ---- + // + sparse_tensor.print %expand2 : tensor<3x4xf64, #SparseMatrix> + sparse_tensor.print %expand3 : tensor<3x4xf64, #SparseMatrix> + sparse_tensor.print %expand6 : tensor<3x2x2xf64, #Sparse3dTensor> + sparse_tensor.print %expand7 : tensor<3x2x2xf64, #Sparse3dTensor> + sparse_tensor.print %expand10 : tensor + sparse_tensor.print %expand11 : tensor // Release sparse resources. diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_filter_conv2d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_filter_conv2d.mlir index 7478b604ff67..37ff2e3ffd3f 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_filter_conv2d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_filter_conv2d.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -53,7 +53,7 @@ module { return %0 : tensor<6x6xi32, #DCSR> } - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %i0 = arith.constant 0 : i32 @@ -100,25 +100,27 @@ module { vector.print %v : vector<6x6xi32> // - // Should be the same as dense output - // CHECK: ( ( 0, 0, -1, -6, -1, 6 ), - // CHECK-SAME: ( -1, 0, 1, 0, 1, 0 ), - // CHECK-SAME: ( 0, -1, 1, 0, 0, 0 ), - // CHECK-SAME: ( -1, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 0, 0, 3, 6, -3, -6 ), - // CHECK-SAME: ( 2, -1, 3, 0, -3, 0 ) ) + // Should be the same as dense output. // - %sparse_ret = sparse_tensor.convert %1 - : tensor<6x6xi32, #DCSR> to tensor<6x6xi32> - %v1 = vector.transfer_read %sparse_ret[%c0, %c0], %i0 - : tensor<6x6xi32>, vector<6x6xi32> - vector.print %v1 : vector<6x6xi32> + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 36 + // CHECK-NEXT: dim = ( 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6 ) + // CHECK-NEXT: pos[0] : ( 0, 6 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[1] : ( 0, 6, 12, 18, 24, 30, 36 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, + // CHECK-SAME: 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 0, 0, -1, -6, -1, 6, -1, 0, 1, 0, 1, 0, 0, -1, 1, + // CHECK-SAME: 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 3, 6, -3, -6, 2, -1, 3, 0, -3, 0 + // CHECK-NEXT: ---- + // + sparse_tensor.print %1 : tensor<6x6xi32, #DCSR> // Release the resources. bufferization.dealloc_tensor %sparse_filter : tensor<3x3xi32, #DCSR> bufferization.dealloc_tensor %0 : tensor<6x6xi32> bufferization.dealloc_tensor %1 : tensor<6x6xi32, #DCSR> - bufferization.dealloc_tensor %sparse_ret : tensor<6x6xi32> return } diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_flatten.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_flatten.mlir index 55ecac8dbc18..8a5712d3fa1b 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_flatten.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_flatten.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -82,7 +82,7 @@ module { // // Main driver that reads tensor from file and calls the sparse kernel. // - func.func @entry() { + func.func @main() { %d0 = arith.constant 0.0 : f64 %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_foreach_slices.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_foreach_slices.mlir index 46b83be21dcf..aef3a947e4f0 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_foreach_slices.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_foreach_slices.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -100,7 +100,7 @@ module { return } - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c2 = arith.constant 2 : index diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir index c1547033062d..e1f73eb4ac4f 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -39,7 +39,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %f0 = arith.constant 0.0 : f64 @@ -78,12 +78,20 @@ module { } %sv = sparse_tensor.convert %output : tensor to tensor - %n0 = sparse_tensor.number_of_entries %sv : tensor - // Print the number of non-zeros for verification. // - // CHECK: 5 - vector.print %n0 : index + // Verify the outputs. + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 5 + // CHECK-NEXT: dim = ( 50 ) + // CHECK-NEXT: lvl = ( 50 ) + // CHECK-NEXT: pos[0] : ( 0, 5 + // CHECK-NEXT: crd[0] : ( 1, 9, 17, 27, 30 + // CHECK-NEXT: values : ( 84, 34, 8, 40, 93 + // CHECK-NEXT: ---- + // + sparse_tensor.print %sv : tensor // Release the resources. bufferization.dealloc_tensor %sv : tensor diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index.mlir index 70a63ae7bc92..3ce45e5fd971 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -160,7 +160,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %du = arith.constant -1 : i64 %df = arith.constant -1.0 : f32 @@ -208,63 +208,112 @@ module { // // Verify result. // - // CHECK: 2 - // CHECK-NEXT: 8 - // CHECK-NEXT: 8 - // CHECK-NEXT: 8 - // CHECK-NEXT: 2 - // CHECK-NEXT: 12 - // CHECK-NEXT: 12 - // CHECK-NEXT: 12 - // CHECK-NEXT: ( 20, 80 ) - // CHECK-NEXT: ( 0, 1, 12, 3, 24, 5, 6, 7 ) - // CHECK-NEXT: ( 0, 2, 8, 24, 64, 160, 384, 896 ) - // CHECK-NEXT: ( 1, 3, 6, 11, 20, 37, 70, 135 ) - // CHECK-NEXT: ( 10, 120 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 1, 12, 3, 4, 2, 3, 4, 25 ) - // CHECK-NEXT: ( 0, 0, 0, 0, 0, 2, 2, 3, 0, 2, 12, 24 ) - // CHECK-NEXT: ( 1, 2, 3, 4, 2, 4, 4, 5, 3, 4, 7, 9 ) + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 2 + // CHECK-NEXT: dim = ( 8 ) + // CHECK-NEXT: lvl = ( 8 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 2, 4 + // CHECK-NEXT: values : ( 20, 80 + // CHECK-NEXT: ---- // - %n0 = sparse_tensor.number_of_entries %0 : tensor<8xi64, #SparseVector> - %n1 = sparse_tensor.number_of_entries %1 : tensor<8xi64, #SparseVector> - %n2 = sparse_tensor.number_of_entries %2 : tensor<8xi64, #SparseVector> - %n3 = sparse_tensor.number_of_entries %3 : tensor<8xi64, #SparseVector> - %n4 = sparse_tensor.number_of_entries %4 : tensor<3x4xi64, #SparseMatrix> - %n5 = sparse_tensor.number_of_entries %5 : tensor<3x4xi64, #SparseMatrix> - %n6 = sparse_tensor.number_of_entries %6 : tensor<3x4xi64, #SparseMatrix> - %n7 = sparse_tensor.number_of_entries %7 : tensor<3x4xi64, #SparseMatrix> - %8 = sparse_tensor.values %0 : tensor<8xi64, #SparseVector> to memref - %9 = sparse_tensor.values %1 : tensor<8xi64, #SparseVector> to memref - %10 = sparse_tensor.values %2 : tensor<8xi64, #SparseVector> to memref - %11 = sparse_tensor.values %3 : tensor<8xi64, #SparseVector> to memref - %12 = sparse_tensor.values %4 : tensor<3x4xi64, #SparseMatrix> to memref - %13 = sparse_tensor.values %5 : tensor<3x4xi64, #SparseMatrix> to memref - %14 = sparse_tensor.values %6 : tensor<3x4xi64, #SparseMatrix> to memref - %15 = sparse_tensor.values %7 : tensor<3x4xi64, #SparseMatrix> to memref - %16 = vector.transfer_read %8[%c0], %du: memref, vector<2xi64> - %17 = vector.transfer_read %9[%c0], %du: memref, vector<8xi64> - %18 = vector.transfer_read %10[%c0], %du: memref, vector<8xi64> - %19 = vector.transfer_read %11[%c0], %du: memref, vector<8xi64> - %20 = vector.transfer_read %12[%c0], %du: memref, vector<2xi64> - %21 = vector.transfer_read %13[%c0], %du: memref, vector<12xi64> - %22 = vector.transfer_read %14[%c0], %du: memref, vector<12xi64> - %23 = vector.transfer_read %15[%c0], %du: memref, vector<12xi64> - vector.print %n0 : index - vector.print %n1 : index - vector.print %n2 : index - vector.print %n3 : index - vector.print %n4 : index - vector.print %n5 : index - vector.print %n6 : index - vector.print %n7 : index - vector.print %16 : vector<2xi64> - vector.print %17 : vector<8xi64> - vector.print %18 : vector<8xi64> - vector.print %19 : vector<8xi64> - vector.print %20 : vector<2xi64> - vector.print %21 : vector<12xi64> - vector.print %22 : vector<12xi64> - vector.print %23 : vector<12xi64> + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 8 ) + // CHECK-NEXT: lvl = ( 8 ) + // CHECK-NEXT: pos[0] : ( 0, 8 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: values : ( 0, 1, 12, 3, 24, 5, 6, 7 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 8 ) + // CHECK-NEXT: lvl = ( 8 ) + // CHECK-NEXT: pos[0] : ( 0, 8 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: values : ( 0, 2, 8, 24, 64, 160, 384, 896 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 8 ) + // CHECK-NEXT: lvl = ( 8 ) + // CHECK-NEXT: pos[0] : ( 0, 8 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: values : ( 1, 3, 6, 11, 20, 37, 70, 135 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 2 + // CHECK-NEXT: dim = ( 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 1, 2 + // CHECK-NEXT: crd[1] : ( 1, 3 + // CHECK-NEXT: values : ( 10, 120 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 12 + // CHECK-NEXT: dim = ( 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 0, 1, 2, 3, 1, 12, 3, 4, 2, 3, 4, 25 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 12 + // CHECK-NEXT: dim = ( 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 0, 0, 0, 0, 0, 2, 2, 3, 0, 2, 12, 24 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 12 + // CHECK-NEXT: dim = ( 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 2, 4, 4, 5, 3, 4, 7, 9 + // CHECK-NEXT: ---- + // + sparse_tensor.print %0 : tensor<8xi64, #SparseVector> + sparse_tensor.print %1 : tensor<8xi64, #SparseVector> + sparse_tensor.print %2 : tensor<8xi64, #SparseVector> + sparse_tensor.print %3 : tensor<8xi64, #SparseVector> + sparse_tensor.print %4 : tensor<3x4xi64, #SparseMatrix> + sparse_tensor.print %5 : tensor<3x4xi64, #SparseMatrix> + sparse_tensor.print %6 : tensor<3x4xi64, #SparseMatrix> + sparse_tensor.print %7 : tensor<3x4xi64, #SparseMatrix> + + // + // Call the f32 kernel, verify the result. + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 6 + // CHECK-NEXT: dim = ( 2, 3 ) + // CHECK-NEXT: lvl = ( 2, 3 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 0, 1 + // CHECK-NEXT: pos[1] : ( 0, 3, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: values : ( 0, 10, 0, 1, 1, 42 + // CHECK-NEXT: ---- + // + %100 = call @add_outer_2d(%sf32) : (tensor<2x3xf32, #SparseMatrix>) + -> tensor<2x3xf32, #SparseMatrix> + sparse_tensor.print %100 : tensor<2x3xf32, #SparseMatrix> // Release resources. bufferization.dealloc_tensor %sv : tensor<8xi64, #SparseVector> @@ -279,17 +328,6 @@ module { bufferization.dealloc_tensor %5 : tensor<3x4xi64, #SparseMatrix> bufferization.dealloc_tensor %6 : tensor<3x4xi64, #SparseMatrix> bufferization.dealloc_tensor %7 : tensor<3x4xi64, #SparseMatrix> - - // - // Call the f32 kernel, verify the result, release the resources. - // - // CHECK-NEXT: ( 0, 10, 0, 1, 1, 42 ) - // - %100 = call @add_outer_2d(%sf32) : (tensor<2x3xf32, #SparseMatrix>) - -> tensor<2x3xf32, #SparseMatrix> - %101 = sparse_tensor.values %100 : tensor<2x3xf32, #SparseMatrix> to memref - %102 = vector.transfer_read %101[%c0], %df: memref, vector<6xf32> - vector.print %102 : vector<6xf32> bufferization.dealloc_tensor %sf32 : tensor<2x3xf32, #SparseMatrix> bufferization.dealloc_tensor %100 : tensor<2x3xf32, #SparseMatrix> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index_dense.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index_dense.mlir index 4bb1f3d12871..fc7b82fdecea 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index_dense.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index_dense.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -138,7 +138,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %du = arith.constant -1 : i64 diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_3d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_3d.mlir index 364a188cf37c..db6612402357 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_3d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_3d.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -48,7 +48,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c2 = arith.constant 2 : index -- GitLab From 16ae493f56c1857ec0f6f2777e9b8a2e5151b4ef Mon Sep 17 00:00:00 2001 From: Peter Rong Date: Tue, 12 Mar 2024 18:07:44 -0700 Subject: [PATCH 326/953] [FuzzMutate] Only use undef when explictly asked to (#84959) Per discussion in https://github.com/SecurityLab-UCD/IRFuzzer/issues/49, generating undef during fuzzing seems to be less fruitful. Let's eliminate undef in favor of poison unless the user explicitly asked for it. Signed-off-by: Peter Rong --- llvm/lib/FuzzMutate/OpDescriptor.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/llvm/lib/FuzzMutate/OpDescriptor.cpp b/llvm/lib/FuzzMutate/OpDescriptor.cpp index 4baf45284de1..6ec70d917918 100644 --- a/llvm/lib/FuzzMutate/OpDescriptor.cpp +++ b/llvm/lib/FuzzMutate/OpDescriptor.cpp @@ -8,10 +8,15 @@ #include "llvm/FuzzMutate/OpDescriptor.h" #include "llvm/IR/Constants.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; using namespace fuzzerop; +static cl::opt UseUndef("use-undef", + cl::desc("Use undef when generating programs."), + cl::init(false)); + void fuzzerop::makeConstantsWithType(Type *T, std::vector &Cs) { if (auto *IntTy = dyn_cast(T)) { uint64_t W = IntTy->getBitWidth(); @@ -42,7 +47,8 @@ void fuzzerop::makeConstantsWithType(Type *T, std::vector &Cs) { Cs.push_back(ConstantVector::getSplat(EC, Elt)); } } else { - Cs.push_back(UndefValue::get(T)); + if (UseUndef) + Cs.push_back(UndefValue::get(T)); Cs.push_back(PoisonValue::get(T)); } } -- GitLab From c6a93fe80b3cf30ff82d06e959c1177798c858ae Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Tue, 12 Mar 2024 18:25:36 -0700 Subject: [PATCH 327/953] [libc] Use __builtin_ffsll for RPC lane mask (#85000) src/__support/GPU/utils.h doesn't compile on a 32-bit platforms because __builtin_ffsl uses long which is a 32-bit number. Use __builtin_ffsll which uses long long which is guaranteed to be at least 64-bits. --- libc/src/__support/GPU/utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc/src/__support/GPU/utils.h b/libc/src/__support/GPU/utils.h index 93022e8de811..cb04a3562eb1 100644 --- a/libc/src/__support/GPU/utils.h +++ b/libc/src/__support/GPU/utils.h @@ -23,7 +23,7 @@ namespace LIBC_NAMESPACE { namespace gpu { /// Get the first active thread inside the lane. LIBC_INLINE uint64_t get_first_lane_id(uint64_t lane_mask) { - return __builtin_ffsl(lane_mask) - 1; + return __builtin_ffsll(lane_mask) - 1; } /// Conditional that is only true for a single thread in a lane. -- GitLab From 9d6c43b4aed117f53167e72749b31a943941345d Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Wed, 13 Mar 2024 09:26:53 +0800 Subject: [PATCH 328/953] [NFC] [C++20] [Modules] [P1689] [Scanner] Don't use thread pool in P1689 per file mode (#84285) I suddenly found that the clang scan deps may use all concurrent threads to scan the files. It makes sense in the batch mode. But in P1689 per file mode, it simply wastes times and resources. This patch itself should be a NFC patch. It simply moves codes. --- clang/tools/clang-scan-deps/ClangScanDeps.cpp | 195 +++++++++--------- 1 file changed, 100 insertions(+), 95 deletions(-) diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp index d042fecc3dbe..eaa76dd43e41 100644 --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -867,13 +867,6 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) { // Print out the dependency results to STDOUT by default. SharedStream DependencyOS(llvm::outs()); - DependencyScanningService Service(ScanMode, Format, OptimizeArgs, - EagerLoadModules); - llvm::DefaultThreadPool Pool(llvm::hardware_concurrency(NumThreads)); - std::vector> WorkerTools; - for (unsigned I = 0; I < Pool.getMaxConcurrency(); ++I) - WorkerTools.push_back(std::make_unique(Service)); - std::vector Inputs = AdjustingCompilations->getAllCompileCommands(); @@ -893,102 +886,114 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) { if (Format == ScanningOutputFormat::Full) FD.emplace(ModuleName.empty() ? Inputs.size() : 0); - if (Verbose) { - llvm::outs() << "Running clang-scan-deps on " << Inputs.size() - << " files using " << Pool.getMaxConcurrency() << " workers\n"; - } + auto ScanningTask = [&](DependencyScanningService &Service) { + DependencyScanningTool WorkerTool(Service); + + llvm::DenseSet AlreadySeenModules; + while (auto MaybeInputIndex = GetNextInputIndex()) { + size_t LocalIndex = *MaybeInputIndex; + const tooling::CompileCommand *Input = &Inputs[LocalIndex]; + std::string Filename = std::move(Input->Filename); + std::string CWD = std::move(Input->Directory); + + std::optional MaybeModuleName; + if (!ModuleName.empty()) + MaybeModuleName = ModuleName; + + std::string OutputDir(ModuleFilesDir); + if (OutputDir.empty()) + OutputDir = getModuleCachePath(Input->CommandLine); + auto LookupOutput = [&](const ModuleID &MID, ModuleOutputKind MOK) { + return ::lookupModuleOutput(MID, MOK, OutputDir); + }; + + // Run the tool on it. + if (Format == ScanningOutputFormat::Make) { + auto MaybeFile = WorkerTool.getDependencyFile(Input->CommandLine, CWD); + if (handleMakeDependencyToolResult(Filename, MaybeFile, DependencyOS, + Errs)) + HadErrors = true; + } else if (Format == ScanningOutputFormat::P1689) { + // It is useful to generate the make-format dependency output during + // the scanning for P1689. Otherwise the users need to scan again for + // it. We will generate the make-format dependency output if we find + // `-MF` in the command lines. + std::string MakeformatOutputPath; + std::string MakeformatOutput; + + auto MaybeRule = WorkerTool.getP1689ModuleDependencyFile( + *Input, CWD, MakeformatOutput, MakeformatOutputPath); + + if (handleP1689DependencyToolResult(Filename, MaybeRule, PD, Errs)) + HadErrors = true; + + if (!MakeformatOutputPath.empty() && !MakeformatOutput.empty() && + !HadErrors) { + static std::mutex Lock; + // With compilation database, we may open different files + // concurrently or we may write the same file concurrently. So we + // use a map here to allow multiple compile commands to write to the + // same file. Also we need a lock here to avoid data race. + static llvm::StringMap OSs; + std::unique_lock LockGuard(Lock); + + auto OSIter = OSs.find(MakeformatOutputPath); + if (OSIter == OSs.end()) { + std::error_code EC; + OSIter = + OSs.try_emplace(MakeformatOutputPath, MakeformatOutputPath, EC) + .first; + if (EC) + llvm::errs() << "Failed to open P1689 make format output file \"" + << MakeformatOutputPath << "\" for " << EC.message() + << "\n"; + } + + SharedStream MakeformatOS(OSIter->second); + llvm::Expected MaybeOutput(MakeformatOutput); + if (handleMakeDependencyToolResult(Filename, MaybeOutput, + MakeformatOS, Errs)) + HadErrors = true; + } + } else if (MaybeModuleName) { + auto MaybeModuleDepsGraph = WorkerTool.getModuleDependencies( + *MaybeModuleName, Input->CommandLine, CWD, AlreadySeenModules, + LookupOutput); + if (handleModuleResult(*MaybeModuleName, MaybeModuleDepsGraph, *FD, + LocalIndex, DependencyOS, Errs)) + HadErrors = true; + } else { + auto MaybeTUDeps = WorkerTool.getTranslationUnitDependencies( + Input->CommandLine, CWD, AlreadySeenModules, LookupOutput); + if (handleTranslationUnitResult(Filename, MaybeTUDeps, *FD, LocalIndex, + DependencyOS, Errs)) + HadErrors = true; + } + } + }; + + DependencyScanningService Service(ScanMode, Format, OptimizeArgs, + EagerLoadModules); llvm::Timer T; T.startTimer(); - for (unsigned I = 0; I < Pool.getMaxConcurrency(); ++I) { - Pool.async([&, I]() { - llvm::DenseSet AlreadySeenModules; - while (auto MaybeInputIndex = GetNextInputIndex()) { - size_t LocalIndex = *MaybeInputIndex; - const tooling::CompileCommand *Input = &Inputs[LocalIndex]; - std::string Filename = std::move(Input->Filename); - std::string CWD = std::move(Input->Directory); - - std::optional MaybeModuleName; - if (!ModuleName.empty()) - MaybeModuleName = ModuleName; - - std::string OutputDir(ModuleFilesDir); - if (OutputDir.empty()) - OutputDir = getModuleCachePath(Input->CommandLine); - auto LookupOutput = [&](const ModuleID &MID, ModuleOutputKind MOK) { - return ::lookupModuleOutput(MID, MOK, OutputDir); - }; + if (Inputs.size() == 1) { + ScanningTask(Service); + } else { + llvm::DefaultThreadPool Pool(llvm::hardware_concurrency(NumThreads)); - // Run the tool on it. - if (Format == ScanningOutputFormat::Make) { - auto MaybeFile = - WorkerTools[I]->getDependencyFile(Input->CommandLine, CWD); - if (handleMakeDependencyToolResult(Filename, MaybeFile, DependencyOS, - Errs)) - HadErrors = true; - } else if (Format == ScanningOutputFormat::P1689) { - // It is useful to generate the make-format dependency output during - // the scanning for P1689. Otherwise the users need to scan again for - // it. We will generate the make-format dependency output if we find - // `-MF` in the command lines. - std::string MakeformatOutputPath; - std::string MakeformatOutput; - - auto MaybeRule = WorkerTools[I]->getP1689ModuleDependencyFile( - *Input, CWD, MakeformatOutput, MakeformatOutputPath); - - if (handleP1689DependencyToolResult(Filename, MaybeRule, PD, Errs)) - HadErrors = true; + if (Verbose) { + llvm::outs() << "Running clang-scan-deps on " << Inputs.size() + << " files using " << Pool.getMaxConcurrency() + << " workers\n"; + } - if (!MakeformatOutputPath.empty() && !MakeformatOutput.empty() && - !HadErrors) { - static std::mutex Lock; - // With compilation database, we may open different files - // concurrently or we may write the same file concurrently. So we - // use a map here to allow multiple compile commands to write to the - // same file. Also we need a lock here to avoid data race. - static llvm::StringMap OSs; - std::unique_lock LockGuard(Lock); - - auto OSIter = OSs.find(MakeformatOutputPath); - if (OSIter == OSs.end()) { - std::error_code EC; - OSIter = OSs.try_emplace(MakeformatOutputPath, - MakeformatOutputPath, EC) - .first; - if (EC) - llvm::errs() - << "Failed to open P1689 make format output file \"" - << MakeformatOutputPath << "\" for " << EC.message() - << "\n"; - } + for (unsigned I = 0; I < Pool.getMaxConcurrency(); ++I) + Pool.async([ScanningTask, &Service]() { ScanningTask(Service); }); - SharedStream MakeformatOS(OSIter->second); - llvm::Expected MaybeOutput(MakeformatOutput); - if (handleMakeDependencyToolResult(Filename, MaybeOutput, - MakeformatOS, Errs)) - HadErrors = true; - } - } else if (MaybeModuleName) { - auto MaybeModuleDepsGraph = WorkerTools[I]->getModuleDependencies( - *MaybeModuleName, Input->CommandLine, CWD, AlreadySeenModules, - LookupOutput); - if (handleModuleResult(*MaybeModuleName, MaybeModuleDepsGraph, *FD, - LocalIndex, DependencyOS, Errs)) - HadErrors = true; - } else { - auto MaybeTUDeps = WorkerTools[I]->getTranslationUnitDependencies( - Input->CommandLine, CWD, AlreadySeenModules, LookupOutput); - if (handleTranslationUnitResult(Filename, MaybeTUDeps, *FD, - LocalIndex, DependencyOS, Errs)) - HadErrors = true; - } - } - }); + Pool.wait(); } - Pool.wait(); T.stopTimer(); if (PrintTiming) -- GitLab From 88986d65e4ed1b2ddd6693ff3e70b84436af767a Mon Sep 17 00:00:00 2001 From: Yinying Li Date: Tue, 12 Mar 2024 21:39:37 -0400 Subject: [PATCH 329/953] [mlir][sparse] Fix sparse_generate test (#85009) std::uniform_int_distribution may behave differently in different systems. --- .../SparseTensor/CPU/sparse_generate.mlir | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir index e1f73eb4ac4f..63a6d3acd737 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir @@ -78,20 +78,13 @@ module { } %sv = sparse_tensor.convert %output : tensor to tensor + %n0 = sparse_tensor.number_of_entries %sv : tensor + // Print the number of non-zeros for verification + // as shuffle may generate different numbers. // - // Verify the outputs. - // - // CHECK: ---- Sparse Tensor ---- - // CHECK-NEXT: nse = 5 - // CHECK-NEXT: dim = ( 50 ) - // CHECK-NEXT: lvl = ( 50 ) - // CHECK-NEXT: pos[0] : ( 0, 5 - // CHECK-NEXT: crd[0] : ( 1, 9, 17, 27, 30 - // CHECK-NEXT: values : ( 84, 34, 8, 40, 93 - // CHECK-NEXT: ---- - // - sparse_tensor.print %sv : tensor + // CHECK: 5 + vector.print %n0 : index // Release the resources. bufferization.dealloc_tensor %sv : tensor -- GitLab From 096d061c1c2f91edef7186bd8b61067020f49898 Mon Sep 17 00:00:00 2001 From: Sterling Augustine Date: Wed, 13 Mar 2024 01:37:53 +0000 Subject: [PATCH 330/953] Add missing dependency after 80ab8234ac309418637488b97e0a62d8377b2ecf --- .../llvm-project-overlay/libc/test/src/__support/BUILD.bazel | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel index 6837b9880d5a..5434761a9b13 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel @@ -65,6 +65,7 @@ libc_test( srcs = ["integer_to_string_test.cpp"], deps = [ "//libc:__support_cpp_span", + "//libc:__support_cpp_limits", "//libc:__support_cpp_string_view", "//libc:__support_integer_literals", "//libc:__support_integer_to_string", -- GitLab From 34cf6847752a3aad68eaa889ab6e0073a38fc2db Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Tue, 12 Mar 2024 19:33:16 -0700 Subject: [PATCH 331/953] [libc] Move `struct timespec` from POSIX to StdC (#85010) `struct timespec` is actually defined in the C standard, not POSIX. --- libc/spec/posix.td | 4 ---- libc/spec/spec.td | 4 ++++ libc/spec/stdc.td | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libc/spec/posix.td b/libc/spec/posix.td index d0f5a4584dd4..591919aac95d 100644 --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -42,10 +42,6 @@ def StructDirentPtr : PtrType; def StructDirentPtrPtr : PtrType; def ConstStructDirentPtrPtr : ConstType; -def StructTimeSpec : NamedType<"struct timespec">; -def StructTimeSpecPtr : PtrType; -def ConstStructTimeSpecPtr : ConstType; - def StructSchedParam : NamedType<"struct sched_param">; def StructSchedParamPtr : PtrType; def ConstStructSchedParamPtr : ConstType; diff --git a/libc/spec/spec.td b/libc/spec/spec.td index a44a7ae131b5..580bd9c8c3c1 100644 --- a/libc/spec/spec.td +++ b/libc/spec/spec.td @@ -118,6 +118,10 @@ def SigHandlerT : NamedType<"__sighandler_t">; def TimeTType : NamedType<"time_t">; +def StructTimeSpec : NamedType<"struct timespec">; +def StructTimeSpecPtr : PtrType; +def ConstStructTimeSpecPtr : ConstType; + def BSearchCompareT : NamedType<"__bsearchcompare_t">; def QSortCompareT : NamedType<"__qsortcompare_t">; diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index e012d0dee089..e8f73dde88fc 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -1202,6 +1202,7 @@ def StdC : StandardSpec<"stdc"> { [ // Types ClockT, StructTmType, + StructTimeSpec, TimeTType, ], [], // Enumerations -- GitLab From a62222f5f0bf30a5437255521df62750060a4bf4 Mon Sep 17 00:00:00 2001 From: Sterling Augustine Date: Wed, 13 Mar 2024 02:51:09 +0000 Subject: [PATCH 332/953] Update BUILD.bazel for 0ebf511ad011a83022edb171e044c98d9d16b1fa --- utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 5f6c43cd6af7..073353a89c89 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -595,6 +595,7 @@ libc_support_library( name = "__support_math_extras", hdrs = ["src/__support/math_extras.h"], deps = [ + ":__support_cpp_bit", ":__support_cpp_limits", ":__support_cpp_type_traits", ":__support_macros_attributes", -- GitLab From 5d7796e674224be54c48a8db981f4134845bcc7c Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Wed, 13 Mar 2024 11:20:38 +0800 Subject: [PATCH 333/953] [NFC] [C++20] [Modules] Refactor ReducedBMIGenerator Changes: - Don't lookup the emitting module from HeaderSearch. We will use the module from the ASTContext directly. - Remove some useless arguments. Let's addback in the future if required. --- clang/include/clang/Serialization/ASTWriter.h | 8 +++- clang/lib/Frontend/FrontendActions.cpp | 8 ++-- clang/lib/Serialization/GeneratePCH.cpp | 42 ++++++++++++------- 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index e5db486a71a4..3ed9803fa374 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -868,6 +868,8 @@ protected: return SemaPtr->getDiagnostics(); } + virtual Module *getEmittingModule(ASTContext &Ctx); + public: PCHGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache, StringRef OutputFile, StringRef isysroot, @@ -887,10 +889,12 @@ public: }; class ReducedBMIGenerator : public PCHGenerator { +protected: + virtual Module *getEmittingModule(ASTContext &Ctx) override; + public: ReducedBMIGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache, - StringRef OutputFile, std::shared_ptr Buffer, - bool IncludeTimestamps); + StringRef OutputFile); void HandleTranslationUnit(ASTContext &Ctx) override; }; diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 50338bfa670f..81fcd8d5ae9b 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -293,11 +293,9 @@ GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI, std::unique_ptr GenerateReducedModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - auto Buffer = std::make_shared(); - return std::make_unique( - CI.getPreprocessor(), CI.getModuleCache(), - CI.getFrontendOpts().OutputFile, Buffer, - /*IncludeTimestamps=*/+CI.getFrontendOpts().IncludeTimestamps); + return std::make_unique(CI.getPreprocessor(), + CI.getModuleCache(), + CI.getFrontendOpts().OutputFile); } bool GenerateHeaderUnitAction::BeginSourceFileAction(CompilerInstance &CI) { diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp index 2b511b2d5a90..f54db36d4a01 100644 --- a/clang/lib/Serialization/GeneratePCH.cpp +++ b/clang/lib/Serialization/GeneratePCH.cpp @@ -41,6 +41,21 @@ PCHGenerator::PCHGenerator( PCHGenerator::~PCHGenerator() { } +Module *PCHGenerator::getEmittingModule(ASTContext &) { + Module *M = nullptr; + + if (PP.getLangOpts().isCompilingModule()) { + M = PP.getHeaderSearchInfo().lookupModule(PP.getLangOpts().CurrentModule, + SourceLocation(), + /*AllowSearch*/ false); + if (!M) + assert(PP.getDiagnostics().hasErrorOccurred() && + "emitting module but current module doesn't exist"); + } + + return M; +} + void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { // Don't create a PCH if there were fatal failures during module loading. if (PP.getModuleLoader().HadFatalFailure) @@ -50,16 +65,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { if (hasErrors && !AllowASTWithErrors) return; - Module *Module = nullptr; - if (PP.getLangOpts().isCompilingModule()) { - Module = PP.getHeaderSearchInfo().lookupModule( - PP.getLangOpts().CurrentModule, SourceLocation(), - /*AllowSearch*/ false); - if (!Module) { - assert(hasErrors && "emitting module but current module doesn't exist"); - return; - } - } + Module *Module = getEmittingModule(Ctx); // Errors that do not prevent the PCH from being written should not cause the // overall compilation to fail either. @@ -84,16 +90,22 @@ ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() { ReducedBMIGenerator::ReducedBMIGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache, - StringRef OutputFile, - std::shared_ptr Buffer, - bool IncludeTimestamps) + StringRef OutputFile) : PCHGenerator( - PP, ModuleCache, OutputFile, llvm::StringRef(), Buffer, + PP, ModuleCache, OutputFile, llvm::StringRef(), + std::make_shared(), /*Extensions=*/ArrayRef>(), - /*AllowASTWithErrors*/ false, /*IncludeTimestamps=*/IncludeTimestamps, + /*AllowASTWithErrors*/ false, /*IncludeTimestamps=*/false, /*BuildingImplicitModule=*/false, /*ShouldCacheASTInMemory=*/false, /*GeneratingReducedBMI=*/true) {} +Module *ReducedBMIGenerator::getEmittingModule(ASTContext &Ctx) { + Module *M = Ctx.getCurrentNamedModule(); + assert(M->isNamedModuleUnit() && + "ReducedBMIGenerator should only be used with C++20 Named modules."); + return M; +} + void ReducedBMIGenerator::HandleTranslationUnit(ASTContext &Ctx) { PCHGenerator::HandleTranslationUnit(Ctx); -- GitLab From 15a55486a54183d4fc597ed86c0d49fe9482f2bd Mon Sep 17 00:00:00 2001 From: Michael Flanders Date: Tue, 12 Mar 2024 20:25:05 -0700 Subject: [PATCH 334/953] [libc][math] Adds entrypoint and test for `nextafterf128` (#84882) --- libc/config/linux/aarch64/entrypoints.txt | 1 + libc/config/linux/riscv/entrypoints.txt | 1 + libc/config/linux/x86_64/entrypoints.txt | 1 + libc/docs/math/index.rst | 2 ++ libc/spec/stdc.td | 1 + libc/src/math/CMakeLists.txt | 1 + libc/src/math/generic/CMakeLists.txt | 19 +++++++++++++++--- libc/src/math/generic/nextafterf128.cpp | 19 ++++++++++++++++++ libc/src/math/nextafterf128.h | 20 +++++++++++++++++++ libc/test/src/math/CMakeLists.txt | 15 ++++++++++++++ libc/test/src/math/nextafterf128_test.cpp | 13 ++++++++++++ libc/test/src/math/smoke/CMakeLists.txt | 15 ++++++++++++++ .../src/math/smoke/nextafterf128_test.cpp | 13 ++++++++++++ 13 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 libc/src/math/generic/nextafterf128.cpp create mode 100644 libc/src/math/nextafterf128.h create mode 100644 libc/test/src/math/nextafterf128_test.cpp create mode 100644 libc/test/src/math/smoke/nextafterf128_test.cpp diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 1656973cb27c..abd1f83794ed 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -438,6 +438,7 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.lrintf128 libc.src.math.lroundf128 libc.src.math.modff128 + libc.src.math.nextafterf128 libc.src.math.rintf128 libc.src.math.roundf128 libc.src.math.sqrtf128 diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 07d1acfcfe07..006aa787ea6a 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -446,6 +446,7 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.lrintf128 libc.src.math.lroundf128 libc.src.math.modff128 + libc.src.math.nextafterf128 libc.src.math.rintf128 libc.src.math.roundf128 libc.src.math.sqrtf128 diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index e0324061a9c7..4fb31c593b9d 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -481,6 +481,7 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.lrintf128 libc.src.math.lroundf128 libc.src.math.modff128 + libc.src.math.nextafterf128 libc.src.math.rintf128 libc.src.math.roundf128 libc.src.math.sqrtf128 diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst index 6984b785125f..ed54a7d091ec 100644 --- a/libc/docs/math/index.rst +++ b/libc/docs/math/index.rst @@ -271,6 +271,8 @@ Basic Operations +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | nextafterl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nextafterf128| |check| | |check| | | |check| | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | nexttoward | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | nexttowardf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index e8f73dde88fc..938d3722a0f8 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -530,6 +530,7 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"nextafterf", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"nextafter", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"nextafterl", RetValSpec, [ArgSpec, ArgSpec]>, + GuardedFunctionSpec<"nextafterf128", RetValSpec, [ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"nexttowardf", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"nexttoward", RetValSpec, [ArgSpec, ArgSpec]>, diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index bba02aa78a23..750fd5f0e3a9 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -198,6 +198,7 @@ add_math_entrypoint_object(nearbyintl) add_math_entrypoint_object(nextafter) add_math_entrypoint_object(nextafterf) add_math_entrypoint_object(nextafterl) +add_math_entrypoint_object(nextafterf128) add_math_entrypoint_object(nexttoward) add_math_entrypoint_object(nexttowardf) diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index bc4e9b34cfc2..667381d615d1 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -1789,7 +1789,7 @@ add_entrypoint_object( DEPENDS libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( @@ -1801,7 +1801,7 @@ add_entrypoint_object( DEPENDS libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( @@ -1813,7 +1813,20 @@ add_entrypoint_object( DEPENDS libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 +) + +add_entrypoint_object( + nextafterf128 + SRCS + nextafterf128.cpp + HDRS + ../nextafterf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 ) add_entrypoint_object( diff --git a/libc/src/math/generic/nextafterf128.cpp b/libc/src/math/generic/nextafterf128.cpp new file mode 100644 index 000000000000..905c89022ba1 --- /dev/null +++ b/libc/src/math/generic/nextafterf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of nextafterf128 function --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/math/nextafterf128.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, nextafterf128, (float128 x, float128 y)) { + return fputil::nextafter(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/nextafterf128.h b/libc/src/math/nextafterf128.h new file mode 100644 index 000000000000..a404d33810ec --- /dev/null +++ b/libc/src/math/nextafterf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for nextafterf128 ------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_MATH_NEXTAFTERF128_H +#define LLVM_LIBC_SRC_MATH_NEXTAFTERF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 nextafterf128(float128 x, float128 y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_NEXTAFTERF128_H diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt index b8a4aafcd97a..7b952901da76 100644 --- a/libc/test/src/math/CMakeLists.txt +++ b/libc/test/src/math/CMakeLists.txt @@ -1273,6 +1273,21 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + nextafterf128_test + SUITE + libc-math-unittests + SRCS + nextafterf128_test.cpp + HDRS + NextAfterTest.h + DEPENDS + libc.include.math + libc.src.math.nextafterf128 + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.fp_bits +) + # TODO(lntue): The current implementation of fputil::general::fma is only # correctly rounded for the default rounding mode round-to-nearest tie-to-even. add_fp_unittest( diff --git a/libc/test/src/math/nextafterf128_test.cpp b/libc/test/src/math/nextafterf128_test.cpp new file mode 100644 index 000000000000..a8d000ff4de3 --- /dev/null +++ b/libc/test/src/math/nextafterf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nextafterf128 ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "NextAfterTest.h" + +#include "src/math/nextafterf128.h" + +LIST_NEXTAFTER_TESTS(float128, LIBC_NAMESPACE::nextafterf128) diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index d9be172056a8..293e65abd44f 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -1551,6 +1551,21 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + nextafterf128_test + SUITE + libc-math-smoke-tests + SRCS + nextafterf128_test.cpp + HDRS + NextAfterTest.h + DEPENDS + libc.include.math + libc.src.math.nextafterf128 + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.fp_bits +) + # FIXME: These tests are currently spurious for the GPU. if(NOT LIBC_TARGET_OS_IS_GPU) add_fp_unittest( diff --git a/libc/test/src/math/smoke/nextafterf128_test.cpp b/libc/test/src/math/smoke/nextafterf128_test.cpp new file mode 100644 index 000000000000..a8d000ff4de3 --- /dev/null +++ b/libc/test/src/math/smoke/nextafterf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nextafterf128 ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "NextAfterTest.h" + +#include "src/math/nextafterf128.h" + +LIST_NEXTAFTER_TESTS(float128, LIBC_NAMESPACE::nextafterf128) -- GitLab From e4edbae0aa6a9739954ee3b494b18f8c599d9d79 Mon Sep 17 00:00:00 2001 From: Lu Weining Date: Wed, 13 Mar 2024 11:51:47 +0800 Subject: [PATCH 335/953] Revert "[llvm][LoongArch] Improve loongarch_lasx_xvpermi_q instrinsic" (#84708) Reverts llvm/llvm-project#82984 See the discussion in https://github.com/llvm/llvm-project/pull/83540. --- .../LoongArch/LoongArchISelLowering.cpp | 25 +--------------- .../CodeGen/LoongArch/lasx/intrinsic-permi.ll | 30 ------------------- 2 files changed, 1 insertion(+), 54 deletions(-) diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index c87f5341d7fe..c13b10a320f8 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -968,28 +968,6 @@ static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp, return SDValue(); } -static SDValue checkAndModifyXVPERMI_QIntrinsicImmArg(SDValue Op, - SelectionDAG &DAG) { - SDValue Op3 = Op->getOperand(3); - uint64_t Imm = Op3->getAsZExtVal(); - // Check the range of ImmArg. - if (!isUInt<8>(Imm)) { - DAG.getContext()->emitError(Op->getOperationName(0) + - ": argument out of range."); - return DAG.getNode(ISD::UNDEF, SDLoc(Op), Op.getValueType()); - } - - // For instruction xvpermi.q, only [1:0] and [5:4] bits of operands[3] - // are used. The unused bits in operands[3] need to be set to 0 to avoid - // causing undefined behavior on LA464. - if ((Imm & 0x33) != Imm) { - Op3 = DAG.getTargetConstant(Imm & 0x33, SDLoc(Op), Op3.getValueType()); - DAG.UpdateNodeOperands(Op.getNode(), Op->getOperand(0), Op->getOperand(1), - Op->getOperand(2), Op3); - } - return SDValue(); -} - SDValue LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const { @@ -1247,14 +1225,13 @@ LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, case Intrinsic::loongarch_lsx_vextrins_d: case Intrinsic::loongarch_lasx_xvshuf4i_d: case Intrinsic::loongarch_lasx_xvpermi_w: + case Intrinsic::loongarch_lasx_xvpermi_q: case Intrinsic::loongarch_lasx_xvbitseli_b: case Intrinsic::loongarch_lasx_xvextrins_b: case Intrinsic::loongarch_lasx_xvextrins_h: case Intrinsic::loongarch_lasx_xvextrins_w: case Intrinsic::loongarch_lasx_xvextrins_d: return checkIntrinsicImmArg<8>(Op, 3, DAG); - case Intrinsic::loongarch_lasx_xvpermi_q: - return checkAndModifyXVPERMI_QIntrinsicImmArg(Op, DAG); case Intrinsic::loongarch_lsx_vrepli_b: case Intrinsic::loongarch_lsx_vrepli_h: case Intrinsic::loongarch_lsx_vrepli_w: diff --git a/llvm/test/CodeGen/LoongArch/lasx/intrinsic-permi.ll b/llvm/test/CodeGen/LoongArch/lasx/intrinsic-permi.ll index 92669d2e5895..0d9f9daabc44 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/intrinsic-permi.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/intrinsic-permi.ll @@ -36,33 +36,3 @@ entry: %res = call <32 x i8> @llvm.loongarch.lasx.xvpermi.q(<32 x i8> %va, <32 x i8> %vb, i32 1) ret <32 x i8> %res } - -define <32 x i8> @lasx_xvpermi_q_204(<32 x i8> %va, <32 x i8> %vb) nounwind { -; CHECK-LABEL: lasx_xvpermi_q_204: -; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xvpermi.q $xr0, $xr1, 0 -; CHECK-NEXT: ret -entry: - %res = call <32 x i8> @llvm.loongarch.lasx.xvpermi.q(<32 x i8> %va, <32 x i8> %vb, i32 204) - ret <32 x i8> %res -} - -define <32 x i8> @lasx_xvpermi_q_221(<32 x i8> %va, <32 x i8> %vb) nounwind { -; CHECK-LABEL: lasx_xvpermi_q_221: -; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xvpermi.q $xr0, $xr1, 17 -; CHECK-NEXT: ret -entry: - %res = call <32 x i8> @llvm.loongarch.lasx.xvpermi.q(<32 x i8> %va, <32 x i8> %vb, i32 221) - ret <32 x i8> %res -} - -define <32 x i8> @lasx_xvpermi_q_255(<32 x i8> %va, <32 x i8> %vb) nounwind { -; CHECK-LABEL: lasx_xvpermi_q_255: -; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xvpermi.q $xr0, $xr1, 51 -; CHECK-NEXT: ret -entry: - %res = call <32 x i8> @llvm.loongarch.lasx.xvpermi.q(<32 x i8> %va, <32 x i8> %vb, i32 255) - ret <32 x i8> %res -} -- GitLab From 2dbaf265255a5fa9643a8092ec2dffa881d2cf93 Mon Sep 17 00:00:00 2001 From: Jeff Niu Date: Wed, 13 Mar 2024 00:12:37 -0400 Subject: [PATCH 336/953] [mlir][ods] Fix generation of optional custom parsers (#84821) We need to generate `.has_value` for `OptionalParseResult`, also ensure that `auto result` doesn't conflict with `result` which is the variable name for `OperationState`. --- mlir/test/IR/custom-print-parse.mlir | 5 +++++ mlir/test/IR/invalid-custom-print-parse.mlir | 5 +++++ mlir/test/lib/Dialect/Test/TestDialect.cpp | 17 +++++++++++++++++ mlir/test/lib/Dialect/Test/TestOps.td | 11 +++++++++++ mlir/test/mlir-tblgen/attr-or-type-format.td | 2 +- mlir/test/mlir-tblgen/op-format.td | 8 ++++---- mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp | 2 +- mlir/tools/mlir-tblgen/OpFormatGen.cpp | 8 ++++---- 8 files changed, 48 insertions(+), 10 deletions(-) diff --git a/mlir/test/IR/custom-print-parse.mlir b/mlir/test/IR/custom-print-parse.mlir index b157fd1b1ea3..0eadc2e42956 100644 --- a/mlir/test/IR/custom-print-parse.mlir +++ b/mlir/test/IR/custom-print-parse.mlir @@ -14,4 +14,9 @@ module @dimension_list { test.custom_dimension_list_attr dimension_list = ? // CHECK: test.custom_dimension_list_attr dimension_list = ?x? test.custom_dimension_list_attr dimension_list = ?x? + + // CHECK: test.optional_custom_attr + test.optional_custom_attr bar + // CHECK: test.optional_custom_attr foo false + test.optional_custom_attr foo false } diff --git a/mlir/test/IR/invalid-custom-print-parse.mlir b/mlir/test/IR/invalid-custom-print-parse.mlir index 456b16c91bc0..00da145e35e0 100644 --- a/mlir/test/IR/invalid-custom-print-parse.mlir +++ b/mlir/test/IR/invalid-custom-print-parse.mlir @@ -14,3 +14,8 @@ test.custom_dimension_list_attr dimension_list = -1 // expected-error@+2 {{expected ']'}} // expected-error@+1 {{custom op 'test.custom_dimension_list_attr' Failed parsing dimension list.}} test.custom_dimension_list_attr dimension_list = [2x3] + +// ----- + +// expected-error @below {{expected attribute value}} +test.optional_custom_attr foo diff --git a/mlir/test/lib/Dialect/Test/TestDialect.cpp b/mlir/test/lib/Dialect/Test/TestDialect.cpp index 1ee52fc08d77..380c74a47e50 100644 --- a/mlir/test/lib/Dialect/Test/TestDialect.cpp +++ b/mlir/test/lib/Dialect/Test/TestDialect.cpp @@ -499,6 +499,23 @@ void AffineScopeOp::print(OpAsmPrinter &p) { p.printRegion(getRegion(), /*printEntryBlockArgs=*/false); } +//===----------------------------------------------------------------------===// +// Test OptionalCustomAttrOp +//===----------------------------------------------------------------------===// + +static OptionalParseResult parseOptionalCustomParser(AsmParser &p, + IntegerAttr &result) { + if (succeeded(p.parseOptionalKeyword("foo"))) + return p.parseAttribute(result); + return {}; +} + +static void printOptionalCustomParser(AsmPrinter &p, Operation *, + IntegerAttr result) { + p << "foo "; + p.printAttribute(result); +} + //===----------------------------------------------------------------------===// // Test removing op with inner ops. //===----------------------------------------------------------------------===// diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td index dfd2f21a5ea2..e6c3601d08da 100644 --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -2048,6 +2048,17 @@ def CustomDimensionListAttrOp : TEST_Op<"custom_dimension_list_attr"> { }]; } +def OptionalCustomAttrOp : TEST_Op<"optional_custom_attr"> { + let description = [{ + Test using a custom directive as the optional group anchor and the first + element to parse. It is expected to return an `OptionalParseResult`. + }]; + let arguments = (ins OptionalAttr:$attr); + let assemblyFormat = [{ + attr-dict (custom($attr)^) : (`bar`)? + }]; +} + //===----------------------------------------------------------------------===// // Test OpAsmInterface. diff --git a/mlir/test/mlir-tblgen/attr-or-type-format.td b/mlir/test/mlir-tblgen/attr-or-type-format.td index b9041e45f856..2884c4ed6a90 100644 --- a/mlir/test/mlir-tblgen/attr-or-type-format.td +++ b/mlir/test/mlir-tblgen/attr-or-type-format.td @@ -648,7 +648,7 @@ def TypeN : TestType<"TestP"> { // TYPE-LABEL: TestQType::parse // TYPE: if (auto result = [&]() -> ::mlir::OptionalParseResult { // TYPE: auto odsCustomResult = parseAB(odsParser -// TYPE: if (!odsCustomResult) return {}; +// TYPE: if (!odsCustomResult.has_value()) return {}; // TYPE: if (::mlir::failed(*odsCustomResult)) return ::mlir::failure(); // TYPE: return ::mlir::success(); // TYPE: }(); result.has_value() && ::mlir::failed(*result)) { diff --git a/mlir/test/mlir-tblgen/op-format.td b/mlir/test/mlir-tblgen/op-format.td index 3250589605f3..4a19ffb3dfcc 100644 --- a/mlir/test/mlir-tblgen/op-format.td +++ b/mlir/test/mlir-tblgen/op-format.td @@ -93,14 +93,14 @@ def OptionalGroupC : TestFormat_Op<[{ }]>, Arguments<(ins DefaultValuedStrAttr:$a)>; // CHECK-LABEL: OptionalGroupD::parse -// CHECK: if (auto result = [&]() -> ::mlir::OptionalParseResult { +// CHECK: if (auto optResult = [&]() -> ::mlir::OptionalParseResult { // CHECK: auto odsResult = parseCustom(parser, aOperand, bOperand); -// CHECK: if (!odsResult) return {}; +// CHECK: if (!odsResult.has_value()) return {}; // CHECK: if (::mlir::failed(*odsResult)) return ::mlir::failure(); // CHECK: return ::mlir::success(); -// CHECK: }(); result.has_value() && ::mlir::failed(*result)) { +// CHECK: }(); optResult.has_value() && ::mlir::failed(*optResult)) { // CHECK: return ::mlir::failure(); -// CHECK: } else if (result.has_value()) { +// CHECK: } else if (optResult.has_value()) { // CHECK-LABEL: OptionalGroupD::print // CHECK-NEXT: if (((getA()) || (getB()))) { diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp index f8e0c83da3c8..6098808c646f 100644 --- a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp +++ b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp @@ -622,7 +622,7 @@ void DefFormat::genCustomParser(CustomDirective *el, FmtContext &ctx, } os.unindent() << ");\n"; if (isOptional) { - os << "if (!odsCustomResult) return {};\n"; + os << "if (!odsCustomResult.has_value()) return {};\n"; os << "if (::mlir::failed(*odsCustomResult)) return ::mlir::failure();\n"; } else { os << "if (::mlir::failed(odsCustomResult)) return {};\n"; diff --git a/mlir/tools/mlir-tblgen/OpFormatGen.cpp b/mlir/tools/mlir-tblgen/OpFormatGen.cpp index eb8c0aba1d33..1ffac059f198 100644 --- a/mlir/tools/mlir-tblgen/OpFormatGen.cpp +++ b/mlir/tools/mlir-tblgen/OpFormatGen.cpp @@ -1025,7 +1025,7 @@ static void genCustomDirectiveParser(CustomDirective *dir, MethodBody &body, body << ");\n"; if (isOptional) { - body << " if (!odsResult) return {};\n" + body << " if (!odsResult.has_value()) return {};\n" << " if (::mlir::failed(*odsResult)) return ::mlir::failure();\n"; } else { body << " if (odsResult) return ::mlir::failure();\n"; @@ -1285,13 +1285,13 @@ void OperationFormat::genElementParser(FormatElement *element, MethodBody &body, region->name); } } else if (auto *custom = dyn_cast(firstElement)) { - body << " if (auto result = [&]() -> ::mlir::OptionalParseResult {\n"; + body << " if (auto optResult = [&]() -> ::mlir::OptionalParseResult {\n"; genCustomDirectiveParser(custom, body, useProperties, opCppClassName, /*isOptional=*/true); body << " return ::mlir::success();\n" - << " }(); result.has_value() && ::mlir::failed(*result)) {\n" + << " }(); optResult.has_value() && ::mlir::failed(*optResult)) {\n" << " return ::mlir::failure();\n" - << " } else if (result.has_value()) {\n"; + << " } else if (optResult.has_value()) {\n"; } genElementParsers(firstElement, thenElements.drop_front(), -- GitLab From e25bf70d50cbf8bdebeacdaf3313486c1b1d0395 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Tue, 12 Mar 2024 21:26:58 -0700 Subject: [PATCH 337/953] [libc] Add an empty definition of mbstate_t (#84993) We expect to eventually provide a complete implementation, but having an empty definition is necessary to unblock the use of libc++ in embedded environments. See #84884 for more details. --- libc/config/baremetal/api.td | 4 ++++ libc/config/baremetal/arm/headers.txt | 1 + libc/config/baremetal/riscv/headers.txt | 1 + libc/include/CMakeLists.txt | 10 ++++++++++ libc/include/llvm-libc-types/CMakeLists.txt | 1 + libc/include/llvm-libc-types/mbstate_t.h | 16 ++++++++++++++++ libc/include/uchar.h.def | 16 ++++++++++++++++ libc/spec/spec.td | 2 ++ libc/spec/stdc.td | 12 ++++++++++++ 9 files changed, 63 insertions(+) create mode 100644 libc/include/llvm-libc-types/mbstate_t.h create mode 100644 libc/include/uchar.h.def diff --git a/libc/config/baremetal/api.td b/libc/config/baremetal/api.td index 33b3a03828e9..f096cdcbc9a3 100644 --- a/libc/config/baremetal/api.td +++ b/libc/config/baremetal/api.td @@ -66,3 +66,7 @@ def StdlibAPI : PublicAPI<"stdlib.h"> { def StringAPI : PublicAPI<"string.h"> { let Types = ["size_t"]; } + +def UCharAPI : PublicAPI<"uchar.h"> { + let Types = ["mbstate_t"]; +} diff --git a/libc/config/baremetal/arm/headers.txt b/libc/config/baremetal/arm/headers.txt index 68d7017fda80..962981f8a208 100644 --- a/libc/config/baremetal/arm/headers.txt +++ b/libc/config/baremetal/arm/headers.txt @@ -13,4 +13,5 @@ set(TARGET_PUBLIC_HEADERS libc.include.string libc.include.strings libc.include.sys_queue + libc.include.uchar ) diff --git a/libc/config/baremetal/riscv/headers.txt b/libc/config/baremetal/riscv/headers.txt index 68d7017fda80..962981f8a208 100644 --- a/libc/config/baremetal/riscv/headers.txt +++ b/libc/config/baremetal/riscv/headers.txt @@ -13,4 +13,5 @@ set(TARGET_PUBLIC_HEADERS libc.include.string libc.include.strings libc.include.sys_queue + libc.include.uchar ) diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt index 34d6839fd789..b2cb10459c53 100644 --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -582,6 +582,15 @@ add_gen_header( .llvm-libc-types.tcflag_t ) +add_gen_header( + uchar + DEF_FILE uchar.h.def + GEN_HDR uchar.h + DEPENDS + .llvm_libc_common_h + .llvm-libc-types.mbstate_t +) + add_gen_header( wchar DEF_FILE wchar.h.def @@ -589,6 +598,7 @@ add_gen_header( DEPENDS .llvm_libc_common_h .llvm-libc-macros.wchar_macros + .llvm-libc-types.mbstate_t .llvm-libc-types.size_t .llvm-libc-types.wint_t .llvm-libc-types.wchar_t diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt index e4f23b2a7813..7fef976d7b32 100644 --- a/libc/include/llvm-libc-types/CMakeLists.txt +++ b/libc/include/llvm-libc-types/CMakeLists.txt @@ -39,6 +39,7 @@ add_header(uid_t HDR uid_t.h) add_header(imaxdiv_t HDR imaxdiv_t.h) add_header(ino_t HDR ino_t.h) add_header(jmp_buf HDR jmp_buf.h) +add_header(mbstate_t HDR mbstate_t.h) add_header(mode_t HDR mode_t.h) add_header(mtx_t HDR mtx_t.h DEPENDS .__futex_word .__mutex_type) add_header(nlink_t HDR nlink_t.h) diff --git a/libc/include/llvm-libc-types/mbstate_t.h b/libc/include/llvm-libc-types/mbstate_t.h new file mode 100644 index 000000000000..540d50975a26 --- /dev/null +++ b/libc/include/llvm-libc-types/mbstate_t.h @@ -0,0 +1,16 @@ +//===-- Definition of mbstate_t type --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_TYPES_MBSTATE_T_H +#define LLVM_LIBC_TYPES_MBSTATE_T_H + +// TODO: Complete this once we implement functions that operate on this type. +typedef struct { +} mbstate_t; + +#endif // LLVM_LIBC_TYPES_MBSTATE_T_H diff --git a/libc/include/uchar.h.def b/libc/include/uchar.h.def new file mode 100644 index 000000000000..7e62d43e9cc4 --- /dev/null +++ b/libc/include/uchar.h.def @@ -0,0 +1,16 @@ +//===-- C standard library header uchar.h ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_UCHAR_H +#define LLVM_LIBC_UCHAR_H + +#include <__llvm-libc-common.h> + +%%public_api() + +#endif // LLVM_LIBC_UCHAR_H diff --git a/libc/spec/spec.td b/libc/spec/spec.td index 580bd9c8c3c1..87bf4435e167 100644 --- a/libc/spec/spec.td +++ b/libc/spec/spec.td @@ -153,6 +153,8 @@ def EntryType : NamedType<"ENTRY">; def EntryTypePtr : PtrType; def EntryTypePtrPtr : PtrType; +def MBStateTType : NamedType<"mbstate_t">; + class Macro { string Name = name; } diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index 938d3722a0f8..afe01b1bb685 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -1284,12 +1284,23 @@ def StdC : StandardSpec<"stdc"> { ] >; + HeaderSpec UChar = HeaderSpec< + "uchar.h", + [], // Macros + [ //Types + MBStateTType, + ], + [], // Enumerations + [] + >; + HeaderSpec WChar = HeaderSpec< "wchar.h", [ // Macros Macro<"WEOF">, ], [ //Types + MBStateTType, SizeTType, WIntType, WCharType, @@ -1324,6 +1335,7 @@ def StdC : StandardSpec<"stdc"> { Signal, Threads, Time, + UChar, WChar, ]; } -- GitLab From a0283987d07c2d4ce2cc5a4adaee0512f9553797 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Tue, 12 Mar 2024 21:33:49 -0700 Subject: [PATCH 338/953] [libc] Include additional baremetal entrypoints (#85020) These functions are usable on embedded platforms and are sometimes used in various baremetal projects. --- libc/config/baremetal/api.td | 1 + libc/config/baremetal/arm/entrypoints.txt | 45 +++++++++++++++++++++ libc/config/baremetal/riscv/entrypoints.txt | 44 ++++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/libc/config/baremetal/api.td b/libc/config/baremetal/api.td index f096cdcbc9a3..80d0e0ba22ca 100644 --- a/libc/config/baremetal/api.td +++ b/libc/config/baremetal/api.td @@ -2,6 +2,7 @@ include "config/public_api.td" include "spec/stdc.td" include "spec/stdc_ext.td" +include "spec/bsd_ext.td" include "spec/llvm_libc_stdfix_ext.td" def AssertMacro : MacroDef<"assert"> { diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt index 6e4fdb036264..589ec5237e98 100644 --- a/libc/config/baremetal/arm/entrypoints.txt +++ b/libc/config/baremetal/arm/entrypoints.txt @@ -30,6 +30,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.bcmp libc.src.string.bcopy libc.src.string.bzero + libc.src.string.index libc.src.string.memccpy libc.src.string.memchr libc.src.string.memcmp @@ -39,6 +40,8 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.mempcpy libc.src.string.memrchr libc.src.string.memset + libc.src.string.memset_explicit + libc.src.string.rindex libc.src.string.stpcpy libc.src.string.stpncpy libc.src.string.strcasecmp @@ -47,8 +50,11 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strchr libc.src.string.strchrnul libc.src.string.strcmp + libc.src.string.strcoll libc.src.string.strcpy libc.src.string.strcspn + libc.src.string.strerror + libc.src.string.strerror_r libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen @@ -59,10 +65,12 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strnlen libc.src.string.strpbrk libc.src.string.strrchr + libc.src.string.strsep libc.src.string.strspn libc.src.string.strstr libc.src.string.strtok libc.src.string.strtok_r + libc.src.string.strxfrm # inttypes.h entrypoints libc.src.inttypes.imaxabs @@ -117,6 +125,36 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdbit.stdc_first_trailing_one_ui libc.src.stdbit.stdc_first_trailing_one_ul libc.src.stdbit.stdc_first_trailing_one_ull + libc.src.stdbit.stdc_count_zeros_uc + libc.src.stdbit.stdc_count_zeros_us + libc.src.stdbit.stdc_count_zeros_ui + libc.src.stdbit.stdc_count_zeros_ul + libc.src.stdbit.stdc_count_zeros_ull + libc.src.stdbit.stdc_count_ones_uc + libc.src.stdbit.stdc_count_ones_us + libc.src.stdbit.stdc_count_ones_ui + libc.src.stdbit.stdc_count_ones_ul + libc.src.stdbit.stdc_count_ones_ull + libc.src.stdbit.stdc_has_single_bit_uc + libc.src.stdbit.stdc_has_single_bit_us + libc.src.stdbit.stdc_has_single_bit_ui + libc.src.stdbit.stdc_has_single_bit_ul + libc.src.stdbit.stdc_has_single_bit_ull + libc.src.stdbit.stdc_bit_width_uc + libc.src.stdbit.stdc_bit_width_us + libc.src.stdbit.stdc_bit_width_ui + libc.src.stdbit.stdc_bit_width_ul + libc.src.stdbit.stdc_bit_width_ull + libc.src.stdbit.stdc_bit_floor_uc + libc.src.stdbit.stdc_bit_floor_us + libc.src.stdbit.stdc_bit_floor_ui + libc.src.stdbit.stdc_bit_floor_ul + libc.src.stdbit.stdc_bit_floor_ull + libc.src.stdbit.stdc_bit_ceil_uc + libc.src.stdbit.stdc_bit_ceil_us + libc.src.stdbit.stdc_bit_ceil_ui + libc.src.stdbit.stdc_bit_ceil_ul + libc.src.stdbit.stdc_bit_ceil_ull # stdlib.h entrypoints libc.src.stdlib.abort @@ -132,6 +170,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdlib.llabs libc.src.stdlib.lldiv libc.src.stdlib.qsort + libc.src.stdlib.qsort_r + libc.src.stdlib.rand + libc.src.stdlib.srand libc.src.stdlib.strtod libc.src.stdlib.strtof libc.src.stdlib.strtol @@ -201,6 +242,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fminl libc.src.math.fmod libc.src.math.fmodf + libc.src.math.fmodl libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl @@ -212,6 +254,9 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.ldexp libc.src.math.ldexpf libc.src.math.ldexpl + libc.src.math.llogb + libc.src.math.llogbf + libc.src.math.llogbl libc.src.math.llrint libc.src.math.llrintf libc.src.math.llrintl diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt index 6e4fdb036264..09de1b416e0e 100644 --- a/libc/config/baremetal/riscv/entrypoints.txt +++ b/libc/config/baremetal/riscv/entrypoints.txt @@ -30,6 +30,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.bcmp libc.src.string.bcopy libc.src.string.bzero + libc.src.string.index libc.src.string.memccpy libc.src.string.memchr libc.src.string.memcmp @@ -39,6 +40,8 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.mempcpy libc.src.string.memrchr libc.src.string.memset + libc.src.string.memset_explicit + libc.src.string.rindex libc.src.string.stpcpy libc.src.string.stpncpy libc.src.string.strcasecmp @@ -47,8 +50,11 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strchr libc.src.string.strchrnul libc.src.string.strcmp + libc.src.string.strcoll libc.src.string.strcpy libc.src.string.strcspn + libc.src.string.strerror + libc.src.string.strerror_r libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen @@ -59,10 +65,12 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strnlen libc.src.string.strpbrk libc.src.string.strrchr + libc.src.string.strsep libc.src.string.strspn libc.src.string.strstr libc.src.string.strtok libc.src.string.strtok_r + libc.src.string.strxfrm # inttypes.h entrypoints libc.src.inttypes.imaxabs @@ -117,6 +125,36 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdbit.stdc_first_trailing_one_ui libc.src.stdbit.stdc_first_trailing_one_ul libc.src.stdbit.stdc_first_trailing_one_ull + libc.src.stdbit.stdc_count_zeros_uc + libc.src.stdbit.stdc_count_zeros_us + libc.src.stdbit.stdc_count_zeros_ui + libc.src.stdbit.stdc_count_zeros_ul + libc.src.stdbit.stdc_count_zeros_ull + libc.src.stdbit.stdc_count_ones_uc + libc.src.stdbit.stdc_count_ones_us + libc.src.stdbit.stdc_count_ones_ui + libc.src.stdbit.stdc_count_ones_ul + libc.src.stdbit.stdc_count_ones_ull + libc.src.stdbit.stdc_has_single_bit_uc + libc.src.stdbit.stdc_has_single_bit_us + libc.src.stdbit.stdc_has_single_bit_ui + libc.src.stdbit.stdc_has_single_bit_ul + libc.src.stdbit.stdc_has_single_bit_ull + libc.src.stdbit.stdc_bit_width_uc + libc.src.stdbit.stdc_bit_width_us + libc.src.stdbit.stdc_bit_width_ui + libc.src.stdbit.stdc_bit_width_ul + libc.src.stdbit.stdc_bit_width_ull + libc.src.stdbit.stdc_bit_floor_uc + libc.src.stdbit.stdc_bit_floor_us + libc.src.stdbit.stdc_bit_floor_ui + libc.src.stdbit.stdc_bit_floor_ul + libc.src.stdbit.stdc_bit_floor_ull + libc.src.stdbit.stdc_bit_ceil_uc + libc.src.stdbit.stdc_bit_ceil_us + libc.src.stdbit.stdc_bit_ceil_ui + libc.src.stdbit.stdc_bit_ceil_ul + libc.src.stdbit.stdc_bit_ceil_ull # stdlib.h entrypoints libc.src.stdlib.abort @@ -132,6 +170,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdlib.llabs libc.src.stdlib.lldiv libc.src.stdlib.qsort + libc.src.stdlib.qsort_r + libc.src.stdlib.rand + libc.src.stdlib.srand libc.src.stdlib.strtod libc.src.stdlib.strtof libc.src.stdlib.strtol @@ -212,6 +253,9 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.ldexp libc.src.math.ldexpf libc.src.math.ldexpl + libc.src.math.llogb + libc.src.math.llogbf + libc.src.math.llogbl libc.src.math.llrint libc.src.math.llrintf libc.src.math.llrintl -- GitLab From deebf6b312227e028dd3258b162306b9cdb21cf7 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Tue, 12 Mar 2024 22:21:15 -0700 Subject: [PATCH 339/953] [tsan] Disabled test dead locking on glibc-2.38 https://github.com/google/sanitizers/issues/1733 --- compiler-rt/test/lit.common.cfg.py | 2 +- compiler-rt/test/tsan/getline_nohang.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py index ae28681915af..bd9b926c1505 100644 --- a/compiler-rt/test/lit.common.cfg.py +++ b/compiler-rt/test/lit.common.cfg.py @@ -632,7 +632,7 @@ if config.host_os == "Linux": ver = LooseVersion(ver_string) any_glibc = False - for required in ["2.19", "2.27", "2.30", "2.33", "2.34", "2.37"]: + for required in ["2.19", "2.27", "2.30", "2.33", "2.34", "2.37", "2.38"]: if ver >= LooseVersion(required): config.available_features.add("glibc-" + required) any_glibc = True diff --git a/compiler-rt/test/tsan/getline_nohang.cpp b/compiler-rt/test/tsan/getline_nohang.cpp index d1bb279a450f..c0762da96abb 100644 --- a/compiler-rt/test/tsan/getline_nohang.cpp +++ b/compiler-rt/test/tsan/getline_nohang.cpp @@ -5,6 +5,10 @@ // Make sure TSan doesn't deadlock on a file stream lock at program shutdown. // See https://github.com/google/sanitizers/issues/454 + +// https://github.com/google/sanitizers/issues/1733 +// UNSUPPORTED: glibc-2.38 + #ifdef __FreeBSD__ #define _WITH_GETLINE // to declare getline() #endif -- GitLab From 53613044ddf1bab186cde8d687f7f41bc0b1f9b1 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 12 Mar 2024 22:28:32 -0700 Subject: [PATCH 340/953] [llvm-objcopy] Use SmallVector to make some structs smaller. NFC --- llvm/include/llvm/ObjCopy/CommonConfig.h | 17 ++++++++--------- llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/llvm/include/llvm/ObjCopy/CommonConfig.h b/llvm/include/llvm/ObjCopy/CommonConfig.h index 383395941475..3f894b0cd958 100644 --- a/llvm/include/llvm/ObjCopy/CommonConfig.h +++ b/llvm/include/llvm/ObjCopy/CommonConfig.h @@ -22,7 +22,6 @@ // Necessary for llvm::DebugCompressionType::None #include "llvm/Target/TargetOptions.h" #include -#include namespace llvm { namespace objcopy { @@ -126,8 +125,8 @@ public: // provided for that option. class NameMatcher { DenseSet PosNames; - std::vector PosPatterns; - std::vector NegMatchers; + SmallVector PosPatterns; + SmallVector NegMatchers; public: Error addMatcher(Expected Matcher) { @@ -179,8 +178,8 @@ struct NewSymbolInfo { StringRef SymbolName; StringRef SectionName; uint64_t Value = 0; - std::vector Flags; - std::vector BeforeSyms; + SmallVector Flags; + SmallVector BeforeSyms; }; // Specify section name and section body for newly added or updated section. @@ -218,9 +217,9 @@ struct CommonConfig { DiscardType DiscardMode = DiscardType::None; // Repeated options - std::vector AddSection; - std::vector DumpSection; - std::vector UpdateSection; + SmallVector AddSection; + SmallVector DumpSection; + SmallVector UpdateSection; // Section matchers NameMatcher KeepSection; @@ -244,7 +243,7 @@ struct CommonConfig { StringMap SymbolsToRename; // Symbol info specified by --add-symbol option. - std::vector SymbolsToAdd; + SmallVector SymbolsToAdd; // Boolean options bool DeterministicArchives = true; diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp index 6318578b1100..c5c7cc254d79 100644 --- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp +++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp @@ -528,7 +528,7 @@ static Expected parseNewSymbolInfo(StringRef FlagValue) { // ArgValue, loads data from the file, and stores section name and data // into the vector of new sections \p NewSections. static Error loadNewSectionData(StringRef ArgValue, StringRef OptionName, - std::vector &NewSections) { + SmallVector &NewSections) { if (!ArgValue.contains('=')) return createStringError(errc::invalid_argument, "bad format for " + OptionName + ": missing '='"); -- GitLab From 0d98582c8b86644e77f8ddd68fc251e41127b7f4 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 12 Mar 2024 22:31:06 -0700 Subject: [PATCH 341/953] [llvm-objcopy] Remove unneeded #include. NFC --- llvm/include/llvm/ObjCopy/CommonConfig.h | 3 +-- llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/ObjCopy/CommonConfig.h b/llvm/include/llvm/ObjCopy/CommonConfig.h index 3f894b0cd958..8f69c9fbeaf5 100644 --- a/llvm/include/llvm/ObjCopy/CommonConfig.h +++ b/llvm/include/llvm/ObjCopy/CommonConfig.h @@ -16,11 +16,10 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Object/ELFTypes.h" +#include "llvm/Support/Compression.h" #include "llvm/Support/GlobPattern.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Regex.h" -// Necessary for llvm::DebugCompressionType::None -#include "llvm/Target/TargetOptions.h" #include namespace llvm { diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp index c5c7cc254d79..a0c6415bf0e6 100644 --- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp +++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp @@ -10,6 +10,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/ObjCopy/CommonConfig.h" #include "llvm/ObjCopy/ConfigManager.h" -- GitLab From 4d62929852849f768d7397f634cfdebc85de96a4 Mon Sep 17 00:00:00 2001 From: Chuanqi Xu Date: Wed, 13 Mar 2024 13:48:32 +0800 Subject: [PATCH 342/953] [C++20] [Modules] Disambuguous Clang module and C++20 Named module further This patch tries to make the boundary of clang module and C++20 named module more clear. The changes included: - Rename `TranslationUnitKind::TU_Module` to `TranslationUnitKind::TU_ClangModule`. - Rename `Sema::ActOnModuleInclude` to `Sema::ActOnAnnotModuleInclude`. - Rename `ActOnModuleBegin` to `Sema::ActOnAnnotModuleBegin`. - Rename `Sema::ActOnModuleEnd` to `Sema::ActOnAnnotModuleEnd`. - Removes a warning if we're trying to compile a non-module unit as C++20 module unit. This is not actually useful and makes (the future) implementation unnecessarily complex. This patch meant to be a NFC fix. But it shows that it fixed a bug suprisingly that previously we would surppress the unused-value warning in named modules. Because it shares the same logic with clang modules, which has headers semantics. This shows the change is meaningful. --- .../clang/Basic/DiagnosticSemaKinds.td | 2 - clang/include/clang/Basic/LangOptions.h | 9 +-- .../include/clang/Frontend/FrontendActions.h | 8 ++- clang/include/clang/Sema/Sema.h | 6 +- clang/lib/Parse/Parser.cpp | 30 ++++----- clang/lib/Sema/Sema.cpp | 63 ++++++++----------- clang/lib/Sema/SemaModule.cpp | 10 +-- .../dcl.module/dcl.module.interface/p1.cppm | 4 -- .../Modules/missing-module-declaration.cppm | 13 ---- clang/test/Modules/pr72828.cppm | 2 +- 10 files changed, 58 insertions(+), 89 deletions(-) delete mode 100644 clang/test/Modules/missing-module-declaration.cppm diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c54105507753..d7ab1635cf12 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11516,8 +11516,6 @@ def err_module_not_defined : Error< def err_module_redeclaration : Error< "translation unit contains multiple module declarations">; def note_prev_module_declaration : Note<"previous module declaration is here">; -def err_module_declaration_missing : Error< - "missing 'export module' declaration in module interface unit">; def err_module_declaration_missing_after_global_module_introducer : Error< "missing 'module' declaration at end of global module fragment " "introduced here">; diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 862952d336ef..08fc706e3cbf 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -560,11 +560,6 @@ public: return getCompilingModule() != CMK_None; } - /// Are we compiling a standard c++ module interface? - bool isCompilingModuleInterface() const { - return getCompilingModule() == CMK_ModuleInterface; - } - /// Are we compiling a module implementation? bool isCompilingModuleImplementation() const { return !isCompilingModule() && !ModuleName.empty(); @@ -993,8 +988,8 @@ enum TranslationUnitKind { /// not complete. TU_Prefix, - /// The translation unit is a module. - TU_Module, + /// The translation unit is a clang module. + TU_ClangModule, /// The translation unit is a is a complete translation unit that we might /// incrementally extend later. diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h index 8441af2ee3e7..a620ddfc4044 100644 --- a/clang/include/clang/Frontend/FrontendActions.h +++ b/clang/include/clang/Frontend/FrontendActions.h @@ -125,7 +125,7 @@ protected: StringRef InFile) override; TranslationUnitKind getTranslationUnitKind() override { - return TU_Module; + return TU_ClangModule; } bool hasASTFileSupport() const override { return false; } @@ -138,7 +138,9 @@ protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override; - TranslationUnitKind getTranslationUnitKind() override { return TU_Module; } + TranslationUnitKind getTranslationUnitKind() override { + return TU_ClangModule; + } bool hasASTFileSupport() const override { return false; } }; @@ -159,6 +161,8 @@ protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override; + TranslationUnitKind getTranslationUnitKind() override { return TU_Complete; } + std::unique_ptr CreateOutputFile(CompilerInstance &CI, StringRef InFile) override; }; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b226851f0303..d6ab2b0c2def 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8064,13 +8064,13 @@ public: /// The parser has processed a module import translated from a /// #include or similar preprocessing directive. - void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod); + void ActOnAnnotModuleInclude(SourceLocation DirectiveLoc, Module *Mod); void BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod); /// The parsed has entered a submodule. - void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod); + void ActOnAnnotModuleBegin(SourceLocation DirectiveLoc, Module *Mod); /// The parser has left a submodule. - void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod); + void ActOnAnnotModuleEnd(SourceLocation DirectiveLoc, Module *Mod); /// Create an implicit import of the given module at the given /// source location, for error recovery, if possible. diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 1701d153bd0e..cc0e41ed221c 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -685,7 +685,7 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result, // FIXME: We need a better way to disambiguate C++ clang modules and // standard C++ modules. if (!getLangOpts().CPlusPlusModules || !Mod->isHeaderUnit()) - Actions.ActOnModuleInclude(Loc, Mod); + Actions.ActOnAnnotModuleInclude(Loc, Mod); else { DeclResult Import = Actions.ActOnModuleImport(Loc, SourceLocation(), Loc, Mod); @@ -697,15 +697,17 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result, } case tok::annot_module_begin: - Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast( - Tok.getAnnotationValue())); + Actions.ActOnAnnotModuleBegin( + Tok.getLocation(), + reinterpret_cast(Tok.getAnnotationValue())); ConsumeAnnotationToken(); ImportState = Sema::ModuleImportState::NotACXX20Module; return false; case tok::annot_module_end: - Actions.ActOnModuleEnd(Tok.getLocation(), reinterpret_cast( - Tok.getAnnotationValue())); + Actions.ActOnAnnotModuleEnd( + Tok.getLocation(), + reinterpret_cast(Tok.getAnnotationValue())); ConsumeAnnotationToken(); ImportState = Sema::ModuleImportState::NotACXX20Module; return false; @@ -2708,9 +2710,9 @@ bool Parser::parseMisplacedModuleImport() { // happens. if (MisplacedModuleBeginCount) { --MisplacedModuleBeginCount; - Actions.ActOnModuleEnd(Tok.getLocation(), - reinterpret_cast( - Tok.getAnnotationValue())); + Actions.ActOnAnnotModuleEnd( + Tok.getLocation(), + reinterpret_cast(Tok.getAnnotationValue())); ConsumeAnnotationToken(); continue; } @@ -2720,18 +2722,18 @@ bool Parser::parseMisplacedModuleImport() { return true; case tok::annot_module_begin: // Recover by entering the module (Sema will diagnose). - Actions.ActOnModuleBegin(Tok.getLocation(), - reinterpret_cast( - Tok.getAnnotationValue())); + Actions.ActOnAnnotModuleBegin( + Tok.getLocation(), + reinterpret_cast(Tok.getAnnotationValue())); ConsumeAnnotationToken(); ++MisplacedModuleBeginCount; continue; case tok::annot_module_include: // Module import found where it should not be, for instance, inside a // namespace. Recover by importing the module. - Actions.ActOnModuleInclude(Tok.getLocation(), - reinterpret_cast( - Tok.getAnnotationValue())); + Actions.ActOnAnnotModuleInclude( + Tok.getLocation(), + reinterpret_cast(Tok.getAnnotationValue())); ConsumeAnnotationToken(); // If there is another module import, process it. continue; diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 720d5fd5f042..cd0c42d5ffba 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1207,26 +1207,35 @@ void Sema::ActOnEndOfTranslationUnit() { } // A global-module-fragment is only permitted within a module unit. - bool DiagnosedMissingModuleDeclaration = false; if (!ModuleScopes.empty() && ModuleScopes.back().Module->Kind == Module::ExplicitGlobalModuleFragment) { Diag(ModuleScopes.back().BeginLoc, diag::err_module_declaration_missing_after_global_module_introducer); - DiagnosedMissingModuleDeclaration = true; - } - - if (TUKind == TU_Module) { - // If we are building a module interface unit, we need to have seen the - // module declaration by now. - if (getLangOpts().getCompilingModule() == - LangOptions::CMK_ModuleInterface && - !isCurrentModulePurview() && !DiagnosedMissingModuleDeclaration) { - // FIXME: Make a better guess as to where to put the module declaration. - Diag(getSourceManager().getLocForStartOfFile( - getSourceManager().getMainFileID()), - diag::err_module_declaration_missing); - } + } + + // Now we can decide whether the modules we're building need an initializer. + if (Module *CurrentModule = getCurrentModule(); + CurrentModule && CurrentModule->isInterfaceOrPartition()) { + auto DoesModNeedInit = [this](Module *M) { + if (!getASTContext().getModuleInitializers(M).empty()) + return true; + for (auto [Exported, _] : M->Exports) + if (Exported->isNamedModuleInterfaceHasInit()) + return true; + for (Module *I : M->Imports) + if (I->isNamedModuleInterfaceHasInit()) + return true; + + return false; + }; + CurrentModule->NamedModuleHasInit = + DoesModNeedInit(CurrentModule) || + llvm::any_of(CurrentModule->submodules(), + [&](auto *SubM) { return DoesModNeedInit(SubM); }); + } + + if (TUKind == TU_ClangModule) { // If we are building a module, resolve all of the exported declarations // now. if (Module *CurrentModule = PP.getCurrentModule()) { @@ -1251,28 +1260,6 @@ void Sema::ActOnEndOfTranslationUnit() { } } - // Now we can decide whether the modules we're building need an initializer. - if (Module *CurrentModule = getCurrentModule(); - CurrentModule && CurrentModule->isInterfaceOrPartition()) { - auto DoesModNeedInit = [this](Module *M) { - if (!getASTContext().getModuleInitializers(M).empty()) - return true; - for (auto [Exported, _] : M->Exports) - if (Exported->isNamedModuleInterfaceHasInit()) - return true; - for (Module *I : M->Imports) - if (I->isNamedModuleInterfaceHasInit()) - return true; - - return false; - }; - - CurrentModule->NamedModuleHasInit = - DoesModNeedInit(CurrentModule) || - llvm::any_of(CurrentModule->submodules(), - [&](auto *SubM) { return DoesModNeedInit(SubM); }); - } - // Warnings emitted in ActOnEndOfTranslationUnit() should be emitted for // modules when they are built, not every time they are used. emitAndClearUnusedLocalTypedefWarnings(); @@ -1358,7 +1345,7 @@ void Sema::ActOnEndOfTranslationUnit() { // noise. Don't warn for a use from a module: either we should warn on all // file-scope declarations in modules or not at all, but whether the // declaration is used is immaterial. - if (!Diags.hasErrorOccurred() && TUKind != TU_Module) { + if (!Diags.hasErrorOccurred() && TUKind != TU_ClangModule) { // Output warning for unused file scoped decls. for (UnusedFileScopedDeclsType::iterator I = UnusedFileScopedDecls.begin(ExternalSource.get()), diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index f08c1cb3a13e..2ddf9d70263a 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -713,7 +713,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, return Import; } -void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { +void Sema::ActOnAnnotModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true); BuildModuleInclude(DirectiveLoc, Mod); } @@ -723,9 +723,9 @@ void Sema::BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { // in that buffer do not qualify as module imports; they're just an // implementation detail of us building the module. // - // FIXME: Should we even get ActOnModuleInclude calls for those? + // FIXME: Should we even get ActOnAnnotModuleInclude calls for those? bool IsInModuleIncludes = - TUKind == TU_Module && + TUKind == TU_ClangModule && getSourceManager().isWrittenInMainFile(DirectiveLoc); // If we are really importing a module (not just checking layering) due to an @@ -752,7 +752,7 @@ void Sema::BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { } } -void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) { +void Sema::ActOnAnnotModuleBegin(SourceLocation DirectiveLoc, Module *Mod) { checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true); ModuleScopes.push_back({}); @@ -776,7 +776,7 @@ void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) { } } -void Sema::ActOnModuleEnd(SourceLocation EomLoc, Module *Mod) { +void Sema::ActOnAnnotModuleEnd(SourceLocation EomLoc, Module *Mod) { if (getLangOpts().ModulesLocalVisibility) { VisibleModules = std::move(ModuleScopes.back().OuterVisibleModules); // Leaving a module hides namespace names, so our visible namespace cache diff --git a/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.interface/p1.cppm b/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.interface/p1.cppm index 3072b760f9d7..1a01ffac0154 100644 --- a/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.interface/p1.cppm +++ b/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.interface/p1.cppm @@ -15,10 +15,6 @@ module A; // #module-decl // expected-error@-2 {{missing 'export' specifier in module declaration while building module interface}} #define INTERFACE #endif -#else - #ifdef BUILT_AS_INTERFACE - // expected-error@1 {{missing 'export module' declaration in module interface unit}} - #endif #endif #ifndef INTERFACE diff --git a/clang/test/Modules/missing-module-declaration.cppm b/clang/test/Modules/missing-module-declaration.cppm deleted file mode 100644 index d52f6639fe4f..000000000000 --- a/clang/test/Modules/missing-module-declaration.cppm +++ /dev/null @@ -1,13 +0,0 @@ -// RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: cd %t -// -// RUN: %clang_cc1 -std=c++20 %t/B.cppm -I%t -emit-module-interface -o %t/B.pcm -// RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -fprebuilt-module-path=%t -emit-module-interface -verify - -//--- A.cppm -import B; // expected-error{{missing 'export module' declaration in module interface unit}} - -//--- B.cppm -module; -export module B; diff --git a/clang/test/Modules/pr72828.cppm b/clang/test/Modules/pr72828.cppm index 574523188507..7432f2831f24 100644 --- a/clang/test/Modules/pr72828.cppm +++ b/clang/test/Modules/pr72828.cppm @@ -17,7 +17,7 @@ struct s { void f() { auto [x] = s(); - [x] {}; + (void) [x] {}; } // Check that we can generate the LLVM IR expectedly. -- GitLab From fe1d02b08ce2ca74de5b18d9f141d503b7985ec5 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 12 Mar 2024 23:09:36 -0700 Subject: [PATCH 343/953] [sanitizer] Reject unsupported -static at link time (#83524) Most sanitizers don't support static linking. One primary reason is the incompatibility with interceptors. `GetTlsSize` is another reason. asan/memprof use `__interception::DoesNotSupportStaticLinking` (`_DYNAMIC` reference) to reject -static at link time. Port this detector to other sanitizers. dfsan actually supports -static for certain cases. Don't touch dfsan. --- compiler-rt/lib/hwasan/hwasan_interceptors.cpp | 1 + compiler-rt/lib/lsan/lsan_interceptors.cpp | 1 + compiler-rt/lib/msan/msan_interceptors.cpp | 2 ++ compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp | 2 ++ compiler-rt/test/sanitizer_common/TestCases/Linux/static-link.c | 2 ++ 5 files changed, 8 insertions(+) create mode 100644 compiler-rt/test/sanitizer_common/TestCases/Linux/static-link.c diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp index 96df4dd0c24d..d519ac3a459b 100644 --- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp @@ -520,6 +520,7 @@ void InitializeInterceptors() { CHECK_EQ(inited, 0); # if HWASAN_WITH_INTERCEPTORS + __interception::DoesNotSupportStaticLinking(); InitializeCommonInterceptors(); (void)(read_iovec); diff --git a/compiler-rt/lib/lsan/lsan_interceptors.cpp b/compiler-rt/lib/lsan/lsan_interceptors.cpp index 885f7ad5ddba..1fd0010f9ea9 100644 --- a/compiler-rt/lib/lsan/lsan_interceptors.cpp +++ b/compiler-rt/lib/lsan/lsan_interceptors.cpp @@ -543,6 +543,7 @@ namespace __lsan { void InitializeInterceptors() { // Fuchsia doesn't use interceptors that require any setup. #if !SANITIZER_FUCHSIA + __interception::DoesNotSupportStaticLinking(); InitializeSignalInterceptors(); INTERCEPT_FUNCTION(malloc); diff --git a/compiler-rt/lib/msan/msan_interceptors.cpp b/compiler-rt/lib/msan/msan_interceptors.cpp index 2c9f2c01e14b..6e0b2bf2ef5b 100644 --- a/compiler-rt/lib/msan/msan_interceptors.cpp +++ b/compiler-rt/lib/msan/msan_interceptors.cpp @@ -1762,6 +1762,8 @@ void InitializeInterceptors() { static int inited = 0; CHECK_EQ(inited, 0); + __interception::DoesNotSupportStaticLinking(); + new(interceptor_ctx()) InterceptorContext(); InitializeCommonInterceptors(); diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp index 24309ab66b2e..8ffc703b05ea 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -2861,6 +2861,8 @@ void InitializeInterceptors() { REAL(memcpy) = internal_memcpy; #endif + __interception::DoesNotSupportStaticLinking(); + new(interceptor_ctx()) InterceptorContext(); // Interpose __tls_get_addr before the common interposers. This is needed diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/static-link.c b/compiler-rt/test/sanitizer_common/TestCases/Linux/static-link.c new file mode 100644 index 000000000000..f45f718cb08d --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/static-link.c @@ -0,0 +1,2 @@ +// UNSUPPORTED: hwasan, ubsan +// RUN: not %clangxx -static %s -o /dev/null -- GitLab From cd2f6163137dce45d909aa445cfd57b7188f8ed1 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 13 Mar 2024 12:42:15 +0530 Subject: [PATCH 344/953] AMDGPU: Use list-table for metadata table (#85024) The table syntax for sphinx is really insufferably whitespace dependent. I've been meaning to convert the existing attribute and intrinsic tables to use list-table, which is less painful to merge. --- llvm/docs/AMDGPUUsage.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst index 99d7a482710f..fd9ad7fac19a 100644 --- a/llvm/docs/AMDGPUUsage.rst +++ b/llvm/docs/AMDGPUUsage.rst @@ -1317,15 +1317,16 @@ LLVM IR Metadata The AMDGPU backend implements the following LLVM IR metadata. -.. table:: AMDGPU LLVM IR Metadata +.. list-table:: AMDGPU LLVM IR Metatdata :name: amdgpu-llvm-ir-metadata-table - ============================================== ========================================================== - LLVM IR Metadata Description - ============================================== ========================================================== - !amdgpu.last.use Sets TH_LOAD_LU temporal hint on load instructions that support it. - Takes priority over nontemporal hint (TH_LOAD_NT). - ============================================== ========================================================== + * - Metadata Name + - Description + - Values + * - !amdgpu.last.use + - Sets TH_LOAD_LU temporal hint on load instructions that support it. + Takes priority over nontemporal hint (TH_LOAD_NT). + - {} LLVM IR Attributes ------------------ -- GitLab From 0a443f13b49b3f392461a0bb60b0146cfc4607c7 Mon Sep 17 00:00:00 2001 From: Vyacheslav Levytskyy Date: Wed, 13 Mar 2024 08:32:01 +0100 Subject: [PATCH 345/953] [SPIR-V] Add implementation of G_SPLAT_VECTOR opcode and fix invalid types processing (#84766) This PR: * adds support for G_SPLAT_VECTOR generic opcode that may be legally generated instead of G_BUILD_VECTOR by previous passes of the translator (see https://github.com/llvm/llvm-project/pull/80378 for the source of breaking changes); * improves deduction of types for opaque pointers. This PR also fixes the following issues: * if a function has ptr argument(s), two functions that have different SPIR-V type definitions may get identical LLVM function types and break agreements of global register and duplicate checker; * checks for pointer types do not account for TypedPointerType. Update of tests: * A test case is added to cover the issue with function ptr parameters. * The first case, that is support for G_SPLAT_VECTOR generic opcode, is covered by existing test cases. * Multiple additional checks by `spirv-val` is added to cover more possibilities of generation of invalid code. --- llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp | 49 ++++++- llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 136 +++++++++++++----- llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 32 +++-- llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h | 3 +- .../Target/SPIRV/SPIRVInstructionSelector.cpp | 41 ++++++ llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp | 4 +- llvm/lib/Target/SPIRV/SPIRVUtils.h | 26 ++++ llvm/test/CodeGen/SPIRV/ComparePointers.ll | 1 + llvm/test/CodeGen/SPIRV/capability-kernel.ll | 1 + .../pointers/getelementptr-addressspace.ll | 1 + .../SPIRV/pointers/getelementptr-base-type.ll | 1 + .../kernel-argument-pointer-addressspace.ll | 1 + ...er-type-deduction-no-bitcast-to-generic.ll | 1 + .../pointers/kernel-argument-pointer-type.ll | 1 + .../SPIRV/pointers/load-addressspace.ll | 1 + .../pointers/store-operand-ptr-to-struct.ll | 1 + .../SPIRV/pointers/struct-opaque-pointers.ll | 2 +- .../pointers/two-bitcast-or-param-users.ll | 1 + .../SPIRV/pointers/two-subsequent-bitcasts.ll | 1 + .../SPIRV/pointers/type-deduce-by-call-rev.ll | 28 ++++ .../SPIRV/pointers/type-deduce-by-call.ll | 28 ++++ .../CodeGen/SPIRV/pointers/typeof-ptr-int.ll | 29 ++++ llvm/test/CodeGen/SPIRV/relationals.ll | 1 + llvm/test/CodeGen/SPIRV/simple.ll | 1 + .../AtomicCompareExchangeExplicit_cl20.ll | 1 + .../SPIRV/transcoding/BitReversePref.ll | 1 + .../CodeGen/SPIRV/transcoding/BuildNDRange.ll | 1 + .../SPIRV/transcoding/BuildNDRange_2.ll | 1 + .../CodeGen/SPIRV/transcoding/ConvertPtr.ll | 1 + .../SPIRV/transcoding/DecorationAlignment.ll | 1 + .../transcoding/DecorationMaxByteOffset.ll | 1 + llvm/test/CodeGen/SPIRV/transcoding/DivRem.ll | 1 + .../ExecutionMode_SPIR_to_SPIRV.ll | 1 + .../SPIRV/transcoding/GlobalFunAnnotate.ll | 1 + .../transcoding/OpenCL/atomic_cmpxchg.ll | 1 + .../SPIRV/transcoding/OpenCL/atomic_legacy.ll | 1 + .../OpenCL/atomic_work_item_fence.ll | 1 + .../SPIRV/transcoding/OpenCL/barrier.ll | 1 + .../transcoding/OpenCL/sub_group_mask.ll | 1 + .../transcoding/OpenCL/work_group_barrier.ll | 1 + .../CodeGen/SPIRV/transcoding/atomic_flag.ll | 1 + .../SPIRV/transcoding/atomic_load_store.ll | 1 + .../test/CodeGen/SPIRV/transcoding/bitcast.ll | 1 + .../transcoding/block_w_struct_return.ll | 1 + .../SPIRV/transcoding/builtin_calls.ll | 1 + .../CodeGen/SPIRV/transcoding/builtin_vars.ll | 1 + .../transcoding/builtin_vars_arithmetics.ll | 1 + .../SPIRV/transcoding/builtin_vars_opt.ll | 1 + .../SPIRV/transcoding/check_ro_qualifier.ll | 1 + .../CodeGen/SPIRV/transcoding/cl-types.ll | 1 + .../CodeGen/SPIRV/transcoding/clk_event_t.ll | 1 + .../SPIRV/transcoding/enqueue_kernel.ll | 1 + .../SPIRV/transcoding/explicit-conversions.ll | 1 + .../SPIRV/transcoding/extract_insert_value.ll | 1 + llvm/test/CodeGen/SPIRV/transcoding/fadd.ll | 1 + llvm/test/CodeGen/SPIRV/transcoding/fclamp.ll | 1 + llvm/test/CodeGen/SPIRV/transcoding/fcmp.ll | 1 + llvm/test/CodeGen/SPIRV/transcoding/fdiv.ll | 1 + llvm/test/CodeGen/SPIRV/transcoding/fmod.ll | 1 + llvm/test/CodeGen/SPIRV/transcoding/fmul.ll | 1 + llvm/test/CodeGen/SPIRV/transcoding/fneg.ll | 1 + .../fp_contract_reassoc_fast_mode.ll | 1 + llvm/test/CodeGen/SPIRV/transcoding/frem.ll | 1 + llvm/test/CodeGen/SPIRV/transcoding/fsub.ll | 1 + .../transcoding/get_image_num_mip_levels.ll | 1 + .../CodeGen/SPIRV/transcoding/global_block.ll | 1 + .../CodeGen/SPIRV/transcoding/group_ops.ll | 1 + .../test/CodeGen/SPIRV/transcoding/isequal.ll | 1 + .../SPIRV/transcoding/relationals_double.ll | 1 + .../SPIRV/transcoding/relationals_float.ll | 1 + .../SPIRV/transcoding/relationals_half.ll | 1 + 71 files changed, 382 insertions(+), 56 deletions(-) create mode 100644 llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-rev.ll create mode 100644 llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call.ll create mode 100644 llvm/test/CodeGen/SPIRV/pointers/typeof-ptr-int.ll diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp index 2d7a00bab38e..f1fbe2ba1bc4 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp @@ -85,6 +85,42 @@ static ConstantInt *getConstInt(MDNode *MD, unsigned NumOp) { return nullptr; } +// If the function has pointer arguments, we are forced to re-create this +// function type from the very beginning, changing PointerType by +// TypedPointerType for each pointer argument. Otherwise, the same `Type*` +// potentially corresponds to different SPIR-V function type, effectively +// invalidating logic behind global registry and duplicates tracker. +static FunctionType * +fixFunctionTypeIfPtrArgs(SPIRVGlobalRegistry *GR, const Function &F, + FunctionType *FTy, const SPIRVType *SRetTy, + const SmallVector &SArgTys) { + if (F.getParent()->getNamedMetadata("spv.cloned_funcs")) + return FTy; + + bool hasArgPtrs = false; + for (auto &Arg : F.args()) { + // check if it's an instance of a non-typed PointerType + if (Arg.getType()->isPointerTy()) { + hasArgPtrs = true; + break; + } + } + if (!hasArgPtrs) { + Type *RetTy = FTy->getReturnType(); + // check if it's an instance of a non-typed PointerType + if (!RetTy->isPointerTy()) + return FTy; + } + + // re-create function type, using TypedPointerType instead of PointerType to + // properly trace argument types + const Type *RetTy = GR->getTypeForSPIRVType(SRetTy); + SmallVector ArgTys; + for (auto SArgTy : SArgTys) + ArgTys.push_back(const_cast(GR->getTypeForSPIRVType(SArgTy))); + return FunctionType::get(const_cast(RetTy), ArgTys, false); +} + // This code restores function args/retvalue types for composite cases // because the final types should still be aggregate whereas they're i32 // during the translation to cope with aggregate flattening etc. @@ -162,7 +198,7 @@ static SPIRVType *getArgSPIRVType(const Function &F, unsigned ArgIdx, // If OriginalArgType is non-pointer, use the OriginalArgType (the type cannot // be legally reassigned later). - if (!OriginalArgType->isPointerTy()) + if (!isPointerTy(OriginalArgType)) return GR->getOrCreateSPIRVType(OriginalArgType, MIRBuilder, ArgAccessQual); // In case OriginalArgType is of pointer type, there are three possibilities: @@ -179,8 +215,7 @@ static SPIRVType *getArgSPIRVType(const Function &F, unsigned ArgIdx, SPIRVType *ElementType = GR->getOrCreateSPIRVType(ByValRefType, MIRBuilder); return GR->getOrCreateSPIRVPointerType( ElementType, MIRBuilder, - addressSpaceToStorageClass(Arg->getType()->getPointerAddressSpace(), - ST)); + addressSpaceToStorageClass(getPointerAddressSpace(Arg->getType()), ST)); } for (auto User : Arg->users()) { @@ -240,7 +275,6 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, static_cast(&MIRBuilder.getMF().getSubtarget()); // Assign types and names to all args, and store their types for later. - FunctionType *FTy = getOriginalFunctionType(F); SmallVector ArgTypeVRegs; if (VRegs.size() > 0) { unsigned i = 0; @@ -255,7 +289,7 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, if (Arg.hasName()) buildOpName(VRegs[i][0], Arg.getName(), MIRBuilder); - if (Arg.getType()->isPointerTy()) { + if (isPointerTy(Arg.getType())) { auto DerefBytes = static_cast(Arg.getDereferenceableBytes()); if (DerefBytes != 0) buildOpDecorate(VRegs[i][0], MIRBuilder, @@ -322,7 +356,9 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, MRI->setRegClass(FuncVReg, &SPIRV::IDRegClass); if (F.isDeclaration()) GR->add(&F, &MIRBuilder.getMF(), FuncVReg); + FunctionType *FTy = getOriginalFunctionType(F); SPIRVType *RetTy = GR->getOrCreateSPIRVType(FTy->getReturnType(), MIRBuilder); + FTy = fixFunctionTypeIfPtrArgs(GR, F, FTy, RetTy, ArgTypeVRegs); SPIRVType *FuncTy = GR->getOrCreateOpTypeFunctionWithArgs( FTy, RetTy, ArgTypeVRegs, MIRBuilder); uint32_t FuncControl = getFunctionControl(F); @@ -429,7 +465,6 @@ bool SPIRVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, return false; MachineFunction &MF = MIRBuilder.getMF(); GR->setCurrentFunc(MF); - FunctionType *FTy = nullptr; const Function *CF = nullptr; std::string DemangledName; const Type *OrigRetTy = Info.OrigRet.Ty; @@ -444,7 +479,7 @@ bool SPIRVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, // TODO: support constexpr casts and indirect calls. if (CF == nullptr) return false; - if ((FTy = getOriginalFunctionType(*CF)) != nullptr) + if (FunctionType *FTy = getOriginalFunctionType(*CF)) OrigRetTy = FTy->getReturnType(); } diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index 575e903d05bb..c5b901235402 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -57,8 +57,14 @@ class SPIRVEmitIntrinsics bool TrackConstants = true; DenseMap AggrConsts; DenseSet AggrStores; + + // deduce values type + DenseMap DeducedElTys; + Type *deduceElementType(Value *I); + void preprocessCompositeConstants(IRBuilder<> &B); void preprocessUndefs(IRBuilder<> &B); + CallInst *buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef Types, Value *Arg, Value *Arg2, ArrayRef Imms, IRBuilder<> &B) { @@ -72,6 +78,7 @@ class SPIRVEmitIntrinsics Args.push_back(Imm); return B.CreateIntrinsic(IntrID, {Types}, Args); } + void replaceMemInstrUses(Instruction *Old, Instruction *New, IRBuilder<> &B); void processInstrAfterVisit(Instruction *I, IRBuilder<> &B); void insertAssignPtrTypeIntrs(Instruction *I, IRBuilder<> &B); @@ -156,6 +163,48 @@ static inline void reportFatalOnTokenType(const Instruction *I) { false); } +// Deduce and return a successfully deduced Type of the Instruction, +// or nullptr otherwise. +static Type *deduceElementTypeHelper(Value *I, + std::unordered_set &Visited, + DenseMap &DeducedElTys) { + // maybe already known + auto It = DeducedElTys.find(I); + if (It != DeducedElTys.end()) + return It->second; + + // maybe a cycle + if (Visited.find(I) != Visited.end()) + return nullptr; + Visited.insert(I); + + // fallback value in case when we fail to deduce a type + Type *Ty = nullptr; + // look for known basic patterns of type inference + if (auto *Ref = dyn_cast(I)) + Ty = Ref->getAllocatedType(); + else if (auto *Ref = dyn_cast(I)) + Ty = Ref->getResultElementType(); + else if (auto *Ref = dyn_cast(I)) + Ty = Ref->getValueType(); + else if (auto *Ref = dyn_cast(I)) + Ty = deduceElementTypeHelper(Ref->getPointerOperand(), Visited, + DeducedElTys); + + // remember the found relationship + if (Ty) + DeducedElTys[I] = Ty; + + return Ty; +} + +Type *SPIRVEmitIntrinsics::deduceElementType(Value *I) { + std::unordered_set Visited; + if (Type *Ty = deduceElementTypeHelper(I, Visited, DeducedElTys)) + return Ty; + return IntegerType::getInt8Ty(I->getContext()); +} + void SPIRVEmitIntrinsics::replaceMemInstrUses(Instruction *Old, Instruction *New, IRBuilder<> &B) { @@ -280,7 +329,7 @@ Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) { // varying element types. In case of IR coming from older versions of LLVM // such bitcasts do not provide sufficient information, should be just skipped // here, and handled in insertPtrCastOrAssignTypeInstr. - if (I.getType()->isPointerTy()) { + if (isPointerTy(I.getType())) { I.replaceAllUsesWith(Source); I.eraseFromParent(); return nullptr; @@ -333,20 +382,10 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast( while (BitCastInst *BC = dyn_cast(Pointer)) Pointer = BC->getOperand(0); - // Do not emit spv_ptrcast if Pointer is a GlobalValue of expected type. - GlobalValue *GV = dyn_cast(Pointer); - if (GV && GV->getValueType() == ExpectedElementType) - return; - - // Do not emit spv_ptrcast if Pointer is a result of alloca with expected - // type. - AllocaInst *A = dyn_cast(Pointer); - if (A && A->getAllocatedType() == ExpectedElementType) - return; - - // Do not emit spv_ptrcast if Pointer is a result of GEP of expected type. - GetElementPtrInst *GEPI = dyn_cast(Pointer); - if (GEPI && GEPI->getResultElementType() == ExpectedElementType) + // Do not emit spv_ptrcast if Pointer's element type is ExpectedElementType + std::unordered_set Visited; + Type *PointerElemTy = deduceElementTypeHelper(Pointer, Visited, DeducedElTys); + if (PointerElemTy == ExpectedElementType) return; setInsertPointSkippingPhis(B, I); @@ -356,7 +395,7 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast( ValueAsMetadata::getConstant(ExpectedElementTypeConst); MDTuple *TyMD = MDNode::get(F->getContext(), CM); MetadataAsValue *VMD = MetadataAsValue::get(F->getContext(), TyMD); - unsigned AddressSpace = Pointer->getType()->getPointerAddressSpace(); + unsigned AddressSpace = getPointerAddressSpace(Pointer->getType()); bool FirstPtrCastOrAssignPtrType = true; // Do not emit new spv_ptrcast if equivalent one already exists or when @@ -401,9 +440,11 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast( // spv_assign_ptr_type instead. if (FirstPtrCastOrAssignPtrType && (isa(Pointer) || isa(Pointer))) { - buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {Pointer->getType()}, - ExpectedElementTypeConst, Pointer, - {B.getInt32(AddressSpace)}, B); + CallInst *CI = buildIntrWithMD( + Intrinsic::spv_assign_ptr_type, {Pointer->getType()}, + ExpectedElementTypeConst, Pointer, {B.getInt32(AddressSpace)}, B); + DeducedElTys[CI] = ExpectedElementType; + DeducedElTys[Pointer] = ExpectedElementType; return; } @@ -419,7 +460,7 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I, // Handle basic instructions: StoreInst *SI = dyn_cast(I); if (SI && F->getCallingConv() == CallingConv::SPIR_KERNEL && - SI->getValueOperand()->getType()->isPointerTy() && + isPointerTy(SI->getValueOperand()->getType()) && isa(SI->getValueOperand())) { return replacePointerOperandWithPtrCast( I, SI->getValueOperand(), IntegerType::getInt8Ty(F->getContext()), 0, @@ -440,9 +481,34 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I, if (!CI || CI->isIndirectCall() || CI->getCalledFunction()->isIntrinsic()) return; + // collect information about formal parameter types + Function *CalledF = CI->getCalledFunction(); + SmallVector CalledArgTys; + bool HaveTypes = false; + for (auto &CalledArg : CalledF->args()) { + if (!isPointerTy(CalledArg.getType())) { + CalledArgTys.push_back(nullptr); + continue; + } + auto It = DeducedElTys.find(&CalledArg); + Type *ParamTy = It != DeducedElTys.end() ? It->second : nullptr; + if (!ParamTy) { + for (User *U : CalledArg.users()) { + if (Instruction *Inst = dyn_cast(U)) { + std::unordered_set Visited; + ParamTy = deduceElementTypeHelper(Inst, Visited, DeducedElTys); + if (ParamTy) + break; + } + } + } + HaveTypes |= ParamTy != nullptr; + CalledArgTys.push_back(ParamTy); + } + std::string DemangledName = getOclOrSpirvBuiltinDemangledName(CI->getCalledFunction()->getName()); - if (DemangledName.empty()) + if (DemangledName.empty() && !HaveTypes) return; for (unsigned OpIdx = 0; OpIdx < CI->arg_size(); OpIdx++) { @@ -455,8 +521,11 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I, if (!isa(ArgOperand) && !isa(ArgOperand)) continue; - Type *ExpectedType = SPIRV::parseBuiltinCallArgumentBaseType( - DemangledName, OpIdx, I->getContext()); + Type *ExpectedType = + OpIdx < CalledArgTys.size() ? CalledArgTys[OpIdx] : nullptr; + if (!ExpectedType && !DemangledName.empty()) + ExpectedType = SPIRV::parseBuiltinCallArgumentBaseType( + DemangledName, OpIdx, I->getContext()); if (!ExpectedType) continue; @@ -639,30 +708,25 @@ void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV, void SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I, IRBuilder<> &B) { reportFatalOnTokenType(I); - if (!I->getType()->isPointerTy() || !requireAssignType(I) || + if (!isPointerTy(I->getType()) || !requireAssignType(I) || isa(I)) return; setInsertPointSkippingPhis(B, I->getNextNode()); - Constant *EltTyConst; - unsigned AddressSpace = I->getType()->getPointerAddressSpace(); - if (auto *AI = dyn_cast(I)) - EltTyConst = UndefValue::get(AI->getAllocatedType()); - else if (auto *GEP = dyn_cast(I)) - EltTyConst = UndefValue::get(GEP->getResultElementType()); - else - EltTyConst = UndefValue::get(IntegerType::getInt8Ty(I->getContext())); - - buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {I->getType()}, EltTyConst, I, - {B.getInt32(AddressSpace)}, B); + Type *ElemTy = deduceElementType(I); + Constant *EltTyConst = UndefValue::get(ElemTy); + unsigned AddressSpace = getPointerAddressSpace(I->getType()); + CallInst *CI = buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {I->getType()}, + EltTyConst, I, {B.getInt32(AddressSpace)}, B); + DeducedElTys[CI] = ElemTy; } void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I, IRBuilder<> &B) { reportFatalOnTokenType(I); Type *Ty = I->getType(); - if (!Ty->isVoidTy() && !Ty->isPointerTy() && requireAssignType(I)) { + if (!Ty->isVoidTy() && !isPointerTy(Ty) && requireAssignType(I)) { setInsertPointSkippingPhis(B, I->getNextNode()); Type *TypeToAssign = Ty; if (auto *II = dyn_cast(I)) { diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp index 8556581996fe..bda9c57e534c 100644 --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp @@ -750,7 +750,7 @@ SPIRVType *SPIRVGlobalRegistry::createSPIRVType( SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType( const Type *Ty, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) { - if (TypesInProcessing.count(Ty) && !Ty->isPointerTy()) + if (TypesInProcessing.count(Ty) && !isPointerTy(Ty)) return nullptr; TypesInProcessing.insert(Ty); SPIRVType *SpirvType = createSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR); @@ -762,11 +762,15 @@ SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType( // will be added later. For special types it is already added to DT. if (SpirvType->getOpcode() != SPIRV::OpTypeForwardPointer && !Reg.isValid() && !isSpecialOpaqueType(Ty)) { - if (!Ty->isPointerTy()) + if (!isPointerTy(Ty)) DT.add(Ty, &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType)); + else if (isTypedPointerTy(Ty)) + DT.add(cast(Ty)->getElementType(), + getPointerAddressSpace(Ty), &MIRBuilder.getMF(), + getSPIRVTypeID(SpirvType)); else DT.add(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()), - Ty->getPointerAddressSpace(), &MIRBuilder.getMF(), + getPointerAddressSpace(Ty), &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType)); } @@ -787,12 +791,15 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType( const Type *Ty, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) { Register Reg; - if (!Ty->isPointerTy()) + if (!isPointerTy(Ty)) Reg = DT.find(Ty, &MIRBuilder.getMF()); + else if (isTypedPointerTy(Ty)) + Reg = DT.find(cast(Ty)->getElementType(), + getPointerAddressSpace(Ty), &MIRBuilder.getMF()); else Reg = DT.find(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()), - Ty->getPointerAddressSpace(), &MIRBuilder.getMF()); + getPointerAddressSpace(Ty), &MIRBuilder.getMF()); if (Reg.isValid() && !isSpecialOpaqueType(Ty)) return getSPIRVTypeForVReg(Reg); @@ -836,11 +843,16 @@ bool SPIRVGlobalRegistry::isScalarOrVectorOfType(Register VReg, unsigned SPIRVGlobalRegistry::getScalarOrVectorComponentCount(Register VReg) const { - if (SPIRVType *Type = getSPIRVTypeForVReg(VReg)) - return Type->getOpcode() == SPIRV::OpTypeVector - ? static_cast(Type->getOperand(2).getImm()) - : 1; - return 0; + return getScalarOrVectorComponentCount(getSPIRVTypeForVReg(VReg)); +} + +unsigned +SPIRVGlobalRegistry::getScalarOrVectorComponentCount(SPIRVType *Type) const { + if (!Type) + return 0; + return Type->getOpcode() == SPIRV::OpTypeVector + ? static_cast(Type->getOperand(2).getImm()) + : 1; } unsigned diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h index 9c0061d13fd0..25d82ebf9bc7 100644 --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h @@ -198,9 +198,10 @@ public: // opcode (e.g. OpTypeBool, or OpTypeVector %x 4, where %x is OpTypeBool). bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const; - // Return number of elements in a vector if the given VReg is associated with + // Return number of elements in a vector if the argument is associated with // a vector type. Return 1 for a scalar type, and 0 for a missing type. unsigned getScalarOrVectorComponentCount(Register VReg) const; + unsigned getScalarOrVectorComponentCount(SPIRVType *Type) const; // For vectors or scalars of booleans, integers and floats, return the scalar // type's bitwidth. Otherwise calls llvm_unreachable(). diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 74df8de6eb90..fd19b7412c4c 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -125,6 +125,8 @@ private: bool selectConstVector(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const; + bool selectSplatVector(Register ResVReg, const SPIRVType *ResType, + MachineInstr &I) const; bool selectCmp(Register ResVReg, const SPIRVType *ResType, unsigned comparisonOpcode, MachineInstr &I) const; @@ -313,6 +315,8 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg, case TargetOpcode::G_BUILD_VECTOR: return selectConstVector(ResVReg, ResType, I); + case TargetOpcode::G_SPLAT_VECTOR: + return selectSplatVector(ResVReg, ResType, I); case TargetOpcode::G_SHUFFLE_VECTOR: { MachineBasicBlock &BB = *I.getParent(); @@ -1185,6 +1189,43 @@ bool SPIRVInstructionSelector::selectConstVector(Register ResVReg, return MIB.constrainAllUses(TII, TRI, RBI); } +bool SPIRVInstructionSelector::selectSplatVector(Register ResVReg, + const SPIRVType *ResType, + MachineInstr &I) const { + if (ResType->getOpcode() != SPIRV::OpTypeVector) + report_fatal_error("Cannot select G_SPLAT_VECTOR with a non-vector result"); + unsigned N = GR.getScalarOrVectorComponentCount(ResType); + unsigned OpIdx = I.getNumExplicitDefs(); + if (!I.getOperand(OpIdx).isReg()) + report_fatal_error("Unexpected argument in G_SPLAT_VECTOR"); + + // check if we may construct a constant vector + Register OpReg = I.getOperand(OpIdx).getReg(); + bool IsConst = false; + if (SPIRVType *OpDef = MRI->getVRegDef(OpReg)) { + if (OpDef->getOpcode() == SPIRV::ASSIGN_TYPE && + OpDef->getOperand(1).isReg()) { + if (SPIRVType *RefDef = MRI->getVRegDef(OpDef->getOperand(1).getReg())) + OpDef = RefDef; + } + IsConst = OpDef->getOpcode() == TargetOpcode::G_CONSTANT || + OpDef->getOpcode() == TargetOpcode::G_FCONSTANT; + } + + if (!IsConst && N < 2) + report_fatal_error( + "There must be at least two constituent operands in a vector"); + + auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), + TII.get(IsConst ? SPIRV::OpConstantComposite + : SPIRV::OpCompositeConstruct)) + .addDef(ResVReg) + .addUse(GR.getSPIRVTypeID(ResType)); + for (unsigned i = 0; i < N; ++i) + MIB.addUse(OpReg); + return MIB.constrainAllUses(TII, TRI, RBI); +} + bool SPIRVInstructionSelector::selectCmp(Register ResVReg, const SPIRVType *ResType, unsigned CmpOpc, diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp index f81548742a11..4b871bdd5d07 100644 --- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp @@ -149,7 +149,9 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) { getActionDefinitionsBuilder(G_GLOBAL_VALUE).alwaysLegal(); // TODO: add proper rules for vectors legalization. - getActionDefinitionsBuilder({G_BUILD_VECTOR, G_SHUFFLE_VECTOR}).alwaysLegal(); + getActionDefinitionsBuilder( + {G_BUILD_VECTOR, G_SHUFFLE_VECTOR, G_SPLAT_VECTOR}) + .alwaysLegal(); // Vector Reduction Operations getActionDefinitionsBuilder( diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h index e5f35aaca9a8..d5ed501def99 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.h +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h @@ -15,6 +15,7 @@ #include "MCTargetDesc/SPIRVBaseInfo.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/TypedPointerType.h" #include namespace llvm { @@ -100,5 +101,30 @@ bool isEntryPoint(const Function &F); // Parse basic scalar type name, substring TypeName, and return LLVM type. Type *parseBasicTypeName(StringRef TypeName, LLVMContext &Ctx); + +// True if this is an instance of TypedPointerType. +inline bool isTypedPointerTy(const Type *T) { + return T->getTypeID() == Type::TypedPointerTyID; +} + +// True if this is an instance of PointerType. +inline bool isUntypedPointerTy(const Type *T) { + return T->getTypeID() == Type::PointerTyID; +} + +// True if this is an instance of PointerType or TypedPointerType. +inline bool isPointerTy(const Type *T) { + return isUntypedPointerTy(T) || isTypedPointerTy(T); +} + +// Get the address space of this pointer or pointer vector type for instances of +// PointerType or TypedPointerType. +inline unsigned getPointerAddressSpace(const Type *T) { + Type *SubT = T->getScalarType(); + return SubT->getTypeID() == Type::PointerTyID + ? cast(SubT)->getAddressSpace() + : cast(SubT)->getAddressSpace(); +} + } // namespace llvm #endif // LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H diff --git a/llvm/test/CodeGen/SPIRV/ComparePointers.ll b/llvm/test/CodeGen/SPIRV/ComparePointers.ll index fd2084dbc260..9be05944789b 100644 --- a/llvm/test/CodeGen/SPIRV/ComparePointers.ll +++ b/llvm/test/CodeGen/SPIRV/ComparePointers.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --mattr=+spirv1.3 %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; kernel void test(int global *in, int global *in2) { ;; if (!in) diff --git a/llvm/test/CodeGen/SPIRV/capability-kernel.ll b/llvm/test/CodeGen/SPIRV/capability-kernel.ll index 03ea58c985ad..fea19511d4fd 100644 --- a/llvm/test/CodeGen/SPIRV/capability-kernel.ll +++ b/llvm/test/CodeGen/SPIRV/capability-kernel.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: OpCapability Addresses diff --git a/llvm/test/CodeGen/SPIRV/pointers/getelementptr-addressspace.ll b/llvm/test/CodeGen/SPIRV/pointers/getelementptr-addressspace.ll index 062863a0e3ad..7e9c6214c281 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/getelementptr-addressspace.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/getelementptr-addressspace.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK: %[[#INT8:]] = OpTypeInt 8 0 ; CHECK: %[[#PTR1:]] = OpTypePointer CrossWorkgroup %[[#INT8]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/getelementptr-base-type.ll b/llvm/test/CodeGen/SPIRV/pointers/getelementptr-base-type.ll index aaf97f8cc836..fc999ba1a3cd 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/getelementptr-base-type.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/getelementptr-base-type.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK: %[[#FLOAT32:]] = OpTypeFloat 32 ; CHECK: %[[#PTR:]] = OpTypePointer CrossWorkgroup %[[#FLOAT32]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll index 6d1202328197..a3a730ac67e7 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: %[[#INT:]] = OpTypeInt 32 0 ; CHECK-DAG: %[[#PTR1:]] = OpTypePointer Function %[[#INT]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-bitcast-to-generic.ll b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-bitcast-to-generic.ll index 9e136ce88746..b74a3449980d 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-bitcast-to-generic.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-bitcast-to-generic.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: %[[#IMAGE:]] = OpTypeImage %2 2D 0 0 0 0 Unknown ReadOnly diff --git a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type.ll b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type.ll index 1fcc6d9da9c7..b8f205a68e56 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: %[[#FLOAT32:]] = OpTypeFloat 32 ; CHECK-DAG: %[[#PTR1:]] = OpTypePointer Function %[[#FLOAT32]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/load-addressspace.ll b/llvm/test/CodeGen/SPIRV/pointers/load-addressspace.ll index 1b4e7a3e733f..1667abc51be9 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/load-addressspace.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/load-addressspace.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK: %[[#INT8:]] = OpTypeInt 8 0 ; CHECK: %[[#PTR1:]] = OpTypePointer CrossWorkgroup %[[#INT8]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/store-operand-ptr-to-struct.ll b/llvm/test/CodeGen/SPIRV/pointers/store-operand-ptr-to-struct.ll index 00b03c08e7bb..3a0d65e1e95f 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/store-operand-ptr-to-struct.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/store-operand-ptr-to-struct.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; TODO: OpFunctionParameter should be a pointer of struct base type. ; XFAIL: * diff --git a/llvm/test/CodeGen/SPIRV/pointers/struct-opaque-pointers.ll b/llvm/test/CodeGen/SPIRV/pointers/struct-opaque-pointers.ll index 86f5f5bf24f5..d426fc4dfd4e 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/struct-opaque-pointers.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/struct-opaque-pointers.ll @@ -1,5 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s -; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK: %[[TyInt8:.*]] = OpTypeInt 8 0 ; CHECK: %[[TyInt8Ptr:.*]] = OpTypePointer {{[a-zA-Z]+}} %[[TyInt8]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/two-bitcast-or-param-users.ll b/llvm/test/CodeGen/SPIRV/pointers/two-bitcast-or-param-users.ll index 52180d537408..23c3faaf8815 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/two-bitcast-or-param-users.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/two-bitcast-or-param-users.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: %[[#INT:]] = OpTypeInt 32 ; CHECK-DAG: %[[#GLOBAL_PTR_INT:]] = OpTypePointer CrossWorkgroup %[[#INT]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/two-subsequent-bitcasts.ll b/llvm/test/CodeGen/SPIRV/pointers/two-subsequent-bitcasts.ll index 473c2a8b7311..83234e3986c8 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/two-subsequent-bitcasts.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/two-subsequent-bitcasts.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: %[[#float:]] = OpTypeFloat 32 ; CHECK-DAG: %[[#pointer:]] = OpTypePointer CrossWorkgroup %[[#float]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-rev.ll b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-rev.ll new file mode 100644 index 000000000000..76769ab87430 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-rev.ll @@ -0,0 +1,28 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV-DAG: OpName %[[FooArg:.*]] "known_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Foo:.*]] "foo" +; CHECK-SPIRV-DAG: OpName %[[ArgToDeduce:.*]] "unknown_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Bar:.*]] "bar" +; CHECK-SPIRV-DAG: %[[Long:.*]] = OpTypeInt 32 0 +; CHECK-SPIRV-DAG: %[[Void:.*]] = OpTypeVoid +; CHECK-SPIRV-DAG: %[[LongPtr:.*]] = OpTypePointer CrossWorkgroup %[[Long]] +; CHECK-SPIRV-DAG: %[[Fun:.*]] = OpTypeFunction %[[Void]] %[[LongPtr]] +; CHECK-SPIRV: %[[Bar]] = OpFunction %[[Void]] None %[[Fun]] +; CHECK-SPIRV: %[[ArgToDeduce]] = OpFunctionParameter %[[LongPtr]] +; CHECK-SPIRV: OpFunctionCall %[[Void]] %[[Foo]] %[[ArgToDeduce]] +; CHECK-SPIRV: %[[Foo]] = OpFunction %[[Void]] None %[[Fun]] +; CHECK-SPIRV: %[[FooArg]] = OpFunctionParameter %[[LongPtr]] + +define spir_kernel void @bar(ptr addrspace(1) %unknown_type_ptr) { +entry: + call spir_func void @foo(ptr addrspace(1) %unknown_type_ptr) + ret void +} + +define void @foo(ptr addrspace(1) %known_type_ptr) { +entry: + %elem = getelementptr inbounds i32, ptr addrspace(1) %known_type_ptr, i64 0 + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call.ll b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call.ll new file mode 100644 index 000000000000..8cbf360a2e38 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call.ll @@ -0,0 +1,28 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV-DAG: OpName %[[FooArg:.*]] "known_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Foo:.*]] "foo" +; CHECK-SPIRV-DAG: OpName %[[ArgToDeduce:.*]] "unknown_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Bar:.*]] "bar" +; CHECK-SPIRV-DAG: %[[Long:.*]] = OpTypeInt 32 0 +; CHECK-SPIRV-DAG: %[[Void:.*]] = OpTypeVoid +; CHECK-SPIRV-DAG: %[[LongPtr:.*]] = OpTypePointer CrossWorkgroup %[[Long]] +; CHECK-SPIRV-DAG: %[[Fun:.*]] = OpTypeFunction %[[Void]] %[[LongPtr]] +; CHECK-SPIRV: %[[Foo]] = OpFunction %[[Void]] None %[[Fun]] +; CHECK-SPIRV: %[[FooArg]] = OpFunctionParameter %[[LongPtr]] +; CHECK-SPIRV: %[[Bar]] = OpFunction %[[Void]] None %[[Fun]] +; CHECK-SPIRV: %[[ArgToDeduce]] = OpFunctionParameter %[[LongPtr]] +; CHECK-SPIRV: OpFunctionCall %[[Void]] %[[Foo]] %[[ArgToDeduce]] + +define void @foo(ptr addrspace(1) %known_type_ptr) { +entry: + %elem = getelementptr inbounds i32, ptr addrspace(1) %known_type_ptr, i64 0 + ret void +} + +define spir_kernel void @bar(ptr addrspace(1) %unknown_type_ptr) { +entry: + call spir_func void @foo(ptr addrspace(1) %unknown_type_ptr) + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/pointers/typeof-ptr-int.ll b/llvm/test/CodeGen/SPIRV/pointers/typeof-ptr-int.ll new file mode 100644 index 000000000000..f144418cf542 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/typeof-ptr-int.ll @@ -0,0 +1,29 @@ +; This test is to check that two functions have different SPIR-V type +; definitions, even though their LLVM function types are identical. + +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: OpName %[[Fun32:.*]] "tp_arg_i32" +; CHECK-DAG: OpName %[[Fun64:.*]] "tp_arg_i64" +; CHECK-DAG: %[[TyI32:.*]] = OpTypeInt 32 0 +; CHECK-DAG: %[[TyVoid:.*]] = OpTypeVoid +; CHECK-DAG: %[[TyPtr32:.*]] = OpTypePointer Function %[[TyI32]] +; CHECK-DAG: %[[TyFun32:.*]] = OpTypeFunction %[[TyVoid]] %[[TyPtr32]] +; CHECK-DAG: %[[TyI64:.*]] = OpTypeInt 64 0 +; CHECK-DAG: %[[TyPtr64:.*]] = OpTypePointer Function %[[TyI64]] +; CHECK-DAG: %[[TyFun64:.*]] = OpTypeFunction %[[TyVoid]] %[[TyPtr64]] +; CHECK-DAG: %[[Fun32]] = OpFunction %[[TyVoid]] None %[[TyFun32]] +; CHECK-DAG: %[[Fun64]] = OpFunction %[[TyVoid]] None %[[TyFun64]] + +define spir_kernel void @tp_arg_i32(ptr %ptr) { +entry: + store i32 1, ptr %ptr + ret void +} + +define spir_kernel void @tp_arg_i64(ptr %ptr) { +entry: + store i64 1, ptr %ptr + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/relationals.ll b/llvm/test/CodeGen/SPIRV/relationals.ll index 1644dc7c03d9..f4fcf4d9f77b 100644 --- a/llvm/test/CodeGen/SPIRV/relationals.ll +++ b/llvm/test/CodeGen/SPIRV/relationals.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} declare dso_local spir_func <4 x i8> @_Z13__spirv_IsNanIDv4_aDv4_fET_T0_(<4 x float>) declare dso_local spir_func <4 x i8> @_Z13__spirv_IsInfIDv4_aDv4_fET_T0_(<4 x float>) diff --git a/llvm/test/CodeGen/SPIRV/simple.ll b/llvm/test/CodeGen/SPIRV/simple.ll index de9efa838385..63c15968c725 100644 --- a/llvm/test/CodeGen/SPIRV/simple.ll +++ b/llvm/test/CodeGen/SPIRV/simple.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; Support of doubles is required. ; CHECK: OpCapability Float64 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/AtomicCompareExchangeExplicit_cl20.ll b/llvm/test/CodeGen/SPIRV/transcoding/AtomicCompareExchangeExplicit_cl20.ll index fdb26bab60fe..55cfcea999d8 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/AtomicCompareExchangeExplicit_cl20.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/AtomicCompareExchangeExplicit_cl20.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; __kernel void testAtomicCompareExchangeExplicit_cl20( ;; volatile global atomic_int* object, diff --git a/llvm/test/CodeGen/SPIRV/transcoding/BitReversePref.ll b/llvm/test/CodeGen/SPIRV/transcoding/BitReversePref.ll index 55161e670ca1..11b0578a0c9c 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/BitReversePref.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/BitReversePref.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-linux %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK: OpDecorate %[[#FUNC_NAME:]] LinkageAttributes "_Z10BitReversei" ; CHECK-NOT: OpBitReverse diff --git a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll index 95f3673d1c96..b63c1c60d007 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-DAG: %[[#]] = OpBuildNDRange %[[#]] %[[#GWS:]] %[[#LWS:]] %[[#GWO:]] ; CHECK-SPIRV-DAG: %[[#GWS]] = OpConstant %[[#]] 123 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll index a2ae808259a3..65c992c9b28e 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll @@ -19,6 +19,7 @@ ;; bash$ $PATH_TO_GEN/bin/clang -cc1 -x cl -cl-std=CL2.0 -triple spir64-unknown-unknown -emit-llvm -include opencl-20.h BuildNDRange_2.cl -o BuildNDRange_2.ll ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; TODO(#60133): Requires updates following opaque pointer migration. ; XFAIL: * diff --git a/llvm/test/CodeGen/SPIRV/transcoding/ConvertPtr.ll b/llvm/test/CodeGen/SPIRV/transcoding/ConvertPtr.ll index 34036951e31e..93aecc5331aa 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/ConvertPtr.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/ConvertPtr.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; kernel void testConvertPtrToU(global int *a, global unsigned long *res) { ;; res[0] = (unsigned long)&a[0]; diff --git a/llvm/test/CodeGen/SPIRV/transcoding/DecorationAlignment.ll b/llvm/test/CodeGen/SPIRV/transcoding/DecorationAlignment.ll index 2e9b4a494c04..d4fc5c3280b7 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/DecorationAlignment.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/DecorationAlignment.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpDecorate %[[#ALIGNMENT:]] Alignment 16 ; CHECK-SPIRV: %[[#ALIGNMENT]] = OpFunctionParameter %[[#]] diff --git a/llvm/test/CodeGen/SPIRV/transcoding/DecorationMaxByteOffset.ll b/llvm/test/CodeGen/SPIRV/transcoding/DecorationMaxByteOffset.ll index 64f25b7f4203..966d83516bb3 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/DecorationMaxByteOffset.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/DecorationMaxByteOffset.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#PTR_ID:]] "ptr" ; CHECK-SPIRV: OpName %[[#PTR2_ID:]] "ptr2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/DivRem.ll b/llvm/test/CodeGen/SPIRV/transcoding/DivRem.ll index 2f423c2518e8..67c338094188 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/DivRem.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/DivRem.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-DAG: %[[#int:]] = OpTypeInt 32 0 ; CHECK-SPIRV-DAG: %[[#int2:]] = OpTypeVector %[[#int]] 2 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/ExecutionMode_SPIR_to_SPIRV.ll b/llvm/test/CodeGen/SPIRV/transcoding/ExecutionMode_SPIR_to_SPIRV.ll index 6d6dd2481b17..6e8726cf03d4 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/ExecutionMode_SPIR_to_SPIRV.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/ExecutionMode_SPIR_to_SPIRV.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-DAG: OpEntryPoint Kernel %[[#WORKER:]] "worker" ; CHECK-SPIRV-DAG: OpExecutionMode %[[#WORKER]] LocalSizeHint 128 10 1 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/GlobalFunAnnotate.ll b/llvm/test/CodeGen/SPIRV/transcoding/GlobalFunAnnotate.ll index 2796dcbdca94..33bece5b9c00 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/GlobalFunAnnotate.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/GlobalFunAnnotate.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-linux %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpDecorate %[[#]] UserSemantic "annotation_on_function" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_cmpxchg.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_cmpxchg.ll index 331960cdb341..417b89eb36f0 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_cmpxchg.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_cmpxchg.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks that the backend is capable to correctly translate ;; atomic_cmpxchg OpenCL C 1.2 built-in function [1] into corresponding SPIR-V diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_legacy.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_legacy.ll index 95eb6ade11a2..3180b57731d0 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_legacy.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_legacy.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks that the backend is capable to correctly translate ;; legacy atomic OpenCL C 1.2 built-in functions [1] into corresponding SPIR-V diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_work_item_fence.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_work_item_fence.ll index 0f3a62a3e401..c94c13044185 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_work_item_fence.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_work_item_fence.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks that the backend is capable to correctly translate ;; atomic_work_item_fence OpenCL C 2.0 built-in function [1] into corresponding diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/barrier.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/barrier.ll index a126d94e0633..cf4a24754e7b 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/barrier.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/barrier.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks that the backend is capable to correctly translate ;; barrier OpenCL C 1.2 built-in function [1] into corresponding SPIR-V diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/sub_group_mask.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/sub_group_mask.ll index 42b127cf3b69..5d9840d3bd5b 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/sub_group_mask.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/sub_group_mask.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpCapability GroupNonUniformBallot ; CHECK-SPIRV: OpDecorate %[[#]] BuiltIn SubgroupGtMask diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/work_group_barrier.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/work_group_barrier.ll index 0874e6f71e04..0702fd0c9cb9 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/work_group_barrier.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/work_group_barrier.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks that the backend is capable to correctly translate ;; sub_group_barrier built-in function [1] from cl_khr_subgroups extension into diff --git a/llvm/test/CodeGen/SPIRV/transcoding/atomic_flag.ll b/llvm/test/CodeGen/SPIRV/transcoding/atomic_flag.ll index 3c563d373f1b..20204acb1ef5 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/atomic_flag.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/atomic_flag.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; Types: ; CHECK-DAG: %[[#INT:]] = OpTypeInt 32 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/atomic_load_store.ll b/llvm/test/CodeGen/SPIRV/transcoding/atomic_load_store.ll index d013abcade8b..3e5a3ac35693 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/atomic_load_store.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/atomic_load_store.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; Check 'LLVM ==> SPIR-V' conversion of atomic_load and atomic_store. diff --git a/llvm/test/CodeGen/SPIRV/transcoding/bitcast.ll b/llvm/test/CodeGen/SPIRV/transcoding/bitcast.ll index 8dbf4d2c58b4..2c0fc393b135 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/bitcast.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/bitcast.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; Check the bitcast is translated back to bitcast diff --git a/llvm/test/CodeGen/SPIRV/transcoding/block_w_struct_return.ll b/llvm/test/CodeGen/SPIRV/transcoding/block_w_struct_return.ll index 5ecd7f73a52e..2249cbe4e98a 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/block_w_struct_return.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/block_w_struct_return.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV1_4 +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; TODO(#60133): Requires updates following opaque pointer migration. ; XFAIL: * diff --git a/llvm/test/CodeGen/SPIRV/transcoding/builtin_calls.ll b/llvm/test/CodeGen/SPIRV/transcoding/builtin_calls.ll index 9b1ce7663180..0a02a8bf56ac 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/builtin_calls.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/builtin_calls.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-DAG: OpDecorate %[[#Id:]] BuiltIn GlobalInvocationId ; CHECK-SPIRV-DAG: OpDecorate %[[#Id:]] BuiltIn GlobalLinearId diff --git a/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars.ll b/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars.ll index 82866712c077..f18f27a6de51 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpDecorate %[[#Id:]] BuiltIn GlobalLinearId ; CHECK-SPIRV: %[[#Id:]] = OpVariable %[[#]] diff --git a/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_arithmetics.ll b/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_arithmetics.ll index 22aa40c0c7a7..d39ca3c39383 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_arithmetics.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_arithmetics.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-linux %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; The IR was generated from the following source: ;; #include diff --git a/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_opt.ll b/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_opt.ll index 5b3474f97bfe..03456aef6b6b 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_opt.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_opt.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-linux %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; The IR was generated from the following source: ;; #include diff --git a/llvm/test/CodeGen/SPIRV/transcoding/check_ro_qualifier.ll b/llvm/test/CodeGen/SPIRV/transcoding/check_ro_qualifier.ll index 6de610b2240d..824ca1b2d692 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/check_ro_qualifier.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/check_ro_qualifier.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: %[[#IMAGE_TYPE:]] = OpTypeImage ; CHECK-SPIRV: %[[#IMAGE_ARG:]] = OpFunctionParameter %[[#IMAGE_TYPE]] diff --git a/llvm/test/CodeGen/SPIRV/transcoding/cl-types.ll b/llvm/test/CodeGen/SPIRV/transcoding/cl-types.ll index 52b7dac8866f..d7e87c05340d 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/cl-types.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/cl-types.ll @@ -19,6 +19,7 @@ ;; } ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-DAG: OpCapability Sampled1D ; CHECK-SPIRV-DAG: OpCapability SampledBuffer diff --git a/llvm/test/CodeGen/SPIRV/transcoding/clk_event_t.ll b/llvm/test/CodeGen/SPIRV/transcoding/clk_event_t.ll index 9054454879cc..0cd75bb215ad 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/clk_event_t.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/clk_event_t.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpTypeDeviceEvent ; CHECK-SPIRV: OpFunction diff --git a/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll b/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll index cf124ec0a278..d23b0687face 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; TODO(#60133): Requires updates following opaque pointer migration. ; XFAIL: * diff --git a/llvm/test/CodeGen/SPIRV/transcoding/explicit-conversions.ll b/llvm/test/CodeGen/SPIRV/transcoding/explicit-conversions.ll index c186a8135fee..49b84c1e9530 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/explicit-conversions.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/explicit-conversions.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpSatConvertSToU diff --git a/llvm/test/CodeGen/SPIRV/transcoding/extract_insert_value.ll b/llvm/test/CodeGen/SPIRV/transcoding/extract_insert_value.ll index fd29bc8a1ebf..0ed1dc76628c 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/extract_insert_value.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/extract_insert_value.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; TODO(#60133): Requires updates following opaque pointer migration. ; XFAIL: * diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fadd.ll b/llvm/test/CodeGen/SPIRV/transcoding/fadd.ll index 78d9a2326655..af76c0e96f9f 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fadd.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fadd.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#r1:]] "r1" ; CHECK-SPIRV: OpName %[[#r2:]] "r2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fclamp.ll b/llvm/test/CodeGen/SPIRV/transcoding/fclamp.ll index cfdcc728fbe4..550ec1a6f255 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fclamp.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fclamp.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: %[[#]] = OpExtInst %[[#]] %[[#]] fclamp ; CHECK-SPIRV-NOT: %[[#]] = OpExtInst %[[#]] %[[#]] clamp diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fcmp.ll b/llvm/test/CodeGen/SPIRV/transcoding/fcmp.ll index 572ccc3ed625..46eaba9d5ceb 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fcmp.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fcmp.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#r1:]] "r1" ; CHECK-SPIRV: OpName %[[#r2:]] "r2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fdiv.ll b/llvm/test/CodeGen/SPIRV/transcoding/fdiv.ll index d0ed5640e706..79b786814c71 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fdiv.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fdiv.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#r1:]] "r1" ; CHECK-SPIRV: OpName %[[#r2:]] "r2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fmod.ll b/llvm/test/CodeGen/SPIRV/transcoding/fmod.ll index f506787bcb9c..683b5c24f5b7 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fmod.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fmod.ll @@ -2,6 +2,7 @@ ;; { out = fmod( in1, in2 ); } ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: %[[#]] = OpExtInst %[[#]] %[[#]] fmod %[[#]] %[[#]] diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fmul.ll b/llvm/test/CodeGen/SPIRV/transcoding/fmul.ll index 886077a67b4e..fdab29c9041c 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fmul.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fmul.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#r1:]] "r1" ; CHECK-SPIRV: OpName %[[#r2:]] "r2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fneg.ll b/llvm/test/CodeGen/SPIRV/transcoding/fneg.ll index e17601a2c25a..60bbfe6b7f39 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fneg.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fneg.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#r1:]] "r1" ; CHECK-SPIRV: OpName %[[#r2:]] "r2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fp_contract_reassoc_fast_mode.ll b/llvm/test/CodeGen/SPIRV/transcoding/fp_contract_reassoc_fast_mode.ll index c035c35a339e..974043c11991 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fp_contract_reassoc_fast_mode.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fp_contract_reassoc_fast_mode.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-NOT: OpCapability FPFastMathModeINTEL ; CHECK-SPIRV: OpName %[[#mu:]] "mul" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/frem.ll b/llvm/test/CodeGen/SPIRV/transcoding/frem.ll index ecb8f6f950ca..d36ba7f70e45 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/frem.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/frem.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#r1:]] "r1" ; CHECK-SPIRV: OpName %[[#r2:]] "r2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fsub.ll b/llvm/test/CodeGen/SPIRV/transcoding/fsub.ll index 99d0d0eb84f9..3677c0040562 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fsub.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fsub.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#r1:]] "r1" ; CHECK-SPIRV: OpName %[[#r2:]] "r2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/get_image_num_mip_levels.ll b/llvm/test/CodeGen/SPIRV/transcoding/get_image_num_mip_levels.ll index dc307c70612e..fd241963d1e9 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/get_image_num_mip_levels.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/get_image_num_mip_levels.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; Types: ; CHECK-DAG: %[[#INT:]] = OpTypeInt 32 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/global_block.ll b/llvm/test/CodeGen/SPIRV/transcoding/global_block.ll index 2f44e1943b6a..ff1bec4497ba 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/global_block.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/global_block.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV1_4 +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; TODO(#60133): Requires updates following opaque pointer migration. ; XFAIL: * diff --git a/llvm/test/CodeGen/SPIRV/transcoding/group_ops.ll b/llvm/test/CodeGen/SPIRV/transcoding/group_ops.ll index 6aa9faa6c893..2412f406a9c6 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/group_ops.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/group_ops.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-DAG: %[[#int:]] = OpTypeInt 32 0 ; CHECK-SPIRV-DAG: %[[#float:]] = OpTypeFloat 32 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/isequal.ll b/llvm/test/CodeGen/SPIRV/transcoding/isequal.ll index 3c818afcdb16..c5f3f9e1e2e7 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/isequal.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/isequal.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-NOT: OpSConvert diff --git a/llvm/test/CodeGen/SPIRV/transcoding/relationals_double.ll b/llvm/test/CodeGen/SPIRV/transcoding/relationals_double.ll index f771854672ce..de7673ad7f17 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/relationals_double.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/relationals_double.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks following SYCL relational builtins with double and double2 ;; types: diff --git a/llvm/test/CodeGen/SPIRV/transcoding/relationals_float.ll b/llvm/test/CodeGen/SPIRV/transcoding/relationals_float.ll index 1f55cebb0911..69a4a30fd65e 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/relationals_float.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/relationals_float.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks following SYCL relational builtins with float and float2 ;; types: diff --git a/llvm/test/CodeGen/SPIRV/transcoding/relationals_half.ll b/llvm/test/CodeGen/SPIRV/transcoding/relationals_half.ll index 864fb4f29efd..d6a7fda41afd 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/relationals_half.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/relationals_half.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks following SYCL relational builtins with half and half2 types: ;; isfinite, isinf, isnan, isnormal, signbit, isequal, isnotequal, isgreater -- GitLab From 5a4e2210bd60fec854822d3fb2a2aaa1e20ad2e1 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Wed, 13 Mar 2024 00:48:46 -0700 Subject: [PATCH 346/953] Revert "[llvm-exegesis] Use LLVM Support to get thread ID" This reverts commit 1c3b15e9f5bc671e40bcf5d3475f5425466754ce. This (and/or) a related patch was causing build failures on one of the buildbots. More information is available at https://lab.llvm.org/buildbot/#/builders/178/builds/7015. --- llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp | 2 +- .../tools/llvm-exegesis/lib/SubprocessMemory.cpp | 16 +++++++++++----- llvm/tools/llvm-exegesis/lib/SubprocessMemory.h | 5 ++++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp index 17ce0355ef4f..4e97d188d172 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -301,7 +301,7 @@ private: if (AddMemDefError) return AddMemDefError; - long ParentTID = get_threadid(); + long ParentTID = SubprocessMemory::getCurrentTID(); pid_t ParentOrChildPID = fork(); if (ParentOrChildPID == -1) { diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp index 28b341c46180..1fd81bd407be 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp @@ -10,7 +10,6 @@ #include "Error.h" #include "llvm/Support/Error.h" #include "llvm/Support/FormatVariadic.h" -#include "llvm/Support/Threading.h" #include #ifdef __linux__ @@ -25,6 +24,13 @@ namespace exegesis { #if defined(__linux__) && !defined(__ANDROID__) +long SubprocessMemory::getCurrentTID() { + // We're using the raw syscall here rather than the gettid() function provided + // by most libcs for compatibility as gettid() was only added to glibc in + // version 2.30. + return syscall(SYS_gettid); +} + Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessID) { // Add the PID to the shared memory name so that if we're running multiple // processes at the same time, they won't interfere with each other. @@ -32,7 +38,7 @@ Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessID) { // llvm-lit. Additionally add the TID so that downstream consumers // using multiple threads don't run into conflicts. std::string AuxiliaryMemoryName = - formatv("/{0}auxmem{1}", get_threadid(), ProcessID); + formatv("/{0}auxmem{1}", getCurrentTID(), ProcessID); int AuxiliaryMemoryFD = shm_open(AuxiliaryMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryFD == -1) @@ -53,7 +59,7 @@ Error SubprocessMemory::addMemoryDefinition( SharedMemoryNames.reserve(MemoryDefinitions.size()); for (auto &[Name, MemVal] : MemoryDefinitions) { std::string SharedMemoryName = - formatv("/{0}t{1}memdef{2}", ProcessPID, get_threadid(), MemVal.Index); + formatv("/{0}t{1}memdef{2}", ProcessPID, getCurrentTID(), MemVal.Index); SharedMemoryNames.push_back(SharedMemoryName); int SharedMemoryFD = shm_open(SharedMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); @@ -87,7 +93,7 @@ Error SubprocessMemory::addMemoryDefinition( Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, uint64_t ParentTID, int CounterFileDescriptor) { + pid_t ParentPID, long ParentTID, int CounterFileDescriptor) { std::string AuxiliaryMemoryName = formatv("/{0}auxmem{1}", ParentTID, ParentPID); int AuxiliaryMemoryFileDescriptor = @@ -139,7 +145,7 @@ Error SubprocessMemory::addMemoryDefinition( Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, uint64_t ParentTID, int CounterFileDescriptor) { + pid_t ParentPID, long ParentTID, int CounterFileDescriptor) { return make_error( "setupAuxiliaryMemoryInSubprocess is only supported on Linux"); } diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h index 807046e38ce6..572d1085d9cf 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h @@ -35,6 +35,9 @@ public: static constexpr const size_t AuxiliaryMemoryOffset = 1; static constexpr const size_t AuxiliaryMemorySize = 4096; + // Gets the thread ID for the calling thread. + static long getCurrentTID(); + Error initializeSubprocessMemory(pid_t ProcessID); // The following function sets up memory definitions. It creates shared @@ -54,7 +57,7 @@ public: // section. static Expected setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, uint64_t ParentTID, int CounterFileDescriptor); + pid_t ParentPID, long ParentTID, int CounterFileDescriptor); ~SubprocessMemory(); -- GitLab From 1fe9c417a0bf143f9bb9f9e1fbf7b20f44196883 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Wed, 13 Mar 2024 00:49:23 -0700 Subject: [PATCH 347/953] Revert "Reland "[llvm-exegesis] Add thread IDs to subprocess memory names (#84451)"" This reverts commit 8003f553a01a9a2a7eb09fe07e88f1ba9ee7d3a7. This (and/or a related commit) was causing build failures on one of the buildbots that needs more investigation. More information is available at https://lab.llvm.org/buildbot/#/builders/178/builds/7015. --- .../llvm-exegesis/lib/BenchmarkRunner.cpp | 9 +++--- .../llvm-exegesis/lib/SubprocessMemory.cpp | 30 ++++++------------- .../llvm-exegesis/lib/SubprocessMemory.h | 5 +--- .../X86/SubprocessMemoryTest.cpp | 5 +--- 4 files changed, 15 insertions(+), 34 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp index 4e97d188d172..5c9848f3c688 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -301,7 +301,6 @@ private: if (AddMemDefError) return AddMemDefError; - long ParentTID = SubprocessMemory::getCurrentTID(); pid_t ParentOrChildPID = fork(); if (ParentOrChildPID == -1) { @@ -315,7 +314,7 @@ private: // Unregister handlers, signal handling is now handled through ptrace in // the host process. sys::unregisterHandlers(); - prepareAndRunBenchmark(PipeFiles[0], Key, ParentTID); + prepareAndRunBenchmark(PipeFiles[0], Key); // The child process terminates in the above function, so we should never // get to this point. llvm_unreachable("Child process didn't exit when expected."); @@ -416,8 +415,8 @@ private: setrlimit(RLIMIT_CORE, &rlim); } - [[noreturn]] void prepareAndRunBenchmark(int Pipe, const BenchmarkKey &Key, - long ParentTID) const { + [[noreturn]] void prepareAndRunBenchmark(int Pipe, + const BenchmarkKey &Key) const { // Disable core dumps in the child process as otherwise everytime we // encounter an execution failure like a segmentation fault, we will create // a core dump. We report the information directly rather than require the @@ -474,7 +473,7 @@ private: Expected AuxMemFDOrError = SubprocessMemory::setupAuxiliaryMemoryInSubprocess( - Key.MemoryValues, ParentPID, ParentTID, CounterFileDescriptor); + Key.MemoryValues, ParentPID, CounterFileDescriptor); if (!AuxMemFDOrError) exit(ChildProcessExitCodeE::AuxiliaryMemorySetupFailed); diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp index 1fd81bd407be..a49fa077257d 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp @@ -9,13 +9,11 @@ #include "SubprocessMemory.h" #include "Error.h" #include "llvm/Support/Error.h" -#include "llvm/Support/FormatVariadic.h" #include #ifdef __linux__ #include #include -#include #include #endif @@ -24,21 +22,12 @@ namespace exegesis { #if defined(__linux__) && !defined(__ANDROID__) -long SubprocessMemory::getCurrentTID() { - // We're using the raw syscall here rather than the gettid() function provided - // by most libcs for compatibility as gettid() was only added to glibc in - // version 2.30. - return syscall(SYS_gettid); -} - Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessID) { // Add the PID to the shared memory name so that if we're running multiple // processes at the same time, they won't interfere with each other. // This comes up particularly often when running the exegesis tests with - // llvm-lit. Additionally add the TID so that downstream consumers - // using multiple threads don't run into conflicts. - std::string AuxiliaryMemoryName = - formatv("/{0}auxmem{1}", getCurrentTID(), ProcessID); + // llvm-lit + std::string AuxiliaryMemoryName = "/auxmem" + std::to_string(ProcessID); int AuxiliaryMemoryFD = shm_open(AuxiliaryMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryFD == -1) @@ -58,8 +47,8 @@ Error SubprocessMemory::addMemoryDefinition( pid_t ProcessPID) { SharedMemoryNames.reserve(MemoryDefinitions.size()); for (auto &[Name, MemVal] : MemoryDefinitions) { - std::string SharedMemoryName = - formatv("/{0}t{1}memdef{2}", ProcessPID, getCurrentTID(), MemVal.Index); + std::string SharedMemoryName = "/" + std::to_string(ProcessPID) + "memdef" + + std::to_string(MemVal.Index); SharedMemoryNames.push_back(SharedMemoryName); int SharedMemoryFD = shm_open(SharedMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); @@ -93,9 +82,8 @@ Error SubprocessMemory::addMemoryDefinition( Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, long ParentTID, int CounterFileDescriptor) { - std::string AuxiliaryMemoryName = - formatv("/{0}auxmem{1}", ParentTID, ParentPID); + pid_t ParentPID, int CounterFileDescriptor) { + std::string AuxiliaryMemoryName = "/auxmem" + std::to_string(ParentPID); int AuxiliaryMemoryFileDescriptor = shm_open(AuxiliaryMemoryName.c_str(), O_RDWR, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryFileDescriptor == -1) @@ -109,8 +97,8 @@ Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( return make_error("Mapping auxiliary memory failed"); AuxiliaryMemoryMapping[0] = CounterFileDescriptor; for (auto &[Name, MemVal] : MemoryDefinitions) { - std::string MemoryValueName = - formatv("/{0}t{1}memdef{2}", ParentPID, ParentTID, MemVal.Index); + std::string MemoryValueName = "/" + std::to_string(ParentPID) + "memdef" + + std::to_string(MemVal.Index); AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] = shm_open(MemoryValueName.c_str(), O_RDWR, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] == -1) @@ -145,7 +133,7 @@ Error SubprocessMemory::addMemoryDefinition( Expected SubprocessMemory::setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, long ParentTID, int CounterFileDescriptor) { + pid_t ParentPID, int CounterFileDescriptor) { return make_error( "setupAuxiliaryMemoryInSubprocess is only supported on Linux"); } diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h index 572d1085d9cf..e20b50cdc811 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h @@ -35,9 +35,6 @@ public: static constexpr const size_t AuxiliaryMemoryOffset = 1; static constexpr const size_t AuxiliaryMemorySize = 4096; - // Gets the thread ID for the calling thread. - static long getCurrentTID(); - Error initializeSubprocessMemory(pid_t ProcessID); // The following function sets up memory definitions. It creates shared @@ -57,7 +54,7 @@ public: // section. static Expected setupAuxiliaryMemoryInSubprocess( std::unordered_map MemoryDefinitions, - pid_t ParentPID, long ParentTID, int CounterFileDescriptor); + pid_t ParentPID, int CounterFileDescriptor); ~SubprocessMemory(); diff --git a/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp index 7c23e7b7e9c5..c07ec188a602 100644 --- a/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #endif // __linux__ @@ -50,9 +49,7 @@ protected: std::string getSharedMemoryName(const unsigned TestNumber, const unsigned DefinitionNumber) { - long CurrentTID = syscall(SYS_gettid); - return "/" + std::to_string(getSharedMemoryNumber(TestNumber)) + "t" + - std::to_string(CurrentTID) + "memdef" + + return "/" + std::to_string(getSharedMemoryNumber(TestNumber)) + "memdef" + std::to_string(DefinitionNumber); } -- GitLab From 46682f445adfa06cb74239b17b588e36fcd4fdaa Mon Sep 17 00:00:00 2001 From: Danial Klimkin Date: Wed, 13 Mar 2024 09:00:09 +0100 Subject: [PATCH 348/953] Fix missing include past a38b7a432d3cbb093af9310eba5b4982dc0a0243 (#85041) --- clang/include/clang/InstallAPI/FrontendRecords.h | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/include/clang/InstallAPI/FrontendRecords.h b/clang/include/clang/InstallAPI/FrontendRecords.h index 333015b6a113..1f5bc37798be 100644 --- a/clang/include/clang/InstallAPI/FrontendRecords.h +++ b/clang/include/clang/InstallAPI/FrontendRecords.h @@ -11,6 +11,7 @@ #include "clang/AST/Availability.h" #include "clang/AST/DeclObjC.h" +#include "clang/InstallAPI/HeaderFile.h" #include "clang/InstallAPI/MachO.h" namespace clang { -- GitLab From 1c792d24e0a228ad49cc004a1c26bbd7cd87f030 Mon Sep 17 00:00:00 2001 From: Marco Elver Date: Wed, 13 Mar 2024 09:01:00 +0100 Subject: [PATCH 349/953] [compiler-rt] Fix interceptors with AArch64 BTI (#84061) On AArch64 with BTI, we have to start functions with the appropriate BTI hint to indicate that the function is a valid call target. To support interceptors with AArch64 BTI, add "BTI c". --- compiler-rt/lib/interception/interception.h | 4 ++-- compiler-rt/lib/sanitizer_common/sanitizer_asm.h | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/compiler-rt/lib/interception/interception.h b/compiler-rt/lib/interception/interception.h index 00bcd979638b..38c152952e32 100644 --- a/compiler-rt/lib/interception/interception.h +++ b/compiler-rt/lib/interception/interception.h @@ -204,11 +204,11 @@ const interpose_substitution substitution_##func_name[] \ ".type " SANITIZER_STRINGIFY(TRAMPOLINE(func)) ", " \ ASM_TYPE_FUNCTION_STR "\n" \ SANITIZER_STRINGIFY(TRAMPOLINE(func)) ":\n" \ - SANITIZER_STRINGIFY(CFI_STARTPROC) "\n" \ + C_ASM_STARTPROC "\n" \ C_ASM_TAIL_CALL(SANITIZER_STRINGIFY(TRAMPOLINE(func)), \ "__interceptor_" \ SANITIZER_STRINGIFY(ASM_PREEMPTIBLE_SYM(func))) "\n" \ - SANITIZER_STRINGIFY(CFI_ENDPROC) "\n" \ + C_ASM_ENDPROC "\n" \ ".size " SANITIZER_STRINGIFY(TRAMPOLINE(func)) ", " \ ".-" SANITIZER_STRINGIFY(TRAMPOLINE(func)) "\n" \ ); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_asm.h b/compiler-rt/lib/sanitizer_common/sanitizer_asm.h index 3af66a4e4499..30e9d15184e5 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_asm.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_asm.h @@ -42,6 +42,16 @@ # define CFI_RESTORE(reg) #endif +#if defined(__aarch64__) && defined(__ARM_FEATURE_BTI_DEFAULT) +# define ASM_STARTPROC CFI_STARTPROC; hint #34 +# define C_ASM_STARTPROC SANITIZER_STRINGIFY(CFI_STARTPROC) "\nhint #34" +#else +# define ASM_STARTPROC CFI_STARTPROC +# define C_ASM_STARTPROC SANITIZER_STRINGIFY(CFI_STARTPROC) +#endif +#define ASM_ENDPROC CFI_ENDPROC +#define C_ASM_ENDPROC SANITIZER_STRINGIFY(CFI_ENDPROC) + #if defined(__x86_64__) || defined(__i386__) || defined(__sparc__) # define ASM_TAIL_CALL jmp #elif defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \ @@ -114,9 +124,9 @@ .globl __interceptor_trampoline_##name; \ ASM_TYPE_FUNCTION(__interceptor_trampoline_##name); \ __interceptor_trampoline_##name: \ - CFI_STARTPROC; \ + ASM_STARTPROC; \ ASM_TAIL_CALL ASM_PREEMPTIBLE_SYM(__interceptor_##name); \ - CFI_ENDPROC; \ + ASM_ENDPROC; \ ASM_SIZE(__interceptor_trampoline_##name) # define ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT 1 # endif // Architecture supports interceptor trampoline -- GitLab From 0be9592b0077dc63596ce46379cf7b3bd4a405c8 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 13 Mar 2024 09:02:05 +0100 Subject: [PATCH 350/953] [clang] CTAD: Respect requires-clause of the original function template for the synthesized deduction guide (#84913) We ignored the require-clause of the original template when building the deduction guide for type-alias CTAD, this resulted in accepting code which should be rejected (see the test case). This patch fixes it, part of #84492. --- clang/lib/Sema/SemaTemplate.cpp | 19 ++++++++++++++----- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 17 +++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index d8c9a5c09944..51e8db2dfbaa 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2906,18 +2906,27 @@ void DeclareImplicitDeductionGuidesForTypeAlias( Context.getCanonicalTemplateArgument( Context.getInjectedTemplateArg(NewParam)); } - // FIXME: implement the associated constraint per C++ + // Substitute new template parameters into requires-clause if present. + Expr *RequiresClause = nullptr; + if (Expr *InnerRC = F->getTemplateParameters()->getRequiresClause()) { + MultiLevelTemplateArgumentList Args; + Args.setKind(TemplateSubstitutionKind::Rewrite); + Args.addOuterTemplateArguments(TemplateArgsForBuildingFPrime); + ExprResult E = SemaRef.SubstExpr(InnerRC, Args); + if (E.isInvalid()) + return; + RequiresClause = E.getAs(); + } + // FIXME: implement the is_deducible constraint per C++ // [over.match.class.deduct]p3.3: - // The associated constraints ([temp.constr.decl]) are the - // conjunction of the associated constraints of g and a - // constraint that is satisfied if and only if the arguments + // ... and a constraint that is satisfied if and only if the arguments // of A are deducible (see below) from the return type. auto *FPrimeTemplateParamList = TemplateParameterList::Create( Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(), AliasTemplate->getTemplateParameters()->getLAngleLoc(), FPrimeTemplateParams, AliasTemplate->getTemplateParameters()->getRAngleLoc(), - /*RequiresClause=*/nullptr); + /*RequiresClause=*/RequiresClause); // To form a deduction guide f' from f, we leverage clang's instantiation // mechanism, we construct a template argument list where the template diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 794496ed4184..3ce26c8fcd98 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -230,3 +230,20 @@ using AFoo = Foo*; // expected-note {{template is declared here}} AFoo s = {1}; // expected-error {{alias template 'AFoo' requires template arguments; argument deduction only allowed for}} } // namespace test17 + +namespace test18 { +template +concept False = false; // expected-note {{because 'false' evaluated to false}} + +template struct Foo { T t; }; + +template requires False // expected-note {{because 'int' does not satisfy 'False'}} +Foo(T) -> Foo; + +template +using Bar = Foo; // expected-note {{could not match 'Foo' against 'int'}} \ + // expected-note {{candidate template ignored: constraints not satisfied}} \ + // expected-note {{candidate function template not viable}} + +Bar s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}} +} // namespace test18 -- GitLab From e42e97a4ada141ca1320a49e7fe03245d6765bce Mon Sep 17 00:00:00 2001 From: Sander de Smalen Date: Wed, 13 Mar 2024 08:21:33 +0000 Subject: [PATCH 351/953] [AArch64][SME] Don't mark 'smstart za' as using/defining VG. (#84775) VG is only used/defined when changing the streaming mode, using 'smstart sm' or plainly 'smstart' (same for smstop). --- .../Target/AArch64/AArch64ISelLowering.cpp | 12 +++++++++- llvm/lib/Target/AArch64/SMEInstrFormats.td | 2 -- llvm/test/CodeGen/AArch64/sme-write-vg.ll | 24 +++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/sme-write-vg.ll diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 054311d39e7b..5b7a36d2eba7 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -7751,7 +7751,7 @@ void AArch64TargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, // register allocator to pass call args in callee saved regs, without extra // copies to avoid these fake clobbers of actually-preserved GPRs. if (MI.getOpcode() == AArch64::MSRpstatesvcrImm1 || - MI.getOpcode() == AArch64::MSRpstatePseudo) + MI.getOpcode() == AArch64::MSRpstatePseudo) { for (unsigned I = MI.getNumOperands() - 1; I > 0; --I) if (MachineOperand &MO = MI.getOperand(I); MO.isReg() && MO.isImplicit() && MO.isDef() && @@ -7759,6 +7759,16 @@ void AArch64TargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, AArch64::GPR64RegClass.contains(MO.getReg()))) MI.removeOperand(I); + // The SVE vector length can change when entering/leaving streaming mode. + if (MI.getOperand(0).getImm() == AArch64SVCR::SVCRSM || + MI.getOperand(0).getImm() == AArch64SVCR::SVCRSMZA) { + MI.addOperand(MachineOperand::CreateReg(AArch64::VG, /*IsDef=*/false, + /*IsImplicit=*/true)); + MI.addOperand(MachineOperand::CreateReg(AArch64::VG, /*IsDef=*/true, + /*IsImplicit=*/true)); + } + } + // Add an implicit use of 'VG' for ADDXri/SUBXri, which are instructions that // have nothing to do with VG, were it not that they are used to materialise a // frame-address. If they contain a frame-index to a scalable vector, this diff --git a/llvm/lib/Target/AArch64/SMEInstrFormats.td b/llvm/lib/Target/AArch64/SMEInstrFormats.td index 33cb5f9734b8..44d9a8ac7cb6 100644 --- a/llvm/lib/Target/AArch64/SMEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SMEInstrFormats.td @@ -223,8 +223,6 @@ def MSRpstatesvcrImm1 let Inst{8} = imm; let Inst{7-5} = 0b011; // op2 let hasPostISelHook = 1; - let Uses = [VG]; - let Defs = [VG]; } def : InstAlias<"smstart", (MSRpstatesvcrImm1 0b011, 0b1)>; diff --git a/llvm/test/CodeGen/AArch64/sme-write-vg.ll b/llvm/test/CodeGen/AArch64/sme-write-vg.ll new file mode 100644 index 000000000000..577606d45484 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sme-write-vg.ll @@ -0,0 +1,24 @@ +; RUN: llc -mattr=+sme -stop-after=finalize-isel < %s | FileCheck %s + +target triple = "aarch64" + +; Check that we don't define VG for 'smstart za' and 'smstop za' +define void @smstart_za() "aarch64_new_za" nounwind { + ; CHECK-LABEL: name: smstart_za + ; CHECK-NOT: implicit-def {{[^,]*}}$vg + ret void +} + +; Check that we do define VG for 'smstart sm' and 'smstop sm' +define void @smstart_sm() nounwind { + ; CHECK-LABEL: name: smstart_sm + ; CHECK: MSRpstatesvcrImm1 1, 1, + ; CHECK-SAME: implicit-def {{[^,]*}}$vg + ; CHECK: MSRpstatesvcrImm1 1, 0, + ; CHECK-SAME: implicit-def {{[^,]*}}$vg + call void @require_sm() + ret void +} + +declare void @require_sm() "aarch64_pstate_sm_enabled" +declare void @require_za() "aarch64_inout_za" -- GitLab From 06c06e15f45acd3ea24756978629f1d78724870e Mon Sep 17 00:00:00 2001 From: AtariDreams <83477269+AtariDreams@users.noreply.github.com> Date: Wed, 13 Mar 2024 04:23:04 -0400 Subject: [PATCH 352/953] [Float2Int] Resolve FIXME: Pick the smallest legal type that fits (#79158) Pick the type based on the smallest bit-width possible, using DataLayout. --- .../llvm/Transforms/Scalar/Float2Int.h | 2 +- llvm/lib/Transforms/Scalar/Float2Int.cpp | 29 +- llvm/test/Transforms/Float2Int/basic.ll | 251 ++++++++++++++---- 3 files changed, 214 insertions(+), 68 deletions(-) diff --git a/llvm/include/llvm/Transforms/Scalar/Float2Int.h b/llvm/include/llvm/Transforms/Scalar/Float2Int.h index 83be329bed60..337e229efcf3 100644 --- a/llvm/include/llvm/Transforms/Scalar/Float2Int.h +++ b/llvm/include/llvm/Transforms/Scalar/Float2Int.h @@ -44,7 +44,7 @@ private: std::optional calcRange(Instruction *I); void walkBackwards(); void walkForwards(); - bool validateAndTransform(); + bool validateAndTransform(const DataLayout &DL); Value *convert(Instruction *I, Type *ToTy); void cleanup(); diff --git a/llvm/lib/Transforms/Scalar/Float2Int.cpp b/llvm/lib/Transforms/Scalar/Float2Int.cpp index ccca8bcc1a56..6ad4be169b58 100644 --- a/llvm/lib/Transforms/Scalar/Float2Int.cpp +++ b/llvm/lib/Transforms/Scalar/Float2Int.cpp @@ -311,7 +311,7 @@ void Float2IntPass::walkForwards() { } // If there is a valid transform to be done, do it. -bool Float2IntPass::validateAndTransform() { +bool Float2IntPass::validateAndTransform(const DataLayout &DL) { bool MadeChange = false; // Iterate over every disjoint partition of the def-use graph. @@ -376,15 +376,23 @@ bool Float2IntPass::validateAndTransform() { LLVM_DEBUG(dbgs() << "F2I: Value not guaranteed to be representable!\n"); continue; } - if (MinBW > 64) { - LLVM_DEBUG( - dbgs() << "F2I: Value requires more than 64 bits to represent!\n"); - continue; - } - // OK, R is known to be representable. Now pick a type for it. - // FIXME: Pick the smallest legal type that will fit. - Type *Ty = (MinBW > 32) ? Type::getInt64Ty(*Ctx) : Type::getInt32Ty(*Ctx); + // OK, R is known to be representable. + // Pick the smallest legal type that will fit. + Type *Ty = DL.getSmallestLegalIntType(*Ctx, MinBW); + if (!Ty) { + // Every supported target supports 64-bit and 32-bit integers, + // so fallback to a 32 or 64-bit integer if the value fits. + if (MinBW <= 32) { + Ty = Type::getInt32Ty(*Ctx); + } else if (MinBW <= 64) { + Ty = Type::getInt64Ty(*Ctx); + } else { + LLVM_DEBUG(dbgs() << "F2I: Value requires more than bits to represent " + "than the target supports!\n"); + continue; + } + } for (auto MI = ECs.member_begin(It), ME = ECs.member_end(); MI != ME; ++MI) @@ -491,7 +499,8 @@ bool Float2IntPass::runImpl(Function &F, const DominatorTree &DT) { walkBackwards(); walkForwards(); - bool Modified = validateAndTransform(); + const DataLayout &DL = F.getParent()->getDataLayout(); + bool Modified = validateAndTransform(DL); if (Modified) cleanup(); return Modified; diff --git a/llvm/test/Transforms/Float2Int/basic.ll b/llvm/test/Transforms/Float2Int/basic.ll index 2854a83179b7..a454b773f4eb 100644 --- a/llvm/test/Transforms/Float2Int/basic.ll +++ b/llvm/test/Transforms/Float2Int/basic.ll @@ -1,16 +1,29 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -passes='float2int' -S | FileCheck %s +; RUN: opt < %s -passes=float2int -S | FileCheck %s -check-prefixes=CHECK,NONE +; RUN: opt < %s -passes=float2int -S --data-layout="n64" | FileCheck %s -check-prefixes=CHECK,ONLY64 +; RUN: opt < %s -passes=float2int -S --data-layout="n8:16:32:64"| FileCheck %s -check-prefixes=CHECK,MULTIPLE ; ; Positive tests ; define i16 @simple1(i8 %a) { -; CHECK-LABEL: @simple1( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[T21:%.*]] = add i32 [[TMP1]], 1 -; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 -; CHECK-NEXT: ret i16 [[TMP2]] +; NONE-LABEL: @simple1( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[T21:%.*]] = add i32 [[TMP1]], 1 +; NONE-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 +; NONE-NEXT: ret i16 [[TMP2]] +; +; ONLY64-LABEL: @simple1( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[T21:%.*]] = add i64 [[TMP1]], 1 +; ONLY64-NEXT: [[TMP2:%.*]] = trunc i64 [[T21]] to i16 +; ONLY64-NEXT: ret i16 [[TMP2]] +; +; MULTIPLE-LABEL: @simple1( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; MULTIPLE-NEXT: [[T21:%.*]] = add i16 [[TMP1]], 1 +; MULTIPLE-NEXT: ret i16 [[T21]] ; %t1 = uitofp i8 %a to float %t2 = fadd float %t1, 1.0 @@ -19,11 +32,23 @@ define i16 @simple1(i8 %a) { } define i8 @simple2(i8 %a) { -; CHECK-LABEL: @simple2( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[T21:%.*]] = sub i32 [[TMP1]], 1 -; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i8 -; CHECK-NEXT: ret i8 [[TMP2]] +; NONE-LABEL: @simple2( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[T21:%.*]] = sub i32 [[TMP1]], 1 +; NONE-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i8 +; NONE-NEXT: ret i8 [[TMP2]] +; +; ONLY64-LABEL: @simple2( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[T21:%.*]] = sub i64 [[TMP1]], 1 +; ONLY64-NEXT: [[TMP2:%.*]] = trunc i64 [[T21]] to i8 +; ONLY64-NEXT: ret i8 [[TMP2]] +; +; MULTIPLE-LABEL: @simple2( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; MULTIPLE-NEXT: [[T21:%.*]] = sub i16 [[TMP1]], 1 +; MULTIPLE-NEXT: [[TMP2:%.*]] = trunc i16 [[T21]] to i8 +; MULTIPLE-NEXT: ret i8 [[TMP2]] ; %t1 = uitofp i8 %a to float %t2 = fsub float %t1, 1.0 @@ -32,10 +57,22 @@ define i8 @simple2(i8 %a) { } define i32 @simple3(i8 %a) { -; CHECK-LABEL: @simple3( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[T21:%.*]] = sub i32 [[TMP1]], 1 -; CHECK-NEXT: ret i32 [[T21]] +; NONE-LABEL: @simple3( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[T21:%.*]] = sub i32 [[TMP1]], 1 +; NONE-NEXT: ret i32 [[T21]] +; +; ONLY64-LABEL: @simple3( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[T21:%.*]] = sub i64 [[TMP1]], 1 +; ONLY64-NEXT: [[TMP2:%.*]] = trunc i64 [[T21]] to i32 +; ONLY64-NEXT: ret i32 [[TMP2]] +; +; MULTIPLE-LABEL: @simple3( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; MULTIPLE-NEXT: [[T21:%.*]] = sub i16 [[TMP1]], 1 +; MULTIPLE-NEXT: [[TMP2:%.*]] = zext i16 [[T21]] to i32 +; MULTIPLE-NEXT: ret i32 [[TMP2]] ; %t1 = uitofp i8 %a to float %t2 = fsub float %t1, 1.0 @@ -44,11 +81,23 @@ define i32 @simple3(i8 %a) { } define i1 @cmp(i8 %a, i8 %b) { -; CHECK-LABEL: @cmp( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 -; CHECK-NEXT: [[T31:%.*]] = icmp slt i32 [[TMP1]], [[TMP2]] -; CHECK-NEXT: ret i1 [[T31]] +; NONE-LABEL: @cmp( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 +; NONE-NEXT: [[T31:%.*]] = icmp slt i32 [[TMP1]], [[TMP2]] +; NONE-NEXT: ret i1 [[T31]] +; +; ONLY64-LABEL: @cmp( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i64 +; ONLY64-NEXT: [[T31:%.*]] = icmp slt i64 [[TMP1]], [[TMP2]] +; ONLY64-NEXT: ret i1 [[T31]] +; +; MULTIPLE-LABEL: @cmp( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; MULTIPLE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i16 +; MULTIPLE-NEXT: [[T31:%.*]] = icmp slt i16 [[TMP1]], [[TMP2]] +; MULTIPLE-NEXT: ret i1 [[T31]] ; %t1 = uitofp i8 %a to float %t2 = uitofp i8 %b to float @@ -70,12 +119,27 @@ define i32 @simple4(i32 %a) { } define i32 @simple5(i8 %a, i8 %b) { -; CHECK-LABEL: @simple5( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 -; CHECK-NEXT: [[T31:%.*]] = add i32 [[TMP1]], 1 -; CHECK-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] -; CHECK-NEXT: ret i32 [[T42]] +; NONE-LABEL: @simple5( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 +; NONE-NEXT: [[T31:%.*]] = add i32 [[TMP1]], 1 +; NONE-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] +; NONE-NEXT: ret i32 [[T42]] +; +; ONLY64-LABEL: @simple5( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i64 +; ONLY64-NEXT: [[T31:%.*]] = add i64 [[TMP1]], 1 +; ONLY64-NEXT: [[T42:%.*]] = mul i64 [[T31]], [[TMP2]] +; ONLY64-NEXT: [[TMP3:%.*]] = trunc i64 [[T42]] to i32 +; ONLY64-NEXT: ret i32 [[TMP3]] +; +; MULTIPLE-LABEL: @simple5( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; MULTIPLE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 +; MULTIPLE-NEXT: [[T31:%.*]] = add i32 [[TMP1]], 1 +; MULTIPLE-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] +; MULTIPLE-NEXT: ret i32 [[T42]] ; %t1 = uitofp i8 %a to float %t2 = uitofp i8 %b to float @@ -86,12 +150,27 @@ define i32 @simple5(i8 %a, i8 %b) { } define i32 @simple6(i8 %a, i8 %b) { -; CHECK-LABEL: @simple6( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 -; CHECK-NEXT: [[T31:%.*]] = sub i32 0, [[TMP1]] -; CHECK-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] -; CHECK-NEXT: ret i32 [[T42]] +; NONE-LABEL: @simple6( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 +; NONE-NEXT: [[T31:%.*]] = sub i32 0, [[TMP1]] +; NONE-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] +; NONE-NEXT: ret i32 [[T42]] +; +; ONLY64-LABEL: @simple6( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i64 +; ONLY64-NEXT: [[T31:%.*]] = sub i64 0, [[TMP1]] +; ONLY64-NEXT: [[T42:%.*]] = mul i64 [[T31]], [[TMP2]] +; ONLY64-NEXT: [[TMP3:%.*]] = trunc i64 [[T42]] to i32 +; ONLY64-NEXT: ret i32 [[TMP3]] +; +; MULTIPLE-LABEL: @simple6( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; MULTIPLE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 +; MULTIPLE-NEXT: [[T31:%.*]] = sub i32 0, [[TMP1]] +; MULTIPLE-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] +; MULTIPLE-NEXT: ret i32 [[T42]] ; %t1 = uitofp i8 %a to float %t2 = uitofp i8 %b to float @@ -105,15 +184,37 @@ define i32 @simple6(i8 %a, i8 %b) { ; cause failure of the other. define i32 @multi1(i8 %a, i8 %b, i8 %c, float %d) { -; CHECK-LABEL: @multi1( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 -; CHECK-NEXT: [[FC:%.*]] = uitofp i8 [[C:%.*]] to float -; CHECK-NEXT: [[X1:%.*]] = add i32 [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[Z:%.*]] = fadd float [[FC]], [[D:%.*]] -; CHECK-NEXT: [[W:%.*]] = fptoui float [[Z]] to i32 -; CHECK-NEXT: [[R:%.*]] = add i32 [[X1]], [[W]] -; CHECK-NEXT: ret i32 [[R]] +; NONE-LABEL: @multi1( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 +; NONE-NEXT: [[FC:%.*]] = uitofp i8 [[C:%.*]] to float +; NONE-NEXT: [[X1:%.*]] = add i32 [[TMP1]], [[TMP2]] +; NONE-NEXT: [[Z:%.*]] = fadd float [[FC]], [[D:%.*]] +; NONE-NEXT: [[W:%.*]] = fptoui float [[Z]] to i32 +; NONE-NEXT: [[R:%.*]] = add i32 [[X1]], [[W]] +; NONE-NEXT: ret i32 [[R]] +; +; ONLY64-LABEL: @multi1( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i64 +; ONLY64-NEXT: [[FC:%.*]] = uitofp i8 [[C:%.*]] to float +; ONLY64-NEXT: [[X1:%.*]] = add i64 [[TMP1]], [[TMP2]] +; ONLY64-NEXT: [[TMP3:%.*]] = trunc i64 [[X1]] to i32 +; ONLY64-NEXT: [[Z:%.*]] = fadd float [[FC]], [[D:%.*]] +; ONLY64-NEXT: [[W:%.*]] = fptoui float [[Z]] to i32 +; ONLY64-NEXT: [[R:%.*]] = add i32 [[TMP3]], [[W]] +; ONLY64-NEXT: ret i32 [[R]] +; +; MULTIPLE-LABEL: @multi1( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; MULTIPLE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i16 +; MULTIPLE-NEXT: [[FC:%.*]] = uitofp i8 [[C:%.*]] to float +; MULTIPLE-NEXT: [[X1:%.*]] = add i16 [[TMP1]], [[TMP2]] +; MULTIPLE-NEXT: [[TMP3:%.*]] = zext i16 [[X1]] to i32 +; MULTIPLE-NEXT: [[Z:%.*]] = fadd float [[FC]], [[D:%.*]] +; MULTIPLE-NEXT: [[W:%.*]] = fptoui float [[Z]] to i32 +; MULTIPLE-NEXT: [[R:%.*]] = add i32 [[TMP3]], [[W]] +; MULTIPLE-NEXT: ret i32 [[R]] ; %fa = uitofp i8 %a to float %fb = uitofp i8 %b to float @@ -127,11 +228,22 @@ define i32 @multi1(i8 %a, i8 %b, i8 %c, float %d) { } define i16 @simple_negzero(i8 %a) { -; CHECK-LABEL: @simple_negzero( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[T21:%.*]] = add i32 [[TMP1]], 0 -; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 -; CHECK-NEXT: ret i16 [[TMP2]] +; NONE-LABEL: @simple_negzero( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[T21:%.*]] = add i32 [[TMP1]], 0 +; NONE-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 +; NONE-NEXT: ret i16 [[TMP2]] +; +; ONLY64-LABEL: @simple_negzero( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[T21:%.*]] = add i64 [[TMP1]], 0 +; ONLY64-NEXT: [[TMP2:%.*]] = trunc i64 [[T21]] to i16 +; ONLY64-NEXT: ret i16 [[TMP2]] +; +; MULTIPLE-LABEL: @simple_negzero( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; MULTIPLE-NEXT: [[T21:%.*]] = add i16 [[TMP1]], 0 +; MULTIPLE-NEXT: ret i16 [[T21]] ; %t1 = uitofp i8 %a to float %t2 = fadd fast float %t1, -0.0 @@ -140,12 +252,26 @@ define i16 @simple_negzero(i8 %a) { } define i32 @simple_negative(i8 %call) { -; CHECK-LABEL: @simple_negative( -; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[CALL:%.*]] to i32 -; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[TMP1]], -3 -; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[MUL1]] to i8 -; CHECK-NEXT: [[CONV3:%.*]] = sext i8 [[TMP2]] to i32 -; CHECK-NEXT: ret i32 [[CONV3]] +; NONE-LABEL: @simple_negative( +; NONE-NEXT: [[TMP1:%.*]] = sext i8 [[CALL:%.*]] to i32 +; NONE-NEXT: [[MUL1:%.*]] = mul i32 [[TMP1]], -3 +; NONE-NEXT: [[TMP2:%.*]] = trunc i32 [[MUL1]] to i8 +; NONE-NEXT: [[CONV3:%.*]] = sext i8 [[TMP2]] to i32 +; NONE-NEXT: ret i32 [[CONV3]] +; +; ONLY64-LABEL: @simple_negative( +; ONLY64-NEXT: [[TMP1:%.*]] = sext i8 [[CALL:%.*]] to i64 +; ONLY64-NEXT: [[MUL1:%.*]] = mul i64 [[TMP1]], -3 +; ONLY64-NEXT: [[TMP2:%.*]] = trunc i64 [[MUL1]] to i8 +; ONLY64-NEXT: [[CONV3:%.*]] = sext i8 [[TMP2]] to i32 +; ONLY64-NEXT: ret i32 [[CONV3]] +; +; MULTIPLE-LABEL: @simple_negative( +; MULTIPLE-NEXT: [[TMP1:%.*]] = sext i8 [[CALL:%.*]] to i16 +; MULTIPLE-NEXT: [[MUL1:%.*]] = mul i16 [[TMP1]], -3 +; MULTIPLE-NEXT: [[TMP2:%.*]] = trunc i16 [[MUL1]] to i8 +; MULTIPLE-NEXT: [[CONV3:%.*]] = sext i8 [[TMP2]] to i32 +; MULTIPLE-NEXT: ret i32 [[CONV3]] ; %conv1 = sitofp i8 %call to float %mul = fmul float %conv1, -3.000000e+00 @@ -155,11 +281,22 @@ define i32 @simple_negative(i8 %call) { } define i16 @simple_fneg(i8 %a) { -; CHECK-LABEL: @simple_fneg( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[T21:%.*]] = sub i32 0, [[TMP1]] -; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 -; CHECK-NEXT: ret i16 [[TMP2]] +; NONE-LABEL: @simple_fneg( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[T21:%.*]] = sub i32 0, [[TMP1]] +; NONE-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 +; NONE-NEXT: ret i16 [[TMP2]] +; +; ONLY64-LABEL: @simple_fneg( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[T21:%.*]] = sub i64 0, [[TMP1]] +; ONLY64-NEXT: [[TMP2:%.*]] = trunc i64 [[T21]] to i16 +; ONLY64-NEXT: ret i16 [[TMP2]] +; +; MULTIPLE-LABEL: @simple_fneg( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; MULTIPLE-NEXT: [[T21:%.*]] = sub i16 0, [[TMP1]] +; MULTIPLE-NEXT: ret i16 [[T21]] ; %t1 = uitofp i8 %a to float %t2 = fneg fast float %t1 -- GitLab From 676c495195748e8ab2755b62153a718a53f7dae9 Mon Sep 17 00:00:00 2001 From: lcvon007 <141613945+lcvon007@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:38:48 +0800 Subject: [PATCH 353/953] [Attributor][FIX] Register right new created BB. (#84929) CBBB will keep same after the first iteration so registerManifestAddedBasicBlock would always register the same basic block later. Co-authored-by: laichunfeng --- llvm/lib/Transforms/IPO/AttributorAttributes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp index 488a6f0bb153..f98833bd1198 100644 --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -12371,7 +12371,7 @@ struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo { SplitBlockAndInsertIfThen(LastCmp, IP, /* Unreachable */ false); BasicBlock *CBBB = CB->getParent(); A.registerManifestAddedBasicBlock(*ThenTI->getParent()); - A.registerManifestAddedBasicBlock(*CBBB); + A.registerManifestAddedBasicBlock(*IP->getParent()); auto *SplitTI = cast(LastCmp->getNextNode()); BasicBlock *ElseBB; if (&*IP == CB) { -- GitLab From 2d62ce4bebe484f7c6855b9ef479e9b398595df9 Mon Sep 17 00:00:00 2001 From: mikaelholmen Date: Wed, 13 Mar 2024 09:58:47 +0100 Subject: [PATCH 354/953] [ValueTracking] Remove faulty dereference of "InsertBefore" (#85034) In 2fe81edef6f [NFC][RemoveDIs] Insert instruction using iterators in Transforms/ we changed if (*req_idx != *i) return FindInsertedValue(I->getAggregateOperand(), idx_range, - InsertBefore); + *InsertBefore); } but there is no guarantee that is InsertBefore is non-empty at that point, which we e.g can see in the added testcase. Instead just pass on the optional InsertBefore in the recursive call to FindInsertedValue, as we do at several other places already. --- llvm/lib/Analysis/ValueTracking.cpp | 2 +- .../Analysis/Lint/crash_empty_iterator.ll | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Analysis/Lint/crash_empty_iterator.ll diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 371ad41ee965..8a4a2c4f92a0 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5709,7 +5709,7 @@ llvm::FindInsertedValue(Value *V, ArrayRef idx_range, // looking for, then. if (*req_idx != *i) return FindInsertedValue(I->getAggregateOperand(), idx_range, - *InsertBefore); + InsertBefore); } // If we end up here, the indices of the insertvalue match with those // requested (though possibly only partially). Now we recursively look at diff --git a/llvm/test/Analysis/Lint/crash_empty_iterator.ll b/llvm/test/Analysis/Lint/crash_empty_iterator.ll new file mode 100644 index 000000000000..2fbecbcef5cf --- /dev/null +++ b/llvm/test/Analysis/Lint/crash_empty_iterator.ll @@ -0,0 +1,22 @@ +; RUN: opt -passes="lint" -S < %s | FileCheck %s + +; After 2fe81edef6f0b +; [NFC][RemoveDIs] Insert instruction using iterators in Transforms/ +; this crashed in FindInsertedValue when dereferencing an empty +; optional iterator. +; Just see that it doesn't crash anymore. + +; CHECK-LABEL: @test1 + +%struct = type { i32, i32 } + +define void @test1() { +entry: + %.fca.1.insert = insertvalue %struct zeroinitializer, i32 0, 1 + %0 = extractvalue %struct %.fca.1.insert, 0 + %1 = tail call %struct @foo(i32 %0) + ret void +} + +declare %struct @foo(i32) + -- GitLab From e371ada409b225ea990b5ac0d5cafea26a6046e1 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Wed, 13 Mar 2024 09:25:43 +0000 Subject: [PATCH 355/953] [compiler-rt] reimplements GetMemoryProfile for netbsd. (#84841) The actual solution relies on the premise /proc/self/smaps existence. instead relying on native api like freebsd. fixing fuzzer build too. --- compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp | 2 +- .../lib/sanitizer_common/sanitizer_procmaps_bsd.cpp | 13 +++++++++++++ .../sanitizer_common/sanitizer_procmaps_common.cpp | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp index 5729448b0beb..e5409f22f0e3 100644 --- a/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp @@ -44,7 +44,7 @@ void SetThreadName(std::thread &thread, const std::string &name) { #if LIBFUZZER_LINUX || LIBFUZZER_FREEBSD (void)pthread_setname_np(thread.native_handle(), name.c_str()); #elif LIBFUZZER_NETBSD - (void)pthread_set_name_np(thread.native_handle(), "%s", name.c_str()); + (void)pthread_setname_np(thread.native_handle(), "%s", const_cast(name.c_str())); #endif } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp index 7c2d8e6f1731..7d7c009f6444 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp @@ -42,6 +42,19 @@ void GetMemoryProfile(fill_profile_f cb, uptr *stats) { cb(0, InfoProc->ki_rssize * GetPageSizeCached(), false, stats); UnmapOrDie(InfoProc, Size, true); } +#elif SANITIZER_NETBSD +void GetMemoryProfile(fill_profile_f cb, uptr *stats) { + struct kinfo_proc2 *InfoProc; + uptr Len = sizeof(*InfoProc); + uptr Size = Len; + const int Mib[] = {CTL_KERN, KERN_PROC2, KERN_PROC_PID, getpid(), Size, 1}; + InfoProc = (struct kinfo_proc2 *)MmapOrDie(Size, "GetMemoryProfile()"); + CHECK_EQ( + internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)InfoProc, &Len, 0), + 0); + cb(0, InfoProc->p_vm_rssize * GetPageSizeCached(), false, stats); + UnmapOrDie(InfoProc, Size, true); +} #endif void ReadProcMaps(ProcSelfMapsBuff *proc_maps) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cpp index a7805ad1b083..7214a2b9ea46 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cpp @@ -145,7 +145,7 @@ void MemoryMappingLayout::DumpListOfModules( } } -#if SANITIZER_LINUX || SANITIZER_ANDROID || SANITIZER_SOLARIS || SANITIZER_NETBSD +#if SANITIZER_LINUX || SANITIZER_ANDROID || SANITIZER_SOLARIS void GetMemoryProfile(fill_profile_f cb, uptr *stats) { char *smaps = nullptr; uptr smaps_cap = 0; -- GitLab From 995d1d114e4e4ff708a03cdb0a975209c6197f9f Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 13 Mar 2024 09:47:16 +0000 Subject: [PATCH 356/953] [SjLjEHPrepare] Use inverse_depth_first() instead of _ext variant (NFC). (#84920) inverse_depth_first df_iterator_default_set as default set, so there's no need to explicitly use inverse_depth_first_ext. PR: https://github.com/llvm/llvm-project/pull/84920 --- llvm/lib/CodeGen/SjLjEHPrepare.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/llvm/lib/CodeGen/SjLjEHPrepare.cpp b/llvm/lib/CodeGen/SjLjEHPrepare.cpp index 515b5764a094..4bad57d279e9 100644 --- a/llvm/lib/CodeGen/SjLjEHPrepare.cpp +++ b/llvm/lib/CodeGen/SjLjEHPrepare.cpp @@ -150,9 +150,7 @@ static void MarkBlocksLiveIn(BasicBlock *BB, if (!LiveBBs.insert(BB).second) return; // already been here. - df_iterator_default_set Visited; - - for (BasicBlock *B : inverse_depth_first_ext(BB, Visited)) + for (BasicBlock *B : inverse_depth_first(BB)) LiveBBs.insert(B); } -- GitLab From 20b15e645cdbde07ae46aefe46ede5ff4d1e8ba3 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 13 Mar 2024 11:48:33 +0100 Subject: [PATCH 357/953] [Tests] Drop inrange attribute from some tests (NFC) These don't actually test anything related to inrange, so drop the attribute. --- llvm/test/CodeGen/AArch64/fold-global-offsets.ll | 2 +- llvm/test/CodeGen/Hexagon/addrmode-immop.mir | 4 ++-- llvm/test/CodeGen/NVPTX/b52037.ll | 2 +- llvm/test/CodeGen/WinCFGuard/cfguard-mingw.ll | 12 ++++++------ llvm/test/CodeGen/X86/tls-align.ll | 2 +- llvm/test/DebugInfo/X86/tu-to-non-tu.ll | 8 ++++---- .../Transforms/Utils/CallPromotionUtilsTest.cpp | 12 ++++++------ 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/llvm/test/CodeGen/AArch64/fold-global-offsets.ll b/llvm/test/CodeGen/AArch64/fold-global-offsets.ll index 897d35a78495..8de0f0d121f9 100644 --- a/llvm/test/CodeGen/AArch64/fold-global-offsets.ll +++ b/llvm/test/CodeGen/AArch64/fold-global-offsets.ll @@ -131,7 +131,7 @@ define i32 @f7() { ; GISEL-NEXT: ret entry: - %lshr = lshr i128 bitcast (<2 x i64> to i128), 64 + %lshr = lshr i128 bitcast (<2 x i64> to i128), 64 %trunc = trunc i128 %lshr to i64 %inttoptr = inttoptr i64 %trunc to ptr %gep = getelementptr i32, ptr %inttoptr, i64 5 diff --git a/llvm/test/CodeGen/Hexagon/addrmode-immop.mir b/llvm/test/CodeGen/Hexagon/addrmode-immop.mir index 3069cbe5969d..1412d31f35ac 100644 --- a/llvm/test/CodeGen/Hexagon/addrmode-immop.mir +++ b/llvm/test/CodeGen/Hexagon/addrmode-immop.mir @@ -15,7 +15,7 @@ ; Function Attrs: norecurse define void @f0() #0 { b0: - %v0 = load ptr, ptr getelementptr (i8, ptr getelementptr inbounds ({ [3 x ptr], [3 x ptr] }, ptr @g0, i32 0, inrange i32 0, i32 3), i32 sub (i32 ptrtoint (ptr @f1 to i32), i32 1)), align 4 + %v0 = load ptr, ptr getelementptr (i8, ptr getelementptr inbounds ({ [3 x ptr], [3 x ptr] }, ptr @g0, i32 0, i32 0, i32 3), i32 sub (i32 ptrtoint (ptr @f1 to i32), i32 1)), align 4 %v1 = call i32 %v0(ptr nonnull undef) unreachable } @@ -33,7 +33,7 @@ tracksRegLiveness: true body: | bb.0.b0: $r2 = A2_tfrsi @g0 + 12 - $r2 = L2_loadri_io killed $r2, @f1 - 1 :: (load (s32) from `ptr getelementptr (i8, ptr getelementptr inbounds ({ [3 x ptr], [3 x ptr] }, ptr @g0, i32 0, inrange i32 0, i32 3), i32 sub (i32 ptrtoint (ptr @f1 to i32), i32 1))`) + $r2 = L2_loadri_io killed $r2, @f1 - 1 :: (load (s32) from `ptr getelementptr (i8, ptr getelementptr inbounds ({ [3 x ptr], [3 x ptr] }, ptr @g0, i32 0, i32 0, i32 3), i32 sub (i32 ptrtoint (ptr @f1 to i32), i32 1))`) ADJCALLSTACKDOWN 0, 0, implicit-def $r29, implicit-def dead $r30, implicit $r31, implicit $r30, implicit $r29 PS_callr_nr killed $r2, hexagoncsr, implicit undef $r0, implicit-def $r29, implicit-def dead $r0 ADJCALLSTACKUP 0, 0, implicit-def dead $r29, implicit-def dead $r30, implicit-def dead $r31, implicit $r29 diff --git a/llvm/test/CodeGen/NVPTX/b52037.ll b/llvm/test/CodeGen/NVPTX/b52037.ll index d9322dabfa06..5d1c390909f6 100644 --- a/llvm/test/CodeGen/NVPTX/b52037.ll +++ b/llvm/test/CodeGen/NVPTX/b52037.ll @@ -47,7 +47,7 @@ bb: %tmp5 = load ptr, ptr %tmp4, align 8 %tmp9 = getelementptr inbounds %struct.zot, ptr %tmp, i64 0, i32 2, i32 1 store ptr %tmp5, ptr %tmp9, align 8 - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @global_1, i64 0, inrange i32 0, i64 3), ptr %tmp, align 16 + store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @global_1, i64 0, i32 0, i64 3), ptr %tmp, align 16 %tmp.i1 = tail call i64 @foo() %tmp44.i16 = getelementptr inbounds i16, ptr %tmp5, i64 undef %tmp45.i17 = load i16, ptr %tmp44.i16, align 2 diff --git a/llvm/test/CodeGen/WinCFGuard/cfguard-mingw.ll b/llvm/test/CodeGen/WinCFGuard/cfguard-mingw.ll index 085cde8c6169..7a5baa09f95e 100644 --- a/llvm/test/CodeGen/WinCFGuard/cfguard-mingw.ll +++ b/llvm/test/CodeGen/WinCFGuard/cfguard-mingw.ll @@ -97,7 +97,7 @@ $_ZTI7Derived = comdat any ; Function Attrs: nounwind uwtable define weak_odr dso_local dllexport void @_ZN4BaseC2Ev(ptr noundef nonnull align 8 dereferenceable(12) %0) unnamed_addr #0 comdat align 2 { - store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, inrange i32 0, i64 2), ptr %0, align 8, !tbaa !5 + store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, i32 0, i64 2), ptr %0, align 8, !tbaa !5 %2 = getelementptr inbounds %class.Base, ptr %0, i64 0, i32 1 store i32 0, ptr %2, align 8, !tbaa !8 ret void @@ -105,7 +105,7 @@ define weak_odr dso_local dllexport void @_ZN4BaseC2Ev(ptr noundef nonnull align ; Function Attrs: nounwind uwtable define weak_odr dso_local dllexport void @_ZN4BaseC1Ev(ptr noundef nonnull align 8 dereferenceable(12) %0) unnamed_addr #0 comdat align 2 { - store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, inrange i32 0, i64 2), ptr %0, align 8, !tbaa !5 + store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, i32 0, i64 2), ptr %0, align 8, !tbaa !5 %2 = getelementptr inbounds %class.Base, ptr %0, i64 0, i32 1 store i32 0, ptr %2, align 8, !tbaa !8 ret void @@ -140,10 +140,10 @@ declare dso_local void @_ZdlPv(ptr noundef) local_unnamed_addr #2 ; Function Attrs: nounwind uwtable define weak_odr dso_local dllexport void @_ZN7DerivedC2Ev(ptr noundef nonnull align 8 dereferenceable(16) %0) unnamed_addr #0 comdat align 2 { - store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, inrange i32 0, i64 2), ptr %0, align 8, !tbaa !5 + store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, i32 0, i64 2), ptr %0, align 8, !tbaa !5 %2 = getelementptr inbounds %class.Base, ptr %0, i64 0, i32 1 store i32 0, ptr %2, align 8, !tbaa !8 - store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV7Derived, i64 0, inrange i32 0, i64 2), ptr %0, align 8, !tbaa !5 + store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV7Derived, i64 0, i32 0, i64 2), ptr %0, align 8, !tbaa !5 %3 = getelementptr inbounds %class.Derived, ptr %0, i64 0, i32 1 store i32 0, ptr %3, align 4, !tbaa !12 ret void @@ -151,10 +151,10 @@ define weak_odr dso_local dllexport void @_ZN7DerivedC2Ev(ptr noundef nonnull al ; Function Attrs: nounwind uwtable define weak_odr dso_local dllexport void @_ZN7DerivedC1Ev(ptr noundef nonnull align 8 dereferenceable(16) %0) unnamed_addr #0 comdat align 2 { - store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, inrange i32 0, i64 2), ptr %0, align 8, !tbaa !5 + store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, i32 0, i64 2), ptr %0, align 8, !tbaa !5 %2 = getelementptr inbounds %class.Base, ptr %0, i64 0, i32 1 store i32 0, ptr %2, align 8, !tbaa !8 - store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV7Derived, i64 0, inrange i32 0, i64 2), ptr %0, align 8, !tbaa !5 + store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV7Derived, i64 0, i32 0, i64 2), ptr %0, align 8, !tbaa !5 %3 = getelementptr inbounds %class.Derived, ptr %0, i64 0, i32 1 store i32 0, ptr %3, align 4, !tbaa !12 ret void diff --git a/llvm/test/CodeGen/X86/tls-align.ll b/llvm/test/CodeGen/X86/tls-align.ll index 3c8ee6b3f8ab..e996c00dbf1d 100644 --- a/llvm/test/CodeGen/X86/tls-align.ll +++ b/llvm/test/CodeGen/X86/tls-align.ll @@ -12,7 +12,7 @@ define internal fastcc void @foo() unnamed_addr { entry: - store <8 x ptr> , ptr @array, align 32 + store <8 x ptr> , ptr @array, align 32 ret void } diff --git a/llvm/test/DebugInfo/X86/tu-to-non-tu.ll b/llvm/test/DebugInfo/X86/tu-to-non-tu.ll index 3ad97adbb5ad..f80bd8b97896 100644 --- a/llvm/test/DebugInfo/X86/tu-to-non-tu.ll +++ b/llvm/test/DebugInfo/X86/tu-to-non-tu.ll @@ -156,14 +156,14 @@ %struct.templ_non_tu.1 = type { ptr } @_ZTV6non_tu = dso_local unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI6non_tu, ptr @_ZN6non_tu2f1Ev] }, align 8 -@v1 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV6non_tu, i32 0, inrange i32 0, i32 2) } }, align 8, !dbg !0 +@v1 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV6non_tu, i32 0, i32 0, i32 2) } }, align 8, !dbg !0 @v5 = dso_local global %struct.ref_internal zeroinitializer, align 1, !dbg !5 @_ZTV12templ_non_tuIiE = dso_local unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI12templ_non_tuIiE, ptr @_ZN12templ_non_tuIiE2f1Ev] }, align 8 -@v2 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV12templ_non_tuIiE, i32 0, inrange i32 0, i32 2) } }, align 8, !dbg !13 +@v2 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV12templ_non_tuIiE, i32 0, i32 0, i32 2) } }, align 8, !dbg !13 @_ZTV12templ_non_tuIlE = dso_local unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI12templ_non_tuIlE, ptr @_ZN12templ_non_tuIlE2f1Ev] }, align 8 -@v3 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV12templ_non_tuIlE, i32 0, inrange i32 0, i32 2) } }, align 8, !dbg !32 +@v3 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV12templ_non_tuIlE, i32 0, i32 0, i32 2) } }, align 8, !dbg !32 @_ZTV12templ_non_tuIbE = dso_local unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI12templ_non_tuIbE, ptr @_ZN12templ_non_tuIbE2f1Ev] }, align 8 -@v4 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV12templ_non_tuIbE, i32 0, inrange i32 0, i32 2) } }, align 8, !dbg !46 +@v4 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV12templ_non_tuIbE, i32 0, i32 0, i32 2) } }, align 8, !dbg !46 @v6 = dso_local global %class.ref_internal_template zeroinitializer, align 1, !dbg !60 @v7 = dso_local global %class.ref_from_ref_internal_template zeroinitializer, align 1, !dbg !69 @_ZTVN10__cxxabiv117__class_type_infoE = external dso_local global ptr diff --git a/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp b/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp index eff8e27d36d6..0e9641c5846f 100644 --- a/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp +++ b/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp @@ -37,7 +37,7 @@ define void @f() { entry: %o = alloca %class.Impl %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0 - store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %base + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1 store i32 3, i32* %f %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0 @@ -171,7 +171,7 @@ define void @f() { entry: %o = alloca %class.Impl %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0 - store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %base + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1 store i32 3, i32* %f %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0 @@ -213,7 +213,7 @@ define void @f() { entry: %o = alloca %class.Impl %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0 - store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %base + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1 store i32 3, i32* %f %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0 @@ -256,7 +256,7 @@ entry: %a = alloca %struct.A, align 8 %0 = bitcast %struct.A* %a to i8* %1 = getelementptr %struct.A, %struct.A* %a, i64 0, i32 0 - store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8 + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8 %2 = bitcast %struct.A* %a to i8* %3 = bitcast i8* %2 to i8** %vtable.i = load i8*, i8** %3, align 8 @@ -271,7 +271,7 @@ entry: %a = alloca %struct.A, align 8 %0 = bitcast %struct.A* %a to i8* %1 = getelementptr %struct.A, %struct.A* %a, i64 0, i32 0 - store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8 + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8 %2 = bitcast %struct.A* %a to i8* %3 = bitcast i8* %2 to i8** %vtable.i = load i8*, i8** %3, align 8 @@ -340,7 +340,7 @@ define %struct1 @f() { entry: %o = alloca %class.Impl %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0 - store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %base + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1 store i32 3, i32* %f %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0 -- GitLab From e4b27359fde552f65fd3434398a6b80104e1a20d Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 13 Mar 2024 11:53:35 +0100 Subject: [PATCH 358/953] [ThinLTO] Drop inrange attribute from tests (NFC) The inrange attribute is not relevant to the optimizations being tested here. Additionally, all the inrange attributes in these files don't actually carry any additional information, as the "range" covers the whole object. --- llvm/test/ThinLTO/X86/Inputs/devirt_single_hybrid_bar.ll | 2 +- llvm/test/ThinLTO/X86/devirt_after_filtering_unreachable.ll | 2 +- llvm/test/ThinLTO/X86/devirt_external_comdat_same_guid.ll | 2 +- llvm/test/ThinLTO/X86/devirt_local_same_guid.ll | 2 +- llvm/test/ThinLTO/X86/lower_type_test_phi.ll | 4 ++-- llvm/test/ThinLTO/X86/nodevirt-nonpromoted-typeid.ll | 2 +- llvm/test/ThinLTO/X86/type_test_noindircall.ll | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/llvm/test/ThinLTO/X86/Inputs/devirt_single_hybrid_bar.ll b/llvm/test/ThinLTO/X86/Inputs/devirt_single_hybrid_bar.ll index 721d6efb7b53..d8c6525ed606 100644 --- a/llvm/test/ThinLTO/X86/Inputs/devirt_single_hybrid_bar.ll +++ b/llvm/test/ThinLTO/X86/Inputs/devirt_single_hybrid_bar.ll @@ -23,7 +23,7 @@ define hidden i32 @_Z3barv() local_unnamed_addr #0 { entry: %b = alloca %struct.A, align 8 call void @llvm.lifetime.start.p0(i64 8, ptr nonnull %b) - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %b, align 8, !tbaa !4 + store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %b, align 8, !tbaa !4 %call = call i32 @_Z3fooP1A(ptr nonnull %b) %add = add nsw i32 %call, 10 call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %b) #4 diff --git a/llvm/test/ThinLTO/X86/devirt_after_filtering_unreachable.ll b/llvm/test/ThinLTO/X86/devirt_after_filtering_unreachable.ll index 68b83debef7d..39f42da77d81 100644 --- a/llvm/test/ThinLTO/X86/devirt_after_filtering_unreachable.ll +++ b/llvm/test/ThinLTO/X86/devirt_after_filtering_unreachable.ll @@ -71,7 +71,7 @@ target triple = "x86_64-unknown-linux-gnu" define hidden i32 @main() { entry: %call = tail call ptr @_Znwm(i64 8) - store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV7Derived, i64 0, inrange i32 0, i64 2), ptr %call + store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV7Derived, i64 0, i32 0, i64 2), ptr %call tail call void @_Z3fooP4Base(ptr nonnull %call) ret i32 0 } diff --git a/llvm/test/ThinLTO/X86/devirt_external_comdat_same_guid.ll b/llvm/test/ThinLTO/X86/devirt_external_comdat_same_guid.ll index 241753256804..1f0737b71925 100644 --- a/llvm/test/ThinLTO/X86/devirt_external_comdat_same_guid.ll +++ b/llvm/test/ThinLTO/X86/devirt_external_comdat_same_guid.ll @@ -51,7 +51,7 @@ define i32 @_ZN1B1nEi(ptr %this, i32 %a) #0 comdat($_ZTV1B) { ; Ensures that vtable of B is live so that we will attempt devirt. define dso_local i32 @use_B(ptr %a) { entry: - store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %a, align 8 + store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %a, align 8 ret i32 0 } diff --git a/llvm/test/ThinLTO/X86/devirt_local_same_guid.ll b/llvm/test/ThinLTO/X86/devirt_local_same_guid.ll index 3efea8de3fbc..2205545e3250 100644 --- a/llvm/test/ThinLTO/X86/devirt_local_same_guid.ll +++ b/llvm/test/ThinLTO/X86/devirt_local_same_guid.ll @@ -37,7 +37,7 @@ define internal i32 @_ZN1B1nEi(ptr %this, i32 %a) #0 { ; Ensures that vtable of B is live so that we will attempt devirt. define dso_local i32 @use_B(ptr %a) { entry: - store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %a, align 8 + store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %a, align 8 ret i32 0 } diff --git a/llvm/test/ThinLTO/X86/lower_type_test_phi.ll b/llvm/test/ThinLTO/X86/lower_type_test_phi.ll index 722ffe3cc228..81d85f64584f 100644 --- a/llvm/test/ThinLTO/X86/lower_type_test_phi.ll +++ b/llvm/test/ThinLTO/X86/lower_type_test_phi.ll @@ -117,7 +117,7 @@ $_ZTV2D2 = comdat any define ptr @_Z2b1v() { entry: %call = tail call ptr @_Znwm(i64 8) - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV2D1, i64 0, inrange i32 0, i64 2), ptr %call, align 8 + store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV2D1, i64 0, i32 0, i64 2), ptr %call, align 8 ret ptr %call } @@ -126,7 +126,7 @@ declare ptr @_Znwm(i64) define ptr @_Z2b2v() { entry: %call = tail call ptr @_Znwm(i64 8) - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV2D2, i64 0, inrange i32 0, i64 2), ptr %call, align 8 + store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV2D2, i64 0, i32 0, i64 2), ptr %call, align 8 ret ptr %call } diff --git a/llvm/test/ThinLTO/X86/nodevirt-nonpromoted-typeid.ll b/llvm/test/ThinLTO/X86/nodevirt-nonpromoted-typeid.ll index c6e61edcd97a..7d71c595fbb1 100644 --- a/llvm/test/ThinLTO/X86/nodevirt-nonpromoted-typeid.ll +++ b/llvm/test/ThinLTO/X86/nodevirt-nonpromoted-typeid.ll @@ -55,7 +55,7 @@ entry: %this.addr = alloca ptr, align 8 store ptr %this, ptr %this.addr, align 8 %this1 = load ptr, ptr %this.addr - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1D, i64 0, inrange i32 0, i64 2), ptr %this1, align 8 + store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1D, i64 0, i32 0, i64 2), ptr %this1, align 8 ret void } diff --git a/llvm/test/ThinLTO/X86/type_test_noindircall.ll b/llvm/test/ThinLTO/X86/type_test_noindircall.ll index 2d0faaa25602..cc85e44c2806 100644 --- a/llvm/test/ThinLTO/X86/type_test_noindircall.ll +++ b/llvm/test/ThinLTO/X86/type_test_noindircall.ll @@ -38,8 +38,8 @@ target triple = "x86_64-grtev4-linux-gnu" define internal void @_ZN12_GLOBAL__N_18RealFileD2Ev(ptr %this) unnamed_addr #0 align 2 { entry: ; CHECK-IR: store - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN12_GLOBAL__N_18RealFileE, i64 0, inrange i32 0, i64 2), ptr %this, align 8 - %0 = tail call i1 @llvm.type.test(ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN12_GLOBAL__N_18RealFileE, i64 0, inrange i32 0, i64 2), metadata !"4$09c6cc733fc6accb91e5d7b87cb48f2d") + store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN12_GLOBAL__N_18RealFileE, i64 0, i32 0, i64 2), ptr %this, align 8 + %0 = tail call i1 @llvm.type.test(ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN12_GLOBAL__N_18RealFileE, i64 0, i32 0, i64 2), metadata !"4$09c6cc733fc6accb91e5d7b87cb48f2d") tail call void @llvm.assume(i1 %0) ; CHECK-IR-NEXT: ret void ret void -- GitLab From 5a744776bb6192dae04360609457c9f49dce43a2 Mon Sep 17 00:00:00 2001 From: dyung Date: Wed, 13 Mar 2024 04:10:03 -0700 Subject: [PATCH 359/953] Mark test as XFAIL that started failing after 418f0066eb. (#85027) Similar failures were previously seen and XFAILed in https://reviews.llvm.org/D118468. See the phabricator review for a description of the problem, and the linked discourse thread for what the failing output looks like. This change should fix the issue on two buildbots that are running older versions of GDB: - https://lab.llvm.org/buildbot/#/builders/217/builds/37559 - https://lab.llvm.org/buildbot/#/builders/247/builds/15173 --- .../debuginfo-tests/llgdb-tests/forward-declare-class.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cross-project-tests/debuginfo-tests/llgdb-tests/forward-declare-class.cpp b/cross-project-tests/debuginfo-tests/llgdb-tests/forward-declare-class.cpp index 850eed6ad95d..130c439faec8 100644 --- a/cross-project-tests/debuginfo-tests/llgdb-tests/forward-declare-class.cpp +++ b/cross-project-tests/debuginfo-tests/llgdb-tests/forward-declare-class.cpp @@ -1,6 +1,7 @@ // RUN: %clangxx %target_itanium_abi_host_triple -O0 -g %s -c -o %t.o // RUN: %test_debuginfo %s %t.o // Radar 9168773 +// XFAIL: !system-darwin && gdb-clang-incompatibility // DEBUGGER: ptype A // Work around a gdb bug where it believes that a class is a -- GitLab From 560d7c51fdee4cc15766aa9b62c0cd8f0f18a353 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 13 Mar 2024 11:13:28 +0000 Subject: [PATCH 360/953] [DAG] Add SDPatternMatch m_And/m_Or/m_Xor matchers for logic ops --- llvm/include/llvm/CodeGen/SDPatternMatch.h | 15 +++++++++++++++ .../CodeGen/SelectionDAGPatternMatchTest.cpp | 11 +++++++++++ 2 files changed, 26 insertions(+) diff --git a/llvm/include/llvm/CodeGen/SDPatternMatch.h b/llvm/include/llvm/CodeGen/SDPatternMatch.h index 412bf42677cc..92b478cec0a0 100644 --- a/llvm/include/llvm/CodeGen/SDPatternMatch.h +++ b/llvm/include/llvm/CodeGen/SDPatternMatch.h @@ -495,6 +495,21 @@ inline BinaryOpc_match m_Mul(const LHS &L, const RHS &R) { return BinaryOpc_match(ISD::MUL, L, R); } +template +inline BinaryOpc_match m_And(const LHS &L, const RHS &R) { + return BinaryOpc_match(ISD::AND, L, R); +} + +template +inline BinaryOpc_match m_Or(const LHS &L, const RHS &R) { + return BinaryOpc_match(ISD::OR, L, R); +} + +template +inline BinaryOpc_match m_Xor(const LHS &L, const RHS &R) { + return BinaryOpc_match(ISD::XOR, L, R); +} + template inline BinaryOpc_match m_UDiv(const LHS &L, const RHS &R) { return BinaryOpc_match(ISD::UDIV, L, R); diff --git a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp index 17fc3ce8af26..2b764c9e1f0f 100644 --- a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp +++ b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp @@ -130,6 +130,9 @@ TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) { SDValue Add = DAG->getNode(ISD::ADD, DL, Int32VT, Op0, Op1); SDValue Sub = DAG->getNode(ISD::SUB, DL, Int32VT, Add, Op0); SDValue Mul = DAG->getNode(ISD::MUL, DL, Int32VT, Add, Sub); + SDValue And = DAG->getNode(ISD::AND, DL, Int32VT, Op0, Op1); + SDValue Xor = DAG->getNode(ISD::XOR, DL, Int32VT, Op1, Op0); + SDValue Or = DAG->getNode(ISD::OR, DL, Int32VT, Op0, Op1); SDValue SFAdd = DAG->getNode(ISD::STRICT_FADD, DL, {Float32VT, MVT::Other}, {DAG->getEntryNode(), Op2, Op2}); @@ -144,6 +147,14 @@ TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) { EXPECT_TRUE( sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_SpecificVT(Float32VT), m_SpecificVT(Float32VT)))); + + EXPECT_TRUE(sd_match(And, m_c_BinOp(ISD::AND, m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(And, m_And(m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(Xor, m_c_BinOp(ISD::XOR, m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(Xor, m_Xor(m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(Or, m_c_BinOp(ISD::OR, m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(Or, m_Or(m_Value(), m_Value()))); + SDValue BindVal; EXPECT_TRUE(sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_Value(BindVal), m_Deferred(BindVal)))); -- GitLab From 99be3875fb161a5786aaad5dab0b92fa052e47d1 Mon Sep 17 00:00:00 2001 From: Jonathan Thackray Date: Wed, 13 Mar 2024 11:19:32 +0000 Subject: [PATCH 361/953] [ARM][AArch64] Add missing Arm CPU part-ids to enable -mcpu=native (#84899) Update Host.cpp with some missing Arm CPU part identifiers, to enable `-mcpu=native` on these processors. These are found in the Technical Reference Manuals listed under "part num" or "part no" --- llvm/lib/TargetParser/Host.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/llvm/lib/TargetParser/Host.cpp b/llvm/lib/TargetParser/Host.cpp index ee4fd0425ca5..f65ed259eade 100644 --- a/llvm/lib/TargetParser/Host.cpp +++ b/llvm/lib/TargetParser/Host.cpp @@ -196,14 +196,24 @@ StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) { .Case("0xb36", "arm1136j-s") .Case("0xb56", "arm1156t2-s") .Case("0xb76", "arm1176jz-s") + .Case("0xc05", "cortex-a5") + .Case("0xc07", "cortex-a7") .Case("0xc08", "cortex-a8") .Case("0xc09", "cortex-a9") .Case("0xc0f", "cortex-a15") + .Case("0xc0e", "cortex-a17") .Case("0xc20", "cortex-m0") .Case("0xc23", "cortex-m3") .Case("0xc24", "cortex-m4") + .Case("0xc27", "cortex-m7") + .Case("0xd20", "cortex-m23") + .Case("0xd21", "cortex-m33") .Case("0xd24", "cortex-m52") .Case("0xd22", "cortex-m55") + .Case("0xd23", "cortex-m85") + .Case("0xc18", "cortex-r8") + .Case("0xd13", "cortex-r52") + .Case("0xd15", "cortex-r82") .Case("0xd02", "cortex-a34") .Case("0xd04", "cortex-a35") .Case("0xd03", "cortex-a53") @@ -211,13 +221,17 @@ StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) { .Case("0xd46", "cortex-a510") .Case("0xd80", "cortex-a520") .Case("0xd07", "cortex-a57") + .Case("0xd06", "cortex-a65") + .Case("0xd43", "cortex-a65ae") .Case("0xd08", "cortex-a72") .Case("0xd09", "cortex-a73") .Case("0xd0a", "cortex-a75") .Case("0xd0b", "cortex-a76") + .Case("0xd0e", "cortex-a76ae") .Case("0xd0d", "cortex-a77") .Case("0xd41", "cortex-a78") .Case("0xd42", "cortex-a78ae") + .Case("0xd4b", "cortex-a78c") .Case("0xd47", "cortex-a710") .Case("0xd4d", "cortex-a715") .Case("0xd81", "cortex-a720") @@ -226,6 +240,7 @@ StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) { .Case("0xd48", "cortex-x2") .Case("0xd4e", "cortex-x3") .Case("0xd82", "cortex-x4") + .Case("0xd4a", "neoverse-e1") .Case("0xd0c", "neoverse-n1") .Case("0xd49", "neoverse-n2") .Case("0xd40", "neoverse-v1") -- GitLab From a7af53e99bb1fc92f45c14df2acf2da8f849af2f Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 13 Mar 2024 12:00:15 +0000 Subject: [PATCH 362/953] [DAG] visitSUB - convert some folds to use SDPatternMatch General cleanup and allows us to handle several commutable matches with a single pattern --- llvm/include/llvm/CodeGen/SDPatternMatch.h | 1 + llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 78 ++++++------------- llvm/test/CodeGen/AArch64/xor.ll | 2 +- 3 files changed, 25 insertions(+), 56 deletions(-) diff --git a/llvm/include/llvm/CodeGen/SDPatternMatch.h b/llvm/include/llvm/CodeGen/SDPatternMatch.h index 92b478cec0a0..a86c7400fa09 100644 --- a/llvm/include/llvm/CodeGen/SDPatternMatch.h +++ b/llvm/include/llvm/CodeGen/SDPatternMatch.h @@ -663,6 +663,7 @@ inline SpecificInt_match m_SpecificInt(uint64_t V) { } inline SpecificInt_match m_Zero() { return m_SpecificInt(0U); } +inline SpecificInt_match m_One() { return m_SpecificInt(1U); } inline SpecificInt_match m_AllOnes() { return m_SpecificInt(~0U); } /// Match true boolean value based on the information provided by diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 735cec8ecc06..87033e824aa5 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3789,63 +3789,34 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { return DAG.getNode(ISD::SUB, DL, VT, NewC, N0.getOperand(1)); } - // fold ((A+(B+or-C))-B) -> A+or-C - if (N0.getOpcode() == ISD::ADD && - (N0.getOperand(1).getOpcode() == ISD::SUB || - N0.getOperand(1).getOpcode() == ISD::ADD) && - N0.getOperand(1).getOperand(0) == N1) - return DAG.getNode(N0.getOperand(1).getOpcode(), DL, VT, N0.getOperand(0), - N0.getOperand(1).getOperand(1)); - - // fold ((A+(C+B))-B) -> A+C - if (N0.getOpcode() == ISD::ADD && N0.getOperand(1).getOpcode() == ISD::ADD && - N0.getOperand(1).getOperand(1) == N1) - return DAG.getNode(ISD::ADD, DL, VT, N0.getOperand(0), - N0.getOperand(1).getOperand(0)); + SDValue A, B, C; + + // fold ((A+(B+C))-B) -> A+C + if (sd_match(N0, m_Add(m_Value(A), m_Add(m_Specific(N1), m_Value(C))))) + return DAG.getNode(ISD::ADD, DL, VT, A, C); + + // fold ((A+(B-C))-B) -> A-C + if (sd_match(N0, m_Add(m_Value(A), m_Sub(m_Specific(N1), m_Value(C))))) + return DAG.getNode(ISD::SUB, DL, VT, A, C); // fold ((A-(B-C))-C) -> A-B - if (N0.getOpcode() == ISD::SUB && N0.getOperand(1).getOpcode() == ISD::SUB && - N0.getOperand(1).getOperand(1) == N1) - return DAG.getNode(ISD::SUB, DL, VT, N0.getOperand(0), - N0.getOperand(1).getOperand(0)); + if (sd_match(N0, m_Sub(m_Value(A), m_Sub(m_Value(B), m_Specific(N1))))) + return DAG.getNode(ISD::SUB, DL, VT, A, B); // fold (A-(B-C)) -> A+(C-B) - if (N1.getOpcode() == ISD::SUB && N1.hasOneUse()) + if (sd_match(N1, m_OneUse(m_Sub(m_Value(B), m_Value(C))))) return DAG.getNode(ISD::ADD, DL, VT, N0, - DAG.getNode(ISD::SUB, DL, VT, N1.getOperand(1), - N1.getOperand(0))); + DAG.getNode(ISD::SUB, DL, VT, C, B)); // A - (A & B) -> A & (~B) - if (N1.getOpcode() == ISD::AND) { - SDValue A = N1.getOperand(0); - SDValue B = N1.getOperand(1); - if (A != N0) - std::swap(A, B); - if (A == N0 && - (N1.hasOneUse() || isConstantOrConstantVector(B, /*NoOpaques=*/true))) { - SDValue InvB = - DAG.getNode(ISD::XOR, DL, VT, B, DAG.getAllOnesConstant(DL, VT)); - return DAG.getNode(ISD::AND, DL, VT, A, InvB); - } - } + if (sd_match(N1, m_And(m_Specific(N0), m_Value(B))) && + (N1.hasOneUse() || isConstantOrConstantVector(B, /*NoOpaques=*/true))) + return DAG.getNode(ISD::AND, DL, VT, N0, DAG.getNOT(DL, B, VT)); - // fold (X - (-Y * Z)) -> (X + (Y * Z)) - if (N1.getOpcode() == ISD::MUL && N1.hasOneUse()) { - if (N1.getOperand(0).getOpcode() == ISD::SUB && - isNullOrNullSplat(N1.getOperand(0).getOperand(0))) { - SDValue Mul = DAG.getNode(ISD::MUL, DL, VT, - N1.getOperand(0).getOperand(1), - N1.getOperand(1)); - return DAG.getNode(ISD::ADD, DL, VT, N0, Mul); - } - if (N1.getOperand(1).getOpcode() == ISD::SUB && - isNullOrNullSplat(N1.getOperand(1).getOperand(0))) { - SDValue Mul = DAG.getNode(ISD::MUL, DL, VT, - N1.getOperand(0), - N1.getOperand(1).getOperand(1)); - return DAG.getNode(ISD::ADD, DL, VT, N0, Mul); - } - } + // fold (A - (-B * C)) -> (A + (B * C)) + if (sd_match(N1, m_OneUse(m_Mul(m_Sub(m_Zero(), m_Value(B)), m_Value(C))))) + return DAG.getNode(ISD::ADD, DL, VT, N0, + DAG.getNode(ISD::MUL, DL, VT, B, C)); // If either operand of a sub is undef, the result is undef if (N0.isUndef()) @@ -3865,12 +3836,9 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { if (SDValue V = foldSubToUSubSat(VT, N)) return V; - // (x - y) - 1 -> add (xor y, -1), x - if (N0.getOpcode() == ISD::SUB && N0.hasOneUse() && isOneOrOneSplat(N1)) { - SDValue Xor = DAG.getNode(ISD::XOR, DL, VT, N0.getOperand(1), - DAG.getAllOnesConstant(DL, VT)); - return DAG.getNode(ISD::ADD, DL, VT, Xor, N0.getOperand(0)); - } + // (A - B) - 1 -> add (xor B, -1), A + if (sd_match(N, m_Sub(m_OneUse(m_Sub(m_Value(A), m_Value(B))), m_One()))) + return DAG.getNode(ISD::ADD, DL, VT, A, DAG.getNOT(DL, B, VT)); // Look for: // sub y, (xor x, -1) diff --git a/llvm/test/CodeGen/AArch64/xor.ll b/llvm/test/CodeGen/AArch64/xor.ll index d92402cf43b3..7d7f7bfdbf38 100644 --- a/llvm/test/CodeGen/AArch64/xor.ll +++ b/llvm/test/CodeGen/AArch64/xor.ll @@ -51,7 +51,7 @@ define <4 x i32> @vec_add_of_not_decrement(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: vec_add_of_not_decrement: ; CHECK: // %bb.0: ; CHECK-NEXT: mvn v1.16b, v1.16b -; CHECK-NEXT: add v0.4s, v1.4s, v0.4s +; CHECK-NEXT: add v0.4s, v0.4s, v1.4s ; CHECK-NEXT: ret %t0 = sub <4 x i32> %x, %y %r = sub <4 x i32> %t0, -- GitLab From 7cd61f888c479da51215071336b34f6918cad3d8 Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Wed, 13 Mar 2024 11:50:58 +0000 Subject: [PATCH 363/953] [AMDGPU] Remove unneeded MnemonicAlias. NFC. This is unneeded because MUBUF_Real_Atomic_gfx11_gfx12 on the line above generates it automatically. --- llvm/lib/Target/AMDGPU/BUFInstructions.td | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/lib/Target/AMDGPU/BUFInstructions.td b/llvm/lib/Target/AMDGPU/BUFInstructions.td index c7091028b3b5..4ae514ffcf78 100644 --- a/llvm/lib/Target/AMDGPU/BUFInstructions.td +++ b/llvm/lib/Target/AMDGPU/BUFInstructions.td @@ -2616,7 +2616,6 @@ defm BUFFER_ATOMIC_CMPSWAP_X2 : MUBUF_Real_Atomic_gfx11_gfx12<0x042, "buffer defm BUFFER_ATOMIC_FCMPSWAP : MUBUF_Real_Atomic_gfx11<0x050, "buffer_atomic_cmpswap_f32">; defm BUFFER_ATOMIC_COND_SUB_U32 : MUBUF_Real_Atomic_gfx12<0x050>; defm BUFFER_ATOMIC_CSUB : MUBUF_Real_Atomic_gfx11_gfx12<0x037, "buffer_atomic_sub_clamp_u32", "buffer_atomic_csub_u32">; -def : Mnem_gfx11_gfx12<"buffer_atomic_csub", "buffer_atomic_csub_u32">; defm BUFFER_ATOMIC_DEC : MUBUF_Real_Atomic_gfx11_gfx12<0x040, "buffer_atomic_dec_u32">; defm BUFFER_ATOMIC_DEC_X2 : MUBUF_Real_Atomic_gfx11_gfx12<0x04D, "buffer_atomic_dec_u64">; defm BUFFER_ATOMIC_INC : MUBUF_Real_Atomic_gfx11_gfx12<0x03F, "buffer_atomic_inc_u32">; -- GitLab From ceb744eb2fa0895db1526110462745962fdf43c0 Mon Sep 17 00:00:00 2001 From: Harald van Dijk Date: Wed, 13 Mar 2024 12:08:39 +0000 Subject: [PATCH 364/953] [AMDGPU] Fix canonicalization of truncated values. (#83054) We were relying on roundings to implicitly canonicalize, which is generally safe, except with roundings that may be optimized away. Fixes #82937. --- llvm/lib/Target/AMDGPU/AMDGPUInstructions.td | 24 +- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 65 +- llvm/lib/Target/AMDGPU/SIISelLowering.h | 4 +- llvm/lib/Target/AMDGPU/SIInstructions.td | 51 +- llvm/test/CodeGen/AMDGPU/bf16.ll | 911 ++++-------------- llvm/test/CodeGen/AMDGPU/clamp.ll | 64 +- .../AMDGPU/fcanonicalize-elimination.ll | 103 +- llvm/test/CodeGen/AMDGPU/fcanonicalize.f16.ll | 728 ++++++++------ llvm/test/CodeGen/AMDGPU/fcanonicalize.ll | 22 +- llvm/test/CodeGen/AMDGPU/fneg-combines.f16.ll | 22 +- llvm/test/CodeGen/AMDGPU/fneg-combines.new.ll | 2 - llvm/test/CodeGen/AMDGPU/llvm.maxnum.f16.ll | 122 +-- llvm/test/CodeGen/AMDGPU/llvm.minnum.f16.ll | 122 +-- llvm/test/CodeGen/AMDGPU/mad-mix-lo.ll | 191 ++-- 14 files changed, 1021 insertions(+), 1410 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td b/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td index 5ed82c0c4b1b..86f77f7b64e8 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td +++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td @@ -194,7 +194,25 @@ class HasOneUseTernaryOp : PatFrag< }]; } -class is_canonicalized : PatFrag< +class is_canonicalized_1 : PatFrag< + (ops node:$src0), + (op $src0), + [{ + const SITargetLowering &Lowering = + *static_cast(getTargetLowering()); + + return Lowering.isCanonicalized(*CurDAG, N->getOperand(0)); + }]> { + + let GISelPredicateCode = [{ + const SITargetLowering *TLI = static_cast( + MF.getSubtarget().getTargetLowering()); + + return TLI->isCanonicalized(MI.getOperand(1).getReg(), MF); + }]; +} + +class is_canonicalized_2 : PatFrag< (ops node:$src0, node:$src1), (op $src0, $src1), [{ @@ -210,8 +228,8 @@ class is_canonicalized : PatFrag< const SITargetLowering *TLI = static_cast( MF.getSubtarget().getTargetLowering()); - return TLI->isCanonicalized(MI.getOperand(1).getReg(), const_cast(MF)) && - TLI->isCanonicalized(MI.getOperand(2).getReg(), const_cast(MF)); + return TLI->isCanonicalized(MI.getOperand(1).getReg(), MF) && + TLI->isCanonicalized(MI.getOperand(2).getReg(), MF); }]; } diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index 9bc1b8eb598f..5ccf21f76015 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -12572,6 +12572,10 @@ bool SITargetLowering::isCanonicalized(SelectionDAG &DAG, SDValue Op, case ISD::FREM: case ISD::FP_ROUND: case ISD::FP_EXTEND: + case ISD::FP16_TO_FP: + case ISD::FP_TO_FP16: + case ISD::BF16_TO_FP: + case ISD::FP_TO_BF16: case ISD::FLDEXP: case AMDGPUISD::FMUL_LEGACY: case AMDGPUISD::FMAD_FTZ: @@ -12591,6 +12595,9 @@ bool SITargetLowering::isCanonicalized(SelectionDAG &DAG, SDValue Op, case AMDGPUISD::CVT_F32_UBYTE1: case AMDGPUISD::CVT_F32_UBYTE2: case AMDGPUISD::CVT_F32_UBYTE3: + case AMDGPUISD::FP_TO_FP16: + case AMDGPUISD::SIN_HW: + case AMDGPUISD::COS_HW: return true; // It can/will be lowered or combined as a bit operation. @@ -12600,6 +12607,20 @@ bool SITargetLowering::isCanonicalized(SelectionDAG &DAG, SDValue Op, case ISD::FCOPYSIGN: return isCanonicalized(DAG, Op.getOperand(0), MaxDepth - 1); + case ISD::AND: + if (Op.getValueType() == MVT::i32) { + // Be careful as we only know it is a bitcast floating point type. It + // could be f32, v2f16, we have no way of knowing. Luckily the constant + // value that we optimize for, which comes up in fp32 to bf16 conversions, + // is valid to optimize for all types. + if (auto *RHS = dyn_cast(Op.getOperand(1))) { + if (RHS->getZExtValue() == 0xffff0000) { + return isCanonicalized(DAG, Op.getOperand(0), MaxDepth - 1); + } + } + } + break; + case ISD::FSIN: case ISD::FCOS: case ISD::FSINCOS: @@ -12665,6 +12686,9 @@ bool SITargetLowering::isCanonicalized(SelectionDAG &DAG, SDValue Op, return false; case ISD::BITCAST: + // TODO: This is incorrect as it loses track of the operand's type. We may + // end up effectively bitcasting from f32 to v2f16 or vice versa, and the + // same bits that are canonicalized in one type need not be in the other. return isCanonicalized(DAG, Op.getOperand(0), MaxDepth - 1); case ISD::TRUNCATE: { // Hack round the mess we make when legalizing extract_vector_elt @@ -12694,25 +12718,26 @@ bool SITargetLowering::isCanonicalized(SelectionDAG &DAG, SDValue Op, case Intrinsic::amdgcn_trig_preop: case Intrinsic::amdgcn_log: case Intrinsic::amdgcn_exp2: + case Intrinsic::amdgcn_sqrt: return true; default: break; } - [[fallthrough]]; + break; } default: - // FIXME: denormalsEnabledForType is broken for dynamic - return denormalsEnabledForType(DAG, Op.getValueType()) && - DAG.isKnownNeverSNaN(Op); + break; } - llvm_unreachable("invalid operation"); + // FIXME: denormalsEnabledForType is broken for dynamic + return denormalsEnabledForType(DAG, Op.getValueType()) && + DAG.isKnownNeverSNaN(Op); } -bool SITargetLowering::isCanonicalized(Register Reg, MachineFunction &MF, +bool SITargetLowering::isCanonicalized(Register Reg, const MachineFunction &MF, unsigned MaxDepth) const { - MachineRegisterInfo &MRI = MF.getRegInfo(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); MachineInstr *MI = MRI.getVRegDef(Reg); unsigned Opcode = MI->getOpcode(); @@ -12931,27 +12956,7 @@ SDValue SITargetLowering::performFCanonicalizeCombine( } } - unsigned SrcOpc = N0.getOpcode(); - - // If it's free to do so, push canonicalizes further up the source, which may - // find a canonical source. - // - // TODO: More opcodes. Note this is unsafe for the _ieee minnum/maxnum for - // sNaNs. - if (SrcOpc == ISD::FMINNUM || SrcOpc == ISD::FMAXNUM) { - auto *CRHS = dyn_cast(N0.getOperand(1)); - if (CRHS && N0.hasOneUse()) { - SDLoc SL(N); - SDValue Canon0 = DAG.getNode(ISD::FCANONICALIZE, SL, VT, - N0.getOperand(0)); - SDValue Canon1 = getCanonicalConstantFP(DAG, SL, VT, CRHS->getValueAPF()); - DCI.AddToWorklist(Canon0.getNode()); - - return DAG.getNode(N0.getOpcode(), SL, VT, Canon0, Canon1); - } - } - - return isCanonicalized(DAG, N0) ? N0 : SDValue(); + return SDValue(); } static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc) { @@ -15939,8 +15944,8 @@ bool SITargetLowering::denormalsEnabledForType(const SelectionDAG &DAG, } } -bool SITargetLowering::denormalsEnabledForType(LLT Ty, - MachineFunction &MF) const { +bool SITargetLowering::denormalsEnabledForType( + LLT Ty, const MachineFunction &MF) const { switch (Ty.getScalarSizeInBits()) { case 32: return !denormalModeIsFlushAllF32(MF); diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h index a20442e3737e..89da4428e3ab 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.h +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h @@ -523,10 +523,10 @@ public: bool isCanonicalized(SelectionDAG &DAG, SDValue Op, unsigned MaxDepth = 5) const; - bool isCanonicalized(Register Reg, MachineFunction &MF, + bool isCanonicalized(Register Reg, const MachineFunction &MF, unsigned MaxDepth = 5) const; bool denormalsEnabledForType(const SelectionDAG &DAG, EVT VT) const; - bool denormalsEnabledForType(LLT Ty, MachineFunction &MF) const; + bool denormalsEnabledForType(LLT Ty, const MachineFunction &MF) const; bool checkForPhysRegDependency(SDNode *Def, SDNode *User, unsigned Op, const TargetRegisterInfo *TRI, diff --git a/llvm/lib/Target/AMDGPU/SIInstructions.td b/llvm/lib/Target/AMDGPU/SIInstructions.td index 33c93cdf20c4..3ab788406ecb 100644 --- a/llvm/lib/Target/AMDGPU/SIInstructions.td +++ b/llvm/lib/Target/AMDGPU/SIInstructions.td @@ -2944,6 +2944,34 @@ def : GCNPat< (V_BFREV_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$a, sub1))), sub0, (V_BFREV_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$a, sub0))), sub1)>; +// If fcanonicalize's operand is implicitly canonicalized, we only need a copy. +let AddedComplexity = 1000 in { +def : GCNPat< + (is_canonicalized_1 f16:$src), + (COPY f16:$src) +>; + +def : GCNPat< + (is_canonicalized_1 v2f16:$src), + (COPY v2f16:$src) +>; + +def : GCNPat< + (is_canonicalized_1 f32:$src), + (COPY f32:$src) +>; + +def : GCNPat< + (is_canonicalized_1 v2f32:$src), + (COPY v2f32:$src) +>; + +def : GCNPat< + (is_canonicalized_1 f64:$src), + (COPY f64:$src) +>; +} + // Prefer selecting to max when legal, but using mul is always valid. let AddedComplexity = -5 in { @@ -3277,8 +3305,8 @@ def : GCNPat < let AddedComplexity = 5 in { def : GCNPat < - (v2f16 (is_canonicalized (f16 (VOP3Mods (f16 VGPR_32:$src0), i32:$src0_mods)), - (f16 (VOP3Mods (f16 VGPR_32:$src1), i32:$src1_mods)))), + (v2f16 (is_canonicalized_2 (f16 (VOP3Mods (f16 VGPR_32:$src0), i32:$src0_mods)), + (f16 (VOP3Mods (f16 VGPR_32:$src1), i32:$src1_mods)))), (V_PACK_B32_F16_e64 $src0_mods, VGPR_32:$src0, $src1_mods, VGPR_32:$src1) >; } @@ -3590,6 +3618,17 @@ FPMinMaxPat; +class +FPMinCanonMaxPat : GCNPat < + (min_or_max (is_canonicalized_1 + (max_or_min_oneuse (VOP3Mods vt:$src0, i32:$src0_mods), + (VOP3Mods vt:$src1, i32:$src1_mods))), + (vt (VOP3Mods vt:$src2, i32:$src2_mods))), + (minmaxInst $src0_mods, $src0, $src1_mods, $src1, $src2_mods, $src2, + DSTCLAMP.NONE, DSTOMOD.NONE) +>; + let OtherPredicates = [isGFX11Plus] in { def : IntMinMaxPat; def : IntMinMaxPat; @@ -3599,6 +3638,10 @@ def : FPMinMaxPat; def : FPMinMaxPat; def : FPMinMaxPat; def : FPMinMaxPat; +def : FPMinCanonMaxPat; +def : FPMinCanonMaxPat; +def : FPMinCanonMaxPat; +def : FPMinCanonMaxPat; } let OtherPredicates = [isGFX9Plus] in { @@ -3612,6 +3655,10 @@ def : FPMinMaxPat, fmi def : FPMinMaxPat, fmaximum_oneuse>; def : FPMinMaxPat, fminimum_oneuse>; def : FPMinMaxPat, fmaximum_oneuse>; +def : FPMinCanonMaxPat, fminimum_oneuse>; +def : FPMinCanonMaxPat, fmaximum_oneuse>; +def : FPMinCanonMaxPat, fminimum_oneuse>; +def : FPMinCanonMaxPat, fmaximum_oneuse>; } // Convert a floating-point power of 2 to the integer exponent. diff --git a/llvm/test/CodeGen/AMDGPU/bf16.ll b/llvm/test/CodeGen/AMDGPU/bf16.ll index ebb77c13c4af..98658834e897 100644 --- a/llvm/test/CodeGen/AMDGPU/bf16.ll +++ b/llvm/test/CodeGen/AMDGPU/bf16.ll @@ -16968,7 +16968,7 @@ define bfloat @v_fabs_bf16(bfloat %a) { ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e64 v0, 1.0, |v0| +; GCN-NEXT: v_and_b32_e32 v0, 0x7fffffff, v0 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: s_setpc_b64 s[30:31] ; @@ -16977,7 +16977,7 @@ define bfloat @v_fabs_bf16(bfloat %a) { ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e64 v0, 1.0, |v0| +; GFX7-NEXT: v_and_b32_e32 v0, 0x7fffffff, v0 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: s_setpc_b64 s[30:31] ; @@ -17163,9 +17163,9 @@ define bfloat @v_fneg_fabs_bf16(bfloat %a) { ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e64 v0, 1.0, |v0| +; GCN-NEXT: v_and_b32_e32 v0, 0x7fffffff, v0 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v0, -1.0, v0 +; GCN-NEXT: v_xor_b32_e32 v0, 0x80000000, v0 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: s_setpc_b64 s[30:31] ; @@ -17174,9 +17174,9 @@ define bfloat @v_fneg_fabs_bf16(bfloat %a) { ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e64 v0, 1.0, |v0| +; GFX7-NEXT: v_and_b32_e32 v0, 0x7fffffff, v0 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v0, -1.0, v0 +; GFX7-NEXT: v_xor_b32_e32 v0, 0x80000000, v0 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: s_setpc_b64 s[30:31] ; @@ -17280,8 +17280,6 @@ define bfloat @v_minnum_bf16(bfloat %a, bfloat %b) { ; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_min_f32_e32 v0, v0, v1 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: s_setpc_b64 s[30:31] @@ -17293,8 +17291,6 @@ define bfloat @v_minnum_bf16(bfloat %a, bfloat %b) { ; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_min_f32_e32 v0, v0, v1 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: s_setpc_b64 s[30:31] @@ -17375,10 +17371,6 @@ define <2 x bfloat> @v_minnum_v2bf16(<2 x bfloat> %a, <2 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_min_f32_e32 v1, v1, v3 ; GCN-NEXT: v_min_f32_e32 v0, v0, v2 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 @@ -17396,10 +17388,6 @@ define <2 x bfloat> @v_minnum_v2bf16(<2 x bfloat> %a, <2 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_min_f32_e32 v1, v1, v3 ; GFX7-NEXT: v_min_f32_e32 v0, v0, v2 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 @@ -17522,12 +17510,6 @@ define <3 x bfloat> @v_minnum_v3bf16(<3 x bfloat> %a, <3 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_min_f32_e32 v2, v2, v5 ; GCN-NEXT: v_min_f32_e32 v1, v1, v4 ; GCN-NEXT: v_min_f32_e32 v0, v0, v3 @@ -17551,12 +17533,6 @@ define <3 x bfloat> @v_minnum_v3bf16(<3 x bfloat> %a, <3 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_min_f32_e32 v2, v2, v5 ; GFX7-NEXT: v_min_f32_e32 v1, v1, v4 ; GFX7-NEXT: v_min_f32_e32 v0, v0, v3 @@ -17688,14 +17664,6 @@ define <4 x bfloat> @v_minnum_v4bf16(<4 x bfloat> %a, <4 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_min_f32_e32 v3, v3, v7 ; GCN-NEXT: v_min_f32_e32 v2, v2, v6 ; GCN-NEXT: v_min_f32_e32 v1, v1, v5 @@ -17725,14 +17693,6 @@ define <4 x bfloat> @v_minnum_v4bf16(<4 x bfloat> %a, <4 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_min_f32_e32 v3, v3, v7 ; GFX7-NEXT: v_min_f32_e32 v2, v2, v6 ; GFX7-NEXT: v_min_f32_e32 v1, v1, v5 @@ -17951,22 +17911,6 @@ define <8 x bfloat> @v_minnum_v8bf16(<8 x bfloat> %a, <8 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_min_f32_e32 v7, v7, v15 ; GCN-NEXT: v_min_f32_e32 v6, v6, v14 ; GCN-NEXT: v_min_f32_e32 v5, v5, v13 @@ -18020,22 +17964,6 @@ define <8 x bfloat> @v_minnum_v8bf16(<8 x bfloat> %a, <8 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_min_f32_e32 v7, v7, v15 ; GFX7-NEXT: v_min_f32_e32 v6, v6, v14 ; GFX7-NEXT: v_min_f32_e32 v5, v5, v13 @@ -18382,71 +18310,51 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GCN-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 ; GCN-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 -; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 -; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GCN-NEXT: v_min_f32_e32 v14, v14, v30 ; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GCN-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 ; GCN-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 -; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 -; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: v_min_f32_e32 v13, v13, v29 ; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GCN-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 ; GCN-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 -; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 -; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: v_min_f32_e32 v12, v12, v28 ; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GCN-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 ; GCN-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 -; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 -; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: v_min_f32_e32 v11, v11, v27 ; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GCN-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 ; GCN-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 -; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: v_min_f32_e32 v10, v10, v26 ; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GCN-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 ; GCN-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: v_min_f32_e32 v9, v9, v25 ; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GCN-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 ; GCN-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 -; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 -; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: v_min_f32_e32 v8, v8, v24 ; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GCN-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 ; GCN-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: v_min_f32_e32 v7, v7, v23 ; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GCN-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 ; GCN-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 -; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: v_min_f32_e32 v6, v6, v22 ; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GCN-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 ; GCN-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 -; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: v_min_f32_e32 v5, v5, v21 ; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 @@ -18461,8 +18369,6 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GCN-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 ; GCN-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 -; GCN-NEXT: v_mul_f32_e32 v20, 1.0, v20 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GCN-NEXT: v_min_f32_e32 v4, v4, v20 ; GCN-NEXT: buffer_load_dword v20, off, s[0:3], s32 ; GCN-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 @@ -18474,21 +18380,10 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GCN-NEXT: v_mul_f32_e32 v19, 1.0, v19 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v18, 1.0, v18 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v17, 1.0, v17 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_min_f32_e32 v3, v3, v19 ; GCN-NEXT: v_min_f32_e32 v2, v2, v18 ; GCN-NEXT: v_min_f32_e32 v1, v1, v17 ; GCN-NEXT: v_min_f32_e32 v0, v0, v16 -; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v20 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 @@ -18503,8 +18398,9 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 ; GCN-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 ; GCN-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 +; GCN-NEXT: s_waitcnt vmcnt(0) +; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v20 ; GCN-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GCN-NEXT: v_min_f32_e32 v15, v15, v16 ; GCN-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 ; GCN-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 @@ -18513,14 +18409,12 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-LABEL: v_minnum_v16bf16: ; GFX7: ; %bb.0: ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GFX7-NEXT: v_min_f32_e32 v9, v9, v25 -; GFX7-NEXT: buffer_load_dword v25, off, s[0:3], s32 +; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 +; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 +; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 +; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 +; GFX7-NEXT: v_min_f32_e32 v6, v6, v22 +; GFX7-NEXT: buffer_load_dword v22, off, s[0:3], s32 ; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 @@ -18531,13 +18425,13 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 +; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 +; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 +; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 @@ -18560,13 +18454,13 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 ; GFX7-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 ; GFX7-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 +; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 +; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 ; GFX7-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 -; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 +; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 ; GFX7-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 ; GFX7-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 @@ -18579,48 +18473,14 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 -; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 -; GFX7-NEXT: v_mul_f32_e32 v29, 1.0, v29 -; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 -; GFX7-NEXT: v_mul_f32_e32 v28, 1.0, v28 -; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 -; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 -; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 -; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 -; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 -; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 -; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v20, 1.0, v20 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: s_waitcnt vmcnt(0) -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_mul_f32_e32 v19, 1.0, v19 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v18, 1.0, v18 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v17, 1.0, v17 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v16, 1.0, v16 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_min_f32_e32 v14, v14, v30 ; GFX7-NEXT: v_min_f32_e32 v13, v13, v29 ; GFX7-NEXT: v_min_f32_e32 v12, v12, v28 ; GFX7-NEXT: v_min_f32_e32 v11, v11, v27 ; GFX7-NEXT: v_min_f32_e32 v10, v10, v26 -; GFX7-NEXT: v_min_f32_e32 v15, v15, v25 +; GFX7-NEXT: v_min_f32_e32 v9, v9, v25 ; GFX7-NEXT: v_min_f32_e32 v8, v8, v24 ; GFX7-NEXT: v_min_f32_e32 v7, v7, v23 -; GFX7-NEXT: v_min_f32_e32 v6, v6, v22 ; GFX7-NEXT: v_min_f32_e32 v5, v5, v21 ; GFX7-NEXT: v_min_f32_e32 v4, v4, v20 ; GFX7-NEXT: v_min_f32_e32 v3, v3, v19 @@ -18634,6 +18494,10 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 ; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 +; GFX7-NEXT: s_waitcnt vmcnt(0) +; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 +; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 +; GFX7-NEXT: v_min_f32_e32 v15, v15, v22 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 @@ -19267,287 +19131,223 @@ define <32 x bfloat> @v_minnum_v32bf16(<32 x bfloat> %a, <32 x bfloat> %b) { ; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 ; GCN-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 -; GCN-NEXT: v_mul_f32_e32 v31, 1.0, v31 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:124 ; GCN-NEXT: v_min_f32_e32 v31, v31, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:124 ; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GCN-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 -; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:120 ; GCN-NEXT: v_min_f32_e32 v30, v30, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:120 ; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GCN-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 -; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:116 ; GCN-NEXT: v_min_f32_e32 v29, v29, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:116 ; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GCN-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 -; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:112 ; GCN-NEXT: v_min_f32_e32 v28, v28, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:112 ; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GCN-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 -; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:108 ; GCN-NEXT: v_min_f32_e32 v27, v27, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:108 ; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GCN-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 -; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:104 ; GCN-NEXT: v_min_f32_e32 v26, v26, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:104 ; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GCN-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:100 ; GCN-NEXT: v_min_f32_e32 v25, v25, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:100 ; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GCN-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 -; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:96 ; GCN-NEXT: v_min_f32_e32 v24, v24, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:96 ; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GCN-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 -; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:92 ; GCN-NEXT: v_min_f32_e32 v23, v23, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:92 ; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GCN-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 -; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:88 ; GCN-NEXT: v_min_f32_e32 v22, v22, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:88 ; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GCN-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 -; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:84 ; GCN-NEXT: v_min_f32_e32 v21, v21, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:84 ; GCN-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GCN-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 -; GCN-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:80 ; GCN-NEXT: v_min_f32_e32 v20, v20, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:80 ; GCN-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GCN-NEXT: v_and_b32_e32 v19, 0xffff0000, v19 -; GCN-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:76 ; GCN-NEXT: v_min_f32_e32 v19, v19, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:76 ; GCN-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GCN-NEXT: v_and_b32_e32 v18, 0xffff0000, v18 -; GCN-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:72 ; GCN-NEXT: v_min_f32_e32 v18, v18, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:72 ; GCN-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GCN-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 -; GCN-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:68 ; GCN-NEXT: v_min_f32_e32 v17, v17, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:68 ; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GCN-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:64 ; GCN-NEXT: v_min_f32_e32 v16, v16, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:64 ; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GCN-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 -; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:60 ; GCN-NEXT: v_min_f32_e32 v15, v15, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:60 ; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GCN-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 -; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:56 ; GCN-NEXT: v_min_f32_e32 v14, v14, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:56 ; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 -; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:52 ; GCN-NEXT: v_min_f32_e32 v13, v13, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:52 ; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 -; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:48 ; GCN-NEXT: v_min_f32_e32 v12, v12, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:48 ; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 -; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:44 ; GCN-NEXT: v_min_f32_e32 v11, v11, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:44 ; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:40 ; GCN-NEXT: v_min_f32_e32 v10, v10, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:40 ; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:36 ; GCN-NEXT: v_min_f32_e32 v9, v9, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:36 ; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 -; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:32 ; GCN-NEXT: v_min_f32_e32 v8, v8, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:32 ; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:28 ; GCN-NEXT: v_min_f32_e32 v7, v7, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:28 ; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:24 ; GCN-NEXT: v_min_f32_e32 v6, v6, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:24 ; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:20 ; GCN-NEXT: v_min_f32_e32 v5, v5, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:20 ; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GCN-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:16 ; GCN-NEXT: v_min_f32_e32 v4, v4, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:16 ; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GCN-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:12 ; GCN-NEXT: v_min_f32_e32 v3, v3, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:12 ; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GCN-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:8 ; GCN-NEXT: v_min_f32_e32 v2, v2, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:8 ; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:4 ; GCN-NEXT: v_min_f32_e32 v1, v1, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:4 ; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GCN-NEXT: v_min_f32_e32 v0, v0, v32 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 @@ -19590,322 +19390,258 @@ define <32 x bfloat> @v_minnum_v32bf16(<32 x bfloat> %a, <32 x bfloat> %b) { ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:128 ; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GFX7-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 -; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GFX7-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GFX7-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 -; GFX7-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GFX7-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GFX7-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 -; GFX7-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GFX7-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 -; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GFX7-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 -; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GFX7-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 -; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GFX7-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 -; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 -; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GFX7-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 -; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GFX7-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GFX7-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 -; GFX7-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GFX7-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GFX7-NEXT: v_and_b32_e32 v19, 0xffff0000, v19 -; GFX7-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GFX7-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GFX7-NEXT: v_and_b32_e32 v18, 0xffff0000, v18 -; GFX7-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GFX7-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GFX7-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 -; GFX7-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GFX7-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GFX7-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 -; GFX7-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GFX7-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 -; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GFX7-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 -; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GFX7-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 -; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GFX7-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 -; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GFX7-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 -; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: s_waitcnt vmcnt(1) -; GFX7-NEXT: v_mul_f32_e32 v31, 1.0, v31 -; GFX7-NEXT: s_waitcnt vmcnt(0) -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 -; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 -; GFX7-NEXT: v_mul_f32_e32 v31, 1.0, v31 -; GFX7-NEXT: v_min_f32_e32 v31, v31, v32 -; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:124 ; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 +; GFX7-NEXT: s_waitcnt vmcnt(1) +; GFX7-NEXT: v_mul_f32_e32 v31, 1.0, v31 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 +; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 +; GFX7-NEXT: v_min_f32_e32 v31, v31, v32 +; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:124 +; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 +; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 ; GFX7-NEXT: v_min_f32_e32 v30, v30, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:120 ; GFX7-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v29, v29, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:116 ; GFX7-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v28, v28, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:112 ; GFX7-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v27, v27, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:108 ; GFX7-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v26, v26, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:104 ; GFX7-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v25, v25, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:100 ; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v24, v24, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:96 ; GFX7-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v23, v23, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:92 ; GFX7-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v22, v22, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:88 ; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v21, v21, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:84 ; GFX7-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v20, v20, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:80 ; GFX7-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v19, v19, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:76 ; GFX7-NEXT: v_and_b32_e32 v19, 0xffff0000, v19 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v18, v18, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:72 ; GFX7-NEXT: v_and_b32_e32 v18, 0xffff0000, v18 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v17, v17, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:68 ; GFX7-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v16, v16, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:64 ; GFX7-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v15, v15, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:60 ; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v14, v14, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:56 ; GFX7-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v13, v13, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:52 ; GFX7-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v12, v12, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:48 ; GFX7-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v11, v11, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:44 ; GFX7-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v10, v10, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:40 ; GFX7-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v9, v9, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:36 ; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v8, v8, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:32 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v7, v7, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:28 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v6, v6, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:24 ; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v5, v5, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:20 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v4, v4, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:16 ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v3, v3, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:12 ; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v2, v2, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:8 ; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v1, v1, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:4 ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v0, v0, v32 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: s_setpc_b64 s[30:31] @@ -21097,8 +20833,6 @@ define bfloat @v_maxnum_bf16(bfloat %a, bfloat %b) { ; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_max_f32_e32 v0, v0, v1 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: s_setpc_b64 s[30:31] @@ -21110,8 +20844,6 @@ define bfloat @v_maxnum_bf16(bfloat %a, bfloat %b) { ; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_max_f32_e32 v0, v0, v1 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: s_setpc_b64 s[30:31] @@ -21192,10 +20924,6 @@ define <2 x bfloat> @v_maxnum_v2bf16(<2 x bfloat> %a, <2 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_max_f32_e32 v1, v1, v3 ; GCN-NEXT: v_max_f32_e32 v0, v0, v2 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 @@ -21213,10 +20941,6 @@ define <2 x bfloat> @v_maxnum_v2bf16(<2 x bfloat> %a, <2 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_max_f32_e32 v1, v1, v3 ; GFX7-NEXT: v_max_f32_e32 v0, v0, v2 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 @@ -21339,12 +21063,6 @@ define <3 x bfloat> @v_maxnum_v3bf16(<3 x bfloat> %a, <3 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_max_f32_e32 v2, v2, v5 ; GCN-NEXT: v_max_f32_e32 v1, v1, v4 ; GCN-NEXT: v_max_f32_e32 v0, v0, v3 @@ -21368,12 +21086,6 @@ define <3 x bfloat> @v_maxnum_v3bf16(<3 x bfloat> %a, <3 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_max_f32_e32 v2, v2, v5 ; GFX7-NEXT: v_max_f32_e32 v1, v1, v4 ; GFX7-NEXT: v_max_f32_e32 v0, v0, v3 @@ -21505,14 +21217,6 @@ define <4 x bfloat> @v_maxnum_v4bf16(<4 x bfloat> %a, <4 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_max_f32_e32 v3, v3, v7 ; GCN-NEXT: v_max_f32_e32 v2, v2, v6 ; GCN-NEXT: v_max_f32_e32 v1, v1, v5 @@ -21542,14 +21246,6 @@ define <4 x bfloat> @v_maxnum_v4bf16(<4 x bfloat> %a, <4 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_max_f32_e32 v3, v3, v7 ; GFX7-NEXT: v_max_f32_e32 v2, v2, v6 ; GFX7-NEXT: v_max_f32_e32 v1, v1, v5 @@ -21768,22 +21464,6 @@ define <8 x bfloat> @v_maxnum_v8bf16(<8 x bfloat> %a, <8 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_max_f32_e32 v7, v7, v15 ; GCN-NEXT: v_max_f32_e32 v6, v6, v14 ; GCN-NEXT: v_max_f32_e32 v5, v5, v13 @@ -21837,22 +21517,6 @@ define <8 x bfloat> @v_maxnum_v8bf16(<8 x bfloat> %a, <8 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_max_f32_e32 v7, v7, v15 ; GFX7-NEXT: v_max_f32_e32 v6, v6, v14 ; GFX7-NEXT: v_max_f32_e32 v5, v5, v13 @@ -22199,71 +21863,51 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GCN-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 ; GCN-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 -; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 -; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GCN-NEXT: v_max_f32_e32 v14, v14, v30 ; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GCN-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 ; GCN-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 -; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 -; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: v_max_f32_e32 v13, v13, v29 ; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GCN-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 ; GCN-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 -; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 -; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: v_max_f32_e32 v12, v12, v28 ; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GCN-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 ; GCN-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 -; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 -; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: v_max_f32_e32 v11, v11, v27 ; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GCN-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 ; GCN-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 -; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: v_max_f32_e32 v10, v10, v26 ; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GCN-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 ; GCN-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: v_max_f32_e32 v9, v9, v25 ; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GCN-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 ; GCN-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 -; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 -; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: v_max_f32_e32 v8, v8, v24 ; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GCN-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 ; GCN-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: v_max_f32_e32 v7, v7, v23 ; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GCN-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 ; GCN-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 -; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: v_max_f32_e32 v6, v6, v22 ; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GCN-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 ; GCN-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 -; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: v_max_f32_e32 v5, v5, v21 ; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 @@ -22278,8 +21922,6 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GCN-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 ; GCN-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 -; GCN-NEXT: v_mul_f32_e32 v20, 1.0, v20 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GCN-NEXT: v_max_f32_e32 v4, v4, v20 ; GCN-NEXT: buffer_load_dword v20, off, s[0:3], s32 ; GCN-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 @@ -22291,21 +21933,10 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GCN-NEXT: v_mul_f32_e32 v19, 1.0, v19 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v18, 1.0, v18 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v17, 1.0, v17 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_max_f32_e32 v3, v3, v19 ; GCN-NEXT: v_max_f32_e32 v2, v2, v18 ; GCN-NEXT: v_max_f32_e32 v1, v1, v17 ; GCN-NEXT: v_max_f32_e32 v0, v0, v16 -; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v20 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 @@ -22320,8 +21951,9 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 ; GCN-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 ; GCN-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 +; GCN-NEXT: s_waitcnt vmcnt(0) +; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v20 ; GCN-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GCN-NEXT: v_max_f32_e32 v15, v15, v16 ; GCN-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 ; GCN-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 @@ -22330,14 +21962,12 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-LABEL: v_maxnum_v16bf16: ; GFX7: ; %bb.0: ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GFX7-NEXT: v_max_f32_e32 v9, v9, v25 -; GFX7-NEXT: buffer_load_dword v25, off, s[0:3], s32 +; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 +; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 +; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 +; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 +; GFX7-NEXT: v_max_f32_e32 v6, v6, v22 +; GFX7-NEXT: buffer_load_dword v22, off, s[0:3], s32 ; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 @@ -22348,13 +21978,13 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 +; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 +; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 +; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 @@ -22377,13 +22007,13 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 ; GFX7-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 ; GFX7-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 +; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 +; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 ; GFX7-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 -; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 +; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 ; GFX7-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 ; GFX7-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 @@ -22392,52 +22022,18 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 ; GFX7-NEXT: v_and_b32_e32 v18, 0xffff0000, v18 ; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 -; GFX7-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 -; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 -; GFX7-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 -; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 -; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 -; GFX7-NEXT: v_mul_f32_e32 v29, 1.0, v29 -; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 -; GFX7-NEXT: v_mul_f32_e32 v28, 1.0, v28 -; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 -; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 -; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 -; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 -; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 -; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 -; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v20, 1.0, v20 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: s_waitcnt vmcnt(0) -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_mul_f32_e32 v19, 1.0, v19 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v18, 1.0, v18 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v17, 1.0, v17 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v16, 1.0, v16 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 +; GFX7-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 +; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 +; GFX7-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 +; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: v_max_f32_e32 v14, v14, v30 ; GFX7-NEXT: v_max_f32_e32 v13, v13, v29 ; GFX7-NEXT: v_max_f32_e32 v12, v12, v28 ; GFX7-NEXT: v_max_f32_e32 v11, v11, v27 ; GFX7-NEXT: v_max_f32_e32 v10, v10, v26 -; GFX7-NEXT: v_max_f32_e32 v15, v15, v25 +; GFX7-NEXT: v_max_f32_e32 v9, v9, v25 ; GFX7-NEXT: v_max_f32_e32 v8, v8, v24 ; GFX7-NEXT: v_max_f32_e32 v7, v7, v23 -; GFX7-NEXT: v_max_f32_e32 v6, v6, v22 ; GFX7-NEXT: v_max_f32_e32 v5, v5, v21 ; GFX7-NEXT: v_max_f32_e32 v4, v4, v20 ; GFX7-NEXT: v_max_f32_e32 v3, v3, v19 @@ -22451,6 +22047,10 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 ; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 +; GFX7-NEXT: s_waitcnt vmcnt(0) +; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 +; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 +; GFX7-NEXT: v_max_f32_e32 v15, v15, v22 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 @@ -23084,287 +22684,223 @@ define <32 x bfloat> @v_maxnum_v32bf16(<32 x bfloat> %a, <32 x bfloat> %b) { ; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 ; GCN-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 -; GCN-NEXT: v_mul_f32_e32 v31, 1.0, v31 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:124 ; GCN-NEXT: v_max_f32_e32 v31, v31, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:124 ; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GCN-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 -; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:120 ; GCN-NEXT: v_max_f32_e32 v30, v30, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:120 ; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GCN-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 -; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:116 ; GCN-NEXT: v_max_f32_e32 v29, v29, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:116 ; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GCN-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 -; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:112 ; GCN-NEXT: v_max_f32_e32 v28, v28, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:112 ; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GCN-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 -; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:108 ; GCN-NEXT: v_max_f32_e32 v27, v27, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:108 ; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GCN-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 -; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:104 ; GCN-NEXT: v_max_f32_e32 v26, v26, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:104 ; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GCN-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:100 ; GCN-NEXT: v_max_f32_e32 v25, v25, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:100 ; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GCN-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 -; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:96 ; GCN-NEXT: v_max_f32_e32 v24, v24, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:96 ; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GCN-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 -; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:92 ; GCN-NEXT: v_max_f32_e32 v23, v23, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:92 ; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GCN-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 -; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:88 ; GCN-NEXT: v_max_f32_e32 v22, v22, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:88 ; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GCN-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 -; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:84 ; GCN-NEXT: v_max_f32_e32 v21, v21, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:84 ; GCN-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GCN-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 -; GCN-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:80 ; GCN-NEXT: v_max_f32_e32 v20, v20, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:80 ; GCN-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GCN-NEXT: v_and_b32_e32 v19, 0xffff0000, v19 -; GCN-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:76 ; GCN-NEXT: v_max_f32_e32 v19, v19, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:76 ; GCN-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GCN-NEXT: v_and_b32_e32 v18, 0xffff0000, v18 -; GCN-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:72 ; GCN-NEXT: v_max_f32_e32 v18, v18, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:72 ; GCN-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GCN-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 -; GCN-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:68 ; GCN-NEXT: v_max_f32_e32 v17, v17, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:68 ; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GCN-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:64 ; GCN-NEXT: v_max_f32_e32 v16, v16, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:64 ; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GCN-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 -; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:60 ; GCN-NEXT: v_max_f32_e32 v15, v15, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:60 ; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GCN-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 -; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:56 ; GCN-NEXT: v_max_f32_e32 v14, v14, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:56 ; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 -; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:52 ; GCN-NEXT: v_max_f32_e32 v13, v13, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:52 ; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 -; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:48 ; GCN-NEXT: v_max_f32_e32 v12, v12, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:48 ; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 -; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:44 ; GCN-NEXT: v_max_f32_e32 v11, v11, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:44 ; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:40 ; GCN-NEXT: v_max_f32_e32 v10, v10, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:40 ; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:36 ; GCN-NEXT: v_max_f32_e32 v9, v9, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:36 ; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 -; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:32 ; GCN-NEXT: v_max_f32_e32 v8, v8, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:32 ; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:28 ; GCN-NEXT: v_max_f32_e32 v7, v7, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:28 ; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:24 ; GCN-NEXT: v_max_f32_e32 v6, v6, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:24 ; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:20 ; GCN-NEXT: v_max_f32_e32 v5, v5, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:20 ; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GCN-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:16 ; GCN-NEXT: v_max_f32_e32 v4, v4, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:16 ; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GCN-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:12 ; GCN-NEXT: v_max_f32_e32 v3, v3, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:12 ; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GCN-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:8 ; GCN-NEXT: v_max_f32_e32 v2, v2, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:8 ; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:4 ; GCN-NEXT: v_max_f32_e32 v1, v1, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:4 ; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GCN-NEXT: v_max_f32_e32 v0, v0, v32 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 @@ -23407,322 +22943,258 @@ define <32 x bfloat> @v_maxnum_v32bf16(<32 x bfloat> %a, <32 x bfloat> %b) { ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:128 ; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GFX7-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 -; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GFX7-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GFX7-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 -; GFX7-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GFX7-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GFX7-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 -; GFX7-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GFX7-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 -; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GFX7-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 -; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GFX7-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 -; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GFX7-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 -; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 -; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GFX7-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 -; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GFX7-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GFX7-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 -; GFX7-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GFX7-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GFX7-NEXT: v_and_b32_e32 v19, 0xffff0000, v19 -; GFX7-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GFX7-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GFX7-NEXT: v_and_b32_e32 v18, 0xffff0000, v18 -; GFX7-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GFX7-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GFX7-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 -; GFX7-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GFX7-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GFX7-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 -; GFX7-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GFX7-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 -; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GFX7-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 -; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GFX7-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 -; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GFX7-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 -; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GFX7-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 -; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: s_waitcnt vmcnt(1) -; GFX7-NEXT: v_mul_f32_e32 v31, 1.0, v31 -; GFX7-NEXT: s_waitcnt vmcnt(0) -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 -; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 -; GFX7-NEXT: v_mul_f32_e32 v31, 1.0, v31 -; GFX7-NEXT: v_max_f32_e32 v31, v31, v32 -; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:124 ; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 +; GFX7-NEXT: s_waitcnt vmcnt(1) +; GFX7-NEXT: v_mul_f32_e32 v31, 1.0, v31 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 +; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 +; GFX7-NEXT: v_max_f32_e32 v31, v31, v32 +; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:124 +; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 +; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 ; GFX7-NEXT: v_max_f32_e32 v30, v30, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:120 ; GFX7-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v29, v29, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:116 ; GFX7-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v28, v28, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:112 ; GFX7-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v27, v27, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:108 ; GFX7-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v26, v26, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:104 ; GFX7-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v25, v25, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:100 ; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v24, v24, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:96 ; GFX7-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v23, v23, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:92 ; GFX7-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v22, v22, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:88 ; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v21, v21, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:84 ; GFX7-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v20, v20, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:80 ; GFX7-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v19, v19, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:76 ; GFX7-NEXT: v_and_b32_e32 v19, 0xffff0000, v19 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v18, v18, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:72 ; GFX7-NEXT: v_and_b32_e32 v18, 0xffff0000, v18 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v17, v17, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:68 ; GFX7-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v16, v16, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:64 ; GFX7-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v15, v15, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:60 ; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v14, v14, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:56 ; GFX7-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v13, v13, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:52 ; GFX7-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v12, v12, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:48 ; GFX7-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v11, v11, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:44 ; GFX7-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v10, v10, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:40 ; GFX7-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v9, v9, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:36 ; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v8, v8, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:32 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v7, v7, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:28 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v6, v6, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:24 ; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v5, v5, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:20 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v4, v4, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:16 ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v3, v3, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:12 ; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v2, v2, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:8 ; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v1, v1, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:4 ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v0, v0, v32 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: s_setpc_b64 s[30:31] @@ -25176,7 +24648,6 @@ define { bfloat, i16 } @v_frexp_bf16_i16(bfloat %a) { ; GCN-NEXT: v_frexp_exp_i32_f32_e32 v2, v0 ; GCN-NEXT: v_cmp_lt_f32_e64 vcc, |v0|, s4 ; GCN-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_cndmask_b32_e32 v1, 0, v2, vcc ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: s_setpc_b64 s[30:31] @@ -26818,11 +26289,17 @@ define bfloat @v_canonicalize_bf16(bfloat %a) { ; GCN-LABEL: v_canonicalize_bf16: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 +; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 +; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: s_setpc_b64 s[30:31] ; ; GFX7-LABEL: v_canonicalize_bf16: ; GFX7: ; %bb.0: ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 +; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 +; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: s_setpc_b64 s[30:31] ; ; GFX8-LABEL: v_canonicalize_bf16: diff --git a/llvm/test/CodeGen/AMDGPU/clamp.ll b/llvm/test/CodeGen/AMDGPU/clamp.ll index dfadd8d205b0..947284506a29 100644 --- a/llvm/test/CodeGen/AMDGPU/clamp.ll +++ b/llvm/test/CodeGen/AMDGPU/clamp.ll @@ -2996,18 +2996,16 @@ define amdgpu_kernel void @v_clamp_v2f16_undef_elt(ptr addrspace(1) %out, ptr ad ; GFX6-NEXT: v_mov_b32_e32 v4, 0x7fc00000 ; GFX6-NEXT: s_mov_b64 s[2:3], s[6:7] ; GFX6-NEXT: s_waitcnt vmcnt(0) -; GFX6-NEXT: v_cvt_f32_f16_e32 v3, v2 -; GFX6-NEXT: v_lshrrev_b32_e32 v2, 16, v2 +; GFX6-NEXT: v_lshrrev_b32_e32 v3, 16, v2 ; GFX6-NEXT: v_cvt_f32_f16_e32 v2, v2 -; GFX6-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX6-NEXT: v_max_f32_e32 v3, 0x7fc00000, v3 -; GFX6-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX6-NEXT: v_med3_f32 v2, v2, 0, v4 -; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 -; GFX6-NEXT: v_min_f32_e32 v3, 1.0, v3 +; GFX6-NEXT: v_cvt_f32_f16_e32 v3, v3 +; GFX6-NEXT: v_max_f32_e32 v2, 0x7fc00000, v2 +; GFX6-NEXT: v_med3_f32 v3, v3, 0, v4 ; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v3 -; GFX6-NEXT: v_lshlrev_b32_e32 v2, 16, v2 -; GFX6-NEXT: v_or_b32_e32 v2, v3, v2 +; GFX6-NEXT: v_min_f32_e32 v2, 1.0, v2 +; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 +; GFX6-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; GFX6-NEXT: v_or_b32_e32 v2, v2, v3 ; GFX6-NEXT: buffer_store_dword v2, v[0:1], s[0:3], 0 addr64 ; GFX6-NEXT: s_endpgm ; @@ -3095,16 +3093,15 @@ define amdgpu_kernel void @v_clamp_v2f16_not_zero(ptr addrspace(1) %out, ptr add ; GFX6-NEXT: buffer_load_dword v2, v[0:1], s[4:7], 0 addr64 ; GFX6-NEXT: s_mov_b64 s[2:3], s[6:7] ; GFX6-NEXT: s_waitcnt vmcnt(0) -; GFX6-NEXT: v_cvt_f32_f16_e32 v3, v2 -; GFX6-NEXT: v_lshrrev_b32_e32 v2, 16, v2 -; GFX6-NEXT: v_cvt_f32_f16_e64 v2, v2 clamp -; GFX6-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX6-NEXT: v_max_f32_e32 v3, 2.0, v3 -; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 -; GFX6-NEXT: v_min_f32_e32 v3, 1.0, v3 +; GFX6-NEXT: v_lshrrev_b32_e32 v3, 16, v2 +; GFX6-NEXT: v_cvt_f32_f16_e32 v2, v2 +; GFX6-NEXT: v_cvt_f32_f16_e64 v3, v3 clamp +; GFX6-NEXT: v_max_f32_e32 v2, 2.0, v2 ; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v3 -; GFX6-NEXT: v_lshlrev_b32_e32 v2, 16, v2 -; GFX6-NEXT: v_or_b32_e32 v2, v3, v2 +; GFX6-NEXT: v_min_f32_e32 v2, 1.0, v2 +; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 +; GFX6-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; GFX6-NEXT: v_or_b32_e32 v2, v2, v3 ; GFX6-NEXT: buffer_store_dword v2, v[0:1], s[0:3], 0 addr64 ; GFX6-NEXT: s_endpgm ; @@ -3198,9 +3195,8 @@ define amdgpu_kernel void @v_clamp_v2f16_not_one(ptr addrspace(1) %out, ptr addr ; GFX6-NEXT: s_mov_b64 s[2:3], s[6:7] ; GFX6-NEXT: s_waitcnt vmcnt(0) ; GFX6-NEXT: v_lshrrev_b32_e32 v3, 16, v2 -; GFX6-NEXT: v_cvt_f32_f16_e32 v2, v2 ; GFX6-NEXT: v_cvt_f32_f16_e64 v3, v3 clamp -; GFX6-NEXT: v_mul_f32_e32 v2, 1.0, v2 +; GFX6-NEXT: v_cvt_f32_f16_e32 v2, v2 ; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v3 ; GFX6-NEXT: v_med3_f32 v2, v2, 0, 0 ; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 @@ -3760,19 +3756,17 @@ define amdgpu_kernel void @v_clamp_v2f16_undef_limit_elts0(ptr addrspace(1) %out ; GFX6-NEXT: s_waitcnt lgkmcnt(0) ; GFX6-NEXT: s_mov_b64 s[4:5], s[2:3] ; GFX6-NEXT: buffer_load_dword v2, v[0:1], s[4:7], 0 addr64 -; GFX6-NEXT: s_mov_b32 s2, 0x7fc00000 ; GFX6-NEXT: v_mov_b32_e32 v4, 0x7fc00000 +; GFX6-NEXT: s_mov_b64 s[2:3], s[6:7] ; GFX6-NEXT: s_waitcnt vmcnt(0) ; GFX6-NEXT: v_lshrrev_b32_e32 v3, 16, v2 ; GFX6-NEXT: v_cvt_f32_f16_e32 v3, v3 ; GFX6-NEXT: v_cvt_f32_f16_e32 v2, v2 -; GFX6-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX6-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX6-NEXT: v_med3_f32 v3, v3, s2, 1.0 +; GFX6-NEXT: v_max_f32_e32 v3, 0x7fc00000, v3 +; GFX6-NEXT: v_min_f32_e32 v3, 1.0, v3 ; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v3 ; GFX6-NEXT: v_med3_f32 v2, v2, 0, v4 ; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 -; GFX6-NEXT: s_mov_b64 s[2:3], s[6:7] ; GFX6-NEXT: v_lshlrev_b32_e32 v3, 16, v3 ; GFX6-NEXT: v_or_b32_e32 v2, v2, v3 ; GFX6-NEXT: buffer_store_dword v2, v[0:1], s[0:3], 0 addr64 @@ -3863,18 +3857,16 @@ define amdgpu_kernel void @v_clamp_v2f16_undef_limit_elts1(ptr addrspace(1) %out ; GFX6-NEXT: v_mov_b32_e32 v4, 0x7fc00000 ; GFX6-NEXT: s_mov_b64 s[2:3], s[6:7] ; GFX6-NEXT: s_waitcnt vmcnt(0) -; GFX6-NEXT: v_cvt_f32_f16_e32 v3, v2 -; GFX6-NEXT: v_lshrrev_b32_e32 v2, 16, v2 +; GFX6-NEXT: v_lshrrev_b32_e32 v3, 16, v2 ; GFX6-NEXT: v_cvt_f32_f16_e32 v2, v2 -; GFX6-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX6-NEXT: v_max_f32_e32 v3, 0x7fc00000, v3 -; GFX6-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX6-NEXT: v_med3_f32 v2, v2, 0, v4 -; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 -; GFX6-NEXT: v_min_f32_e32 v3, 1.0, v3 +; GFX6-NEXT: v_cvt_f32_f16_e32 v3, v3 +; GFX6-NEXT: v_max_f32_e32 v2, 0x7fc00000, v2 +; GFX6-NEXT: v_med3_f32 v3, v3, 0, v4 ; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v3 -; GFX6-NEXT: v_lshlrev_b32_e32 v2, 16, v2 -; GFX6-NEXT: v_or_b32_e32 v2, v3, v2 +; GFX6-NEXT: v_min_f32_e32 v2, 1.0, v2 +; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 +; GFX6-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; GFX6-NEXT: v_or_b32_e32 v2, v2, v3 ; GFX6-NEXT: buffer_store_dword v2, v[0:1], s[0:3], 0 addr64 ; GFX6-NEXT: s_endpgm ; diff --git a/llvm/test/CodeGen/AMDGPU/fcanonicalize-elimination.ll b/llvm/test/CodeGen/AMDGPU/fcanonicalize-elimination.ll index 4ed1b8a520b8..e1981972f58d 100644 --- a/llvm/test/CodeGen/AMDGPU/fcanonicalize-elimination.ll +++ b/llvm/test/CodeGen/AMDGPU/fcanonicalize-elimination.ll @@ -471,25 +471,15 @@ define amdgpu_kernel void @test_fold_canonicalize_minnum_value_from_load_f32_iee ret void } -; GCN-LABEL: test_fold_canonicalize_minnum_value_from_load_f32_nnan_ieee_mode: -; VI-FLUSH: v_mul_f32_e32 v{{[0-9]+}}, 1.0, v{{[0-9]+}} -; GCN-DENORM-NOT: v_max -; GCN-DENORM-NOT: v_mul - -; GCN: v_min_f32_e32 v{{[0-9]+}}, 0, v{{[0-9]+}} -; GCN-DENORM-NOT: v_max -; GCN-DENORM-NOT: v_mul - -; GFX9: {{flat|global}}_store_dword -define amdgpu_kernel void @test_fold_canonicalize_minnum_value_from_load_f32_nnan_ieee_mode(ptr addrspace(1) %arg) #1 { - %id = tail call i32 @llvm.amdgcn.workitem.id.x() - %gep = getelementptr inbounds float, ptr addrspace(1) %arg, i32 %id - %load = load float, ptr addrspace(1) %gep, align 4 - %v = tail call float @llvm.minnum.f32(float %load, float 0.0) - %canonicalized = tail call float @llvm.canonicalize.f32(float %v) - store float %canonicalized, ptr addrspace(1) %gep, align 4 - ret void -} +; define amdgpu_kernel void @test_fold_canonicalize_minnum_value_from_load_f32_nnan_ieee_mode(ptr addrspace(1) %arg) #1 { +; %id = tail call i32 @llvm.amdgcn.workitem.id.x() +; %gep = getelementptr inbounds float, ptr addrspace(1) %arg, i32 %id +; %load = load float, ptr addrspace(1) %gep, align 4 +; %v = tail call float @llvm.minnum.f32(float %load, float 0.0) +; %canonicalized = tail call float @llvm.canonicalize.f32(float %v) +; store float %canonicalized, ptr addrspace(1) %gep, align 4 +; ret void +; } ; GCN-LABEL: test_fold_canonicalize_minnum_value_f32: ; GCN: v_min_f32_e32 [[V:v[0-9]+]], 0, v{{[0-9]+}} @@ -523,32 +513,15 @@ define amdgpu_kernel void @test_fold_canonicalize_sNaN_value_f32(ptr addrspace(1 ret void } -; GCN-LABEL: test_fold_canonicalize_denorm_value_f32: -; GCN: {{flat|global}}_load_dword [[VAL:v[0-9]+]] - -; GFX9-DENORM: v_max_f32_e32 [[QUIET:v[0-9]+]], [[VAL]], [[VAL]] -; GFX9-DENORM: v_min_f32_e32 [[RESULT:v[0-9]+]], 0x7fffff, [[QUIET]] - -; GFX9-FLUSH: v_max_f32_e32 [[QUIET:v[0-9]+]], [[VAL]], [[VAL]] -; GFX9-FLUSH: v_min_f32_e32 [[RESULT:v[0-9]+]], 0, [[QUIET]] - -; VI-FLUSH: v_mul_f32_e32 [[QUIET_V0:v[0-9]+]], 1.0, [[VAL]] -; VI-FLUSH: v_min_f32_e32 [[RESULT:v[0-9]+]], 0, [[QUIET_V0]] - -; VI-DENORM: v_min_f32_e32 [[RESULT:v[0-9]+]], 0x7fffff, [[VAL]] - -; GCN-NOT: v_mul -; GCN-NOT: v_max -; GCN: {{flat|global}}_store_dword v{{.+}}, [[RESULT]] -define amdgpu_kernel void @test_fold_canonicalize_denorm_value_f32(ptr addrspace(1) %arg) { - %id = tail call i32 @llvm.amdgcn.workitem.id.x() - %gep = getelementptr inbounds float, ptr addrspace(1) %arg, i32 %id - %load = load float, ptr addrspace(1) %gep, align 4 - %v = tail call float @llvm.minnum.f32(float %load, float bitcast (i32 8388607 to float)) - %canonicalized = tail call float @llvm.canonicalize.f32(float %v) - store float %canonicalized, ptr addrspace(1) %gep, align 4 - ret void -} +; define amdgpu_kernel void @test_fold_canonicalize_denorm_value_f32(ptr addrspace(1) %arg) { +; %id = tail call i32 @llvm.amdgcn.workitem.id.x() +; %gep = getelementptr inbounds float, ptr addrspace(1) %arg, i32 %id +; %load = load float, ptr addrspace(1) %gep, align 4 +; %v = tail call float @llvm.minnum.f32(float %load, float bitcast (i32 8388607 to float)) +; %canonicalized = tail call float @llvm.canonicalize.f32(float %v) +; store float %canonicalized, ptr addrspace(1) %gep, align 4 +; ret void +; } ; GCN-LABEL: test_fold_canonicalize_maxnum_value_from_load_f32_ieee_mode: ; GCN: {{flat|global}}_load_dword [[VAL:v[0-9]+]] @@ -674,10 +647,9 @@ define amdgpu_kernel void @test_fold_canonicalize_load_nnan_value_f64(ptr addrsp } ; GCN-LABEL: {{^}}test_fold_canonicalize_load_nnan_value_f16 -; GCN: {{flat|global}}_load_ushort [[V:v[0-9]+]], -; GCN-NOT: v_mul -; GCN-NOT: v_max -; GCN: {{flat|global}}_store_short v{{.+}}, [[V]] +; GCN: {{flat|global}}_load_ushort [[V1:v[0-9]+]], +; GCN: v_max_f16_e32 [[V2:v[0-9]+]], [[V1]], [[V1]] +; GCN: {{flat|global}}_store_short v{{.+}}, [[V2]] define amdgpu_kernel void @test_fold_canonicalize_load_nnan_value_f16(ptr addrspace(1) %arg, ptr addrspace(1) %out) #1 { %id = tail call i32 @llvm.amdgcn.workitem.id.x() %gep = getelementptr inbounds half, ptr addrspace(1) %arg, i32 %id @@ -807,18 +779,13 @@ define half @v_test_canonicalize_extract_element_v2f16(<2 x half> %vec) { ret half %canonicalized } -; GCN-LABEL: {{^}}v_test_canonicalize_insertelement_v2f16: -; GFX9: v_mul_f16_e32 -; GFX9: v_pk_mul_f16 -; GFX9-NOT: v_max -; GFX9-NOT: v_pk_max -define <2 x half> @v_test_canonicalize_insertelement_v2f16(<2 x half> %vec, half %val, i32 %idx) { - %vec.op = fmul <2 x half> %vec, - %ins.op = fmul half %val, 8.0 - %ins = insertelement <2 x half> %vec.op, half %ins.op, i32 %idx - %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins) - ret <2 x half> %canonicalized -} +; define <2 x half> @v_test_canonicalize_insertelement_v2f16(<2 x half> %vec, half %val, i32 %idx) { +; %vec.op = fmul <2 x half> %vec, +; %ins.op = fmul half %val, 8.0 +; %ins = insertelement <2 x half> %vec.op, half %ins.op, i32 %idx +; %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins) +; ret <2 x half> %canonicalized +; } ; GCN-LABEL: {{^}}v_test_canonicalize_insertelement_noncanon_vec_v2f16: ; GFX9: v_mul_f16 @@ -842,15 +809,11 @@ define <2 x half> @v_test_canonicalize_insertelement_noncanon_insval_v2f16(<2 x ret <2 x half> %canonicalized } -; GCN-LABEL: {{^}}v_test_canonicalize_cvt_pkrtz: -; GCN: s_waitcnt -; GCN-NEXT: v_cvt_pkrtz_f16_f32 v0, v0, v1 -; GCN-NEXT: s_setpc_b64 -define <2 x half> @v_test_canonicalize_cvt_pkrtz(float %a, float %b) { - %cvt = call <2 x half> @llvm.amdgcn.cvt.pkrtz(float %a, float %b) - %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %cvt) - ret <2 x half> %canonicalized -} +; define <2 x half> @v_test_canonicalize_cvt_pkrtz(float %a, float %b) { +; %cvt = call <2 x half> @llvm.amdgcn.cvt.pkrtz(float %a, float %b) +; %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %cvt) +; ret <2 x half> %canonicalized +; } ; GCN-LABEL: {{^}}v_test_canonicalize_cubeid: ; GCN: s_waitcnt diff --git a/llvm/test/CodeGen/AMDGPU/fcanonicalize.f16.ll b/llvm/test/CodeGen/AMDGPU/fcanonicalize.f16.ll index 274621307f54..581b7b4cff9e 100644 --- a/llvm/test/CodeGen/AMDGPU/fcanonicalize.f16.ll +++ b/llvm/test/CodeGen/AMDGPU/fcanonicalize.f16.ll @@ -94,7 +94,6 @@ define amdgpu_kernel void @v_test_canonicalize_var_f16(ptr addrspace(1) %out) #1 ; CI-NEXT: buffer_load_ushort v0, off, s[0:3], 0 ; CI-NEXT: s_waitcnt vmcnt(0) ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; CI-NEXT: s_endpgm @@ -147,7 +146,6 @@ define amdgpu_kernel void @s_test_canonicalize_var_f16(ptr addrspace(1) %out, i1 ; CI-NEXT: s_waitcnt lgkmcnt(0) ; CI-NEXT: v_cvt_f32_f16_e32 v0, s2 ; CI-NEXT: s_mov_b32 s2, -1 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; CI-NEXT: s_endpgm @@ -170,6 +168,35 @@ define amdgpu_kernel void @s_test_canonicalize_var_f16(ptr addrspace(1) %out, i1 ret void } +define half @s_test_canonicalize_arg(half %x) #1 { +; VI-LABEL: s_test_canonicalize_arg: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_max_f16_e32 v0, v0, v0 +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: s_test_canonicalize_arg: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_max_f16_e32 v0, v0, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; CI-LABEL: s_test_canonicalize_arg: +; CI: ; %bb.0: +; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 +; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 +; CI-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: s_test_canonicalize_arg: +; GFX11: ; %bb.0: +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: v_max_f16_e32 v0, v0, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] + %canonicalized = call half @llvm.canonicalize.f16(half %x) + ret half %canonicalized +} + define <2 x half> @v_test_canonicalize_build_vector_v2f16(half %lo, half %hi) #1 { ; VI-LABEL: v_test_canonicalize_build_vector_v2f16: ; VI: ; %bb.0: @@ -242,7 +269,6 @@ define amdgpu_kernel void @v_test_canonicalize_fabs_var_f16(ptr addrspace(1) %ou ; CI-NEXT: buffer_load_ushort v0, off, s[0:3], 0 ; CI-NEXT: s_waitcnt vmcnt(0) ; CI-NEXT: v_cvt_f32_f16_e64 v0, |v0| -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; CI-NEXT: s_endpgm @@ -299,7 +325,6 @@ define amdgpu_kernel void @v_test_canonicalize_fneg_fabs_var_f16(ptr addrspace(1 ; CI-NEXT: buffer_load_ushort v0, off, s[0:3], 0 ; CI-NEXT: s_waitcnt vmcnt(0) ; CI-NEXT: v_cvt_f32_f16_e64 v0, -|v0| -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; CI-NEXT: s_endpgm @@ -357,7 +382,6 @@ define amdgpu_kernel void @v_test_canonicalize_fneg_var_f16(ptr addrspace(1) %ou ; CI-NEXT: buffer_load_ushort v0, off, s[0:3], 0 ; CI-NEXT: s_waitcnt vmcnt(0) ; CI-NEXT: v_cvt_f32_f16_e64 v0, -v0 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; CI-NEXT: s_endpgm @@ -414,7 +438,6 @@ define amdgpu_kernel void @v_test_no_denormals_canonicalize_fneg_var_f16(ptr add ; CI-NEXT: buffer_load_ushort v0, off, s[0:3], 0 ; CI-NEXT: s_waitcnt vmcnt(0) ; CI-NEXT: v_cvt_f32_f16_e64 v0, -v0 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; CI-NEXT: s_endpgm @@ -471,7 +494,6 @@ define amdgpu_kernel void @v_test_no_denormals_canonicalize_fneg_fabs_var_f16(pt ; CI-NEXT: buffer_load_ushort v0, off, s[0:3], 0 ; CI-NEXT: s_waitcnt vmcnt(0) ; CI-NEXT: v_cvt_f32_f16_e64 v0, -|v0| -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; CI-NEXT: s_endpgm @@ -1246,9 +1268,7 @@ define amdgpu_kernel void @v_test_canonicalize_var_v2f16(ptr addrspace(1) %out) ; CI-NEXT: v_lshrrev_b32_e32 v1, 16, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; CI-NEXT: v_or_b32_e32 v0, v0, v1 @@ -1323,9 +1343,7 @@ define amdgpu_kernel void @v_test_canonicalize_fabs_var_v2f16(ptr addrspace(1) % ; CI-NEXT: v_lshrrev_b32_e32 v1, 16, v0 ; CI-NEXT: v_cvt_f32_f16_e64 v1, |v1| ; CI-NEXT: v_cvt_f32_f16_e64 v0, |v0| -; CI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; CI-NEXT: v_or_b32_e32 v0, v0, v1 @@ -1404,9 +1422,7 @@ define amdgpu_kernel void @v_test_canonicalize_fneg_fabs_var_v2f16(ptr addrspace ; CI-NEXT: v_lshrrev_b32_e32 v1, 16, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; CI-NEXT: v_or_b32_e32 v0, v0, v1 @@ -1485,9 +1501,7 @@ define amdgpu_kernel void @v_test_canonicalize_fneg_var_v2f16(ptr addrspace(1) % ; CI-NEXT: v_lshrrev_b32_e32 v1, 16, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; CI-NEXT: v_or_b32_e32 v0, v0, v1 @@ -1551,9 +1565,7 @@ define amdgpu_kernel void @s_test_canonicalize_var_v2f16(ptr addrspace(1) %out, ; CI-NEXT: v_cvt_f32_f16_e32 v1, s2 ; CI-NEXT: s_mov_b32 s3, 0xf000 ; CI-NEXT: s_mov_b32 s2, -1 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; CI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 ; CI-NEXT: v_or_b32_e32 v0, v1, v0 @@ -2424,7 +2436,6 @@ define <2 x half> @v_test_canonicalize_reg_undef_v2f16(half %val) #1 { ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_mov_b32_e32 v1, 0x7fc00000 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: s_setpc_b64 s[30:31] ; ; GFX11-LABEL: v_test_canonicalize_reg_undef_v2f16: @@ -2456,8 +2467,7 @@ define <2 x half> @v_test_canonicalize_undef_reg_v2f16(half %val) #1 { ; CI: ; %bb.0: ; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v1, 1.0, v0 +; CI-NEXT: v_cvt_f32_f16_e32 v1, v0 ; CI-NEXT: v_mov_b32_e32 v0, 0x7fc00000 ; CI-NEXT: s_setpc_b64 s[30:31] ; @@ -2738,7 +2748,6 @@ define <4 x half> @v_test_canonicalize_reg_undef_undef_undef_v4f16(half %val) #1 ; CI-NEXT: v_mov_b32_e32 v2, 0x7fc00000 ; CI-NEXT: v_mov_b32_e32 v3, 0x7fc00000 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: s_setpc_b64 s[30:31] ; ; GFX11-LABEL: v_test_canonicalize_reg_undef_undef_undef_v4f16: @@ -2782,8 +2791,6 @@ define <4 x half> @v_test_canonicalize_reg_reg_undef_undef_v4f16(half %val0, hal ; CI-NEXT: v_mov_b32_e32 v3, 0x7fc00000 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; CI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; CI-NEXT: s_setpc_b64 s[30:31] ; ; GFX11-LABEL: v_test_canonicalize_reg_reg_undef_undef_v4f16: @@ -2826,13 +2833,10 @@ define <4 x half> @v_test_canonicalize_reg_undef_reg_reg_v4f16(half %val0, half ; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 -; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 +; CI-NEXT: v_cvt_f16_f32_e32 v3, v2 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; CI-NEXT: v_cvt_f32_f16_e32 v3, v2 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; CI-NEXT: v_mul_f32_e32 v2, 1.0, v1 -; CI-NEXT: v_mul_f32_e32 v3, 1.0, v3 +; CI-NEXT: v_cvt_f32_f16_e32 v2, v1 +; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 ; CI-NEXT: v_mov_b32_e32 v1, 0x7fc00000 ; CI-NEXT: s_setpc_b64 s[30:31] ; @@ -2878,18 +2882,18 @@ define <6 x half> @v_test_canonicalize_var_v6f16(<6 x half> %val) #1 { ; CI-LABEL: v_test_canonicalize_var_v6f16: ; CI: ; %bb.0: ; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 +; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 -; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 -; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 +; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 +; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v2, v2 ; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 -; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 -; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 ; CI-NEXT: s_setpc_b64 s[30:31] ; ; GFX11-LABEL: v_test_canonicalize_var_v6f16: @@ -2933,22 +2937,22 @@ define <8 x half> @v_test_canonicalize_var_v8f16(<8 x half> %val) #1 { ; CI-LABEL: v_test_canonicalize_var_v8f16: ; CI: ; %bb.0: ; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 +; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 +; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 +; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 -; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 -; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 -; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 -; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 +; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 +; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 +; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 +; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v2, v2 ; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 -; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 -; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 -; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 -; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 ; CI-NEXT: s_setpc_b64 s[30:31] ; ; GFX11-LABEL: v_test_canonicalize_var_v8f16: @@ -3001,30 +3005,30 @@ define <12 x half> @v_test_canonicalize_var_v12f16(<12 x half> %val) #1 { ; CI-LABEL: v_test_canonicalize_var_v12f16: ; CI: ; %bb.0: ; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CI-NEXT: v_cvt_f16_f32_e32 v11, v11 +; CI-NEXT: v_cvt_f16_f32_e32 v10, v10 +; CI-NEXT: v_cvt_f16_f32_e32 v9, v9 +; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 +; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 +; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 +; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 +; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 -; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 -; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 -; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 -; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 -; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 -; CI-NEXT: v_cvt_f16_f32_e32 v9, v9 -; CI-NEXT: v_cvt_f16_f32_e32 v10, v10 -; CI-NEXT: v_cvt_f16_f32_e32 v11, v11 +; CI-NEXT: v_cvt_f32_f16_e32 v11, v11 +; CI-NEXT: v_cvt_f32_f16_e32 v10, v10 +; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 +; CI-NEXT: v_cvt_f32_f16_e32 v8, v8 +; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 +; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 +; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 +; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v2, v2 ; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 -; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 -; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 -; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 -; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 -; CI-NEXT: v_cvt_f32_f16_e32 v8, v8 -; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 -; CI-NEXT: v_cvt_f32_f16_e32 v10, v10 -; CI-NEXT: v_cvt_f32_f16_e32 v11, v11 ; CI-NEXT: s_setpc_b64 s[30:31] ; ; GFX11-LABEL: v_test_canonicalize_var_v12f16: @@ -3087,38 +3091,38 @@ define <16 x half> @v_test_canonicalize_var_v16f16(<16 x half> %val) #1 { ; CI-LABEL: v_test_canonicalize_var_v16f16: ; CI: ; %bb.0: ; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CI-NEXT: v_cvt_f16_f32_e32 v15, v15 +; CI-NEXT: v_cvt_f16_f32_e32 v14, v14 +; CI-NEXT: v_cvt_f16_f32_e32 v13, v13 +; CI-NEXT: v_cvt_f16_f32_e32 v12, v12 +; CI-NEXT: v_cvt_f16_f32_e32 v11, v11 +; CI-NEXT: v_cvt_f16_f32_e32 v10, v10 +; CI-NEXT: v_cvt_f16_f32_e32 v9, v9 +; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 +; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 +; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 +; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 +; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 -; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 -; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 -; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 -; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 -; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 -; CI-NEXT: v_cvt_f16_f32_e32 v9, v9 -; CI-NEXT: v_cvt_f16_f32_e32 v10, v10 -; CI-NEXT: v_cvt_f16_f32_e32 v11, v11 -; CI-NEXT: v_cvt_f16_f32_e32 v12, v12 -; CI-NEXT: v_cvt_f16_f32_e32 v13, v13 -; CI-NEXT: v_cvt_f16_f32_e32 v14, v14 -; CI-NEXT: v_cvt_f16_f32_e32 v15, v15 +; CI-NEXT: v_cvt_f32_f16_e32 v15, v15 +; CI-NEXT: v_cvt_f32_f16_e32 v14, v14 +; CI-NEXT: v_cvt_f32_f16_e32 v13, v13 +; CI-NEXT: v_cvt_f32_f16_e32 v12, v12 +; CI-NEXT: v_cvt_f32_f16_e32 v11, v11 +; CI-NEXT: v_cvt_f32_f16_e32 v10, v10 +; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 +; CI-NEXT: v_cvt_f32_f16_e32 v8, v8 +; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 +; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 +; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 +; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v2, v2 ; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 -; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 -; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 -; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 -; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 -; CI-NEXT: v_cvt_f32_f16_e32 v8, v8 -; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 -; CI-NEXT: v_cvt_f32_f16_e32 v10, v10 -; CI-NEXT: v_cvt_f32_f16_e32 v11, v11 -; CI-NEXT: v_cvt_f32_f16_e32 v12, v12 -; CI-NEXT: v_cvt_f32_f16_e32 v13, v13 -; CI-NEXT: v_cvt_f32_f16_e32 v14, v14 -; CI-NEXT: v_cvt_f32_f16_e32 v15, v15 ; CI-NEXT: s_setpc_b64 s[30:31] ; ; GFX11-LABEL: v_test_canonicalize_var_v16f16: @@ -3216,68 +3220,68 @@ define <32 x half> @v_test_canonicalize_var_v32f16(<32 x half> %val) #1 { ; CI: ; %bb.0: ; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; CI-NEXT: buffer_load_dword v31, off, s[0:3], s32 +; CI-NEXT: v_cvt_f16_f32_e32 v30, v30 +; CI-NEXT: v_cvt_f16_f32_e32 v29, v29 +; CI-NEXT: v_cvt_f16_f32_e32 v28, v28 +; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 +; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 +; CI-NEXT: v_cvt_f16_f32_e32 v23, v23 +; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 +; CI-NEXT: v_cvt_f16_f32_e32 v21, v21 +; CI-NEXT: v_cvt_f16_f32_e32 v20, v20 +; CI-NEXT: v_cvt_f16_f32_e32 v19, v19 +; CI-NEXT: v_cvt_f16_f32_e32 v18, v18 +; CI-NEXT: v_cvt_f16_f32_e32 v17, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v16, v16 +; CI-NEXT: v_cvt_f16_f32_e32 v15, v15 +; CI-NEXT: v_cvt_f16_f32_e32 v14, v14 +; CI-NEXT: v_cvt_f16_f32_e32 v13, v13 +; CI-NEXT: v_cvt_f16_f32_e32 v12, v12 +; CI-NEXT: v_cvt_f16_f32_e32 v11, v11 +; CI-NEXT: v_cvt_f16_f32_e32 v10, v10 +; CI-NEXT: v_cvt_f16_f32_e32 v9, v9 +; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 +; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 +; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 +; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 +; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 -; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 -; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 -; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 -; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 -; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 -; CI-NEXT: v_cvt_f16_f32_e32 v9, v9 -; CI-NEXT: v_cvt_f16_f32_e32 v10, v10 -; CI-NEXT: v_cvt_f16_f32_e32 v11, v11 -; CI-NEXT: v_cvt_f16_f32_e32 v12, v12 -; CI-NEXT: v_cvt_f16_f32_e32 v13, v13 -; CI-NEXT: v_cvt_f16_f32_e32 v14, v14 -; CI-NEXT: v_cvt_f16_f32_e32 v15, v15 -; CI-NEXT: v_cvt_f16_f32_e32 v16, v16 -; CI-NEXT: v_cvt_f16_f32_e32 v17, v17 -; CI-NEXT: v_cvt_f16_f32_e32 v18, v18 -; CI-NEXT: v_cvt_f16_f32_e32 v19, v19 -; CI-NEXT: v_cvt_f16_f32_e32 v20, v20 -; CI-NEXT: v_cvt_f16_f32_e32 v21, v21 -; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 -; CI-NEXT: v_cvt_f16_f32_e32 v23, v23 -; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 -; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 -; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 -; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 -; CI-NEXT: v_cvt_f16_f32_e32 v28, v28 -; CI-NEXT: v_cvt_f16_f32_e32 v29, v29 -; CI-NEXT: v_cvt_f16_f32_e32 v30, v30 +; CI-NEXT: v_cvt_f32_f16_e32 v30, v30 +; CI-NEXT: v_cvt_f32_f16_e32 v29, v29 +; CI-NEXT: v_cvt_f32_f16_e32 v28, v28 +; CI-NEXT: v_cvt_f32_f16_e32 v27, v27 +; CI-NEXT: v_cvt_f32_f16_e32 v26, v26 +; CI-NEXT: v_cvt_f32_f16_e32 v25, v25 +; CI-NEXT: v_cvt_f32_f16_e32 v24, v24 +; CI-NEXT: v_cvt_f32_f16_e32 v23, v23 +; CI-NEXT: v_cvt_f32_f16_e32 v22, v22 +; CI-NEXT: v_cvt_f32_f16_e32 v21, v21 +; CI-NEXT: v_cvt_f32_f16_e32 v20, v20 +; CI-NEXT: v_cvt_f32_f16_e32 v19, v19 +; CI-NEXT: v_cvt_f32_f16_e32 v18, v18 +; CI-NEXT: v_cvt_f32_f16_e32 v17, v17 +; CI-NEXT: v_cvt_f32_f16_e32 v16, v16 +; CI-NEXT: v_cvt_f32_f16_e32 v15, v15 +; CI-NEXT: v_cvt_f32_f16_e32 v14, v14 +; CI-NEXT: v_cvt_f32_f16_e32 v13, v13 +; CI-NEXT: v_cvt_f32_f16_e32 v12, v12 +; CI-NEXT: v_cvt_f32_f16_e32 v11, v11 +; CI-NEXT: v_cvt_f32_f16_e32 v10, v10 +; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 +; CI-NEXT: v_cvt_f32_f16_e32 v8, v8 +; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 +; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 +; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 +; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v2, v2 ; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 -; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 -; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 -; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 -; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 -; CI-NEXT: v_cvt_f32_f16_e32 v8, v8 -; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 -; CI-NEXT: v_cvt_f32_f16_e32 v10, v10 -; CI-NEXT: v_cvt_f32_f16_e32 v11, v11 -; CI-NEXT: v_cvt_f32_f16_e32 v12, v12 -; CI-NEXT: v_cvt_f32_f16_e32 v13, v13 -; CI-NEXT: v_cvt_f32_f16_e32 v14, v14 -; CI-NEXT: v_cvt_f32_f16_e32 v15, v15 -; CI-NEXT: v_cvt_f32_f16_e32 v16, v16 -; CI-NEXT: v_cvt_f32_f16_e32 v17, v17 -; CI-NEXT: v_cvt_f32_f16_e32 v18, v18 -; CI-NEXT: v_cvt_f32_f16_e32 v19, v19 -; CI-NEXT: v_cvt_f32_f16_e32 v20, v20 -; CI-NEXT: v_cvt_f32_f16_e32 v21, v21 -; CI-NEXT: v_cvt_f32_f16_e32 v22, v22 -; CI-NEXT: v_cvt_f32_f16_e32 v23, v23 -; CI-NEXT: v_cvt_f32_f16_e32 v24, v24 -; CI-NEXT: v_cvt_f32_f16_e32 v25, v25 -; CI-NEXT: v_cvt_f32_f16_e32 v26, v26 -; CI-NEXT: v_cvt_f32_f16_e32 v27, v27 -; CI-NEXT: v_cvt_f32_f16_e32 v28, v28 -; CI-NEXT: v_cvt_f32_f16_e32 v29, v29 -; CI-NEXT: v_cvt_f32_f16_e32 v30, v30 ; CI-NEXT: s_waitcnt vmcnt(0) ; CI-NEXT: v_cvt_f16_f32_e32 v31, v31 ; CI-NEXT: v_cvt_f32_f16_e32 v31, v31 @@ -3456,228 +3460,354 @@ define <64 x half> @v_test_canonicalize_var_v64f16(<64 x half> %val) #1 { ; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 +; CI-NEXT: buffer_load_dword v31, off, s[0:3], s32 offset:104 +; CI-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:108 +; CI-NEXT: v_cvt_f32_f16_e32 v2, v2 +; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 +; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 +; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 +; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 ; CI-NEXT: v_lshlrev_b32_e32 v2, 16, v2 ; CI-NEXT: v_or_b32_e32 v1, v1, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v2, v4 ; CI-NEXT: v_cvt_f16_f32_e32 v4, v5 ; CI-NEXT: v_cvt_f16_f32_e32 v5, v7 ; CI-NEXT: v_cvt_f16_f32_e32 v7, v9 +; CI-NEXT: v_cvt_f32_f16_e32 v2, v2 +; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 +; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 +; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 +; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 +; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 +; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 +; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 ; CI-NEXT: v_lshlrev_b32_e32 v2, 16, v2 ; CI-NEXT: v_or_b32_e32 v2, v3, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v3, v6 ; CI-NEXT: v_cvt_f16_f32_e32 v6, v10 ; CI-NEXT: v_cvt_f16_f32_e32 v9, v13 -; CI-NEXT: v_cvt_f16_f32_e32 v10, v18 +; CI-NEXT: v_cvt_f16_f32_e32 v10, v16 +; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 +; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 +; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 +; CI-NEXT: v_cvt_f16_f32_e32 v13, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 +; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 +; CI-NEXT: v_cvt_f16_f32_e32 v9, v9 +; CI-NEXT: v_cvt_f32_f16_e32 v13, v13 ; CI-NEXT: v_lshlrev_b32_e32 v3, 16, v3 ; CI-NEXT: v_or_b32_e32 v3, v4, v3 ; CI-NEXT: v_cvt_f16_f32_e32 v4, v8 ; CI-NEXT: v_cvt_f16_f32_e32 v8, v14 -; CI-NEXT: v_cvt_f16_f32_e32 v13, v21 -; CI-NEXT: v_cvt_f16_f32_e32 v14, v26 +; CI-NEXT: buffer_load_dword v14, off, s[0:3], s32 +; CI-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:4 +; CI-NEXT: v_cvt_f16_f32_e32 v17, v23 +; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 +; CI-NEXT: v_cvt_f32_f16_e32 v8, v8 +; CI-NEXT: v_cvt_f32_f16_e32 v17, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 +; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 ; CI-NEXT: v_lshlrev_b32_e32 v4, 16, v4 ; CI-NEXT: v_or_b32_e32 v4, v5, v4 ; CI-NEXT: v_lshlrev_b32_e32 v5, 16, v6 ; CI-NEXT: v_cvt_f16_f32_e32 v6, v12 ; CI-NEXT: v_or_b32_e32 v5, v7, v5 ; CI-NEXT: v_cvt_f16_f32_e32 v7, v11 -; CI-NEXT: v_cvt_f16_f32_e32 v11, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v11, v15 +; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 +; CI-NEXT: v_cvt_f16_f32_e32 v15, v21 +; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 +; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 +; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 ; CI-NEXT: v_lshlrev_b32_e32 v6, 16, v6 -; CI-NEXT: v_cvt_f16_f32_e32 v12, v22 ; CI-NEXT: v_or_b32_e32 v6, v7, v6 ; CI-NEXT: v_lshlrev_b32_e32 v7, 16, v8 -; CI-NEXT: v_cvt_f16_f32_e32 v8, v16 +; CI-NEXT: v_cvt_f16_f32_e32 v8, v19 ; CI-NEXT: v_or_b32_e32 v7, v9, v7 -; CI-NEXT: v_cvt_f16_f32_e32 v9, v15 -; CI-NEXT: v_cvt_f16_f32_e32 v15, v25 +; CI-NEXT: v_cvt_f16_f32_e32 v9, v20 +; CI-NEXT: v_cvt_f32_f16_e32 v12, v8 +; CI-NEXT: v_cvt_f32_f16_e32 v8, v10 +; CI-NEXT: v_cvt_f32_f16_e32 v10, v11 +; CI-NEXT: v_cvt_f16_f32_e32 v11, v18 +; CI-NEXT: buffer_load_dword v18, off, s[0:3], s32 offset:124 +; CI-NEXT: buffer_load_dword v19, off, s[0:3], s32 offset:112 +; CI-NEXT: buffer_load_dword v20, off, s[0:3], s32 offset:116 +; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 +; CI-NEXT: v_cvt_f16_f32_e32 v10, v10 +; CI-NEXT: v_cvt_f32_f16_e32 v11, v11 +; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 ; CI-NEXT: v_lshlrev_b32_e32 v8, 16, v8 -; CI-NEXT: v_cvt_f16_f32_e32 v25, v29 -; CI-NEXT: v_or_b32_e32 v8, v9, v8 +; CI-NEXT: v_or_b32_e32 v8, v10, v8 +; CI-NEXT: v_cvt_f16_f32_e32 v10, v11 +; CI-NEXT: v_cvt_f16_f32_e32 v11, v13 +; CI-NEXT: v_cvt_f16_f32_e32 v13, v9 +; CI-NEXT: v_cvt_f16_f32_e32 v12, v12 ; CI-NEXT: v_lshlrev_b32_e32 v9, 16, v10 -; CI-NEXT: v_cvt_f16_f32_e32 v10, v20 ; CI-NEXT: v_or_b32_e32 v9, v11, v9 -; CI-NEXT: v_cvt_f16_f32_e32 v11, v19 -; CI-NEXT: buffer_load_dword v16, off, s[0:3], s32 offset:4 -; CI-NEXT: buffer_load_dword v17, off, s[0:3], s32 -; CI-NEXT: buffer_load_dword v18, off, s[0:3], s32 offset:12 -; CI-NEXT: buffer_load_dword v19, off, s[0:3], s32 offset:8 -; CI-NEXT: v_lshlrev_b32_e32 v10, 16, v10 -; CI-NEXT: v_or_b32_e32 v10, v11, v10 -; CI-NEXT: v_lshlrev_b32_e32 v11, 16, v12 -; CI-NEXT: v_cvt_f16_f32_e32 v12, v24 +; CI-NEXT: v_lshlrev_b32_e32 v10, 16, v13 +; CI-NEXT: v_cvt_f16_f32_e32 v11, v25 +; CI-NEXT: v_cvt_f16_f32_e32 v13, v22 +; CI-NEXT: v_or_b32_e32 v10, v12, v10 +; CI-NEXT: v_cvt_f16_f32_e32 v12, v26 +; CI-NEXT: v_cvt_f32_f16_e32 v16, v11 +; CI-NEXT: v_cvt_f32_f16_e32 v11, v13 +; CI-NEXT: v_cvt_f32_f16_e32 v13, v15 +; CI-NEXT: v_cvt_f16_f32_e32 v15, v24 +; CI-NEXT: v_cvt_f32_f16_e32 v12, v12 +; CI-NEXT: v_cvt_f16_f32_e32 v11, v11 +; CI-NEXT: v_cvt_f16_f32_e32 v13, v13 +; CI-NEXT: v_cvt_f32_f16_e32 v15, v15 +; CI-NEXT: v_cvt_f16_f32_e32 v22, v30 +; CI-NEXT: v_lshlrev_b32_e32 v11, 16, v11 ; CI-NEXT: v_or_b32_e32 v11, v13, v11 -; CI-NEXT: v_cvt_f16_f32_e32 v13, v23 -; CI-NEXT: buffer_load_dword v20, off, s[0:3], s32 offset:20 -; CI-NEXT: buffer_load_dword v21, off, s[0:3], s32 offset:16 -; CI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:28 -; CI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:24 -; CI-NEXT: v_lshlrev_b32_e32 v12, 16, v12 -; CI-NEXT: v_cvt_f16_f32_e32 v24, v30 -; CI-NEXT: v_or_b32_e32 v12, v13, v12 -; CI-NEXT: v_lshlrev_b32_e32 v13, 16, v14 -; CI-NEXT: v_or_b32_e32 v13, v15, v13 -; CI-NEXT: v_cvt_f16_f32_e32 v14, v28 +; CI-NEXT: v_cvt_f16_f32_e32 v13, v15 +; CI-NEXT: v_cvt_f16_f32_e32 v15, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v17, v12 +; CI-NEXT: v_cvt_f16_f32_e32 v25, v29 +; CI-NEXT: v_lshlrev_b32_e32 v12, 16, v13 +; CI-NEXT: v_or_b32_e32 v12, v15, v12 +; CI-NEXT: s_waitcnt vmcnt(6) +; CI-NEXT: v_cvt_f16_f32_e32 v15, v31 +; CI-NEXT: v_lshlrev_b32_e32 v13, 16, v17 +; CI-NEXT: buffer_load_dword v17, off, s[0:3], s32 offset:128 +; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:132 +; CI-NEXT: buffer_load_dword v34, off, s[0:3], s32 offset:120 +; CI-NEXT: v_cvt_f32_f16_e32 v22, v22 +; CI-NEXT: v_cvt_f32_f16_e32 v23, v15 ; CI-NEXT: v_cvt_f16_f32_e32 v15, v27 -; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:36 -; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:32 -; CI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:44 -; CI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:40 +; CI-NEXT: v_cvt_f32_f16_e32 v25, v25 +; CI-NEXT: s_waitcnt vmcnt(7) +; CI-NEXT: v_cvt_f16_f32_e32 v14, v14 +; CI-NEXT: s_waitcnt vmcnt(6) +; CI-NEXT: v_cvt_f16_f32_e32 v21, v33 +; CI-NEXT: v_cvt_f32_f16_e32 v15, v15 +; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 +; CI-NEXT: v_cvt_f32_f16_e32 v24, v14 +; CI-NEXT: v_cvt_f16_f32_e32 v14, v28 +; CI-NEXT: v_cvt_f16_f32_e32 v15, v15 +; CI-NEXT: v_cvt_f32_f16_e32 v21, v21 +; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 +; CI-NEXT: v_cvt_f32_f16_e32 v14, v14 +; CI-NEXT: v_cvt_f16_f32_e32 v16, v16 +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 +; CI-NEXT: v_cvt_f16_f32_e32 v28, v23 +; CI-NEXT: v_cvt_f16_f32_e32 v14, v14 +; CI-NEXT: v_or_b32_e32 v13, v16, v13 +; CI-NEXT: v_cvt_f16_f32_e32 v16, v32 +; CI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:12 ; CI-NEXT: v_lshlrev_b32_e32 v14, 16, v14 ; CI-NEXT: v_or_b32_e32 v14, v15, v14 -; CI-NEXT: v_lshlrev_b32_e32 v15, 16, v24 +; CI-NEXT: v_lshlrev_b32_e32 v15, 16, v22 ; CI-NEXT: v_or_b32_e32 v15, v25, v15 -; CI-NEXT: s_waitcnt vmcnt(11) -; CI-NEXT: v_cvt_f16_f32_e32 v16, v16 -; CI-NEXT: s_waitcnt vmcnt(10) -; CI-NEXT: v_cvt_f16_f32_e32 v17, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v25, v21 +; CI-NEXT: buffer_load_dword v21, off, s[0:3], s32 offset:96 +; CI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:100 +; CI-NEXT: v_cvt_f32_f16_e32 v16, v16 +; CI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:64 +; CI-NEXT: v_lshlrev_b32_e32 v25, 16, v25 +; CI-NEXT: v_cvt_f16_f32_e32 v27, v16 +; CI-NEXT: v_or_b32_e32 v16, v24, v25 +; CI-NEXT: v_lshlrev_b32_e32 v24, 16, v27 +; CI-NEXT: v_or_b32_e32 v25, v28, v24 ; CI-NEXT: s_waitcnt vmcnt(9) ; CI-NEXT: v_cvt_f16_f32_e32 v18, v18 ; CI-NEXT: s_waitcnt vmcnt(8) ; CI-NEXT: v_cvt_f16_f32_e32 v19, v19 -; CI-NEXT: v_lshlrev_b32_e32 v16, 16, v16 -; CI-NEXT: v_or_b32_e32 v16, v17, v16 -; CI-NEXT: v_lshlrev_b32_e32 v17, 16, v18 -; CI-NEXT: v_or_b32_e32 v17, v19, v17 ; CI-NEXT: s_waitcnt vmcnt(7) -; CI-NEXT: v_cvt_f16_f32_e32 v18, v20 +; CI-NEXT: v_cvt_f16_f32_e32 v20, v20 +; CI-NEXT: v_cvt_f32_f16_e32 v18, v18 +; CI-NEXT: v_cvt_f32_f16_e32 v19, v19 +; CI-NEXT: v_cvt_f32_f16_e32 v20, v20 +; CI-NEXT: v_cvt_f16_f32_e32 v18, v18 +; CI-NEXT: v_cvt_f16_f32_e32 v19, v19 +; CI-NEXT: v_cvt_f16_f32_e32 v20, v20 +; CI-NEXT: v_lshlrev_b32_e32 v18, 16, v18 +; CI-NEXT: v_lshlrev_b32_e32 v20, 16, v20 +; CI-NEXT: v_or_b32_e32 v20, v19, v20 +; CI-NEXT: buffer_load_dword v19, off, s[0:3], s32 offset:20 +; CI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:8 +; CI-NEXT: s_waitcnt vmcnt(8) +; CI-NEXT: v_cvt_f16_f32_e32 v17, v17 +; CI-NEXT: s_waitcnt vmcnt(7) +; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 ; CI-NEXT: s_waitcnt vmcnt(6) -; CI-NEXT: v_cvt_f16_f32_e32 v19, v21 -; CI-NEXT: s_waitcnt vmcnt(5) +; CI-NEXT: v_cvt_f16_f32_e32 v27, v34 +; CI-NEXT: v_cvt_f32_f16_e32 v17, v17 +; CI-NEXT: v_cvt_f32_f16_e32 v26, v26 +; CI-NEXT: v_cvt_f32_f16_e32 v27, v27 +; CI-NEXT: v_cvt_f16_f32_e32 v17, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 +; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_lshlrev_b32_e32 v26, 16, v26 +; CI-NEXT: v_or_b32_e32 v17, v17, v26 +; CI-NEXT: v_add_i32_e32 v26, vcc, 0x7c, v0 +; CI-NEXT: v_or_b32_e32 v18, v27, v18 +; CI-NEXT: buffer_store_dword v17, v26, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x78, v0 +; CI-NEXT: buffer_store_dword v18, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x74, v0 +; CI-NEXT: buffer_store_dword v20, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x70, v0 +; CI-NEXT: buffer_store_dword v25, v17, s[0:3], 0 offen +; CI-NEXT: s_waitcnt vmcnt(8) +; CI-NEXT: v_cvt_f16_f32_e32 v21, v21 +; CI-NEXT: s_waitcnt vmcnt(7) ; CI-NEXT: v_cvt_f16_f32_e32 v20, v22 -; CI-NEXT: s_waitcnt vmcnt(4) -; CI-NEXT: v_cvt_f16_f32_e32 v21, v23 -; CI-NEXT: v_lshlrev_b32_e32 v18, 16, v18 -; CI-NEXT: v_or_b32_e32 v18, v19, v18 -; CI-NEXT: v_lshlrev_b32_e32 v19, 16, v20 -; CI-NEXT: v_or_b32_e32 v19, v21, v19 -; CI-NEXT: s_waitcnt vmcnt(3) -; CI-NEXT: v_cvt_f16_f32_e32 v20, v26 -; CI-NEXT: s_waitcnt vmcnt(2) -; CI-NEXT: v_cvt_f16_f32_e32 v21, v27 -; CI-NEXT: s_waitcnt vmcnt(1) -; CI-NEXT: v_cvt_f16_f32_e32 v26, v28 -; CI-NEXT: s_waitcnt vmcnt(0) -; CI-NEXT: v_cvt_f16_f32_e32 v27, v29 +; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:88 +; CI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:92 +; CI-NEXT: buffer_load_dword v17, off, s[0:3], s32 offset:80 +; CI-NEXT: buffer_load_dword v18, off, s[0:3], s32 offset:84 +; CI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:72 +; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:76 +; CI-NEXT: v_cvt_f16_f32_e32 v22, v23 +; CI-NEXT: v_cvt_f32_f16_e32 v21, v21 +; CI-NEXT: v_cvt_f32_f16_e32 v20, v20 +; CI-NEXT: s_waitcnt vmcnt(12) +; CI-NEXT: v_cvt_f16_f32_e32 v29, v29 +; CI-NEXT: v_cvt_f32_f16_e32 v22, v22 +; CI-NEXT: v_cvt_f16_f32_e32 v21, v21 +; CI-NEXT: v_cvt_f16_f32_e32 v20, v20 +; CI-NEXT: v_cvt_f32_f16_e32 v29, v29 +; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 ; CI-NEXT: v_lshlrev_b32_e32 v20, 16, v20 ; CI-NEXT: v_or_b32_e32 v20, v21, v20 -; CI-NEXT: v_lshlrev_b32_e32 v21, 16, v26 -; CI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:52 -; CI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:48 -; CI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:60 -; CI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:56 -; CI-NEXT: v_or_b32_e32 v21, v27, v21 -; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:132 -; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:128 -; CI-NEXT: s_waitcnt vmcnt(5) -; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 -; CI-NEXT: s_waitcnt vmcnt(4) -; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 -; CI-NEXT: s_waitcnt vmcnt(3) +; CI-NEXT: v_add_i32_e32 v21, vcc, 0x6c, v0 +; CI-NEXT: buffer_store_dword v20, v21, s[0:3], 0 offen +; CI-NEXT: v_lshlrev_b32_e32 v20, 16, v22 +; CI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:24 +; CI-NEXT: v_cvt_f16_f32_e32 v29, v29 +; CI-NEXT: s_waitcnt vmcnt(13) +; CI-NEXT: v_cvt_f16_f32_e32 v19, v19 +; CI-NEXT: s_waitcnt vmcnt(12) +; CI-NEXT: v_cvt_f16_f32_e32 v23, v24 +; CI-NEXT: buffer_load_dword v21, off, s[0:3], s32 offset:28 +; CI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:16 +; CI-NEXT: v_cvt_f32_f16_e32 v19, v19 +; CI-NEXT: v_cvt_f32_f16_e32 v23, v23 +; CI-NEXT: v_cvt_f16_f32_e32 v19, v19 ; CI-NEXT: v_cvt_f16_f32_e32 v23, v23 -; CI-NEXT: s_waitcnt vmcnt(2) -; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 -; CI-NEXT: s_waitcnt vmcnt(1) +; CI-NEXT: v_lshlrev_b32_e32 v19, 16, v19 +; CI-NEXT: v_or_b32_e32 v20, v23, v20 +; CI-NEXT: s_waitcnt vmcnt(9) +; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: s_waitcnt vmcnt(8) +; CI-NEXT: v_cvt_f16_f32_e32 v23, v28 +; CI-NEXT: s_waitcnt vmcnt(7) +; CI-NEXT: v_cvt_f16_f32_e32 v17, v17 +; CI-NEXT: s_waitcnt vmcnt(6) +; CI-NEXT: v_cvt_f16_f32_e32 v18, v18 +; CI-NEXT: v_cvt_f32_f16_e32 v27, v27 +; CI-NEXT: v_cvt_f32_f16_e32 v23, v23 +; CI-NEXT: s_waitcnt vmcnt(4) ; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 -; CI-NEXT: s_waitcnt vmcnt(0) +; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 ; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 -; CI-NEXT: v_lshlrev_b32_e32 v24, 16, v24 -; CI-NEXT: v_or_b32_e32 v24, v25, v24 -; CI-NEXT: v_lshlrev_b32_e32 v26, 16, v26 -; CI-NEXT: v_or_b32_e32 v26, v27, v26 -; CI-NEXT: v_add_i32_e32 v27, vcc, 0x7c, v0 -; CI-NEXT: buffer_store_dword v26, v27, s[0:3], 0 offen -; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:124 -; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:120 +; CI-NEXT: v_cvt_f16_f32_e32 v23, v23 +; CI-NEXT: v_cvt_f32_f16_e32 v18, v18 +; CI-NEXT: v_cvt_f32_f16_e32 v26, v26 +; CI-NEXT: v_cvt_f32_f16_e32 v17, v17 ; CI-NEXT: v_lshlrev_b32_e32 v23, 16, v23 -; CI-NEXT: v_or_b32_e32 v22, v22, v23 -; CI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:88 -; CI-NEXT: s_waitcnt vmcnt(2) +; CI-NEXT: v_or_b32_e32 v23, v27, v23 +; CI-NEXT: v_add_i32_e32 v27, vcc, 0x68, v0 +; CI-NEXT: buffer_store_dword v23, v27, s[0:3], 0 offen +; CI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:32 +; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:36 +; CI-NEXT: v_cvt_f32_f16_e32 v25, v25 +; CI-NEXT: v_cvt_f16_f32_e32 v18, v18 ; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 -; CI-NEXT: s_waitcnt vmcnt(1) -; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_cvt_f16_f32_e32 v17, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 +; CI-NEXT: v_lshlrev_b32_e32 v18, 16, v18 ; CI-NEXT: v_lshlrev_b32_e32 v26, 16, v26 -; CI-NEXT: v_or_b32_e32 v26, v27, v26 -; CI-NEXT: v_add_i32_e32 v27, vcc, 0x78, v0 -; CI-NEXT: buffer_store_dword v26, v27, s[0:3], 0 offen -; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:116 -; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:112 -; CI-NEXT: s_waitcnt vmcnt(3) +; CI-NEXT: v_or_b32_e32 v17, v17, v18 +; CI-NEXT: v_add_i32_e32 v18, vcc, 0x64, v0 +; CI-NEXT: v_or_b32_e32 v25, v25, v26 +; CI-NEXT: buffer_store_dword v17, v18, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x60, v0 +; CI-NEXT: buffer_store_dword v25, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x5c, v0 +; CI-NEXT: s_waitcnt vmcnt(5) +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 +; CI-NEXT: v_cvt_f16_f32_e32 v21, v21 +; CI-NEXT: v_cvt_f32_f16_e32 v24, v24 +; CI-NEXT: v_cvt_f32_f16_e32 v21, v21 +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 +; CI-NEXT: v_cvt_f16_f32_e32 v21, v21 +; CI-NEXT: v_or_b32_e32 v19, v24, v19 +; CI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:44 +; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 +; CI-NEXT: v_lshlrev_b32_e32 v21, 16, v21 +; CI-NEXT: v_cvt_f32_f16_e32 v22, v22 +; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 +; CI-NEXT: v_or_b32_e32 v21, v22, v21 +; CI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:40 +; CI-NEXT: s_waitcnt vmcnt(5) +; CI-NEXT: v_cvt_f16_f32_e32 v23, v23 +; CI-NEXT: s_waitcnt vmcnt(4) +; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_cvt_f32_f16_e32 v23, v23 +; CI-NEXT: v_cvt_f32_f16_e32 v27, v27 ; CI-NEXT: v_cvt_f16_f32_e32 v23, v23 +; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_lshlrev_b32_e32 v27, 16, v27 ; CI-NEXT: s_waitcnt vmcnt(1) -; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 +; CI-NEXT: v_cvt_f32_f16_e32 v24, v24 +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 ; CI-NEXT: s_waitcnt vmcnt(0) +; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 +; CI-NEXT: v_cvt_f32_f16_e32 v22, v22 +; CI-NEXT: v_cvt_f16_f32_e32 v28, v22 +; CI-NEXT: v_or_b32_e32 v22, v23, v27 +; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:52 +; CI-NEXT: v_lshlrev_b32_e32 v23, 16, v24 +; CI-NEXT: v_or_b32_e32 v23, v28, v23 +; CI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:56 +; CI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:48 +; CI-NEXT: s_waitcnt vmcnt(2) ; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 -; CI-NEXT: v_lshlrev_b32_e32 v26, 16, v26 -; CI-NEXT: v_or_b32_e32 v26, v27, v26 -; CI-NEXT: v_add_i32_e32 v27, vcc, 0x74, v0 -; CI-NEXT: buffer_store_dword v26, v27, s[0:3], 0 offen -; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:108 -; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:104 ; CI-NEXT: s_waitcnt vmcnt(1) -; CI-NEXT: v_cvt_f16_f32_e32 v25, v26 +; CI-NEXT: v_cvt_f16_f32_e32 v28, v28 ; CI-NEXT: s_waitcnt vmcnt(0) -; CI-NEXT: v_cvt_f16_f32_e32 v26, v27 -; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:92 -; CI-NEXT: v_lshlrev_b32_e32 v25, 16, v25 -; CI-NEXT: v_or_b32_e32 v25, v26, v25 -; CI-NEXT: v_add_i32_e32 v26, vcc, 0x70, v0 -; CI-NEXT: buffer_store_dword v25, v26, s[0:3], 0 offen -; CI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:100 -; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:96 -; CI-NEXT: s_waitcnt vmcnt(3) +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 +; CI-NEXT: v_cvt_f32_f16_e32 v27, v27 +; CI-NEXT: v_cvt_f32_f16_e32 v28, v28 +; CI-NEXT: v_cvt_f32_f16_e32 v24, v24 ; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_cvt_f16_f32_e32 v28, v28 +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 ; CI-NEXT: v_lshlrev_b32_e32 v27, 16, v27 -; CI-NEXT: v_or_b32_e32 v23, v23, v27 -; CI-NEXT: s_waitcnt vmcnt(1) -; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 +; CI-NEXT: v_or_b32_e32 v24, v24, v27 +; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:60 ; CI-NEXT: s_waitcnt vmcnt(0) -; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 -; CI-NEXT: v_add_i32_e32 v27, vcc, 0x68, v0 -; CI-NEXT: v_lshlrev_b32_e32 v25, 16, v25 -; CI-NEXT: v_or_b32_e32 v25, v26, v25 -; CI-NEXT: v_add_i32_e32 v26, vcc, 0x6c, v0 -; CI-NEXT: buffer_store_dword v25, v26, s[0:3], 0 offen -; CI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:68 -; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:64 -; CI-NEXT: buffer_store_dword v23, v27, s[0:3], 0 offen -; CI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:76 -; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:72 -; CI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:84 -; CI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:80 -; CI-NEXT: s_waitcnt vmcnt(3) -; CI-NEXT: v_cvt_f16_f32_e32 v23, v23 -; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 -; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 -; CI-NEXT: v_lshlrev_b32_e32 v23, 16, v23 -; CI-NEXT: v_lshlrev_b32_e32 v25, 16, v25 -; CI-NEXT: v_or_b32_e32 v25, v26, v25 -; CI-NEXT: s_waitcnt vmcnt(2) -; CI-NEXT: v_cvt_f16_f32_e32 v26, v27 +; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_cvt_f32_f16_e32 v27, v27 +; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_lshlrev_b32_e32 v27, 16, v27 +; CI-NEXT: v_or_b32_e32 v27, v28, v27 +; CI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:68 ; CI-NEXT: s_waitcnt vmcnt(0) -; CI-NEXT: v_cvt_f16_f32_e32 v27, v29 -; CI-NEXT: v_or_b32_e32 v23, v26, v23 -; CI-NEXT: v_cvt_f16_f32_e32 v26, v28 -; CI-NEXT: v_lshlrev_b32_e32 v26, 16, v26 -; CI-NEXT: v_or_b32_e32 v26, v27, v26 -; CI-NEXT: v_add_i32_e32 v27, vcc, 0x64, v0 -; CI-NEXT: buffer_store_dword v26, v27, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v26, vcc, 0x60, v0 -; CI-NEXT: buffer_store_dword v23, v26, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v23, vcc, 0x5c, v0 -; CI-NEXT: buffer_store_dword v25, v23, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v23, vcc, 0x58, v0 -; CI-NEXT: buffer_store_dword v22, v23, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v22, vcc, 0x54, v0 -; CI-NEXT: buffer_store_dword v24, v22, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v22, vcc, 0x50, v0 -; CI-NEXT: buffer_store_dword v21, v22, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v21, vcc, 0x4c, v0 -; CI-NEXT: buffer_store_dword v20, v21, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v20, vcc, 0x48, v0 -; CI-NEXT: buffer_store_dword v19, v20, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v19, vcc, 0x44, v0 -; CI-NEXT: buffer_store_dword v18, v19, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v18, vcc, 64, v0 -; CI-NEXT: buffer_store_dword v17, v18, s[0:3], 0 offen +; CI-NEXT: v_cvt_f16_f32_e32 v28, v28 +; CI-NEXT: v_cvt_f32_f16_e32 v28, v28 +; CI-NEXT: v_cvt_f16_f32_e32 v28, v28 +; CI-NEXT: v_lshlrev_b32_e32 v28, 16, v28 +; CI-NEXT: v_or_b32_e32 v28, v29, v28 +; CI-NEXT: buffer_store_dword v28, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x58, v0 +; CI-NEXT: buffer_store_dword v27, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x54, v0 +; CI-NEXT: buffer_store_dword v24, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x50, v0 +; CI-NEXT: buffer_store_dword v23, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x4c, v0 +; CI-NEXT: buffer_store_dword v22, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x48, v0 +; CI-NEXT: buffer_store_dword v21, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x44, v0 +; CI-NEXT: buffer_store_dword v19, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 64, v0 +; CI-NEXT: buffer_store_dword v20, v17, s[0:3], 0 offen ; CI-NEXT: v_add_i32_e32 v17, vcc, 60, v0 ; CI-NEXT: buffer_store_dword v16, v17, s[0:3], 0 offen ; CI-NEXT: v_add_i32_e32 v16, vcc, 56, v0 diff --git a/llvm/test/CodeGen/AMDGPU/fcanonicalize.ll b/llvm/test/CodeGen/AMDGPU/fcanonicalize.ll index c1093a1e89c8..d53c0411ad88 100644 --- a/llvm/test/CodeGen/AMDGPU/fcanonicalize.ll +++ b/llvm/test/CodeGen/AMDGPU/fcanonicalize.ll @@ -2389,7 +2389,6 @@ define amdgpu_kernel void @test_canonicalize_value_f16_flush(ptr addrspace(1) %a ; GFX6-NEXT: v_mov_b32_e32 v1, s3 ; GFX6-NEXT: s_waitcnt vmcnt(0) ; GFX6-NEXT: v_cvt_f32_f16_e32 v0, v0 -; GFX6-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v0 ; GFX6-NEXT: v_add_i32_e32 v0, vcc, s2, v2 ; GFX6-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc @@ -2471,15 +2470,13 @@ define amdgpu_kernel void @test_canonicalize_value_v2f16_flush(ptr addrspace(1) ; GFX6-NEXT: flat_load_dword v0, v[0:1] ; GFX6-NEXT: v_mov_b32_e32 v3, s3 ; GFX6-NEXT: s_waitcnt vmcnt(0) -; GFX6-NEXT: v_cvt_f32_f16_e32 v1, v0 -; GFX6-NEXT: v_lshrrev_b32_e32 v0, 16, v0 +; GFX6-NEXT: v_lshrrev_b32_e32 v1, 16, v0 +; GFX6-NEXT: v_cvt_f32_f16_e32 v1, v1 ; GFX6-NEXT: v_cvt_f32_f16_e32 v0, v0 -; GFX6-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX6-NEXT: v_cvt_f16_f32_e32 v1, v1 -; GFX6-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX6-NEXT: v_cvt_f16_f32_e32 v0, v0 -; GFX6-NEXT: v_lshlrev_b32_e32 v0, 16, v0 -; GFX6-NEXT: v_or_b32_e32 v4, v1, v0 +; GFX6-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; GFX6-NEXT: v_or_b32_e32 v4, v0, v1 ; GFX6-NEXT: v_add_i32_e32 v0, vcc, s2, v2 ; GFX6-NEXT: v_addc_u32_e32 v1, vcc, 0, v3, vcc ; GFX6-NEXT: flat_store_dword v[0:1], v4 @@ -2724,7 +2721,6 @@ define amdgpu_kernel void @test_canonicalize_value_f16_denorm(ptr addrspace(1) % ; GFX6-NEXT: v_mov_b32_e32 v1, s3 ; GFX6-NEXT: s_waitcnt vmcnt(0) ; GFX6-NEXT: v_cvt_f32_f16_e32 v0, v0 -; GFX6-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v0 ; GFX6-NEXT: v_add_i32_e32 v0, vcc, s2, v2 ; GFX6-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc @@ -2807,15 +2803,13 @@ define amdgpu_kernel void @test_canonicalize_value_v2f16_denorm(ptr addrspace(1) ; GFX6-NEXT: flat_load_dword v0, v[0:1] ; GFX6-NEXT: v_mov_b32_e32 v3, s3 ; GFX6-NEXT: s_waitcnt vmcnt(0) -; GFX6-NEXT: v_cvt_f32_f16_e32 v1, v0 -; GFX6-NEXT: v_lshrrev_b32_e32 v0, 16, v0 +; GFX6-NEXT: v_lshrrev_b32_e32 v1, 16, v0 +; GFX6-NEXT: v_cvt_f32_f16_e32 v1, v1 ; GFX6-NEXT: v_cvt_f32_f16_e32 v0, v0 -; GFX6-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX6-NEXT: v_cvt_f16_f32_e32 v1, v1 -; GFX6-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX6-NEXT: v_cvt_f16_f32_e32 v0, v0 -; GFX6-NEXT: v_lshlrev_b32_e32 v0, 16, v0 -; GFX6-NEXT: v_or_b32_e32 v4, v1, v0 +; GFX6-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; GFX6-NEXT: v_or_b32_e32 v4, v0, v1 ; GFX6-NEXT: v_add_i32_e32 v0, vcc, s2, v2 ; GFX6-NEXT: v_addc_u32_e32 v1, vcc, 0, v3, vcc ; GFX6-NEXT: flat_store_dword v[0:1], v4 diff --git a/llvm/test/CodeGen/AMDGPU/fneg-combines.f16.ll b/llvm/test/CodeGen/AMDGPU/fneg-combines.f16.ll index 78fb89c71e2e..b32630a97b3a 100644 --- a/llvm/test/CodeGen/AMDGPU/fneg-combines.f16.ll +++ b/llvm/test/CodeGen/AMDGPU/fneg-combines.f16.ll @@ -951,8 +951,6 @@ define half @v_fneg_minnum_f16_ieee(half %a, half %b) #0 { ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, v0, v1 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1056,7 +1054,6 @@ define half @v_fneg_posk_minnum_f16_ieee(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, -4.0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1110,7 +1107,6 @@ define half @v_fneg_negk_minnum_f16_ieee(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 4.0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1193,7 +1189,6 @@ define half @v_fneg_neg0_minnum_f16_ieee(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1222,7 +1217,6 @@ define half @v_fneg_inv2pi_minnum_f16(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0xbe230000, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1253,7 +1247,6 @@ define half @v_fneg_neg_inv2pi_minnum_f16(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0xbe230000, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1311,7 +1304,6 @@ define half @v_fneg_0_minnum_foldable_use_f16_ieee(half %a, half %b) #0 { ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; SI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, 0, v0 ; SI-NEXT: v_mul_f32_e64 v0, -v0, v1 ; SI-NEXT: s_setpc_b64 s[30:31] @@ -1346,7 +1338,6 @@ define half @v_fneg_inv2pi_minnum_foldable_use_f16(half %a, half %b) #0 { ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; SI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0xbe230000, v0 ; SI-NEXT: v_mul_f32_e32 v0, v0, v1 ; SI-NEXT: s_setpc_b64 s[30:31] @@ -1413,8 +1404,6 @@ define { half, half } @v_fneg_minnum_multi_use_minnum_f16_ieee(half %a, half %b) ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: v_cvt_f32_f16_e64 v1, -v1 ; SI-NEXT: v_cvt_f32_f16_e64 v0, -v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, v0, v1 ; SI-NEXT: v_mul_f32_e32 v1, -4.0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] @@ -1494,8 +1483,6 @@ define half @v_fneg_maxnum_f16_ieee(half %a, half %b) #0 { ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, v0, v1 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1599,7 +1586,6 @@ define half @v_fneg_posk_maxnum_f16_ieee(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, -4.0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1653,7 +1639,6 @@ define half @v_fneg_negk_maxnum_f16_ieee(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, 4.0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1736,7 +1721,6 @@ define half @v_fneg_neg0_maxnum_f16_ieee(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, 0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1792,7 +1776,6 @@ define half @v_fneg_0_maxnum_foldable_use_f16_ieee(half %a, half %b) #0 { ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; SI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0, v0 ; SI-NEXT: v_mul_f32_e64 v0, -v0, v1 ; SI-NEXT: s_setpc_b64 s[30:31] @@ -1859,8 +1842,6 @@ define { half, half } @v_fneg_maxnum_multi_use_maxnum_f16_ieee(half %a, half %b) ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: v_cvt_f32_f16_e64 v1, -v1 ; SI-NEXT: v_cvt_f32_f16_e64 v0, -v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, v0, v1 ; SI-NEXT: v_mul_f32_e32 v1, -4.0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] @@ -3980,7 +3961,8 @@ define half @v_fneg_canonicalize_f16(half %a) #0 { ; SI-LABEL: v_fneg_canonicalize_f16: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; SI-NEXT: v_xor_b32_e32 v0, 0x80000000, v0 +; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 +; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; ; VI-LABEL: v_fneg_canonicalize_f16: diff --git a/llvm/test/CodeGen/AMDGPU/fneg-combines.new.ll b/llvm/test/CodeGen/AMDGPU/fneg-combines.new.ll index 17f67615c29f..b5440b9c38c9 100644 --- a/llvm/test/CodeGen/AMDGPU/fneg-combines.new.ll +++ b/llvm/test/CodeGen/AMDGPU/fneg-combines.new.ll @@ -1021,7 +1021,6 @@ define half @v_fneg_inv2pi_minnum_f16(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0xbe230000, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1043,7 +1042,6 @@ define half @v_fneg_neg_inv2pi_minnum_f16(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0x3e230000, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; diff --git a/llvm/test/CodeGen/AMDGPU/llvm.maxnum.f16.ll b/llvm/test/CodeGen/AMDGPU/llvm.maxnum.f16.ll index ab7ab4de1861..d056a97dc544 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.maxnum.f16.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.maxnum.f16.ll @@ -32,8 +32,6 @@ define amdgpu_kernel void @maxnum_f16( ; SI-NEXT: s_mov_b32 s1, s5 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; SI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; SI-NEXT: v_max_f32_e32 v0, v0, v1 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: buffer_store_short v0, off, s[0:3], 0 @@ -170,7 +168,6 @@ define amdgpu_kernel void @maxnum_f16_imm_a( ; SI-NEXT: s_mov_b32 s5, s1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0x40400000, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: buffer_store_short v0, off, s[4:7], 0 @@ -279,7 +276,6 @@ define amdgpu_kernel void @maxnum_f16_imm_b( ; SI-NEXT: s_mov_b32 s5, s1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 4.0, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: buffer_store_short v0, off, s[4:7], 0 @@ -384,21 +380,17 @@ define amdgpu_kernel void @maxnum_v2f16( ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: s_lshr_b32 s1, s2, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v1, s0 -; SI-NEXT: s_lshr_b32 s0, s0, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v2, s0 -; SI-NEXT: v_cvt_f32_f16_e32 v3, s1 -; SI-NEXT: v_cvt_f32_f16_e32 v0, s2 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_max_f32_e32 v2, v3, v2 -; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 +; SI-NEXT: s_lshr_b32 s3, s0, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v0, s1 +; SI-NEXT: v_cvt_f32_f16_e32 v1, s3 +; SI-NEXT: v_cvt_f32_f16_e32 v2, s2 +; SI-NEXT: v_cvt_f32_f16_e32 v3, s0 ; SI-NEXT: v_max_f32_e32 v0, v0, v1 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v2 -; SI-NEXT: v_or_b32_e32 v0, v0, v1 +; SI-NEXT: v_max_f32_e32 v1, v2, v3 +; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; SI-NEXT: v_or_b32_e32 v0, v1, v0 ; SI-NEXT: buffer_store_dword v0, off, s[4:7], 0 ; SI-NEXT: s_endpgm ; @@ -497,20 +489,18 @@ define amdgpu_kernel void @maxnum_v2f16_imm_a( ; SI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x9 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: s_load_dword s2, s[2:3], 0x0 -; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_waitcnt lgkmcnt(0) -; SI-NEXT: v_cvt_f32_f16_e32 v0, s2 -; SI-NEXT: s_lshr_b32 s2, s2, 16 +; SI-NEXT: s_lshr_b32 s3, s2, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v0, s3 ; SI-NEXT: v_cvt_f32_f16_e32 v1, s2 +; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_mov_b32 s2, -1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_max_f32_e32 v0, 0x40400000, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_max_f32_e32 v1, 4.0, v1 -; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_max_f32_e32 v0, 4.0, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 -; SI-NEXT: v_or_b32_e32 v0, v0, v1 +; SI-NEXT: v_max_f32_e32 v1, 0x40400000, v1 +; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; SI-NEXT: v_or_b32_e32 v0, v1, v0 ; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0 ; SI-NEXT: s_endpgm ; @@ -589,20 +579,18 @@ define amdgpu_kernel void @maxnum_v2f16_imm_b( ; SI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x9 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: s_load_dword s2, s[2:3], 0x0 -; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_waitcnt lgkmcnt(0) -; SI-NEXT: v_cvt_f32_f16_e32 v0, s2 -; SI-NEXT: s_lshr_b32 s2, s2, 16 +; SI-NEXT: s_lshr_b32 s3, s2, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v0, s3 ; SI-NEXT: v_cvt_f32_f16_e32 v1, s2 +; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_mov_b32 s2, -1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_max_f32_e32 v0, 4.0, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_max_f32_e32 v1, 0x40400000, v1 -; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_max_f32_e32 v0, 0x40400000, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 -; SI-NEXT: v_or_b32_e32 v0, v0, v1 +; SI-NEXT: v_max_f32_e32 v1, 4.0, v1 +; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; SI-NEXT: v_or_b32_e32 v0, v1, v0 ; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0 ; SI-NEXT: s_endpgm ; @@ -688,27 +676,21 @@ define amdgpu_kernel void @maxnum_v3f16( ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_cvt_f32_f16_e32 v0, s3 -; SI-NEXT: v_cvt_f32_f16_e32 v1, s2 -; SI-NEXT: s_lshr_b32 s2, s2, 16 -; SI-NEXT: s_lshr_b32 s3, s0, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v2, s3 +; SI-NEXT: s_lshr_b32 s3, s2, 16 +; SI-NEXT: s_lshr_b32 s8, s0, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v1, s3 +; SI-NEXT: v_cvt_f32_f16_e32 v2, s8 ; SI-NEXT: v_cvt_f32_f16_e32 v3, s2 -; SI-NEXT: v_cvt_f32_f16_e32 v5, s0 -; SI-NEXT: v_cvt_f32_f16_e32 v4, s1 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; SI-NEXT: v_max_f32_e32 v2, v3, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v5 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_max_f32_e32 v1, v1, v3 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v4 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 -; SI-NEXT: v_max_f32_e32 v0, v0, v3 +; SI-NEXT: v_cvt_f32_f16_e32 v4, s0 +; SI-NEXT: v_cvt_f32_f16_e32 v5, s1 +; SI-NEXT: v_max_f32_e32 v1, v1, v2 ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_max_f32_e32 v2, v3, v4 +; SI-NEXT: v_max_f32_e32 v0, v0, v5 +; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v2, 16, v2 -; SI-NEXT: v_or_b32_e32 v1, v1, v2 +; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; SI-NEXT: v_or_b32_e32 v1, v2, v1 ; SI-NEXT: buffer_store_short v0, off, s[4:7], 0 offset:4 ; SI-NEXT: buffer_store_dword v1, off, s[4:7], 0 ; SI-NEXT: s_endpgm @@ -837,25 +819,17 @@ define amdgpu_kernel void @maxnum_v4f16( ; SI-NEXT: v_cvt_f32_f16_e32 v2, s6 ; SI-NEXT: s_lshr_b32 s6, s7, 16 ; SI-NEXT: v_cvt_f32_f16_e32 v3, s6 +; SI-NEXT: v_cvt_f32_f16_e32 v4, s4 ; SI-NEXT: s_lshr_b32 s6, s5, 16 +; SI-NEXT: s_lshr_b32 s4, s4, 16 ; SI-NEXT: v_cvt_f32_f16_e32 v5, s6 +; SI-NEXT: v_cvt_f32_f16_e32 v7, s4 ; SI-NEXT: v_cvt_f32_f16_e32 v1, s7 -; SI-NEXT: v_cvt_f32_f16_e32 v4, s4 -; SI-NEXT: s_lshr_b32 s4, s4, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v7, s5 -; SI-NEXT: v_cvt_f32_f16_e32 v6, s4 -; SI-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 +; SI-NEXT: v_cvt_f32_f16_e32 v6, s5 ; SI-NEXT: v_max_f32_e32 v3, v3, v5 -; SI-NEXT: v_mul_f32_e32 v5, 1.0, v7 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_max_f32_e32 v1, v1, v5 -; SI-NEXT: v_mul_f32_e32 v5, 1.0, v6 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_max_f32_e32 v2, v2, v5 -; SI-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 +; SI-NEXT: v_max_f32_e32 v2, v2, v7 ; SI-NEXT: v_cvt_f16_f32_e32 v3, v3 +; SI-NEXT: v_max_f32_e32 v1, v1, v6 ; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; SI-NEXT: v_max_f32_e32 v0, v0, v4 ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 @@ -986,20 +960,16 @@ define amdgpu_kernel void @fmax_v4f16_imm_a( ; SI-NEXT: v_cvt_f32_f16_e32 v1, s5 ; SI-NEXT: s_lshr_b32 s5, s5, 16 ; SI-NEXT: v_cvt_f32_f16_e32 v0, s4 -; SI-NEXT: v_cvt_f32_f16_e32 v2, s5 ; SI-NEXT: s_lshr_b32 s4, s4, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v2, s5 ; SI-NEXT: v_cvt_f32_f16_e32 v3, s4 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_max_f32_e32 v2, 4.0, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; SI-NEXT: v_max_f32_e32 v1, 0x40400000, v1 +; SI-NEXT: v_max_f32_e32 v0, 0x41000000, v0 +; SI-NEXT: v_max_f32_e32 v2, 4.0, v2 ; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; SI-NEXT: v_max_f32_e32 v3, 2.0, v3 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; SI-NEXT: v_cvt_f16_f32_e32 v3, v3 -; SI-NEXT: v_max_f32_e32 v0, 0x41000000, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: v_lshlrev_b32_e32 v2, 16, v2 ; SI-NEXT: v_or_b32_e32 v1, v1, v2 diff --git a/llvm/test/CodeGen/AMDGPU/llvm.minnum.f16.ll b/llvm/test/CodeGen/AMDGPU/llvm.minnum.f16.ll index b7370ce0fde1..f934a2de9247 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.minnum.f16.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.minnum.f16.ll @@ -32,8 +32,6 @@ define amdgpu_kernel void @minnum_f16_ieee( ; SI-NEXT: s_mov_b32 s1, s5 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; SI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; SI-NEXT: v_min_f32_e32 v0, v0, v1 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: buffer_store_short v0, off, s[0:3], 0 @@ -197,7 +195,6 @@ define amdgpu_kernel void @minnum_f16_imm_a( ; SI-NEXT: s_mov_b32 s5, s1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, 0x40400000, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: buffer_store_short v0, off, s[4:7], 0 @@ -305,7 +302,6 @@ define amdgpu_kernel void @minnum_f16_imm_b( ; SI-NEXT: s_mov_b32 s5, s1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, 4.0, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: buffer_store_short v0, off, s[4:7], 0 @@ -409,21 +405,17 @@ define amdgpu_kernel void @minnum_v2f16_ieee( ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: s_lshr_b32 s1, s2, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v1, s0 -; SI-NEXT: s_lshr_b32 s0, s0, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v2, s0 -; SI-NEXT: v_cvt_f32_f16_e32 v3, s1 -; SI-NEXT: v_cvt_f32_f16_e32 v0, s2 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_min_f32_e32 v2, v3, v2 -; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 +; SI-NEXT: s_lshr_b32 s3, s0, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v0, s1 +; SI-NEXT: v_cvt_f32_f16_e32 v1, s3 +; SI-NEXT: v_cvt_f32_f16_e32 v2, s2 +; SI-NEXT: v_cvt_f32_f16_e32 v3, s0 ; SI-NEXT: v_min_f32_e32 v0, v0, v1 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v2 -; SI-NEXT: v_or_b32_e32 v0, v0, v1 +; SI-NEXT: v_min_f32_e32 v1, v2, v3 +; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; SI-NEXT: v_or_b32_e32 v0, v1, v0 ; SI-NEXT: buffer_store_dword v0, off, s[4:7], 0 ; SI-NEXT: s_endpgm ; @@ -556,20 +548,18 @@ define amdgpu_kernel void @minnum_v2f16_imm_a( ; SI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x9 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: s_load_dword s2, s[2:3], 0x0 -; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_waitcnt lgkmcnt(0) -; SI-NEXT: v_cvt_f32_f16_e32 v0, s2 -; SI-NEXT: s_lshr_b32 s2, s2, 16 +; SI-NEXT: s_lshr_b32 s3, s2, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v0, s3 ; SI-NEXT: v_cvt_f32_f16_e32 v1, s2 +; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_mov_b32 s2, -1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_min_f32_e32 v0, 0x40400000, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_min_f32_e32 v1, 4.0, v1 -; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_min_f32_e32 v0, 4.0, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 -; SI-NEXT: v_or_b32_e32 v0, v0, v1 +; SI-NEXT: v_min_f32_e32 v1, 0x40400000, v1 +; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; SI-NEXT: v_or_b32_e32 v0, v1, v0 ; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0 ; SI-NEXT: s_endpgm ; @@ -647,20 +637,18 @@ define amdgpu_kernel void @minnum_v2f16_imm_b( ; SI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x9 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: s_load_dword s2, s[2:3], 0x0 -; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_waitcnt lgkmcnt(0) -; SI-NEXT: v_cvt_f32_f16_e32 v0, s2 -; SI-NEXT: s_lshr_b32 s2, s2, 16 +; SI-NEXT: s_lshr_b32 s3, s2, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v0, s3 ; SI-NEXT: v_cvt_f32_f16_e32 v1, s2 +; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_mov_b32 s2, -1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_min_f32_e32 v0, 4.0, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_min_f32_e32 v1, 0x40400000, v1 -; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_min_f32_e32 v0, 0x40400000, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 -; SI-NEXT: v_or_b32_e32 v0, v0, v1 +; SI-NEXT: v_min_f32_e32 v1, 4.0, v1 +; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; SI-NEXT: v_or_b32_e32 v0, v1, v0 ; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0 ; SI-NEXT: s_endpgm ; @@ -745,27 +733,21 @@ define amdgpu_kernel void @minnum_v3f16( ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_cvt_f32_f16_e32 v0, s3 -; SI-NEXT: v_cvt_f32_f16_e32 v1, s2 -; SI-NEXT: s_lshr_b32 s2, s2, 16 -; SI-NEXT: s_lshr_b32 s3, s0, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v2, s3 +; SI-NEXT: s_lshr_b32 s3, s2, 16 +; SI-NEXT: s_lshr_b32 s8, s0, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v1, s3 +; SI-NEXT: v_cvt_f32_f16_e32 v2, s8 ; SI-NEXT: v_cvt_f32_f16_e32 v3, s2 -; SI-NEXT: v_cvt_f32_f16_e32 v5, s0 -; SI-NEXT: v_cvt_f32_f16_e32 v4, s1 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; SI-NEXT: v_min_f32_e32 v2, v3, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v5 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_min_f32_e32 v1, v1, v3 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v4 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 -; SI-NEXT: v_min_f32_e32 v0, v0, v3 +; SI-NEXT: v_cvt_f32_f16_e32 v4, s0 +; SI-NEXT: v_cvt_f32_f16_e32 v5, s1 +; SI-NEXT: v_min_f32_e32 v1, v1, v2 ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_min_f32_e32 v2, v3, v4 +; SI-NEXT: v_min_f32_e32 v0, v0, v5 +; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v2, 16, v2 -; SI-NEXT: v_or_b32_e32 v1, v1, v2 +; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; SI-NEXT: v_or_b32_e32 v1, v2, v1 ; SI-NEXT: buffer_store_short v0, off, s[4:7], 0 offset:4 ; SI-NEXT: buffer_store_dword v1, off, s[4:7], 0 ; SI-NEXT: s_endpgm @@ -893,25 +875,17 @@ define amdgpu_kernel void @minnum_v4f16( ; SI-NEXT: v_cvt_f32_f16_e32 v2, s6 ; SI-NEXT: s_lshr_b32 s6, s7, 16 ; SI-NEXT: v_cvt_f32_f16_e32 v3, s6 +; SI-NEXT: v_cvt_f32_f16_e32 v4, s4 ; SI-NEXT: s_lshr_b32 s6, s5, 16 +; SI-NEXT: s_lshr_b32 s4, s4, 16 ; SI-NEXT: v_cvt_f32_f16_e32 v5, s6 +; SI-NEXT: v_cvt_f32_f16_e32 v7, s4 ; SI-NEXT: v_cvt_f32_f16_e32 v1, s7 -; SI-NEXT: v_cvt_f32_f16_e32 v4, s4 -; SI-NEXT: s_lshr_b32 s4, s4, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v7, s5 -; SI-NEXT: v_cvt_f32_f16_e32 v6, s4 -; SI-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 +; SI-NEXT: v_cvt_f32_f16_e32 v6, s5 ; SI-NEXT: v_min_f32_e32 v3, v3, v5 -; SI-NEXT: v_mul_f32_e32 v5, 1.0, v7 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_min_f32_e32 v1, v1, v5 -; SI-NEXT: v_mul_f32_e32 v5, 1.0, v6 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_min_f32_e32 v2, v2, v5 -; SI-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 +; SI-NEXT: v_min_f32_e32 v2, v2, v7 ; SI-NEXT: v_cvt_f16_f32_e32 v3, v3 +; SI-NEXT: v_min_f32_e32 v1, v1, v6 ; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; SI-NEXT: v_min_f32_e32 v0, v0, v4 ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 @@ -1041,20 +1015,16 @@ define amdgpu_kernel void @fmin_v4f16_imm_a( ; SI-NEXT: v_cvt_f32_f16_e32 v1, s5 ; SI-NEXT: s_lshr_b32 s5, s5, 16 ; SI-NEXT: v_cvt_f32_f16_e32 v0, s4 -; SI-NEXT: v_cvt_f32_f16_e32 v2, s5 ; SI-NEXT: s_lshr_b32 s4, s4, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v2, s5 ; SI-NEXT: v_cvt_f32_f16_e32 v3, s4 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_min_f32_e32 v2, 4.0, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; SI-NEXT: v_min_f32_e32 v1, 0x40400000, v1 +; SI-NEXT: v_min_f32_e32 v0, 0x41000000, v0 +; SI-NEXT: v_min_f32_e32 v2, 4.0, v2 ; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; SI-NEXT: v_min_f32_e32 v3, 2.0, v3 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; SI-NEXT: v_cvt_f16_f32_e32 v3, v3 -; SI-NEXT: v_min_f32_e32 v0, 0x41000000, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: v_lshlrev_b32_e32 v2, 16, v2 ; SI-NEXT: v_or_b32_e32 v1, v1, v2 diff --git a/llvm/test/CodeGen/AMDGPU/mad-mix-lo.ll b/llvm/test/CodeGen/AMDGPU/mad-mix-lo.ll index fb3e79b2cf29..5b7f0e72b70d 100644 --- a/llvm/test/CodeGen/AMDGPU/mad-mix-lo.ll +++ b/llvm/test/CodeGen/AMDGPU/mad-mix-lo.ll @@ -951,56 +951,70 @@ define <3 x half> @v_mad_mix_v3f32_clamp_postcvt(<3 x half> %src0, <3 x half> %s ; SDAG-GFX1100-LABEL: v_mad_mix_v3f32_clamp_postcvt: ; SDAG-GFX1100: ; %bb.0: ; SDAG-GFX1100-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-GFX1100-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] ; SDAG-GFX1100-NEXT: v_fma_mixlo_f16 v1, v1, v3, v5 op_sel_hi:[1,1,1] -; SDAG-GFX1100-NEXT: v_fma_mixlo_f16 v3, v0, v2, v4 op_sel_hi:[1,1,1] clamp ; SDAG-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) -; SDAG-GFX1100-NEXT: v_pack_b32_f16 v1, v1, 0 -; SDAG-GFX1100-NEXT: v_fma_mixhi_f16 v3, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp +; SDAG-GFX1100-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX1100-NEXT: v_pack_b32_f16 v0, v1, 0 ; SDAG-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) -; SDAG-GFX1100-NEXT: v_pk_max_f16 v1, v1, v1 clamp -; SDAG-GFX1100-NEXT: v_mov_b32_e32 v0, v3 +; SDAG-GFX1100-NEXT: v_pk_max_f16 v1, v6, 0 +; SDAG-GFX1100-NEXT: v_pk_max_f16 v2, v0, 0 +; SDAG-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) +; SDAG-GFX1100-NEXT: v_pk_min_f16 v0, v1, 1.0 op_sel_hi:[1,0] +; SDAG-GFX1100-NEXT: v_pk_min_f16 v1, v2, 1.0 op_sel_hi:[1,0] ; SDAG-GFX1100-NEXT: s_setpc_b64 s[30:31] ; ; SDAG-GFX900-LABEL: v_mad_mix_v3f32_clamp_postcvt: ; SDAG-GFX900: ; %bb.0: ; SDAG-GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-GFX900-NEXT: v_mad_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] ; SDAG-GFX900-NEXT: v_mad_mixlo_f16 v1, v1, v3, v5 op_sel_hi:[1,1,1] -; SDAG-GFX900-NEXT: v_mad_mixlo_f16 v3, v0, v2, v4 op_sel_hi:[1,1,1] clamp ; SDAG-GFX900-NEXT: v_pack_b32_f16 v1, v1, 0 -; SDAG-GFX900-NEXT: v_mad_mixhi_f16 v3, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; SDAG-GFX900-NEXT: v_pk_max_f16 v1, v1, v1 clamp -; SDAG-GFX900-NEXT: v_mov_b32_e32 v0, v3 +; SDAG-GFX900-NEXT: v_mad_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX900-NEXT: v_pk_max_f16 v1, v1, 0 +; SDAG-GFX900-NEXT: v_pk_max_f16 v0, v6, 0 +; SDAG-GFX900-NEXT: v_pk_min_f16 v0, v0, 1.0 op_sel_hi:[1,0] +; SDAG-GFX900-NEXT: v_pk_min_f16 v1, v1, 1.0 op_sel_hi:[1,0] ; SDAG-GFX900-NEXT: s_setpc_b64 s[30:31] ; ; SDAG-GFX906-LABEL: v_mad_mix_v3f32_clamp_postcvt: ; SDAG-GFX906: ; %bb.0: ; SDAG-GFX906-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-GFX906-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] ; SDAG-GFX906-NEXT: v_fma_mixlo_f16 v1, v1, v3, v5 op_sel_hi:[1,1,1] -; SDAG-GFX906-NEXT: v_fma_mixlo_f16 v3, v0, v2, v4 op_sel_hi:[1,1,1] clamp ; SDAG-GFX906-NEXT: v_pack_b32_f16 v1, v1, 0 -; SDAG-GFX906-NEXT: v_fma_mixhi_f16 v3, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; SDAG-GFX906-NEXT: v_pk_max_f16 v1, v1, v1 clamp -; SDAG-GFX906-NEXT: v_mov_b32_e32 v0, v3 +; SDAG-GFX906-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX906-NEXT: v_pk_max_f16 v1, v1, 0 +; SDAG-GFX906-NEXT: v_pk_max_f16 v0, v6, 0 +; SDAG-GFX906-NEXT: v_pk_min_f16 v0, v0, 1.0 op_sel_hi:[1,0] +; SDAG-GFX906-NEXT: v_pk_min_f16 v1, v1, 1.0 op_sel_hi:[1,0] ; SDAG-GFX906-NEXT: s_setpc_b64 s[30:31] ; ; SDAG-VI-LABEL: v_mad_mix_v3f32_clamp_postcvt: ; SDAG-VI: ; %bb.0: ; SDAG-VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v6, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 +; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v7, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 +; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v3, v3 ; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v2, v2 ; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v8, v4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 ; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v4, v4 -; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v3, v3 ; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v5, v5 ; SDAG-VI-NEXT: v_mac_f32_e32 v8, v6, v7 ; SDAG-VI-NEXT: v_mac_f32_e32 v4, v0, v2 -; SDAG-VI-NEXT: v_cvt_f16_f32_sdwa v0, v8 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD -; SDAG-VI-NEXT: v_cvt_f16_f32_e64 v2, v4 clamp ; SDAG-VI-NEXT: v_mac_f32_e32 v5, v1, v3 -; SDAG-VI-NEXT: v_cvt_f16_f32_e64 v1, v5 clamp +; SDAG-VI-NEXT: v_cvt_f16_f32_e32 v0, v8 +; SDAG-VI-NEXT: v_cvt_f16_f32_e32 v1, v4 +; SDAG-VI-NEXT: v_cvt_f16_f32_e32 v2, v5 +; SDAG-VI-NEXT: v_max_f16_e32 v0, 0, v0 +; SDAG-VI-NEXT: v_max_f16_e32 v3, 0, v1 +; SDAG-VI-NEXT: v_max_f16_e32 v1, 0, v2 +; SDAG-VI-NEXT: v_mov_b32_e32 v2, 0x3c00 +; SDAG-VI-NEXT: v_min_f16_sdwa v0, v0, v2 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD +; SDAG-VI-NEXT: v_min_f16_e32 v2, 1.0, v3 +; SDAG-VI-NEXT: v_min_f16_e32 v1, 1.0, v1 ; SDAG-VI-NEXT: v_or_b32_e32 v0, v2, v0 ; SDAG-VI-NEXT: s_setpc_b64 s[30:31] ; @@ -1139,63 +1153,80 @@ define <3 x half> @v_mad_mix_v3f32_clamp_postcvt(<3 x half> %src0, <3 x half> %s } define <4 x half> @v_mad_mix_v4f32_clamp_postcvt(<4 x half> %src0, <4 x half> %src1, <4 x half> %src2) #0 { -; GFX1100-LABEL: v_mad_mix_v4f32_clamp_postcvt: -; GFX1100: ; %bb.0: -; GFX1100-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX1100-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] clamp -; GFX1100-NEXT: v_fma_mixlo_f16 v7, v1, v3, v5 op_sel_hi:[1,1,1] clamp -; GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) -; GFX1100-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; GFX1100-NEXT: v_fma_mixhi_f16 v7, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX1100-NEXT: v_dual_mov_b32 v0, v6 :: v_dual_mov_b32 v1, v7 -; GFX1100-NEXT: s_setpc_b64 s[30:31] +; SDAG-GFX1100-LABEL: v_mad_mix_v4f32_clamp_postcvt: +; SDAG-GFX1100: ; %bb.0: +; SDAG-GFX1100-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-GFX1100-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] +; SDAG-GFX1100-NEXT: v_fma_mixlo_f16 v7, v1, v3, v5 op_sel_hi:[1,1,1] +; SDAG-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) +; SDAG-GFX1100-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX1100-NEXT: v_fma_mixhi_f16 v7, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) +; SDAG-GFX1100-NEXT: v_pk_max_f16 v0, v6, 0 +; SDAG-GFX1100-NEXT: v_pk_max_f16 v1, v7, 0 +; SDAG-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) +; SDAG-GFX1100-NEXT: v_pk_min_f16 v0, v0, 1.0 op_sel_hi:[1,0] +; SDAG-GFX1100-NEXT: v_pk_min_f16 v1, v1, 1.0 op_sel_hi:[1,0] +; SDAG-GFX1100-NEXT: s_setpc_b64 s[30:31] ; -; GFX900-LABEL: v_mad_mix_v4f32_clamp_postcvt: -; GFX900: ; %bb.0: -; GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX900-NEXT: v_mad_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] clamp -; GFX900-NEXT: v_mad_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; GFX900-NEXT: v_mad_mixlo_f16 v2, v1, v3, v5 op_sel_hi:[1,1,1] clamp -; GFX900-NEXT: v_mad_mixhi_f16 v2, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; GFX900-NEXT: v_mov_b32_e32 v0, v6 -; GFX900-NEXT: v_mov_b32_e32 v1, v2 -; GFX900-NEXT: s_setpc_b64 s[30:31] +; SDAG-GFX900-LABEL: v_mad_mix_v4f32_clamp_postcvt: +; SDAG-GFX900: ; %bb.0: +; SDAG-GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-GFX900-NEXT: v_mad_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] +; SDAG-GFX900-NEXT: v_mad_mixlo_f16 v7, v1, v3, v5 op_sel_hi:[1,1,1] +; SDAG-GFX900-NEXT: v_mad_mixhi_f16 v7, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX900-NEXT: v_mad_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX900-NEXT: v_pk_max_f16 v1, v7, 0 +; SDAG-GFX900-NEXT: v_pk_max_f16 v0, v6, 0 +; SDAG-GFX900-NEXT: v_pk_min_f16 v0, v0, 1.0 op_sel_hi:[1,0] +; SDAG-GFX900-NEXT: v_pk_min_f16 v1, v1, 1.0 op_sel_hi:[1,0] +; SDAG-GFX900-NEXT: s_setpc_b64 s[30:31] ; -; GFX906-LABEL: v_mad_mix_v4f32_clamp_postcvt: -; GFX906: ; %bb.0: -; GFX906-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX906-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] clamp -; GFX906-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; GFX906-NEXT: v_fma_mixlo_f16 v2, v1, v3, v5 op_sel_hi:[1,1,1] clamp -; GFX906-NEXT: v_fma_mixhi_f16 v2, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; GFX906-NEXT: v_mov_b32_e32 v0, v6 -; GFX906-NEXT: v_mov_b32_e32 v1, v2 -; GFX906-NEXT: s_setpc_b64 s[30:31] +; SDAG-GFX906-LABEL: v_mad_mix_v4f32_clamp_postcvt: +; SDAG-GFX906: ; %bb.0: +; SDAG-GFX906-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-GFX906-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] +; SDAG-GFX906-NEXT: v_fma_mixlo_f16 v7, v1, v3, v5 op_sel_hi:[1,1,1] +; SDAG-GFX906-NEXT: v_fma_mixhi_f16 v7, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX906-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX906-NEXT: v_pk_max_f16 v1, v7, 0 +; SDAG-GFX906-NEXT: v_pk_max_f16 v0, v6, 0 +; SDAG-GFX906-NEXT: v_pk_min_f16 v0, v0, 1.0 op_sel_hi:[1,0] +; SDAG-GFX906-NEXT: v_pk_min_f16 v1, v1, 1.0 op_sel_hi:[1,0] +; SDAG-GFX906-NEXT: s_setpc_b64 s[30:31] ; ; SDAG-VI-LABEL: v_mad_mix_v4f32_clamp_postcvt: ; SDAG-VI: ; %bb.0: ; SDAG-VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v6, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v7, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v0, v0 +; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v6, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 +; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v7, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 ; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v8, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v9, v3 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v2, v2 +; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v0, v0 +; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v8, v3 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 +; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v9, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 ; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v3, v3 -; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v10, v5 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v11, v4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v5, v5 +; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v2, v2 +; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v10, v4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 +; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v11, v5 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 ; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v4, v4 +; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v5, v5 ; SDAG-VI-NEXT: v_mac_f32_e32 v10, v7, v9 ; SDAG-VI-NEXT: v_mac_f32_e32 v11, v6, v8 -; SDAG-VI-NEXT: v_mac_f32_e32 v5, v1, v3 ; SDAG-VI-NEXT: v_mac_f32_e32 v4, v0, v2 -; SDAG-VI-NEXT: v_cvt_f16_f32_sdwa v0, v11 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD -; SDAG-VI-NEXT: v_cvt_f16_f32_sdwa v1, v10 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD -; SDAG-VI-NEXT: v_cvt_f16_f32_e64 v2, v4 clamp -; SDAG-VI-NEXT: v_cvt_f16_f32_e64 v3, v5 clamp +; SDAG-VI-NEXT: v_mac_f32_e32 v5, v1, v3 +; SDAG-VI-NEXT: v_cvt_f16_f32_e32 v0, v10 +; SDAG-VI-NEXT: v_cvt_f16_f32_e32 v1, v11 +; SDAG-VI-NEXT: v_cvt_f16_f32_e32 v2, v4 +; SDAG-VI-NEXT: v_cvt_f16_f32_e32 v3, v5 +; SDAG-VI-NEXT: v_max_f16_e32 v0, 0, v0 +; SDAG-VI-NEXT: v_max_f16_e32 v1, 0, v1 +; SDAG-VI-NEXT: v_max_f16_e32 v2, 0, v2 +; SDAG-VI-NEXT: v_max_f16_e32 v3, 0, v3 +; SDAG-VI-NEXT: v_mov_b32_e32 v4, 0x3c00 +; SDAG-VI-NEXT: v_min_f16_sdwa v1, v1, v4 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD +; SDAG-VI-NEXT: v_min_f16_sdwa v0, v0, v4 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD +; SDAG-VI-NEXT: v_min_f16_e32 v3, 1.0, v3 +; SDAG-VI-NEXT: v_min_f16_e32 v2, 1.0, v2 ; SDAG-VI-NEXT: v_or_b32_e32 v0, v2, v0 ; SDAG-VI-NEXT: v_or_b32_e32 v1, v3, v1 ; SDAG-VI-NEXT: s_setpc_b64 s[30:31] @@ -1241,6 +1272,40 @@ define <4 x half> @v_mad_mix_v4f32_clamp_postcvt(<4 x half> %src0, <4 x half> %s ; SDAG-CI-NEXT: v_cvt_f32_f16_e64 v3, v3 clamp ; SDAG-CI-NEXT: s_setpc_b64 s[30:31] ; +; GISEL-GFX1100-LABEL: v_mad_mix_v4f32_clamp_postcvt: +; GISEL-GFX1100: ; %bb.0: +; GISEL-GFX1100-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-GFX1100-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] clamp +; GISEL-GFX1100-NEXT: v_fma_mixlo_f16 v7, v1, v3, v5 op_sel_hi:[1,1,1] clamp +; GISEL-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) +; GISEL-GFX1100-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp +; GISEL-GFX1100-NEXT: v_fma_mixhi_f16 v7, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp +; GISEL-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GISEL-GFX1100-NEXT: v_dual_mov_b32 v0, v6 :: v_dual_mov_b32 v1, v7 +; GISEL-GFX1100-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-GFX900-LABEL: v_mad_mix_v4f32_clamp_postcvt: +; GISEL-GFX900: ; %bb.0: +; GISEL-GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-GFX900-NEXT: v_mad_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] clamp +; GISEL-GFX900-NEXT: v_mad_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp +; GISEL-GFX900-NEXT: v_mad_mixlo_f16 v2, v1, v3, v5 op_sel_hi:[1,1,1] clamp +; GISEL-GFX900-NEXT: v_mad_mixhi_f16 v2, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp +; GISEL-GFX900-NEXT: v_mov_b32_e32 v0, v6 +; GISEL-GFX900-NEXT: v_mov_b32_e32 v1, v2 +; GISEL-GFX900-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-GFX906-LABEL: v_mad_mix_v4f32_clamp_postcvt: +; GISEL-GFX906: ; %bb.0: +; GISEL-GFX906-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-GFX906-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] clamp +; GISEL-GFX906-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp +; GISEL-GFX906-NEXT: v_fma_mixlo_f16 v2, v1, v3, v5 op_sel_hi:[1,1,1] clamp +; GISEL-GFX906-NEXT: v_fma_mixhi_f16 v2, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp +; GISEL-GFX906-NEXT: v_mov_b32_e32 v0, v6 +; GISEL-GFX906-NEXT: v_mov_b32_e32 v1, v2 +; GISEL-GFX906-NEXT: s_setpc_b64 s[30:31] +; ; GISEL-VI-LABEL: v_mad_mix_v4f32_clamp_postcvt: ; GISEL-VI: ; %bb.0: ; GISEL-VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -- GitLab From c18e1215c4f387058961651148be730144d3537b Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 13 Mar 2024 20:15:29 +0800 Subject: [PATCH 365/953] [InstCombine] Simplify `zext nneg i1 X` to zero (#85043) Alive2: https://alive2.llvm.org/ce/z/Wm6kCk --- .../InstCombine/InstCombineCasts.cpp | 4 +++ llvm/test/Transforms/InstCombine/zext.ll | 31 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index 45afa6363ae0..a9817f1af8c1 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -1121,6 +1121,10 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &Zext) { Value *Src = Zext.getOperand(0); Type *SrcTy = Src->getType(), *DestTy = Zext.getType(); + // zext nneg bool x -> 0 + if (SrcTy->isIntOrIntVectorTy(1) && Zext.hasNonNeg()) + return replaceInstUsesWith(Zext, Constant::getNullValue(Zext.getType())); + // Try to extend the entire expression tree to the wide destination type. unsigned BitsToClear; if (shouldChangeType(SrcTy, DestTy) && diff --git a/llvm/test/Transforms/InstCombine/zext.ll b/llvm/test/Transforms/InstCombine/zext.ll index edbd4850fb11..88cd9c70af40 100644 --- a/llvm/test/Transforms/InstCombine/zext.ll +++ b/llvm/test/Transforms/InstCombine/zext.ll @@ -836,3 +836,34 @@ define i64 @zext_nneg_demanded_constant(i8 %a) nounwind { %c = and i64 %b, 254 ret i64 %c } + +define i32 @zext_nneg_i1(i1 %x) { +; CHECK-LABEL: @zext_nneg_i1( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32 0 +; +entry: + %res = zext nneg i1 %x to i32 + ret i32 %res +} + +define <2 x i32> @zext_nneg_i1_vec(<2 x i1> %x) { +; CHECK-LABEL: @zext_nneg_i1_vec( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret <2 x i32> zeroinitializer +; +entry: + %res = zext nneg <2 x i1> %x to <2 x i32> + ret <2 x i32> %res +} + +define i32 @zext_nneg_i2(i2 %x) { +; CHECK-LABEL: @zext_nneg_i2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RES:%.*]] = zext nneg i2 [[X:%.*]] to i32 +; CHECK-NEXT: ret i32 [[RES]] +; +entry: + %res = zext nneg i2 %x to i32 + ret i32 %res +} -- GitLab From 203757776826cfd164c537048ec90f5ada50cae2 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 13 Mar 2024 13:27:20 +0100 Subject: [PATCH 366/953] [llvm-ar] Use COFF archive format for COFF targets. (#82898) Detect COFF files by default and allow specifying it with --format argument. This is important for ARM64EC, which uses a separated symbol map for EC symbols. Since K_COFF is mostly compatible with K_GNU, this shouldn't really make a difference for other targets. This originally landed as #82642, but was reverted due to test failures in tests using no symbol table. Since COFF symbol can't express it, fallback to GNU format in that case. --- llvm/docs/CommandGuide/llvm-ar.rst | 2 +- llvm/docs/ReleaseNotes.rst | 3 + llvm/include/llvm/Object/Archive.h | 1 + llvm/lib/Object/Archive.cpp | 15 ++-- llvm/lib/Object/ArchiveWriter.cpp | 28 ++++---- llvm/test/tools/llvm-ar/coff-symtab.test | 91 ++++++++++++++++++++++++ llvm/test/tools/llvm-ar/no-symtab.yaml | 32 +++++++++ llvm/tools/llvm-ar/llvm-ar.cpp | 22 ++++-- 8 files changed, 171 insertions(+), 23 deletions(-) create mode 100644 llvm/test/tools/llvm-ar/coff-symtab.test create mode 100644 llvm/test/tools/llvm-ar/no-symtab.yaml diff --git a/llvm/docs/CommandGuide/llvm-ar.rst b/llvm/docs/CommandGuide/llvm-ar.rst index 03d5b9e41ada..63b3a519550b 100644 --- a/llvm/docs/CommandGuide/llvm-ar.rst +++ b/llvm/docs/CommandGuide/llvm-ar.rst @@ -261,7 +261,7 @@ Other .. option:: --format= - This option allows for default, gnu, darwin or bsd ```` to be selected. + This option allows for default, gnu, darwin, bsd or coff ```` to be selected. When creating an ``archive`` with the default ````, :program:``llvm-ar`` will attempt to infer it from the input files and fallback to the default toolchain target if unable to do so. diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index b34a5f31c5eb..7be51730663b 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -153,6 +153,9 @@ Changes to the LLVM tools if it's not specified with the ``--format`` argument and cannot be inferred from input files. +* llvm-ar now allows specifying COFF archive format with ``--format`` argument + and uses it by default for COFF targets. + * llvm-objcopy now supports ``--set-symbol-visibility`` and ``--set-symbols-visibility`` options for ELF input to change the visibility of symbols. diff --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h index f71630054dc6..a3165c3235e0 100644 --- a/llvm/include/llvm/Object/Archive.h +++ b/llvm/include/llvm/Object/Archive.h @@ -339,6 +339,7 @@ public: Kind kind() const { return (Kind)Format; } bool isThin() const { return IsThin; } static object::Archive::Kind getDefaultKind(); + static object::Archive::Kind getDefaultKindForTriple(Triple &T); child_iterator child_begin(Error &Err, bool SkipInternal = true) const; child_iterator child_end() const; diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp index 9000e9aa81ff..6139d9996bda 100644 --- a/llvm/lib/Object/Archive.cpp +++ b/llvm/lib/Object/Archive.cpp @@ -969,12 +969,19 @@ Archive::Archive(MemoryBufferRef Source, Error &Err) Err = Error::success(); } +object::Archive::Kind Archive::getDefaultKindForTriple(Triple &T) { + if (T.isOSDarwin()) + return object::Archive::K_DARWIN; + if (T.isOSAIX()) + return object::Archive::K_AIXBIG; + if (T.isOSWindows()) + return object::Archive::K_COFF; + return object::Archive::K_GNU; +} + object::Archive::Kind Archive::getDefaultKind() { Triple HostTriple(sys::getDefaultTargetTriple()); - return HostTriple.isOSDarwin() - ? object::Archive::K_DARWIN - : (HostTriple.isOSAIX() ? object::Archive::K_AIXBIG - : object::Archive::K_GNU); + return getDefaultKindForTriple(HostTriple); } Archive::child_iterator Archive::child_begin(Error &Err, diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp index e0629747b40c..aa57e55de70c 100644 --- a/llvm/lib/Object/ArchiveWriter.cpp +++ b/llvm/lib/Object/ArchiveWriter.cpp @@ -62,12 +62,16 @@ object::Archive::Kind NewArchiveMember::detectKindFromObject() const { Expected> OptionalObject = object::ObjectFile::createObjectFile(MemBufferRef); - if (OptionalObject) - return isa(**OptionalObject) - ? object::Archive::K_DARWIN - : (isa(**OptionalObject) - ? object::Archive::K_AIXBIG - : object::Archive::K_GNU); + if (OptionalObject) { + if (isa(**OptionalObject)) + return object::Archive::K_DARWIN; + if (isa(**OptionalObject)) + return object::Archive::K_AIXBIG; + if (isa(**OptionalObject) || + isa(**OptionalObject)) + return object::Archive::K_COFF; + return object::Archive::K_GNU; + } // Squelch the error in case we had a non-object file. consumeError(OptionalObject.takeError()); @@ -80,10 +84,7 @@ object::Archive::Kind NewArchiveMember::detectKindFromObject() const { MemBufferRef, file_magic::bitcode, &Context)) { auto &IRObject = cast(**ObjOrErr); auto TargetTriple = Triple(IRObject.getTargetTriple()); - return TargetTriple.isOSDarwin() - ? object::Archive::K_DARWIN - : (TargetTriple.isOSAIX() ? object::Archive::K_AIXBIG - : object::Archive::K_GNU); + return object::Archive::getDefaultKindForTriple(TargetTriple); } else { // Squelch the error in case this was not a SymbolicFile. consumeError(ObjOrErr.takeError()); @@ -976,10 +977,12 @@ static Error writeArchiveToStream(raw_ostream &Out, SmallString<0> StringTableBuf; raw_svector_ostream StringTable(StringTableBuf); SymMap SymMap; + bool ShouldWriteSymtab = WriteSymtab != SymtabWritingMode::NoSymtab; // COFF symbol map uses 16-bit indexes, so we can't use it if there are too - // many members. - if (isCOFFArchive(Kind) && NewMembers.size() > 0xfffe) + // many members. COFF format also requires symbol table presence, so use + // GNU format when NoSymtab is requested. + if (isCOFFArchive(Kind) && (NewMembers.size() > 0xfffe || !ShouldWriteSymtab)) Kind = object::Archive::K_GNU; // In the scenario when LLVMContext is populated SymbolicFile will contain a @@ -1008,7 +1011,6 @@ static Error writeArchiveToStream(raw_ostream &Out, uint64_t LastMemberHeaderOffset = 0; uint64_t NumSyms = 0; uint64_t NumSyms32 = 0; // Store symbol number of 32-bit member files. - bool ShouldWriteSymtab = WriteSymtab != SymtabWritingMode::NoSymtab; for (const auto &M : Data) { // Record the start of the member's offset diff --git a/llvm/test/tools/llvm-ar/coff-symtab.test b/llvm/test/tools/llvm-ar/coff-symtab.test new file mode 100644 index 000000000000..4f7270d9e2c6 --- /dev/null +++ b/llvm/test/tools/llvm-ar/coff-symtab.test @@ -0,0 +1,91 @@ +Verify that llvm-ar uses COFF archive format by ensuring that archive map is sorted. + +RUN: rm -rf %t.dir && split-file %s %t.dir && cd %t.dir + +RUN: yaml2obj coff-symtab.yaml -o coff-symtab.obj +RUN: llvm-ar crs out.a coff-symtab.obj +RUN: llvm-nm --print-armap out.a | FileCheck %s + +RUN: llvm-as coff-symtab.ll -o coff-symtab.bc +RUN: llvm-ar crs out2.a coff-symtab.bc +RUN: llvm-nm --print-armap out2.a | FileCheck %s + +RUN: yaml2obj elf.yaml -o coff-symtab.o +RUN: llvm-ar crs --format coff out3.a coff-symtab.o +RUN: llvm-nm --print-armap out3.a | FileCheck %s + +Create an empty archive with no symbol map, add a COFF file to it and check that the output archive is a COFF archive. + +RUN: llvm-ar rcS out4.a +RUN: llvm-ar rs out4.a coff-symtab.obj +RUN: llvm-nm --print-armap out4.a | FileCheck %s + +CHECK: Archive map +CHECK-NEXT: a in coff-symtab +CHECK-NEXT: b in coff-symtab +CHECK-NEXT: c in coff-symtab +CHECK-EMPTY: + +#--- coff-symtab.yaml +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_UNKNOWN + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '' +symbols: + - Name: b + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: c + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: a + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... + + +#--- coff-symtab.ll +target triple = "x86_64-unknown-windows-msvc" + +define void @b() { ret void } +define void @c() { ret void } +define void @a() { ret void } + +#--- elf.yaml +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data : ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: '' +Symbols: + - Name: b + Binding: STB_GLOBAL + Section: .text + - Name: c + Binding: STB_GLOBAL + Section: .text + - Name: a + Binding: STB_GLOBAL + Section: .text +... diff --git a/llvm/test/tools/llvm-ar/no-symtab.yaml b/llvm/test/tools/llvm-ar/no-symtab.yaml new file mode 100644 index 000000000000..7370c9b32355 --- /dev/null +++ b/llvm/test/tools/llvm-ar/no-symtab.yaml @@ -0,0 +1,32 @@ +## Create archives with no symtab in various formats and check that we can read them. + +# RUN: yaml2obj %s -o %t.o +# RUN: rm -f %t.*.a + +# RUN: llvm-ar --format=gnu rcS %t.gnu.a %t.o +# RUN: llvm-ar --format=coff rcS %t.coff.a %t.o +# RUN: llvm-ar --format=darwin rcS %t.darwin.a %t.o +# RUN: llvm-ar --format=bsd rcS %t.bsd.a %t.o +# RUN: llvm-ar --format=bigarchive rcS %t.bigarchive.a %t.o + +# RUN: llvm-nm --print-armap %t.gnu.a | FileCheck %s +# RUN: llvm-nm --print-armap %t.coff.a | FileCheck %s +# RUN: llvm-nm --print-armap %t.darwin.a | FileCheck %s +# RUN: llvm-nm --print-armap %t.bsd.a | FileCheck %s +# RUN: llvm-nm --print-armap %t.bigarchive.a | FileCheck %s + +# CHECK-NOT: Archive map + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS +Symbols: + - Name: symbol + Binding: STB_GLOBAL + Section: .text diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp index 81cb2a21daf1..294b8531b08f 100644 --- a/llvm/tools/llvm-ar/llvm-ar.cpp +++ b/llvm/tools/llvm-ar/llvm-ar.cpp @@ -82,6 +82,7 @@ static void printArHelp(StringRef ToolName) { =darwin - darwin =bsd - bsd =bigarchive - big archive (AIX OS) + =coff - coff --plugin= - ignored for compatibility -h --help - display this help and exit --output - the directory to extract archive members to @@ -193,7 +194,7 @@ static SmallVector PositionalArgs; static bool MRI; namespace { -enum Format { Default, GNU, BSD, DARWIN, BIGARCHIVE, Unknown }; +enum Format { Default, GNU, COFF, BSD, DARWIN, BIGARCHIVE, Unknown }; } static Format FormatType = Default; @@ -1025,14 +1026,21 @@ static void performWriteOperation(ArchiveOperation Operation, Kind = object::Archive::K_GNU; else if (OldArchive) { Kind = OldArchive->kind(); - if (Kind == object::Archive::K_BSD) { - auto InferredKind = object::Archive::K_BSD; + std::optional AltKind; + if (Kind == object::Archive::K_BSD) + AltKind = object::Archive::K_DARWIN; + else if (Kind == object::Archive::K_GNU && !OldArchive->hasSymbolTable()) + // If there is no symbol table, we can't tell GNU from COFF format + // from the old archive type. + AltKind = object::Archive::K_COFF; + if (AltKind) { + auto InferredKind = Kind; if (NewMembersP && !NewMembersP->empty()) InferredKind = NewMembersP->front().detectKindFromObject(); else if (!NewMembers.empty()) InferredKind = NewMembers.front().detectKindFromObject(); - if (InferredKind == object::Archive::K_DARWIN) - Kind = object::Archive::K_DARWIN; + if (InferredKind == AltKind) + Kind = *AltKind; } } else if (NewMembersP) Kind = !NewMembersP->empty() ? NewMembersP->front().detectKindFromObject() @@ -1044,6 +1052,9 @@ static void performWriteOperation(ArchiveOperation Operation, case GNU: Kind = object::Archive::K_GNU; break; + case COFF: + Kind = object::Archive::K_COFF; + break; case BSD: if (Thin) fail("only the gnu format has a thin mode"); @@ -1376,6 +1387,7 @@ static int ar_main(int argc, char **argv) { .Case("darwin", DARWIN) .Case("bsd", BSD) .Case("bigarchive", BIGARCHIVE) + .Case("coff", COFF) .Default(Unknown); if (FormatType == Unknown) fail(std::string("Invalid format ") + Match); -- GitLab From 9e406ef4f4b089f88e74b2713f0fbee51b9537d6 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 13 Mar 2024 09:00:53 -0400 Subject: [PATCH 367/953] [libc++] Remove _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT (#83928) This was slated for removal in LLVM 19. --- libcxx/docs/ReleaseNotes/19.rst | 2 +- libcxx/include/variant | 32 +++---------------- .../variant.variant/variant.assign/T.pass.cpp | 15 ++------- .../variant.assign/conv.pass.cpp | 8 ++--- .../variant.variant/variant.ctor/T.pass.cpp | 15 ++------- .../variant.ctor/conv.pass.cpp | 8 ++--- libcxx/test/support/variant_test_helpers.h | 10 ------ 7 files changed, 18 insertions(+), 72 deletions(-) diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst index 04f16610f811..2b62a36ca8e5 100644 --- a/libcxx/docs/ReleaseNotes/19.rst +++ b/libcxx/docs/ReleaseNotes/19.rst @@ -65,7 +65,7 @@ Deprecations and Removals provided, and such a base template is bound to be incorrect for some types, which could currently cause unexpected behavior while going undetected. -- TODO: The ``_LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT`` macro that changed the behavior for narrowing conversions +- The ``_LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT`` macro that changed the behavior for narrowing conversions in ``std::variant`` has been removed in LLVM 19. - TODO: The ``_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS`` macro has been removed in LLVM 19. diff --git a/libcxx/include/variant b/libcxx/include/variant index d1eea52f0a93..59d7f9b740f3 100644 --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -347,13 +347,13 @@ inline constexpr size_t variant_npos = static_cast(-1); template _LIBCPP_HIDE_FROM_ABI constexpr auto __choose_index_type() { -#ifdef _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION +# ifdef _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION if constexpr (_NumAlternatives < numeric_limits::max()) return static_cast(0); else if constexpr (_NumAlternatives < numeric_limits::max()) return static_cast(0); else -#endif // _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION +# endif // _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION return static_cast(0); } @@ -1085,13 +1085,9 @@ struct __narrowing_check { }; template -using __check_for_narrowing _LIBCPP_NODEBUG = typename _If< -# ifdef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT - false && -# endif - is_arithmetic<_Dest>::value, - __narrowing_check, - __no_narrowing_check >::template _Apply<_Dest, _Source>; +using __check_for_narrowing _LIBCPP_NODEBUG = + typename _If< is_arithmetic<_Dest>::value, __narrowing_check, __no_narrowing_check >::template _Apply<_Dest, + _Source>; template struct __overload { @@ -1099,24 +1095,6 @@ struct __overload { auto operator()(_Tp, _Up&&) const -> __check_for_narrowing<_Tp, _Up>; }; -// TODO(LLVM-19): Remove all occurrences of this macro. -# ifdef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT -template -struct __overload_bool { - template > - auto operator()(bool, _Up&&) const -> enable_if_t, __type_identity<_Tp>>; -}; - -template -struct __overload : __overload_bool {}; -template -struct __overload : __overload_bool {}; -template -struct __overload : __overload_bool {}; -template -struct __overload : __overload_bool {}; -# endif - template struct __all_overloads : _Bases... { void operator()() const; diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp index b3fc2021a6b2..b38b10d89dfd 100644 --- a/libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp @@ -134,8 +134,7 @@ void test_T_assignment_sfinae() { } { using V = std::variant; - static_assert(std::is_assignable::value == VariantAllowsNarrowingConversions, - "no matching operator="); + static_assert(!std::is_assignable::value, "no matching operator="); } { using V = std::variant, bool>; @@ -144,12 +143,8 @@ void test_T_assignment_sfinae() { struct X { operator void*(); }; - static_assert(!std::is_assignable::value, - "no boolean conversion in operator="); -#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT - static_assert(std::is_assignable::value, - "converted to bool in operator="); -#endif + static_assert(!std::is_assignable::value, "no boolean conversion in operator="); + static_assert(std::is_assignable::value, "converted to bool in operator="); } { struct X {}; @@ -188,7 +183,6 @@ void test_T_assignment_basic() { assert(v.index() == 1); assert(std::get<1>(v) == 43); } -#ifndef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS { std::variant v; v = 42; @@ -198,7 +192,6 @@ void test_T_assignment_basic() { assert(v.index() == 0); assert(std::get<0>(v) == 43); } -#endif { std::variant v = true; v = "bar"; @@ -299,13 +292,11 @@ void test_T_assignment_performs_assignment() { } void test_T_assignment_vector_bool() { -#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT std::vector vec = {true}; std::variant v; v = vec[0]; assert(v.index() == 0); assert(std::get<0>(v) == true); -#endif } int main(int, char**) { diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp index 246309c01b4d..90e405d57750 100644 --- a/libcxx/test/std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp @@ -25,18 +25,16 @@ int main(int, char**) { static_assert(!std::is_assignable, int>::value, ""); static_assert(!std::is_assignable, int>::value, ""); - static_assert(std::is_assignable, int>::value == VariantAllowsNarrowingConversions, ""); + static_assert(!std::is_assignable, int>::value, ""); - static_assert(std::is_assignable, int>::value == VariantAllowsNarrowingConversions, ""); - static_assert(std::is_assignable, int>::value == VariantAllowsNarrowingConversions, ""); + static_assert(!std::is_assignable, int>::value, ""); + static_assert(!std::is_assignable, int>::value, ""); static_assert(!std::is_assignable, int>::value, ""); static_assert(!std::is_assignable, decltype("meow")>::value, ""); static_assert(!std::is_assignable, decltype("meow")>::value, ""); -#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT static_assert(std::is_assignable, std::true_type>::value, ""); -#endif static_assert(!std::is_assignable, std::unique_ptr >::value, ""); static_assert(!std::is_assignable, decltype(nullptr)>::value, ""); diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp index 89fd646878ee..6b7de8888849 100644 --- a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp @@ -68,8 +68,7 @@ void test_T_ctor_sfinae() { } { using V = std::variant; - static_assert(std::is_constructible::value == VariantAllowsNarrowingConversions, - "no matching constructor"); + static_assert(!std::is_constructible::value, "no matching constructor"); } { using V = std::variant, bool>; @@ -78,12 +77,8 @@ void test_T_ctor_sfinae() { struct X { operator void*(); }; - static_assert(!std::is_constructible::value, - "no boolean conversion in constructor"); -#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT - static_assert(std::is_constructible::value, - "converted to bool in constructor"); -#endif + static_assert(!std::is_constructible::value, "no boolean conversion in constructor"); + static_assert(std::is_constructible::value, "converted to bool in constructor"); } { struct X {}; @@ -128,13 +123,11 @@ void test_T_ctor_basic() { static_assert(v.index() == 1, ""); static_assert(std::get<1>(v) == 42, ""); } -#ifndef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS { constexpr std::variant v(42); static_assert(v.index() == 1, ""); static_assert(std::get<1>(v) == 42, ""); } -#endif { std::variant v = "foo"; assert(v.index() == 0); @@ -202,12 +195,10 @@ void test_construction_with_repeated_types() { } void test_vector_bool() { -#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT std::vector vec = {true}; std::variant v = vec[0]; assert(v.index() == 0); assert(std::get<0>(v) == true); -#endif } int main(int, char**) { diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp index 7fb44ff40765..0b8eeed1eac8 100644 --- a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp @@ -24,18 +24,16 @@ int main(int, char**) { static_assert(!std::is_constructible, int>::value, ""); static_assert(!std::is_constructible, int>::value, ""); - static_assert(std::is_constructible, int>::value == VariantAllowsNarrowingConversions, ""); + static_assert(!std::is_constructible, int>::value, ""); - static_assert(std::is_constructible, int>::value == VariantAllowsNarrowingConversions, ""); - static_assert(std::is_constructible, int>::value == VariantAllowsNarrowingConversions, ""); + static_assert(!std::is_constructible, int>::value, ""); + static_assert(!std::is_constructible, int>::value, ""); static_assert(!std::is_constructible, int>::value, ""); static_assert(!std::is_constructible, decltype("meow")>::value, ""); static_assert(!std::is_constructible, decltype("meow")>::value, ""); -#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT static_assert(std::is_constructible, std::true_type>::value, ""); -#endif static_assert(!std::is_constructible, std::unique_ptr >::value, ""); static_assert(!std::is_constructible, decltype(nullptr)>::value, ""); diff --git a/libcxx/test/support/variant_test_helpers.h b/libcxx/test/support/variant_test_helpers.h index c174cba32840..345e32170e58 100644 --- a/libcxx/test/support/variant_test_helpers.h +++ b/libcxx/test/support/variant_test_helpers.h @@ -24,16 +24,6 @@ // FIXME: Currently the variant tests are disabled using this macro. #define TEST_VARIANT_HAS_NO_REFERENCES -// TODO(LLVM-19): Remove TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS -#ifdef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT -# define TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS -#endif -#ifdef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS -constexpr bool VariantAllowsNarrowingConversions = true; -#else -constexpr bool VariantAllowsNarrowingConversions = false; -#endif - #ifndef TEST_HAS_NO_EXCEPTIONS struct CopyThrows { CopyThrows() = default; -- GitLab From 5c3d001668ec6117045a9750a1f9d7e3995adfee Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 13 Mar 2024 18:34:23 +0530 Subject: [PATCH 368/953] AMDGPU: Don't use table for metadata docs, and fix section headers (#85046) --- llvm/docs/AMDGPUUsage.rst | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst index fd9ad7fac19a..fe37e85c2a40 100644 --- a/llvm/docs/AMDGPUUsage.rst +++ b/llvm/docs/AMDGPUUsage.rst @@ -1312,24 +1312,30 @@ The AMDGPU backend implements the following LLVM IR intrinsics. List AMDGPU intrinsics. +.. _amdgpu_metadata: + LLVM IR Metadata ------------------- +================ + +The AMDGPU backend implements the following target custom LLVM IR +metadata. + +.. _amdgpu_last_use: -The AMDGPU backend implements the following LLVM IR metadata. +'``amdgpu.last.use``' Metadata +------------------------------ + +Sets TH_LOAD_LU temporal hint on load instructions that support it. +Takes priority over nontemporal hint (TH_LOAD_NT). This takes no +arguments. + +.. code-block:: llvm -.. list-table:: AMDGPU LLVM IR Metatdata - :name: amdgpu-llvm-ir-metadata-table + %val = load i32, ptr %in, align 4, !amdgpu.last.use !{} - * - Metadata Name - - Description - - Values - * - !amdgpu.last.use - - Sets TH_LOAD_LU temporal hint on load instructions that support it. - Takes priority over nontemporal hint (TH_LOAD_NT). - - {} LLVM IR Attributes ------------------- +================== The AMDGPU backend supports the following LLVM IR attributes. @@ -1451,7 +1457,7 @@ The AMDGPU backend supports the following LLVM IR attributes. ======================================= ========================================================== Calling Conventions -------------------- +=================== The AMDGPU backend supports the following calling conventions: -- GitLab From 9fa866020395b215ece6140c2fedc7c31950272c Mon Sep 17 00:00:00 2001 From: Jay Foad Date: Wed, 13 Mar 2024 13:11:45 +0000 Subject: [PATCH 369/953] [AMDGPU] Test new GFX12 opcode name buffer_atomic_min_num_f32 The old name buffer_atomic_min_f32 is still tested as part of the alias tests. --- llvm/test/MC/AMDGPU/gfx12_asm_vbuffer_mubuf.s | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/llvm/test/MC/AMDGPU/gfx12_asm_vbuffer_mubuf.s b/llvm/test/MC/AMDGPU/gfx12_asm_vbuffer_mubuf.s index 08ec5b3f6a52..efeaf8339f69 100644 --- a/llvm/test/MC/AMDGPU/gfx12_asm_vbuffer_mubuf.s +++ b/llvm/test/MC/AMDGPU/gfx12_asm_vbuffer_mubuf.s @@ -3970,70 +3970,70 @@ buffer_atomic_max_u64 v[5:6], off, s[8:11], s3 offset:8388607 dlc buffer_atomic_max_u64 v[5:6], off, s[8:11], s3 offset:8388607 glc slc dlc // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x80,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v255, off, s[8:11], s3 offset:8388607 +buffer_atomic_min_num_f32 v255, off, s[8:11], s3 offset:8388607 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0xff,0x10,0x80,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[12:15], s3 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[12:15], s3 offset:8388607 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x18,0x80,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[96:99], s3 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[96:99], s3 offset:8388607 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0xc0,0x80,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[8:11], s101 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[8:11], s101 offset:8388607 // GFX12: encoding: [0x65,0x40,0x14,0xc4,0x05,0x10,0x80,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[8:11], m0 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[8:11], m0 offset:8388607 // GFX12: encoding: [0x7d,0x40,0x14,0xc4,0x05,0x10,0x80,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[8:11], 0 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[8:11], 0 offset:8388607 // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, off, s[8:11], -1 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[8:11], -1 offset:8388607 // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, off, s[8:11], 0.5 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[8:11], 0.5 offset:8388607 // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, off, s[8:11], -4.0 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[8:11], -4.0 offset:8388607 // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, v0, s[8:11], s3 idxen offset:8388607 +buffer_atomic_min_num_f32 v5, v0, s[8:11], s3 idxen offset:8388607 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x80,0x80,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, v0, s[8:11], s3 offen offset:8388607 +buffer_atomic_min_num_f32 v5, v0, s[8:11], s3 offen offset:8388607 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x80,0x40,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[8:11], s3 +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x80,0x00,0x00,0x00,0x00,0x00] -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:0 +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:0 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x80,0x00,0x00,0x00,0x00,0x00] -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:7 +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:7 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x80,0x00,0x00,0x07,0x00,0x00] -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 th:TH_ATOMIC_RETURN +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 th:TH_ATOMIC_RETURN // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x90,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 th:TH_ATOMIC_RT_RETURN scope:SCOPE_SE +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 th:TH_ATOMIC_RT_RETURN scope:SCOPE_SE // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x94,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 th:TH_ATOMIC_CASCADE_NT scope:SCOPE_DEV +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 th:TH_ATOMIC_CASCADE_NT scope:SCOPE_DEV // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0xe8,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 glc +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 glc // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 slc +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 slc // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 dlc +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 dlc // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 glc slc dlc +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 glc slc dlc // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction buffer_atomic_min_i32 v5, off, s[8:11], s3 offset:8388607 -- GitLab From e48d5a838f69e0a8e0ae95a8aed1a8809f45465a Mon Sep 17 00:00:00 2001 From: NagyDonat Date: Tue, 12 Mar 2024 18:24:26 +0100 Subject: [PATCH 370/953] Reapply "[analyzer] Accept C library functions from the `std` namespace" This reapplies f32b04d4ea91ad1018c25a1d4178cc4392d34968i, after fixing the use-after-free of ASTUnit in the unittest. https://github.com/llvm/llvm-project/pull/84469#issuecomment-1992163439 Co-authored-by: Balazs Benics --- .../Core/PathSensitive/CallDescription.h | 8 +- .../StaticAnalyzer/Core/CheckerContext.cpp | 8 +- clang/unittests/StaticAnalyzer/CMakeLists.txt | 1 + .../StaticAnalyzer/IsCLibraryFunctionTest.cpp | 84 +++++++++++++++++++ .../clang/unittests/StaticAnalyzer/BUILD.gn | 1 + 5 files changed, 93 insertions(+), 9 deletions(-) create mode 100644 clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h index 3432d2648633..b4e1636130ca 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h @@ -41,12 +41,8 @@ public: /// - We also accept calls where the number of arguments or parameters is /// greater than the specified value. /// For the exact heuristics, see CheckerContext::isCLibraryFunction(). - /// Note that functions whose declaration context is not a TU (e.g. - /// methods, functions in namespaces) are not accepted as C library - /// functions. - /// FIXME: If I understand it correctly, this discards calls where C++ code - /// refers a C library function through the namespace `std::` via headers - /// like . + /// (This mode only matches functions that are declared either directly + /// within a TU or in the namespace `std`.) CLibrary, /// Matches "simple" functions that are not methods. (Static methods are diff --git a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp index d6d4cec9dd3d..1a9bff529e9b 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp @@ -87,9 +87,11 @@ bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD, if (!II) return false; - // Look through 'extern "C"' and anything similar invented in the future. - // If this function is not in TU directly, it is not a C library function. - if (!FD->getDeclContext()->getRedeclContext()->isTranslationUnit()) + // C library functions are either declared directly within a TU (the common + // case) or they are accessed through the namespace `std` (when they are used + // in C++ via headers like ). + const DeclContext *DC = FD->getDeclContext()->getRedeclContext(); + if (!(DC->isTranslationUnit() || DC->isStdNamespace())) return false; // If this function is not externally visible, it is not a C library function. diff --git a/clang/unittests/StaticAnalyzer/CMakeLists.txt b/clang/unittests/StaticAnalyzer/CMakeLists.txt index 775f0f8486b8..db56e77331b8 100644 --- a/clang/unittests/StaticAnalyzer/CMakeLists.txt +++ b/clang/unittests/StaticAnalyzer/CMakeLists.txt @@ -11,6 +11,7 @@ add_clang_unittest(StaticAnalysisTests CallEventTest.cpp ConflictingEvalCallsTest.cpp FalsePositiveRefutationBRVisitorTest.cpp + IsCLibraryFunctionTest.cpp NoStateChangeFuncVisitorTest.cpp ParamRegionTest.cpp RangeSetTest.cpp diff --git a/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp b/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp new file mode 100644 index 000000000000..31ff13f428da --- /dev/null +++ b/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp @@ -0,0 +1,84 @@ +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Frontend/ASTUnit.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/Tooling/Tooling.h" +#include "gtest/gtest.h" + +#include + +using namespace clang; +using namespace ento; +using namespace ast_matchers; + +class IsCLibraryFunctionTest : public testing::Test { +public: + const FunctionDecl *getFunctionDecl() const { return Result; } + + testing::AssertionResult buildAST(StringRef Code) { + ASTUnit = tooling::buildASTFromCode(Code); + if (!ASTUnit) + return testing::AssertionFailure() << "AST construction failed"; + + ASTContext &Context = ASTUnit->getASTContext(); + if (Context.getDiagnostics().hasErrorOccurred()) + return testing::AssertionFailure() << "Compilation error"; + + auto Matches = ast_matchers::match(functionDecl().bind("fn"), Context); + if (Matches.empty()) + return testing::AssertionFailure() << "No function declaration found"; + + if (Matches.size() > 1) + return testing::AssertionFailure() + << "Multiple function declarations found"; + + Result = Matches[0].getNodeAs("fn"); + return testing::AssertionSuccess(); + } + +private: + std::unique_ptr ASTUnit; + const FunctionDecl *Result = nullptr; +}; + +TEST_F(IsCLibraryFunctionTest, AcceptsGlobal) { + ASSERT_TRUE(buildAST(R"cpp(void fun();)cpp")); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, AcceptsExternCGlobal) { + ASSERT_TRUE(buildAST(R"cpp(extern "C" { void fun(); })cpp")); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsNoInlineNoExternalLinkage) { + // Functions that are neither inlined nor externally visible cannot be C library functions. + ASSERT_TRUE(buildAST(R"cpp(static void fun();)cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsAnonymousNamespace) { + ASSERT_TRUE(buildAST(R"cpp(namespace { void fun(); })cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, AcceptsStdNamespace) { + ASSERT_TRUE(buildAST(R"cpp(namespace std { void fun(); })cpp")); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsOtherNamespaces) { + ASSERT_TRUE(buildAST(R"cpp(namespace stdx { void fun(); })cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsClassStatic) { + ASSERT_TRUE(buildAST(R"cpp(class A { static void fun(); };)cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsClassMember) { + ASSERT_TRUE(buildAST(R"cpp(class A { void fun(); };)cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} diff --git a/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn index 01c2b6ced336..9c240cff1816 100644 --- a/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn @@ -19,6 +19,7 @@ unittest("StaticAnalysisTests") { "CallEventTest.cpp", "ConflictingEvalCallsTest.cpp", "FalsePositiveRefutationBRVisitorTest.cpp", + "IsCLibraryFunctionTest.cpp", "NoStateChangeFuncVisitorTest.cpp", "ParamRegionTest.cpp", "RangeSetTest.cpp", -- GitLab From 83d178843f4322159b6469f430a8a241b8672d6d Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 13 Mar 2024 21:52:40 +0800 Subject: [PATCH 371/953] [InstCombine] Set zero_is_poison for ctlz/cttz if they are only used as shift amounts (#85035) Alive2: https://alive2.llvm.org/ce/z/r-67t9 It would improve the codegen if the target doesn't provide a defined value for ctlz/cttz with zero. --- .../InstCombine/InstCombineCalls.cpp | 5 + .../Transforms/InstCombine/shift-cttz-ctlz.ll | 93 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 llvm/test/Transforms/InstCombine/shift-cttz-ctlz.ll diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index f5f3716d390d..694b18017bab 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -504,6 +504,11 @@ static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) { return IC.replaceInstUsesWith(II, ConstantInt::getNullValue(II.getType())); } + // If ctlz/cttz is only used as a shift amount, set is_zero_poison to true. + if (II.hasOneUse() && match(Op1, m_Zero()) && + match(II.user_back(), m_Shift(m_Value(), m_Specific(&II)))) + return IC.replaceOperand(II, 1, IC.Builder.getTrue()); + Constant *C; if (IsTZ) { diff --git a/llvm/test/Transforms/InstCombine/shift-cttz-ctlz.ll b/llvm/test/Transforms/InstCombine/shift-cttz-ctlz.ll new file mode 100644 index 000000000000..2b2f820c9a09 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/shift-cttz-ctlz.ll @@ -0,0 +1,93 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define i32 @shl_cttz_false(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @shl_cttz_false( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CTTZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[Y]], i1 true), !range [[RNG0:![0-9]+]] +; CHECK-NEXT: [[RES:%.*]] = shl i32 [[X]], [[CTTZ]] +; CHECK-NEXT: ret i32 [[RES]] +; +entry: + %cttz = call i32 @llvm.cttz.i32(i32 %y, i1 false) + %res = shl i32 %x, %cttz + ret i32 %res +} + +define i32 @shl_ctlz_false(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @shl_ctlz_false( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CTTZ:%.*]] = call i32 @llvm.ctlz.i32(i32 [[Y]], i1 true), !range [[RNG0]] +; CHECK-NEXT: [[RES:%.*]] = shl i32 [[X]], [[CTTZ]] +; CHECK-NEXT: ret i32 [[RES]] +; +entry: + %cttz = call i32 @llvm.ctlz.i32(i32 %y, i1 false) + %res = shl i32 %x, %cttz + ret i32 %res +} + +define i32 @lshr_cttz_false(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @lshr_cttz_false( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CTTZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[Y]], i1 true), !range [[RNG0]] +; CHECK-NEXT: [[RES:%.*]] = lshr i32 [[X]], [[CTTZ]] +; CHECK-NEXT: ret i32 [[RES]] +; +entry: + %cttz = call i32 @llvm.cttz.i32(i32 %y, i1 false) + %res = lshr i32 %x, %cttz + ret i32 %res +} + +define i32 @ashr_cttz_false(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @ashr_cttz_false( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CTTZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[Y]], i1 true), !range [[RNG0]] +; CHECK-NEXT: [[RES:%.*]] = ashr i32 [[X]], [[CTTZ]] +; CHECK-NEXT: ret i32 [[RES]] +; +entry: + %cttz = call i32 @llvm.cttz.i32(i32 %y, i1 false) + %res = ashr i32 %x, %cttz + ret i32 %res +} + +define i32 @shl_cttz_false_multiuse(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @shl_cttz_false_multiuse( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CTTZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[Y]], i1 false), !range [[RNG0]] +; CHECK-NEXT: call void @use(i32 [[CTTZ]]) +; CHECK-NEXT: [[RES:%.*]] = shl i32 [[X]], [[CTTZ]] +; CHECK-NEXT: ret i32 [[RES]] +; +entry: + %cttz = call i32 @llvm.cttz.i32(i32 %y, i1 false) + call void @use(i32 %cttz) + %res = shl i32 %x, %cttz + ret i32 %res +} + +define i32 @shl_cttz_as_lhs(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @shl_cttz_as_lhs( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CTTZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[Y]], i1 false), !range [[RNG0]] +; CHECK-NEXT: [[RES:%.*]] = shl i32 [[CTTZ]], [[X]] +; CHECK-NEXT: ret i32 [[RES]] +; +entry: + %cttz = call i32 @llvm.cttz.i32(i32 %y, i1 false) + %res = shl i32 %cttz, %x + ret i32 %res +} + +declare void @use(i32) +;. +; CHECK: [[RNG0]] = !{i32 0, i32 33} +;. -- GitLab From 960b4aa6dab69125778f230c4c94f2d19c96cc87 Mon Sep 17 00:00:00 2001 From: Jake Egan Date: Wed, 13 Mar 2024 09:54:35 -0400 Subject: [PATCH 372/953] [AIX][ClangRepl] Disable new test on AIX This new test fails on the AIX bot with error `LLVM ERROR: Incompatible object format!`. Disable for now to investigate. Same as 86337beca2e6f939127cd3e088ec80c0cf4a0a64. --- clang/unittests/Interpreter/InterpreterExtensionsTest.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp index 77fd1b4e1981..1cf564b5671b 100644 --- a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp +++ b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp @@ -56,7 +56,11 @@ public: void resetExecutor() { Interpreter::ResetExecutor(); } }; +ifdef _AIX +TEST(InterpreterExtensionsTest, DISABLED_ExecutorCreateReset) { +#else TEST(InterpreterExtensionsTest, ExecutorCreateReset) { +#endif // Make sure we can create the executer on the platform. if (!HostSupportsJit()) GTEST_SKIP(); -- GitLab From 424e0a825fe4d9e3bf98b63ef86edbc4fa5e3799 Mon Sep 17 00:00:00 2001 From: Jake Egan Date: Wed, 13 Mar 2024 09:57:31 -0400 Subject: [PATCH 373/953] [ClangRepl] Add missing hashtag Hashtag missing from commit 960b4aa6dab69125778f230c4c94f2d19c96cc87 --- clang/unittests/Interpreter/InterpreterExtensionsTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp index 1cf564b5671b..b7708616fd24 100644 --- a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp +++ b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp @@ -56,7 +56,7 @@ public: void resetExecutor() { Interpreter::ResetExecutor(); } }; -ifdef _AIX +#ifdef _AIX TEST(InterpreterExtensionsTest, DISABLED_ExecutorCreateReset) { #else TEST(InterpreterExtensionsTest, ExecutorCreateReset) { -- GitLab From 2cf2bc472da87bb4bf971b1448e05b9e3bd983dc Mon Sep 17 00:00:00 2001 From: Sirraide Date: Wed, 13 Mar 2024 14:59:55 +0100 Subject: [PATCH 374/953] [Clang] [CodeGen] Fix codegen bug in constant initialisation in C23 mode (#84981) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consider the following code: ```c bool const inf = (1.0/0.0); ``` When trying to emit the initialiser of this variable in C23, we end up hitting a code path in codegen in `VarDecl::evaluateValueImpl()` where we check for `IsConstantInitialization && (Ctx.getLangOpts().CPlusPlus || Ctx.getLangOpts().C23)`, and if that is the case and we emitted any notes, constant evaluation fails, and as a result, codegen issues this error: ``` :1:12: error: cannot compile this static initializer yet 1 | bool const inf = (1.0/0.0); | ``` As a fix, only fail in C23 mode if we’re initialising a `constexpr` variable. This fixes #84784. --- clang/lib/AST/Decl.cpp | 11 +++++++---- clang/test/CodeGen/const-init.c | 3 +++ clang/test/Sema/const-init.c | 6 ++++++ 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 clang/test/Sema/const-init.c diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 8626f04012f7..95900afdd2c5 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2577,11 +2577,14 @@ APValue *VarDecl::evaluateValueImpl(SmallVectorImpl &Notes, bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, Ctx, this, Notes, IsConstantInitialization); - // In C++/C23, this isn't a constant initializer if we produced notes. In that - // case, we can't keep the result, because it may only be correct under the - // assumption that the initializer is a constant context. + // In C++, or in C23 if we're initialising a 'constexpr' variable, this isn't + // a constant initializer if we produced notes. In that case, we can't keep + // the result, because it may only be correct under the assumption that the + // initializer is a constant context. if (IsConstantInitialization && - (Ctx.getLangOpts().CPlusPlus || Ctx.getLangOpts().C23) && !Notes.empty()) + (Ctx.getLangOpts().CPlusPlus || + (isConstexpr() && Ctx.getLangOpts().C23)) && + !Notes.empty()) Result = false; // Ensure the computed APValue is cleaned up later if evaluation succeeded, diff --git a/clang/test/CodeGen/const-init.c b/clang/test/CodeGen/const-init.c index 0e4fc4ad48af..ad3e9551199a 100644 --- a/clang/test/CodeGen/const-init.c +++ b/clang/test/CodeGen/const-init.c @@ -216,3 +216,6 @@ int PR4517_x2 = PR4517_arrc[PR4517_idx]; // CHECK: @PR4517_x = global i32 42, align 4 // CHECK: @PR4517_idx = constant i32 1, align 4 // CHECK: @PR4517_x2 = global i32 42, align 4 + +// CHECK: @GH84784_inf = constant i8 1 +_Bool const GH84784_inf = (1.0/0.0); diff --git a/clang/test/Sema/const-init.c b/clang/test/Sema/const-init.c new file mode 100644 index 000000000000..5b07ede747eb --- /dev/null +++ b/clang/test/Sema/const-init.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c23 %s + +// Division by 0 here is an error iff the variable is 'constexpr'. +const _Bool inf1 = (1.0/0.0 == __builtin_inf()); +constexpr _Bool inf2 = (1.0/0.0 == __builtin_inf()); // expected-error {{must be initialized by a constant expression}} expected-note {{division by zero}} +constexpr _Bool inf3 = __builtin_inf() == __builtin_inf(); -- GitLab From 390f28702fad7b704d026b5c3e9a6030cecab01b Mon Sep 17 00:00:00 2001 From: mahesh-attarde <145317060+mahesh-attarde@users.noreply.github.com> Date: Wed, 13 Mar 2024 07:03:15 -0700 Subject: [PATCH 375/953] [CodeGen][Tablegen] Fix uninitialized var and shift overflow. (#84896) Fix uninitialized var and shift overflow. --- llvm/include/llvm/CodeGen/AccelTable.h | 2 +- llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp | 3 ++- llvm/utils/TableGen/DecoderEmitter.cpp | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/llvm/include/llvm/CodeGen/AccelTable.h b/llvm/include/llvm/CodeGen/AccelTable.h index 6ee817a7124d..cff8fcbaf2cd 100644 --- a/llvm/include/llvm/CodeGen/AccelTable.h +++ b/llvm/include/llvm/CodeGen/AccelTable.h @@ -353,7 +353,7 @@ public: dwarf::Index Index; dwarf::Form Form; }; - DebugNamesAbbrev(uint32_t DieTag) : DieTag(DieTag) {} + DebugNamesAbbrev(uint32_t DieTag) : DieTag(DieTag), Number(0) {} /// Add attribute encoding to an abbreviation. void addAttribute(const DebugNamesAbbrev::AttributeEncoding &Attr) { AttrVect.push_back(Attr); diff --git a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp index 55cdc3c92864..2e8e7d0a88af 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp @@ -369,7 +369,8 @@ void AppleAccelTableWriter::emit() const { DWARF5AccelTableData::DWARF5AccelTableData(const DIE &Die, const uint32_t UnitID, const bool IsTU) - : OffsetVal(&Die), DieTag(Die.getTag()), IsTU(IsTU), UnitID(UnitID) {} + : OffsetVal(&Die), DieTag(Die.getTag()), AbbrevNumber(0), IsTU(IsTU), + UnitID(UnitID) {} void Dwarf5AccelTableWriter::Header::emit(Dwarf5AccelTableWriter &Ctx) { assert(CompUnitCount > 0 && "Index must have at least one CU."); diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp index dd78dc02159b..628bff520a12 100644 --- a/llvm/utils/TableGen/DecoderEmitter.cpp +++ b/llvm/utils/TableGen/DecoderEmitter.cpp @@ -934,7 +934,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, unsigned Shift = 0; do { OS << ", " << (unsigned)*I; - Value += (*I & 0x7f) << Shift; + Value += ((uint64_t)(*I & 0x7f)) << Shift; Shift += 7; } while (*I++ >= 128); if (Value > 127) { @@ -947,7 +947,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, Shift = 0; do { OS << ", " << (unsigned)*I; - Value += (*I & 0x7f) << Shift; + Value += ((uint64_t)(*I & 0x7f)) << Shift; Shift += 7; } while (*I++ >= 128); if (Value > 127) { -- GitLab From eb21ee49cff081911d99d29ba887c1715fc2b8fc Mon Sep 17 00:00:00 2001 From: David Spickett Date: Wed, 13 Mar 2024 14:14:24 +0000 Subject: [PATCH 376/953] [lldb][test] Disable other runlocker test on AArch64 Linux Flaky on the bot: https://lab.llvm.org/buildbot/#/builders/96/builds/54435 --- lldb/test/API/python_api/run_locker/TestRunLocker.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lldb/test/API/python_api/run_locker/TestRunLocker.py b/lldb/test/API/python_api/run_locker/TestRunLocker.py index 10832840ac09..4e0dd26bff70 100644 --- a/lldb/test/API/python_api/run_locker/TestRunLocker.py +++ b/lldb/test/API/python_api/run_locker/TestRunLocker.py @@ -15,6 +15,8 @@ class TestRunLocker(TestBase): NO_DEBUG_INFO_TESTCASE = True @expectedFailureAll(oslist=["windows"]) + # Is flaky on Linux AArch64 buildbot. + @skipIf(oslist=["linux"], archs=["aarch64"]) def test_run_locker(self): """Test that the run locker is set correctly when we launch""" self.build() -- GitLab From e77324decf74e8203fdee53e53c1866319ebf47c Mon Sep 17 00:00:00 2001 From: Zepp Date: Wed, 13 Mar 2024 22:25:29 +0800 Subject: [PATCH 377/953] [Clang] [Docs] Add reference to documentation of `SysVABIAttr` (#85022) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We for some reason already had documentation for this attribute, but just weren’t linking to it. --- clang/include/clang/Basic/Attr.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 63efd85dcd4e..67d87eca16ed 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2934,7 +2934,7 @@ def Suppress : DeclOrStmtAttr { def SysVABI : DeclOrTypeAttr { let Spellings = [GCC<"sysv_abi">]; // let Subjects = [Function, ObjCMethod]; - let Documentation = [Undocumented]; + let Documentation = [SysVABIDocs]; } def ThisCall : DeclOrTypeAttr { -- GitLab From 37b5eb0a0a75bdf69b96b902417906da31c88dc3 Mon Sep 17 00:00:00 2001 From: Zaara Syeda <95926691+syzaara@users.noreply.github.com> Date: Wed, 13 Mar 2024 10:26:31 -0400 Subject: [PATCH 378/953] [AIX][TOC] Add -mtocdata/-mno-tocdata options on AIX (#67999) This patch enables support that the XL compiler had for AIX under -qdatalocal/-qdataimported. --- clang/docs/UsersManual.rst | 61 ++++++++++ clang/include/clang/Basic/CodeGenOptions.h | 9 ++ .../clang/Basic/DiagnosticDriverKinds.td | 3 + .../clang/Basic/DiagnosticFrontendKinds.td | 2 + clang/include/clang/Driver/Options.td | 21 ++++ clang/lib/CodeGen/CGDecl.cpp | 1 + clang/lib/CodeGen/CodeGenModule.cpp | 26 +++++ clang/lib/CodeGen/Targets/PPC.cpp | 59 ++++++++++ clang/lib/Driver/ToolChains/AIX.cpp | 87 ++++++++++++++ clang/lib/Frontend/CompilerInstance.cpp | 5 + .../test/CodeGen/PowerPC/toc-data-attribute.c | 50 ++++++++ .../CodeGen/PowerPC/toc-data-attribute.cpp | 39 +++++++ .../CodeGen/PowerPC/toc-data-diagnostics.c | 68 +++++++++++ .../PowerPC/toc-data-structs-arrays.cpp | 65 +++++++++++ clang/test/Driver/toc-conf.c | 30 +++++ clang/test/Driver/tocdata-cc1.c | 16 +++ llvm/include/llvm/ADT/STLExtras.h | 13 +++ llvm/lib/MC/MCSectionXCOFF.cpp | 3 +- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 2 + llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 34 ------ llvm/lib/Target/PowerPC/PPCSubtarget.cpp | 22 ++++ llvm/lib/Target/PowerPC/PPCSubtarget.h | 2 + .../CodeGen/PowerPC/toc-data-large-array.ll | 16 +++ .../CodeGen/PowerPC/toc-data-large-array2.ll | 8 ++ .../CodeGen/PowerPC/toc-data-struct-array.ll | 110 ++++++++++++++++++ 25 files changed, 716 insertions(+), 36 deletions(-) create mode 100644 clang/test/CodeGen/PowerPC/toc-data-attribute.c create mode 100644 clang/test/CodeGen/PowerPC/toc-data-attribute.cpp create mode 100644 clang/test/CodeGen/PowerPC/toc-data-diagnostics.c create mode 100644 clang/test/CodeGen/PowerPC/toc-data-structs-arrays.cpp create mode 100644 clang/test/Driver/toc-conf.c create mode 100644 clang/test/Driver/tocdata-cc1.c create mode 100644 llvm/test/CodeGen/PowerPC/toc-data-large-array.ll create mode 100644 llvm/test/CodeGen/PowerPC/toc-data-large-array2.ll create mode 100644 llvm/test/CodeGen/PowerPC/toc-data-struct-array.ll diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 7391e4cf3a9a..7a63d720241a 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -4227,7 +4227,68 @@ Clang expects the GCC executable "gcc.exe" compiled for AIX ^^^ +TOC Data Transformation +""""""""""""""""""""""" +TOC data transformation is off by default (``-mno-tocdata``). +When ``-mtocdata`` is specified, the TOC data transformation will be applied to +all suitable variables with static storage duration, including static data +members of classes and block-scope static variables (if not marked as exceptions, +see further below). +Suitable variables must: + +- have complete types +- be independently generated (i.e., not placed in a pool) +- be at most as large as a pointer +- not be aligned more strictly than a pointer +- not be structs containing flexible array members +- not have internal linkage +- not have aliases +- not have section attributes +- not be thread local storage + +The TOC data transformation results in the variable, not its address, +being placed in the TOC. This eliminates the need to load the address of the +variable from the TOC. + +Note: +If the TOC data transformation is applied to a variable whose definition +is imported, the linker will generate fixup code for reading or writing to the +variable. + +When multiple toc-data options are used, the last option used has the affect. +For example: -mno-tocdata=g5,g1 -mtocdata=g1,g2 -mno-tocdata=g2 -mtocdata=g3,g4 +results in -mtocdata=g1,g3,g4 + +Names of variables not having external linkage will be ignored. + +**Options:** + +.. option:: -mno-tocdata + + This is the default behaviour. Only variables explicitly specified with + ``-mtocdata=`` will have the TOC data transformation applied. + +.. option:: -mtocdata + + Apply the TOC data transformation to all suitable variables with static + storage duration (including static data members of classes and block-scope + static variables) that are not explicitly specified with ``-mno-tocdata=``. + +.. option:: -mno-tocdata= + + Can be used in conjunction with ``-mtocdata`` to mark the comma-separated + list of external linkage variables, specified using their mangled names, as + exceptions to ``-mtocdata``. + +.. option:: -mtocdata= + + Apply the TOC data transformation to the comma-separated list of external + linkage variables, specified using their mangled names, if they are suitable. + Emit diagnostics for all unsuitable variables specified. + +Default Visibility Export Mapping +""""""""""""""""""""""""""""""""" The ``-mdefault-visibility-export-mapping=`` option can be used to control mapping of default visibility to an explicit shared object export (i.e. XCOFF exported visibility). Three values are provided for the option: diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 3f8fe385fef3..cf29e576ef32 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -404,6 +404,15 @@ public: /// List of pass builder callbacks. std::vector> PassBuilderCallbacks; + /// List of global variables explicitly specified by the user as toc-data. + std::vector TocDataVarsUserSpecified; + + /// List of global variables that over-ride the toc-data default. + std::vector NoTocDataVars; + + /// Flag for all global variables to be treated as toc-data. + bool AllTocData; + /// Path to allowlist file specifying which objects /// (files, functions) should exclusively be instrumented /// by sanitizer coverage pass. diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 1bc9885849d5..e33a1f4c45b9 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -587,6 +587,9 @@ def warn_drv_unsupported_gpopt : Warning< "ignoring '-mgpopt' option as it cannot be used with %select{|the implicit" " usage of }0-mabicalls">, InGroup; +def warn_drv_unsupported_tocdata: Warning< + "ignoring '-mtocdata' as it is only supported for -mcmodel=small">, + InGroup; def warn_drv_unsupported_sdata : Warning< "ignoring '-msmall-data-limit=' with -mcmodel=large for -fpic or RV64">, InGroup; diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index dcd2c19fb7ee..794a0a82be6d 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -94,6 +94,8 @@ def err_fe_backend_error_attr : def warn_fe_backend_warning_attr : Warning<"call to '%0' declared with 'warning' attribute: %1">, BackendInfo, InGroup; +def warn_toc_unsupported_type : Warning<"-mtocdata option is ignored " + "for %0 because %1">, InGroup; def err_fe_invalid_code_complete_file : Error< "cannot locate code-completion file %0">, DefaultFatal; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index aca8c9b0d548..1fac7b6f0093 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3609,6 +3609,27 @@ def fpass_plugin_EQ : Joined<["-"], "fpass-plugin=">, MetaVarName<"">, HelpText<"Load pass plugin from a dynamic shared object file (only with new pass manager).">, MarshallingInfoStringVector>; +defm tocdata : BoolOption<"m","tocdata", + CodeGenOpts<"AllTocData">, DefaultFalse, + PosFlag, + NegFlag, + BothFlags<[TargetSpecific], [ClangOption, CLOption]>>, Group; +def mtocdata_EQ : CommaJoined<["-"], "mtocdata=">, + Visibility<[ClangOption, CC1Option]>, + Flags<[TargetSpecific]>, Group, + HelpText<"Specifies a list of variables to which the TOC data transformation" + "will be applied.">, + MarshallingInfoStringVector>; +def mno_tocdata_EQ : CommaJoined<["-"], "mno-tocdata=">, + Visibility<[ClangOption, CC1Option]>, + Flags<[TargetSpecific]>, Group, + HelpText<"Specifies a list of variables to be exempt from the TOC data" + "transformation.">, + MarshallingInfoStringVector>; defm preserve_as_comments : BoolFOption<"preserve-as-comments", CodeGenOpts<"PreserveAsmComments">, DefaultTrue, NegFlag(&D), GV, *this); // Make sure the result is of the correct type. LangAS ExpectedAS = Ty.getAddressSpace(); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 967319bdfc45..8ceecff28cbc 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -626,6 +626,26 @@ static bool checkAliasedGlobal( return true; } +// Emit a warning if toc-data attribute is requested for global variables that +// have aliases and remove the toc-data attribute. +static void checkAliasForTocData(llvm::GlobalVariable *GVar, + const CodeGenOptions &CodeGenOpts, + DiagnosticsEngine &Diags, + SourceLocation Location) { + if (GVar->hasAttribute("toc-data")) { + auto GVId = GVar->getName(); + // Is this a global variable specified by the user as local? + if ((llvm::binary_search(CodeGenOpts.TocDataVarsUserSpecified, GVId))) { + Diags.Report(Location, diag::warn_toc_unsupported_type) + << GVId << "the variable has an alias"; + } + llvm::AttributeSet CurrAttributes = GVar->getAttributes(); + llvm::AttributeSet NewAttributes = + CurrAttributes.removeAttribute(GVar->getContext(), "toc-data"); + GVar->setAttributes(NewAttributes); + } +} + void CodeGenModule::checkAliases() { // Check if the constructed aliases are well formed. It is really unfortunate // that we have to do this in CodeGen, but we only construct mangled names @@ -652,6 +672,12 @@ void CodeGenModule::checkAliases() { continue; } + if (getContext().getTargetInfo().getTriple().isOSAIX()) + if (const llvm::GlobalVariable *GVar = + dyn_cast(GV)) + checkAliasForTocData(const_cast(GVar), + getCodeGenOpts(), Diags, Location); + llvm::Constant *Aliasee = IsIFunc ? cast(Alias)->getResolver() : cast(Alias)->getAliasee(); diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 40dddde508c1..00b04723f17d 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -8,6 +8,7 @@ #include "ABIInfoImpl.h" #include "TargetInfo.h" +#include "clang/Basic/DiagnosticFrontend.h" using namespace clang; using namespace clang::CodeGen; @@ -145,6 +146,9 @@ public: bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const override; + + void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, + CodeGen::CodeGenModule &M) const override; }; } // namespace @@ -265,6 +269,61 @@ bool AIXTargetCodeGenInfo::initDwarfEHRegSizeTable( return PPC_initDwarfEHRegSizeTable(CGF, Address, Is64Bit, /*IsAIX*/ true); } +void AIXTargetCodeGenInfo::setTargetAttributes( + const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const { + if (!isa(GV)) + return; + + auto *GVar = dyn_cast(GV); + auto GVId = GV->getName(); + + // Is this a global variable specified by the user as toc-data? + bool UserSpecifiedTOC = + llvm::binary_search(M.getCodeGenOpts().TocDataVarsUserSpecified, GVId); + // Assumes the same variable cannot be in both TocVarsUserSpecified and + // NoTocVars. + if (UserSpecifiedTOC || + ((M.getCodeGenOpts().AllTocData) && + !llvm::binary_search(M.getCodeGenOpts().NoTocDataVars, GVId))) { + const unsigned long PointerSize = + GV->getParent()->getDataLayout().getPointerSizeInBits() / 8; + auto *VarD = dyn_cast(D); + assert(VarD && "Invalid declaration of global variable."); + + ASTContext &Context = D->getASTContext(); + unsigned Alignment = Context.toBits(Context.getDeclAlign(D)) / 8; + const auto *Ty = VarD->getType().getTypePtr(); + const RecordDecl *RDecl = + Ty->isRecordType() ? Ty->getAs()->getDecl() : nullptr; + + bool EmitDiagnostic = UserSpecifiedTOC && GV->hasExternalLinkage(); + auto reportUnsupportedWarning = [&](bool ShouldEmitWarning, StringRef Msg) { + if (ShouldEmitWarning) + M.getDiags().Report(D->getLocation(), diag::warn_toc_unsupported_type) + << GVId << Msg; + }; + if (!Ty || Ty->isIncompleteType()) + reportUnsupportedWarning(EmitDiagnostic, "of incomplete type"); + else if (RDecl && RDecl->hasFlexibleArrayMember()) + reportUnsupportedWarning(EmitDiagnostic, + "it contains a flexible array member"); + else if (VarD->getTLSKind() != VarDecl::TLS_None) + reportUnsupportedWarning(EmitDiagnostic, "of thread local storage"); + else if (PointerSize < Context.getTypeInfo(VarD->getType()).Width / 8) + reportUnsupportedWarning(EmitDiagnostic, + "variable is larger than a pointer"); + else if (PointerSize < Alignment) + reportUnsupportedWarning(EmitDiagnostic, + "variable is aligned wider than a pointer"); + else if (D->hasAttr()) + reportUnsupportedWarning(EmitDiagnostic, + "variable has a section attribute"); + else if (GV->hasExternalLinkage() || + (M.getCodeGenOpts().AllTocData && !GV->hasLocalLinkage())) + GVar->addAttribute("toc-data"); + } +} + // PowerPC-32 namespace { /// PPC32_SVR4_ABIInfo - The 32-bit PowerPC ELF (SVR4) ABI information. diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp index 3c7049a99982..6e089903a315 100644 --- a/clang/lib/Driver/ToolChains/AIX.cpp +++ b/clang/lib/Driver/ToolChains/AIX.cpp @@ -433,6 +433,88 @@ void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); } +// This function processes all the mtocdata options to build the final +// simplified toc data options to pass to CC1. +static void addTocDataOptions(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CC1Args, + const Driver &D) { + + // Check the global toc-data setting. The default is -mno-tocdata. + // To enable toc-data globally, -mtocdata must be specified. + // Additionally, it must be last to take effect. + const bool TOCDataGloballyinEffect = [&Args]() { + if (const Arg *LastArg = + Args.getLastArg(options::OPT_mtocdata, options::OPT_mno_tocdata)) + return LastArg->getOption().matches(options::OPT_mtocdata); + else + return false; + }(); + + // Currently only supported for small code model. + if (TOCDataGloballyinEffect && + (Args.getLastArgValue(options::OPT_mcmodel_EQ).equals("large") || + Args.getLastArgValue(options::OPT_mcmodel_EQ).equals("medium"))) { + D.Diag(clang::diag::warn_drv_unsupported_tocdata); + return; + } + + enum TOCDataSetting { + AddressInTOC = 0, // Address of the symbol stored in the TOC. + DataInTOC = 1 // Symbol defined in the TOC. + }; + + const TOCDataSetting DefaultTocDataSetting = + TOCDataGloballyinEffect ? DataInTOC : AddressInTOC; + + // Process the list of variables in the explicitly specified options + // -mtocdata= and -mno-tocdata= to see which variables are opposite to + // the global setting of tocdata in TOCDataGloballyinEffect. + // Those that have the opposite setting to TOCDataGloballyinEffect, are added + // to ExplicitlySpecifiedGlobals. + llvm::StringSet<> ExplicitlySpecifiedGlobals; + for (const auto Arg : + Args.filtered(options::OPT_mtocdata_EQ, options::OPT_mno_tocdata_EQ)) { + TOCDataSetting ArgTocDataSetting = + Arg->getOption().matches(options::OPT_mtocdata_EQ) ? DataInTOC + : AddressInTOC; + + if (ArgTocDataSetting != DefaultTocDataSetting) + for (const char *Val : Arg->getValues()) + ExplicitlySpecifiedGlobals.insert(Val); + else + for (const char *Val : Arg->getValues()) + ExplicitlySpecifiedGlobals.erase(Val); + } + + auto buildExceptionList = [](const llvm::StringSet<> &ExplicitValues, + const char *OptionSpelling) { + std::string Option(OptionSpelling); + bool IsFirst = true; + for (const auto &E : ExplicitValues) { + if (!IsFirst) + Option += ","; + + IsFirst = false; + Option += E.first(); + } + return Option; + }; + + // Pass the final tocdata options to CC1 consisting of the default + // tocdata option (-mtocdata/-mno-tocdata) along with the list + // option (-mno-tocdata=/-mtocdata=) if there are any explicitly specified + // variables which would be exceptions to the default setting. + const char *TocDataGlobalOption = + TOCDataGloballyinEffect ? "-mtocdata" : "-mno-tocdata"; + CC1Args.push_back(TocDataGlobalOption); + + const char *TocDataListOption = + TOCDataGloballyinEffect ? "-mno-tocdata=" : "-mtocdata="; + if (!ExplicitlySpecifiedGlobals.empty()) + CC1Args.push_back(Args.MakeArgString(llvm::Twine( + buildExceptionList(ExplicitlySpecifiedGlobals, TocDataListOption)))); +} + void AIX::addClangTargetOptions( const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind DeviceOffloadingKind) const { @@ -440,6 +522,11 @@ void AIX::addClangTargetOptions( Args.AddLastArg(CC1Args, options::OPT_mdefault_visibility_export_mapping_EQ); Args.addOptInFlag(CC1Args, options::OPT_mxcoff_roptr, options::OPT_mno_xcoff_roptr); + // Forward last mtocdata/mno_tocdata options to -cc1. + if (Args.hasArg(options::OPT_mtocdata_EQ, options::OPT_mno_tocdata_EQ, + options::OPT_mtocdata)) + addTocDataOptions(Args, CC1Args, getDriver()); + if (Args.hasFlag(options::OPT_fxl_pragma_pack, options::OPT_fno_xl_pragma_pack, true)) CC1Args.push_back("-fxl-pragma-pack"); diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index ec4e68209d65..019f847ccbaa 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1047,6 +1047,11 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { if (getFrontendOpts().ShowStats || !getFrontendOpts().StatsFile.empty()) llvm::EnableStatistics(false); + // Sort vectors containing toc data and no toc data variables to facilitate + // binary search later. + llvm::sort(getCodeGenOpts().TocDataVarsUserSpecified); + llvm::sort(getCodeGenOpts().NoTocDataVars); + for (const FrontendInputFile &FIF : getFrontendOpts().Inputs) { // Reset the ID tables if we are reusing the SourceManager and parsing // regular files. diff --git a/clang/test/CodeGen/PowerPC/toc-data-attribute.c b/clang/test/CodeGen/PowerPC/toc-data-attribute.c new file mode 100644 index 000000000000..db23d74759ee --- /dev/null +++ b/clang/test/CodeGen/PowerPC/toc-data-attribute.c @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -S -mtocdata=f,g,h,i,j,k,l,m,n,o,p -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,CHECK32 --match-full-lines +// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -S -mtocdata -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,CHECK32 --match-full-lines + +// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -S -mtocdata=f,g,h,i,j,k,l,m,n,o,p -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,CHECK64 --match-full-lines +// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -S -mtocdata -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,CHECK64 --match-full-lines + +extern int f; +long long g = 5; +const char *h = "h"; +int *i; +int __attribute__((aligned(128))) j = 0; +float k = 100.00; +double l = 2.5; +int m __attribute__((section("foo"))) = 10; +__thread int n; + +extern int p[]; + +struct SomeStruct; +extern struct SomeStruct o; + +static int func_a() { + return g+(int)h[0]+*i+j+k+l+m+n+p[0]; +} + +int func_b() { + f = 1; + return func_a(); +} + +struct SomeStruct* getAddress(void) { + return &o; +} + +// CHECK32: @g = global i64 5, align 8 +// CHECK64: @g = global i64 5, align 8 #0 +// COMMON: {{.*}} = private unnamed_addr constant [2 x i8] c"h\00", align 1 +// COMMON: @h = global {{...*}} #0 +// COMMON: @j = global i32 0, align 128 +// COMMON: @k = global float 1.000000e+02, align 4 #0 +// CHECK32: @l = global double 2.500000e+00, align 8 +// CHECK64: @l = global double 2.500000e+00, align 8 #0 +// COMMON: @m = global i32 10, section "foo", align 4 +// COMMON: @f = external global i32, align 4 #0 +// COMMON: @o = external global %struct.SomeStruct, align 1 +// CHECK32: @i = global ptr null, align 4 #0 +// CHECK64: @i = global ptr null, align 8 #0 +// COMMON: @n = thread_local global i32 0, align 4 +// COMMON: @p = external global [0 x i32], align 4 +// COMMON: attributes #0 = { "toc-data" } diff --git a/clang/test/CodeGen/PowerPC/toc-data-attribute.cpp b/clang/test/CodeGen/PowerPC/toc-data-attribute.cpp new file mode 100644 index 000000000000..8183e3b727e7 --- /dev/null +++ b/clang/test/CodeGen/PowerPC/toc-data-attribute.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -S -mtocdata -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,ALLTOC +// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -S -mtocdata=n,_ZN11MyNamespace10myVariableE,_ZL1s,_ZZ4testvE7counter -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,TOCLIST +// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -S -mtocdata -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,ALLTOC +// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -S -mtocdata=n,_ZN11MyNamespace10myVariableE,_ZL1s,_ZZ4testvE7counter -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,TOCLIST + +extern int n; +static int s = 100; + +inline int test() { + static int counter = 0; + counter++; + return counter; +} + +int a () { + n = test(); + return 0; +} + +namespace MyNamespace { + int myVariable = 10; +} + +int b(int x) { + using namespace MyNamespace; + return x + myVariable; +} + +int c(int x) { + s += x; + return s; +} + +// COMMON: @n = external global i32, align 4 #0 +// COMMON: @_ZN11MyNamespace10myVariableE = global i32 10, align 4 #0 +// COMMON-NOT: @_ZL1s = internal global i32 100, align 4 #0 +// ALLTOC: @_ZZ4testvE7counter = linkonce_odr global i32 0, align 4 #0 +// TOCLIST-NOT: @_ZZ4testvE7counter = linkonce_odr global i32 0, align 4 #0 +// COMMON: attributes #0 = { "toc-data" } diff --git a/clang/test/CodeGen/PowerPC/toc-data-diagnostics.c b/clang/test/CodeGen/PowerPC/toc-data-diagnostics.c new file mode 100644 index 000000000000..ba8955530e46 --- /dev/null +++ b/clang/test/CodeGen/PowerPC/toc-data-diagnostics.c @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 %s -triple=powerpc-ibm-aix-xcoff -S -mtocdata=h,g,f,e,d,c,b,a,globalOneWithAlias,globalTwoWithAlias,ll,t3 -verify -emit-llvm -o - | FileCheck %s -check-prefix=CHECK --match-full-lines +// RUN: %clang_cc1 %s -triple=powerpc-ibm-aix-xcoff -S -mtocdata -verify=none -emit-llvm -o - | FileCheck %s -check-prefix=CHECK --match-full-lines + +// none-no-diagnostics + +struct large_struct { + int x; + short y; + short z; + char c; +}; + +struct large_struct a; // expected-warning {{-mtocdata option is ignored for a because variable is larger than a pointer}} +long long b = 5; // expected-warning {{-mtocdata option is ignored for b because variable is larger than a pointer}} +int __attribute__((aligned(128))) c = 0; // expected-warning {{-mtocdata option is ignored for c because variable is aligned wider than a pointer}} +double d = 2.5; // expected-warning {{-mtocdata option is ignored for d because variable is larger than a pointer}} +int e __attribute__((section("foo"))) = 10; // expected-warning {{-mtocdata option is ignored for e because variable has a section attribute}} +__thread int f; // expected-warning {{-mtocdata option is ignored for f because of thread local storage}} + +struct SomeStruct; +extern struct SomeStruct g; // expected-warning {{-mtocdata option is ignored for g because of incomplete type}} + +extern int h[]; // expected-warning {{-mtocdata option is ignored for h because of incomplete type}} + +struct ty3 { + int A; + char C[]; +}; +struct ty3 t3 = { 4, "fo" }; // expected-warning {{-mtocdata option is ignored for t3 because it contains a flexible array member}} + +int globalOneWithAlias = 10; +__attribute__((__alias__("globalOneWithAlias"))) extern int aliasOne; // expected-warning {{-mtocdata option is ignored for globalOneWithAlias because the variable has an alias}} +__attribute__((__alias__("globalTwoWithAlias"))) extern int aliasTwo; // expected-warning {{-mtocdata option is ignored for globalTwoWithAlias because the variable has an alias}} +int globalTwoWithAlias = 20; + + +int func() { + return a.x+b+c+d+e+f+h[0]; +} + +struct SomeStruct* getAddress(void) { + return &g; +} + +int test() { + return globalOneWithAlias + globalTwoWithAlias + aliasOne + aliasTwo; +} + +long long test2() { + static long long ll = 5; + ll++; + return ll; +} + +// CHECK: @b = global i64 5, align 8 +// CHECK: @c = global i32 0, align 128 +// CHECK: @d = global double 2.500000e+00, align 8 +// CHECK: @e = global i32 10, section "foo", align 4 +// CHECK: @globalOneWithAlias = global i32 10, align 4 +// CHECK: @globalTwoWithAlias = global i32 20, align 4 +// CHECK: @a = global %struct.large_struct zeroinitializer, align 4 +// CHECK: @f = thread_local global i32 0, align 4 +// CHECK: @h = external global [0 x i32], align 4 +// CHECK: @g = external global %struct.SomeStruct, align 1 +// CHECK: @test2.ll = internal global i64 5, align 8 +// CHECK: @aliasOne = alias i32, ptr @globalOneWithAlias +// CHECK: @aliasTwo = alias i32, ptr @globalTwoWithAlias +// CHECK-NOT: attributes #0 = { "toc-data" } diff --git a/clang/test/CodeGen/PowerPC/toc-data-structs-arrays.cpp b/clang/test/CodeGen/PowerPC/toc-data-structs-arrays.cpp new file mode 100644 index 000000000000..a717995cdceb --- /dev/null +++ b/clang/test/CodeGen/PowerPC/toc-data-structs-arrays.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -S -mtocdata=a4,a5,a8,a9,b,c,d,e,v -emit-llvm -o - 2>&1 \ +// RUN: | FileCheck %s -check-prefixes=CHECK32 --match-full-lines +// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -S -mtocdata -emit-llvm -o - 2>&1 \ +// RUN: | FileCheck %s -check-prefixes=CHECK32 --match-full-lines + +// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -S -mtocdata=a4,a5,a8,a9,b,c,d,e,v -emit-llvm -o - 2>&1 \ +// RUN: | FileCheck %s -check-prefixes=CHECK64 --match-full-lines +// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -S -mtocdata -emit-llvm -o - 2>&1 \ +// RUN: | FileCheck %s -check-prefixes=CHECK64 --match-full-lines + +struct size4_struct { + int x; +}; + +struct size5_struct { + int x; + char c; +}; + +struct size8_struct { + int x; + short y; + short z; +}; + +struct size9_struct { + int x; + short y; + short z; + char c; +}; + +struct size4_struct a4; +struct size5_struct a5; +struct size8_struct a8; +struct size9_struct a9; + +short b[2]; +short c[3]; +short d[4]; +short e[5]; + +int func_a() { + return a4.x+a5.x+a8.x+a9.x+b[0]+c[0]+d[0]+e[0]; +} + +// CHECK32: @a4 = global %struct.size4_struct zeroinitializer, align 4 #0 +// CHECK32: @a5 = global %struct.size5_struct zeroinitializer, align 4 +// CHECK32: @a8 = global %struct.size8_struct zeroinitializer, align 4 +// CHECK32: @a9 = global %struct.size9_struct zeroinitializer, align 4 +// CHECK32: @b = global [2 x i16] zeroinitializer, align 2 #0 +// CHECK32: @c = global [3 x i16] zeroinitializer, align 2 +// CHECK32: @d = global [4 x i16] zeroinitializer, align 2 +// CHECK32: @e = global [5 x i16] zeroinitializer, align 2 +// CHECK32: attributes #0 = { "toc-data" } + +// CHECK64: @a4 = global %struct.size4_struct zeroinitializer, align 4 #0 +// CHECK64: @a5 = global %struct.size5_struct zeroinitializer, align 4 #0 +// CHECK64: @a8 = global %struct.size8_struct zeroinitializer, align 4 #0 +// CHECK64: @a9 = global %struct.size9_struct zeroinitializer, align 4 +// CHECK64: @b = global [2 x i16] zeroinitializer, align 2 #0 +// CHECK64: @c = global [3 x i16] zeroinitializer, align 2 #0 +// CHECK64: @d = global [4 x i16] zeroinitializer, align 2 #0 +// CHECK64: @e = global [5 x i16] zeroinitializer, align 2 +// CHECK64: attributes #0 = { "toc-data" } diff --git a/clang/test/Driver/toc-conf.c b/clang/test/Driver/toc-conf.c new file mode 100644 index 000000000000..80d92ee1a90b --- /dev/null +++ b/clang/test/Driver/toc-conf.c @@ -0,0 +1,30 @@ +// RUN: %clang %s --target=powerpc-unknown-aix -mno-tocdata -mtocdata -mno-tocdata -### 2>&1 | FileCheck %s -check-prefix=CHECK-FLAG1 +// RUN: %clang %s --target=powerpc-unknown-aix -mno-tocdata -mtocdata -mno-tocdata -mtocdata -### 2>&1 | FileCheck %s -check-prefix=CHECK-FLAG2 +// RUN: %clang %s --target=powerpc-unknown-aix -mtocdata=g1,g2 -mno-tocdata=g2 -mtocdata=g3,g4 -mno-tocdata=g5,g1 -### 2>&1 | FileCheck %s -check-prefix=CHECK-EQCONF +// RUN: %clang %s --target=powerpc-unknown-aix -mtocdata=g1 -mtocdata -mno-tocdata -mtocdata=g2,g3 -mno-tocdata=g4,g5,g3 -### 2>&1 | FileCheck %s -check-prefix=CHECK-CONF1 +// RUN: %clang %s --target=powerpc-unknown-aix -mno-tocdata=g1 -mno-tocdata -mtocdata -### 2>&1 | FileCheck %s -check-prefix=CHECK-CONF2 + +int g1, g4, g5; +extern int g2; +int g3 = 0; +void func() { + g2 = 0; +} + +// CHECK-FLAG1-NOT: warning: +// CHECK-FLAG1: "-cc1"{{.*}}" "-mno-tocdata" + +// CHECK-FLAG2-NOT: warning: +// CHECK-FLAG2: "-cc1"{{.*}}" "-mtocdata" + +// CHECK-EQCONF-NOT: warning: +// CHECK-EQCONF: "-cc1"{{.*}}" "-mno-tocdata" +// CHECK-EQCONF: "-mtocdata=g3,g4" + +// CHECK-CONF1-NOT: warning: +// CHECK-CONF1: "-cc1"{{.*}}" "-mno-tocdata" +// CHECK-CONF1: "-mtocdata=g2,g1" + +// CHECK-CONF2-NOT: warning: +// CHECK-CONF2: "-cc1"{{.*}}" "-mtocdata" +// CHECK-CONF2: "-mno-tocdata=g1" diff --git a/clang/test/Driver/tocdata-cc1.c b/clang/test/Driver/tocdata-cc1.c new file mode 100644 index 000000000000..fe0d97ea02db --- /dev/null +++ b/clang/test/Driver/tocdata-cc1.c @@ -0,0 +1,16 @@ +// RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mcmodel=medium -mtocdata %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mcmodel=large -mtocdata %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mtocdata %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-TOC %s +// RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mcmodel=medium -mtocdata %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mcmodel=large -mtocdata %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mtocdata %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-TOC %s +// CHECK-NOTOC: warning: ignoring '-mtocdata' as it is only supported for -mcmodel=small +// CHECK-NOTOC-NOT: "-cc1"{{.*}}" "-mtocdata" +// CHECK-TOC: "-cc1"{{.*}}" "-mtocdata" +// CHECK-TOC-NOT: warning: ignoring '-mtocdata' as it is only supported for -mcmodel=small diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index 5ac549c44756..02a3074ae1f0 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -1945,6 +1945,19 @@ auto partition(R &&Range, UnaryPredicate P) { return std::partition(adl_begin(Range), adl_end(Range), P); } +/// Provide wrappers to std::binary_search which take ranges instead of having +/// to pass begin/end explicitly. +template auto binary_search(R &&Range, T &&Value) { + return std::binary_search(adl_begin(Range), adl_end(Range), + std::forward(Value)); +} + +template +auto binary_search(R &&Range, T &&Value, Compare C) { + return std::binary_search(adl_begin(Range), adl_end(Range), + std::forward(Value), C); +} + /// Provide wrappers to std::lower_bound which take ranges instead of having to /// pass begin/end explicitly. template auto lower_bound(R &&Range, T &&Value) { diff --git a/llvm/lib/MC/MCSectionXCOFF.cpp b/llvm/lib/MC/MCSectionXCOFF.cpp index 95d32e3580e3..609ef0962930 100644 --- a/llvm/lib/MC/MCSectionXCOFF.cpp +++ b/llvm/lib/MC/MCSectionXCOFF.cpp @@ -87,8 +87,7 @@ void MCSectionXCOFF::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T, if (getKind().isCommon() && !getKind().isBSSLocal()) return; - assert((getKind().isBSSExtern() || getKind().isBSSLocal()) && - "Unexepected section kind for toc-data"); + assert(getKind().isBSS() && "Unexpected section kind for toc-data"); printCsectDirective(OS); return; } diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 9396ca22dacf..6f33b16f045a 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -2659,6 +2659,8 @@ void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { // If the Global Variable has the toc-data attribute, it needs to be emitted // when we emit the .toc section. if (GV->hasAttribute("toc-data")) { + unsigned PointerSize = GV->getParent()->getDataLayout().getPointerSize(); + Subtarget->tocDataChecks(PointerSize, GV); TOCDataGlobalVars.push_back(GV); return; } diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 9e5f0b36616d..2462cbb19282 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -521,40 +521,6 @@ static bool hasTocDataAttr(SDValue Val, unsigned PointerSize) { if (!GV->hasAttribute("toc-data")) return false; - - // TODO: These asserts should be updated as more support for the toc data - // transformation is added (struct support, etc.). - - assert( - PointerSize >= GV->getAlign().valueOrOne().value() && - "GlobalVariables with an alignment requirement stricter than TOC entry " - "size not supported by the toc data transformation."); - - Type *GVType = GV->getValueType(); - - assert(GVType->isSized() && "A GlobalVariable's size must be known to be " - "supported by the toc data transformation."); - - if (GVType->isVectorTy()) - report_fatal_error("A GlobalVariable of Vector type is not currently " - "supported by the toc data transformation."); - - if (GVType->isArrayTy()) - report_fatal_error("A GlobalVariable of Array type is not currently " - "supported by the toc data transformation."); - - if (GVType->isStructTy()) - report_fatal_error("A GlobalVariable of Struct type is not currently " - "supported by the toc data transformation."); - - assert(GVType->getPrimitiveSizeInBits() <= PointerSize * 8 && - "A GlobalVariable with size larger than a TOC entry is not currently " - "supported by the toc data transformation."); - - if (GV->hasPrivateLinkage()) - report_fatal_error("A GlobalVariable with private linkage is not " - "currently supported by the toc data transformation."); - return true; } diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp index 5380ec1c4c0d..884f2f5c57b2 100644 --- a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp @@ -185,6 +185,28 @@ bool PPCSubtarget::enableSubRegLiveness() const { return UseSubRegLiveness; } +void PPCSubtarget::tocDataChecks(unsigned PointerSize, + const GlobalVariable *GV) const { + // TODO: These asserts should be updated as more support for the toc data + // transformation is added (struct support, etc.). + assert( + PointerSize >= GV->getAlign().valueOrOne().value() && + "GlobalVariables with an alignment requirement stricter than TOC entry " + "size not supported by the toc data transformation."); + + Type *GVType = GV->getValueType(); + assert(GVType->isSized() && "A GlobalVariable's size must be known to be " + "supported by the toc data transformation."); + if (GV->getParent()->getDataLayout().getTypeSizeInBits(GVType) > + PointerSize * 8) + report_fatal_error( + "A GlobalVariable with size larger than a TOC entry is not currently " + "supported by the toc data transformation."); + if (GV->hasPrivateLinkage()) + report_fatal_error("A GlobalVariable with private linkage is not " + "currently supported by the toc data transformation."); +} + bool PPCSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const { // Large code model always uses the TOC even for local symbols. if (TM.getCodeModel() == CodeModel::Large) diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.h b/llvm/lib/Target/PowerPC/PPCSubtarget.h index 306a52dca836..d913f22bd5ba 100644 --- a/llvm/lib/Target/PowerPC/PPCSubtarget.h +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.h @@ -245,6 +245,8 @@ public: /// True if the GV will be accessed via an indirect symbol. bool isGVIndirectSymbol(const GlobalValue *GV) const; + void tocDataChecks(unsigned PointerSize, const GlobalVariable *GV) const; + /// True if the ABI is descriptor based. bool usesFunctionDescriptors() const { // Both 32-bit and 64-bit AIX are descriptor based. For ELF only the 64-bit diff --git a/llvm/test/CodeGen/PowerPC/toc-data-large-array.ll b/llvm/test/CodeGen/PowerPC/toc-data-large-array.ll new file mode 100644 index 000000000000..90f40d9f0fec --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/toc-data-large-array.ll @@ -0,0 +1,16 @@ +; RUN: not --crash llc -mtriple powerpc-ibm-aix-xcoff < %s 2>&1 | FileCheck %s --check-prefix CHECK-ERROR +; RUN: not --crash llc -mtriple powerpc64-ibm-aix-xcoff < %s 2>&1 | FileCheck %s --check-prefix CHECK-ERROR + +@a = global [5 x i16] zeroinitializer, align 2 #0 + +; Function Attrs: noinline +define i16 @foo() #1 { +entry: + %0 = load i16, ptr @a, align 2 + ret i16 %0 +} + +attributes #0 = { "toc-data" } +attributes #1 = { noinline } + +; CHECK-ERROR: LLVM ERROR: A GlobalVariable with size larger than a TOC entry is not currently supported by the toc data transformation. diff --git a/llvm/test/CodeGen/PowerPC/toc-data-large-array2.ll b/llvm/test/CodeGen/PowerPC/toc-data-large-array2.ll new file mode 100644 index 000000000000..f870e996a401 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/toc-data-large-array2.ll @@ -0,0 +1,8 @@ +; RUN: not --crash llc -mtriple powerpc-ibm-aix-xcoff < %s 2>&1 | FileCheck %s --check-prefix CHECK-ERROR +; RUN: not --crash llc -mtriple powerpc64-ibm-aix-xcoff < %s 2>&1 | FileCheck %s --check-prefix CHECK-ERROR + +@a = global [5 x i16] zeroinitializer, align 2 #0 + +attributes #0 = { "toc-data" } + +; CHECK-ERROR: LLVM ERROR: A GlobalVariable with size larger than a TOC entry is not currently supported by the toc data transformation. diff --git a/llvm/test/CodeGen/PowerPC/toc-data-struct-array.ll b/llvm/test/CodeGen/PowerPC/toc-data-struct-array.ll new file mode 100644 index 000000000000..a5c9a8b909d1 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/toc-data-struct-array.ll @@ -0,0 +1,110 @@ +; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck %s --check-prefix CHECK +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s --check-prefix CHECK + +; RUN: llc -filetype=obj -mtriple powerpc-ibm-aix-xcoff < %s -o %t32.o +; RUN: llvm-readobj %t32.o --syms | FileCheck %s --check-prefix=OBJ32 +; RUN: llc -filetype=obj -mtriple powerpc64-ibm-aix-xcoff < %s -o %t64.o +; RUN: llvm-readobj %t64.o --syms | FileCheck %s --check-prefix=OBJ64 + +%struct.small_struct = type { i16 } + +@a = global %struct.small_struct zeroinitializer, align 2 #0 +@b = global [2 x i16] zeroinitializer, align 2 #0 + +; Function Attrs: noinline +define i16 @foo() #1 { +entry: + %0 = load i16, ptr @a, align 2 + %1 = load i16, ptr @b, align 2 + %add = add nsw i16 %0, %1 + ret i16 %add +} + +attributes #0 = { "toc-data" } +attributes #1 = { noinline } + +; CHECK: .toc +; CHECK-NEXT: .csect a[TD],2 +; CHECK-NEXT: .globl a[TD] # @a +; CHECK-NEXT: .align 1 +; CHECK-NEXT: .space 2 +; CHECK-NEXT: .csect b[TD],2 +; CHECK-NEXT: .globl b[TD] # @b +; CHECK-NEXT: .align 1 +; CHECK-NEXT: .space 4 + +; OBJ32: Symbol { +; OBJ32: Name: a +; OBJ32-NEXT: Value (RelocatableAddress): 0x3C +; OBJ32-NEXT: Section: .data +; OBJ32-NEXT: Type: 0x0 +; OBJ32-NEXT: StorageClass: C_EXT (0x2) +; OBJ32-NEXT: NumberOfAuxEntries: 1 +; OBJ32-NEXT: CSECT Auxiliary Entry { +; OBJ32-NEXT: Index: {{[0-9]+}} +; OBJ32-NEXT: SectionLen: 2 +; OBJ32-NEXT: ParameterHashIndex: 0x0 +; OBJ32-NEXT: TypeChkSectNum: 0x0 +; OBJ32-NEXT: SymbolAlignmentLog2: 2 +; OBJ32-NEXT: SymbolType: XTY_SD (0x1) +; OBJ32-NEXT: StorageMappingClass: XMC_TD (0x10) +; OBJ32-NEXT: StabInfoIndex: 0x0 +; OBJ32-NEXT: StabSectNum: 0x0 +; OBJ32-NEXT: } +; OBJ32-NEXT: } +; OBJ32-NEXT: Symbol { +; OBJ32: Name: b +; OBJ32-NEXT: Value (RelocatableAddress): 0x40 +; OBJ32-NEXT: Section: .data +; OBJ32-NEXT: Type: 0x0 +; OBJ32-NEXT: StorageClass: C_EXT (0x2) +; OBJ32-NEXT: NumberOfAuxEntries: 1 +; OBJ32-NEXT: CSECT Auxiliary Entry { +; OBJ32-NEXT: Index: {{[0-9]+}} +; OBJ32-NEXT: SectionLen: 4 +; OBJ32-NEXT: ParameterHashIndex: 0x0 +; OBJ32-NEXT: TypeChkSectNum: 0x0 +; OBJ32-NEXT: SymbolAlignmentLog2: 2 +; OBJ32-NEXT: SymbolType: XTY_SD (0x1) +; OBJ32-NEXT: StorageMappingClass: XMC_TD (0x10) +; OBJ32-NEXT: StabInfoIndex: 0x0 +; OBJ32-NEXT: StabSectNum: 0x0 +; OBJ32-NEXT: } +; OBJ32-NEXT: } + +; OBJ64: Symbol { +; OBJ64: Name: a +; OBJ64-NEXT: Value (RelocatableAddress): 0x48 +; OBJ64-NEXT: Section: .data +; OBJ64-NEXT: Type: 0x0 +; OBJ64-NEXT: StorageClass: C_EXT (0x2) +; OBJ64-NEXT: NumberOfAuxEntries: 1 +; OBJ64-NEXT: CSECT Auxiliary Entry { +; OBJ64-NEXT: Index: {{[0-9]+}} +; OBJ64-NEXT: SectionLen: 2 +; OBJ64-NEXT: ParameterHashIndex: 0x0 +; OBJ64-NEXT: TypeChkSectNum: 0x0 +; OBJ64-NEXT: SymbolAlignmentLog2: 2 +; OBJ64-NEXT: SymbolType: XTY_SD (0x1) +; OBJ64-NEXT: StorageMappingClass: XMC_TD (0x10) +; OBJ64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; OBJ64-NEXT: } +; OBJ64-NEXT: } +; OBJ64-NEXT: Symbol { +; OBJ64: Name: b +; OBJ64-NEXT: Value (RelocatableAddress): 0x4C +; OBJ64-NEXT: Section: .data +; OBJ64-NEXT: Type: 0x0 +; OBJ64-NEXT: StorageClass: C_EXT (0x2) +; OBJ64-NEXT: NumberOfAuxEntries: 1 +; OBJ64-NEXT: CSECT Auxiliary Entry { +; OBJ64-NEXT: Index: {{[0-9]+}} +; OBJ64-NEXT: SectionLen: 4 +; OBJ64-NEXT: ParameterHashIndex: 0x0 +; OBJ64-NEXT: TypeChkSectNum: 0x0 +; OBJ64-NEXT: SymbolAlignmentLog2: 2 +; OBJ64-NEXT: SymbolType: XTY_SD (0x1) +; OBJ64-NEXT: StorageMappingClass: XMC_TD (0x10) +; OBJ64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; OBJ64-NEXT: } +; OBJ64-NEXT: } -- GitLab From 1402c016ffe860446552a959e9fc4696c39392f9 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 13 Mar 2024 14:29:59 +0000 Subject: [PATCH 379/953] [VPlan] Use VPBuilder to create BranchOnCond in VPHCFGBuilder. This simplifies the code to create the recipe slightly as well as properly retaining the debug location of the input IR. --- .../Transforms/Vectorize/VPlanHCFGBuilder.cpp | 3 +- .../LoopVectorize/dbg-outer-loop-vect.ll | 40 +++++++++---------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp b/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp index 6474a9697dce..877b5d438115 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp @@ -296,8 +296,7 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB, // recipes. if (Br->isConditional()) { VPValue *Cond = getOrCreateVPOperand(Br->getCondition()); - VPBB->appendRecipe( - new VPInstruction(VPInstruction::BranchOnCond, {Cond})); + VPIRBuilder.createNaryOp(VPInstruction::BranchOnCond, {Cond}, Inst); } // Skip the rest of the Instruction processing for Branch instructions. diff --git a/llvm/test/Transforms/LoopVectorize/dbg-outer-loop-vect.ll b/llvm/test/Transforms/LoopVectorize/dbg-outer-loop-vect.ll index 7f209634fe05..2c665a417ab5 100644 --- a/llvm/test/Transforms/LoopVectorize/dbg-outer-loop-vect.ll +++ b/llvm/test/Transforms/LoopVectorize/dbg-outer-loop-vect.ll @@ -7,7 +7,7 @@ define void @foo(ptr %h) !dbg !4 { ; CHECK-LABEL: define void @foo( ; CHECK-SAME: ptr [[H:%.*]]) !dbg [[DBG4:![0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 0, metadata [[META11:![0-9]+]], metadata !DIExpression()), !dbg [[DBG20:![0-9]+]] +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 0, metadata [[META11:![0-9]+]], metadata !DIExpression()), !dbg [[DBG20:![0-9]+]] ; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]], !dbg [[DBG21:![0-9]+]] ; CHECK: vector.ph: ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]], !dbg [[DBG21]] @@ -27,15 +27,15 @@ define void @foo(ptr %h) !dbg !4 { ; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> , <4 x ptr> [[TMP3]], i32 4, <4 x i1> ), !dbg [[DBG22]] ; CHECK-NEXT: [[TMP4]] = add nuw nsw <4 x i64> [[VEC_PHI]], , !dbg [[DBG24:![0-9]+]] ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq <4 x i64> [[TMP4]], , !dbg [[DBG25:![0-9]+]] -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x i1> [[TMP5]], i32 0 -; CHECK-NEXT: br i1 [[TMP6]], label [[FOR_COND_CLEANUP32]], label [[FOR_COND5_PREHEADER1]] +; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x i1> [[TMP5]], i32 0, !dbg [[DBG26:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP6]], label [[FOR_COND_CLEANUP32]], label [[FOR_COND5_PREHEADER1]], !dbg [[DBG26]] ; CHECK: for.cond.cleanup32: -; CHECK-NEXT: [[TMP7:%.*]] = add nuw nsw <4 x i64> [[VEC_IND]], , !dbg [[DBG26:![0-9]+]] -; CHECK-NEXT: [[TMP8:%.*]] = icmp eq <4 x i64> [[TMP7]], , !dbg [[DBG27:![0-9]+]] +; CHECK-NEXT: [[TMP7:%.*]] = add nuw nsw <4 x i64> [[VEC_IND]], , !dbg [[DBG27:![0-9]+]] +; CHECK-NEXT: [[TMP8:%.*]] = icmp eq <4 x i64> [[TMP7]], , !dbg [[DBG28:![0-9]+]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], ; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], 20 -; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP28:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP29:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: br i1 false, label [[EXIT:%.*]], label [[SCALAR_PH]], !dbg [[DBG21]] ; CHECK: scalar.ph: @@ -43,8 +43,8 @@ define void @foo(ptr %h) !dbg !4 { ; CHECK-NEXT: br label [[FOR_COND1_PREHEADER:%.*]], !dbg [[DBG21]] ; CHECK: for.cond1.preheader: ; CHECK-NEXT: [[I_023:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC13:%.*]], [[FOR_COND_CLEANUP3:%.*]] ] -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 [[I_023]], metadata [[META11]], metadata !DIExpression()), !dbg [[DBG20]] -; CHECK-NEXT: br label [[FOR_COND5_PREHEADER:%.*]], !dbg [[DBG32:![0-9]+]] +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 [[I_023]], metadata [[META11]], metadata !DIExpression()), !dbg [[DBG20]] +; CHECK-NEXT: br label [[FOR_COND5_PREHEADER:%.*]], !dbg [[DBG26]] ; CHECK: for.cond5.preheader: ; CHECK-NEXT: [[L_022:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER]] ], [ [[INC10:%.*]], [[FOR_COND5_PREHEADER]] ] ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i32, ptr [[H]], i64 [[L_022]] @@ -57,11 +57,11 @@ define void @foo(ptr %h) !dbg !4 { ; CHECK-NEXT: store i32 3, ptr [[ARRAYIDX_3]], align 4, !dbg [[DBG22]] ; CHECK-NEXT: [[INC10]] = add nuw nsw i64 [[L_022]], 1, !dbg [[DBG24]] ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INC10]], 5, !dbg [[DBG25]] -; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP3]], label [[FOR_COND5_PREHEADER]], !dbg [[DBG32]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP3]], label [[FOR_COND5_PREHEADER]], !dbg [[DBG26]] ; CHECK: for.cond.cleanup3: -; CHECK-NEXT: [[INC13]] = add nuw nsw i64 [[I_023]], 1, !dbg [[DBG26]] -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 [[INC13]], metadata [[META11]], metadata !DIExpression()), !dbg [[DBG20]] -; CHECK-NEXT: [[EXITCOND24_NOT:%.*]] = icmp eq i64 [[INC13]], 23, !dbg [[DBG27]] +; CHECK-NEXT: [[INC13]] = add nuw nsw i64 [[I_023]], 1, !dbg [[DBG27]] +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 [[INC13]], metadata [[META11]], metadata !DIExpression()), !dbg [[DBG20]] +; CHECK-NEXT: [[EXITCOND24_NOT:%.*]] = icmp eq i64 [[INC13]], 23, !dbg [[DBG28]] ; CHECK-NEXT: br i1 [[EXITCOND24_NOT]], label [[EXIT]], label [[FOR_COND1_PREHEADER]], !dbg [[DBG21]], !llvm.loop [[LOOP34:![0-9]+]] ; CHECK: exit: ; CHECK-NEXT: ret void, !dbg [[DBG35:![0-9]+]] @@ -163,14 +163,14 @@ declare void @llvm.dbg.value(metadata, metadata, metadata) ; CHECK: [[META23]] = distinct !DILexicalBlock(scope: [[META18]], file: [[META1]], line: 12, column: 7) ; CHECK: [[DBG24]] = !DILocation(line: 11, column: 32, scope: [[META19]]) ; CHECK: [[DBG25]] = !DILocation(line: 11, column: 26, scope: [[META19]]) -; CHECK: [[DBG26]] = !DILocation(line: 10, column: 30, scope: [[META16]]) -; CHECK: [[DBG27]] = !DILocation(line: 10, column: 24, scope: [[META16]]) -; CHECK: [[LOOP28]] = distinct !{[[LOOP28]], [[DBG21]], [[META29:![0-9]+]], [[META30:![0-9]+]], [[META31:![0-9]+]]} -; CHECK: [[META29]] = !DILocation(line: 13, column: 13, scope: [[META12]]) -; CHECK: [[META30]] = !{!"llvm.loop.isvectorized", i32 1} -; CHECK: [[META31]] = !{!"llvm.loop.unroll.runtime.disable"} -; CHECK: [[DBG32]] = !DILocation(line: 11, column: 5, scope: [[META15]]) +; CHECK: [[DBG26]] = !DILocation(line: 11, column: 5, scope: [[META15]]) +; CHECK: [[DBG27]] = !DILocation(line: 10, column: 30, scope: [[META16]]) +; CHECK: [[DBG28]] = !DILocation(line: 10, column: 24, scope: [[META16]]) +; CHECK: [[LOOP29]] = distinct !{[[LOOP29]], [[DBG21]], [[META30:![0-9]+]], [[META31:![0-9]+]], [[META32:![0-9]+]]} +; CHECK: [[META30]] = !DILocation(line: 13, column: 13, scope: [[META12]]) +; CHECK: [[META31]] = !{!"llvm.loop.isvectorized", i32 1} +; CHECK: [[META32]] = !{!"llvm.loop.unroll.runtime.disable"} ; CHECK: [[DBG33]] = !DILocation(line: 13, column: 2, scope: [[META23]]) -; CHECK: [[LOOP34]] = distinct !{[[LOOP34]], [[DBG21]], [[META29]], [[META30]]} +; CHECK: [[LOOP34]] = distinct !{[[LOOP34]], [[DBG21]], [[META30]], [[META31]]} ; CHECK: [[DBG35]] = !DILocation(line: 14, column: 1, scope: [[DBG4]]) ;. -- GitLab From 4e49ee55c587637e17dec7a72b9ce86d85f8f241 Mon Sep 17 00:00:00 2001 From: David Spickett Date: Wed, 13 Mar 2024 14:29:43 +0000 Subject: [PATCH 380/953] [lldb][Test] Disable ConcurrentVFork tests on Arm/AArch64 Linux They are either flaky, or not cleaning up after themselves. See https://github.com/llvm/llvm-project/issues/85084. --- .../fork/concurrent_vfork/TestConcurrentVFork.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lldb/test/API/functionalities/fork/concurrent_vfork/TestConcurrentVFork.py b/lldb/test/API/functionalities/fork/concurrent_vfork/TestConcurrentVFork.py index 2dcbb728549f..1790bd497f4e 100644 --- a/lldb/test/API/functionalities/fork/concurrent_vfork/TestConcurrentVFork.py +++ b/lldb/test/API/functionalities/fork/concurrent_vfork/TestConcurrentVFork.py @@ -48,6 +48,8 @@ class TestConcurrentVFork(TestBase): self.expect("continue", patterns=[r"exited with status = 1[0-4]"]) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_parent_vfork_no_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent. @@ -56,6 +58,8 @@ class TestConcurrentVFork(TestBase): self.follow_parent_helper(use_fork=False, call_exec=False) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_parent_fork_no_exec(self): """ Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-parent. @@ -64,6 +68,8 @@ class TestConcurrentVFork(TestBase): self.follow_parent_helper(use_fork=True, call_exec=False) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_parent_vfork_call_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent. @@ -72,6 +78,8 @@ class TestConcurrentVFork(TestBase): self.follow_parent_helper(use_fork=False, call_exec=True) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_parent_fork_call_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent. @@ -80,6 +88,8 @@ class TestConcurrentVFork(TestBase): self.follow_parent_helper(use_fork=True, call_exec=True) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_child_vfork_no_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-child. @@ -88,6 +98,8 @@ class TestConcurrentVFork(TestBase): self.follow_child_helper(use_fork=False, call_exec=False) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_child_fork_no_exec(self): """ Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-child. @@ -96,6 +108,8 @@ class TestConcurrentVFork(TestBase): self.follow_child_helper(use_fork=True, call_exec=False) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_child_vfork_call_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-child. @@ -104,6 +118,8 @@ class TestConcurrentVFork(TestBase): self.follow_child_helper(use_fork=False, call_exec=True) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_child_fork_call_exec(self): """ Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-child. -- GitLab From 63180ba444dc09fb9e85fdb98af56b2fc86f6027 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 13 Mar 2024 14:02:46 +0000 Subject: [PATCH 381/953] [DAG] Use SelectionDAG::getNOT helper where possible. NFC. --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 87033e824aa5..40b078a201ac 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2799,8 +2799,7 @@ SDValue DAGCombiner::visitADDLike(SDNode *N) { // Limit this to after legalization if the add has wrap flags (Level >= AfterLegalizeDAG || (!N->getFlags().hasNoUnsignedWrap() && !N->getFlags().hasNoSignedWrap()))) { - SDValue Not = DAG.getNode(ISD::XOR, DL, VT, N0.getOperand(0), - DAG.getAllOnesConstant(DL, VT)); + SDValue Not = DAG.getNOT(DL, N0.getOperand(0), VT); return DAG.getNode(ISD::SUB, DL, VT, N0.getOperand(1), Not); } } @@ -3025,8 +3024,7 @@ SDValue DAGCombiner::visitADDLikeCommutative(SDValue N0, SDValue N1, // Limit this to after legalization if the add has wrap flags (Level >= AfterLegalizeDAG || (!N0->getFlags().hasNoUnsignedWrap() && !N0->getFlags().hasNoSignedWrap()))) { - SDValue Not = DAG.getNode(ISD::XOR, DL, VT, N0.getOperand(0), - DAG.getAllOnesConstant(DL, VT)); + SDValue Not = DAG.getNOT(DL, N0.getOperand(0), VT); return DAG.getNode(ISD::SUB, DL, VT, N1, Not); } -- GitLab From f18d78b477c76bc09dc580cdaedd55e121f5ebf5 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Wed, 13 Mar 2024 14:47:23 +0000 Subject: [PATCH 382/953] [DAG] isKnownToBeAPowerOfTwo - use sd_match to match both commutations of `x & -x` pattern`. NFC. Allows us to remove some tricky commutation matching --- .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index c24303592769..b8c7d08da3e2 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -37,6 +37,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/SDPatternMatch.h" #include "llvm/CodeGen/SelectionDAGAddressAnalysis.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/SelectionDAGTargetInfo.h" @@ -81,6 +82,7 @@ #include using namespace llvm; +using namespace llvm::SDPatternMatch; /// makeVTList - Return an instance of the SDVTList struct initialized with the /// specified members. @@ -4290,21 +4292,15 @@ bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val, unsigned Depth) const { return isKnownToBeAPowerOfTwo(Val.getOperand(2), Depth + 1) && isKnownToBeAPowerOfTwo(Val.getOperand(1), Depth + 1); - if (Val.getOpcode() == ISD::AND) { - // Looking for `x & -x` pattern: - // If x == 0: - // x & -x -> 0 - // If x != 0: - // x & -x -> non-zero pow2 - // so if we find the pattern return whether we know `x` is non-zero. - for (unsigned OpIdx = 0; OpIdx < 2; ++OpIdx) { - SDValue NegOp = Val.getOperand(OpIdx); - if (NegOp.getOpcode() == ISD::SUB && - NegOp.getOperand(1) == Val.getOperand(1 - OpIdx) && - isNullOrNullSplat(NegOp.getOperand(0))) - return isKnownNeverZero(Val.getOperand(1 - OpIdx), Depth); - } - } + // Looking for `x & -x` pattern: + // If x == 0: + // x & -x -> 0 + // If x != 0: + // x & -x -> non-zero pow2 + // so if we find the pattern return whether we know `x` is non-zero. + SDValue X; + if (sd_match(Val, m_And(m_Value(X), m_Sub(m_Zero(), m_Deferred(X))))) + return isKnownNeverZero(X, Depth); if (Val.getOpcode() == ISD::ZERO_EXTEND) return isKnownToBeAPowerOfTwo(Val.getOperand(0), Depth + 1); -- GitLab From f46f5a01f4d5a7dcaf4a8fde5fc44eafdd9dbf27 Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Wed, 13 Mar 2024 14:51:09 +0000 Subject: [PATCH 383/953] [flang][OpenMP][OMPIRBuilder][mlir] Optionally pass reduction vars by ref (#84304) Previously reduction variables were always passed by value into and out of the initialization and combiner regions of the OpenMP reduction declare operation. This worked well for reductions of primitive types (and might perform better than passing by reference). But passing by reference will be useful for array and derived type reductions (e.g. to move allocation inside of the init region). Passing reductions by reference requires different LLVM-IR generation when lowering from MLIR because some of the loads/stores/allocations will now be moved inside of the init and combiner regions. This alternate code generation is requested using a new attribute to omp.wsloop and omp.parallel. Existing lowerings from mlir are unaffected (these will continue to use the by-value argument passing. Flang will continue to pass by-value argument passing for trivial types unless a (hidden) command line argument is supplied. Non-trivial types will always use the by-ref lowering. Array reductions are not ready yet (but are coming very soon). In the meantime, this is tested by forcing existing reductions to use by-ref. Commit series for by-ref OpenMP reductions 3/3 --------- Co-authored-by: Mats Petersson --- flang/lib/Lower/OpenMP/OpenMP.cpp | 18 +- flang/lib/Lower/OpenMP/ReductionProcessor.cpp | 137 ++++-- flang/lib/Lower/OpenMP/ReductionProcessor.h | 18 +- .../FIR/parallel-reduction-add-byref.f90 | 117 +++++ .../OpenMP/FIR/wsloop-reduction-add-byref.f90 | 392 ++++++++++++++++ .../FIR/wsloop-reduction-iand-byref.f90 | 46 ++ .../FIR/wsloop-reduction-ieor-byref.f90 | 45 ++ .../OpenMP/FIR/wsloop-reduction-ior-byref.f90 | 45 ++ .../wsloop-reduction-logical-eqv-byref.f90 | 187 ++++++++ .../wsloop-reduction-logical-neqv-byref.f90 | 189 ++++++++ .../OpenMP/FIR/wsloop-reduction-max-byref.f90 | 90 ++++ .../OpenMP/FIR/wsloop-reduction-min-byref.f90 | 91 ++++ .../Lower/OpenMP/default-clause-byref.f90 | 385 ++++++++++++++++ .../delayed-privatization-reduction-byref.f90 | 30 ++ .../OpenMP/parallel-reduction-add-byref.f90 | 125 +++++ .../Lower/OpenMP/parallel-reduction-byref.f90 | 44 ++ .../parallel-wsloop-reduction-byref.f90 | 16 + .../OpenMP/wsloop-reduction-add-byref.f90 | 433 ++++++++++++++++++ .../wsloop-reduction-add-hlfir-byref.f90 | 58 +++ .../OpenMP/wsloop-reduction-iand-byref.f90 | 64 +++ .../OpenMP/wsloop-reduction-ieor-byref.f90 | 55 +++ .../OpenMP/wsloop-reduction-ior-byref.f90 | 64 +++ .../wsloop-reduction-logical-and-byref.f90 | 206 +++++++++ .../wsloop-reduction-logical-eqv-byref.f90 | 202 ++++++++ .../wsloop-reduction-logical-neqv-byref.f90 | 207 +++++++++ .../wsloop-reduction-logical-or-byref.f90 | 204 +++++++++ .../OpenMP/wsloop-reduction-max-2-byref.f90 | 20 + .../OpenMP/wsloop-reduction-max-byref.f90 | 152 ++++++ .../wsloop-reduction-max-hlfir-byref.f90 | 62 +++ .../OpenMP/wsloop-reduction-min-byref.f90 | 154 +++++++ .../Lower/OpenMP/wsloop-reduction-min2.f90 | 41 ++ .../OpenMP/wsloop-reduction-mul-byref.f90 | 414 +++++++++++++++++ .../llvm/Frontend/OpenMP/OMPIRBuilder.h | 4 +- llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp | 30 +- mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td | 12 +- mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 5 +- .../OpenMP/OpenMPToLLVMIRTranslation.cpp | 99 ++-- .../Target/LLVMIR/openmp-reduction-byref.mlir | 66 +++ 38 files changed, 4451 insertions(+), 76 deletions(-) create mode 100644 flang/test/Lower/OpenMP/FIR/parallel-reduction-add-byref.f90 create mode 100644 flang/test/Lower/OpenMP/FIR/wsloop-reduction-add-byref.f90 create mode 100644 flang/test/Lower/OpenMP/FIR/wsloop-reduction-iand-byref.f90 create mode 100644 flang/test/Lower/OpenMP/FIR/wsloop-reduction-ieor-byref.f90 create mode 100644 flang/test/Lower/OpenMP/FIR/wsloop-reduction-ior-byref.f90 create mode 100644 flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-eqv-byref.f90 create mode 100644 flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-neqv-byref.f90 create mode 100644 flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 create mode 100644 flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 create mode 100644 flang/test/Lower/OpenMP/default-clause-byref.f90 create mode 100644 flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 create mode 100644 flang/test/Lower/OpenMP/parallel-reduction-add-byref.f90 create mode 100644 flang/test/Lower/OpenMP/parallel-reduction-byref.f90 create mode 100644 flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-add-byref.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir-byref.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-max-2-byref.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir-byref.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-min2.f90 create mode 100644 flang/test/Lower/OpenMP/wsloop-reduction-mul-byref.f90 create mode 100644 mlir/test/Target/LLVMIR/openmp-reduction-byref.mlir diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 4f0bb80cd7fd..1016c8389c6e 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -601,6 +601,10 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, return reductionSymbols; }; + mlir::UnitAttr byrefAttr; + if (ReductionProcessor::doReductionByRef(reductionVars)) + byrefAttr = converter.getFirOpBuilder().getUnitAttr(); + OpWithBodyGenInfo genInfo = OpWithBodyGenInfo(converter, semaCtx, currentLocation, eval) .setGenNested(genNested) @@ -620,7 +624,7 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), reductionDeclSymbols), procBindKindAttr, /*private_vars=*/llvm::SmallVector{}, - /*privatizers=*/nullptr); + /*privatizers=*/nullptr, byrefAttr); } bool privatize = !outerCombined; @@ -684,7 +688,8 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, delayedPrivatizationInfo.privatizers.empty() ? nullptr : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), - privatizers)); + privatizers), + byrefAttr); } static mlir::omp::SectionOp @@ -1583,7 +1588,7 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter, llvm::SmallVector reductionSymbols; mlir::omp::ClauseOrderKindAttr orderClauseOperand; mlir::omp::ClauseScheduleKindAttr scheduleValClauseOperand; - mlir::UnitAttr nowaitClauseOperand, scheduleSimdClauseOperand; + mlir::UnitAttr nowaitClauseOperand, byrefOperand, scheduleSimdClauseOperand; mlir::IntegerAttr orderedClauseOperand; mlir::omp::ScheduleModifierAttr scheduleModClauseOperand; std::size_t loopVarTypeSize; @@ -1600,6 +1605,9 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter, convertLoopBounds(converter, loc, lowerBound, upperBound, step, loopVarTypeSize); + if (ReductionProcessor::doReductionByRef(reductionVars)) + byrefOperand = firOpBuilder.getUnitAttr(); + auto wsLoopOp = firOpBuilder.create( loc, lowerBound, upperBound, step, linearVars, linearStepVars, reductionVars, @@ -1609,8 +1617,8 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter, reductionDeclSymbols), scheduleValClauseOperand, scheduleChunkClauseOperand, /*schedule_modifiers=*/nullptr, - /*simd_modifier=*/nullptr, nowaitClauseOperand, orderedClauseOperand, - orderClauseOperand, + /*simd_modifier=*/nullptr, nowaitClauseOperand, byrefOperand, + orderedClauseOperand, orderClauseOperand, /*inclusive=*/firOpBuilder.getUnitAttr()); // Handle attribute based clauses. diff --git a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp index a8b98f3f5672..e6a63dd4b939 100644 --- a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp @@ -14,9 +14,16 @@ #include "flang/Lower/AbstractConverter.h" #include "flang/Optimizer/Builder/Todo.h" +#include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" #include "flang/Parser/tools.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "llvm/Support/CommandLine.h" + +static llvm::cl::opt forceByrefReduction( + "force-byref-reduction", + llvm::cl::desc("Pass all reduction arguments by reference"), + llvm::cl::Hidden); namespace Fortran { namespace lower { @@ -76,16 +83,24 @@ bool ReductionProcessor::supportedIntrinsicProcReduction( } std::string ReductionProcessor::getReductionName(llvm::StringRef name, - mlir::Type ty) { + mlir::Type ty, bool isByRef) { + ty = fir::unwrapRefType(ty); + + // extra string to distinguish reduction functions for variables passed by + // reference + llvm::StringRef byrefAddition{""}; + if (isByRef) + byrefAddition = "_byref"; + return (llvm::Twine(name) + (ty.isIntOrIndex() ? llvm::Twine("_i_") : llvm::Twine("_f_")) + - llvm::Twine(ty.getIntOrFloatBitWidth())) + llvm::Twine(ty.getIntOrFloatBitWidth()) + byrefAddition) .str(); } std::string ReductionProcessor::getReductionName( Fortran::parser::DefinedOperator::IntrinsicOperator intrinsicOp, - mlir::Type ty) { + mlir::Type ty, bool isByRef) { std::string reductionName; switch (intrinsicOp) { @@ -108,13 +123,14 @@ std::string ReductionProcessor::getReductionName( break; } - return getReductionName(reductionName, ty); + return getReductionName(reductionName, ty, isByRef); } mlir::Value ReductionProcessor::getReductionInitValue(mlir::Location loc, mlir::Type type, ReductionIdentifier redId, fir::FirOpBuilder &builder) { + type = fir::unwrapRefType(type); assert((fir::isa_integer(type) || fir::isa_real(type) || type.isa()) && "only integer, logical and real types are currently supported"); @@ -188,6 +204,7 @@ mlir::Value ReductionProcessor::createScalarCombiner( fir::FirOpBuilder &builder, mlir::Location loc, ReductionIdentifier redId, mlir::Type type, mlir::Value op1, mlir::Value op2) { mlir::Value reductionOp; + type = fir::unwrapRefType(type); switch (redId) { case ReductionIdentifier::MAX: reductionOp = @@ -268,7 +285,8 @@ mlir::Value ReductionProcessor::createScalarCombiner( mlir::omp::ReductionDeclareOp ReductionProcessor::createReductionDecl( fir::FirOpBuilder &builder, llvm::StringRef reductionOpName, - const ReductionIdentifier redId, mlir::Type type, mlir::Location loc) { + const ReductionIdentifier redId, mlir::Type type, mlir::Location loc, + bool isByRef) { mlir::OpBuilder::InsertionGuard guard(builder); mlir::ModuleOp module = builder.getModule(); @@ -278,14 +296,24 @@ mlir::omp::ReductionDeclareOp ReductionProcessor::createReductionDecl( return decl; mlir::OpBuilder modBuilder(module.getBodyRegion()); + mlir::Type valTy = fir::unwrapRefType(type); + if (!isByRef) + type = valTy; decl = modBuilder.create(loc, reductionOpName, type); builder.createBlock(&decl.getInitializerRegion(), decl.getInitializerRegion().end(), {type}, {loc}); builder.setInsertionPointToEnd(&decl.getInitializerRegion().back()); + mlir::Value init = getReductionInitValue(loc, type, redId, builder); - builder.create(loc, init); + if (isByRef) { + mlir::Value alloca = builder.create(loc, valTy); + builder.createStoreWithConvert(loc, init, alloca); + builder.create(loc, alloca); + } else { + builder.create(loc, init); + } builder.createBlock(&decl.getReductionRegion(), decl.getReductionRegion().end(), {type, type}, @@ -294,14 +322,45 @@ mlir::omp::ReductionDeclareOp ReductionProcessor::createReductionDecl( builder.setInsertionPointToEnd(&decl.getReductionRegion().back()); mlir::Value op1 = decl.getReductionRegion().front().getArgument(0); mlir::Value op2 = decl.getReductionRegion().front().getArgument(1); + mlir::Value outAddr = op1; + + op1 = builder.loadIfRef(loc, op1); + op2 = builder.loadIfRef(loc, op2); mlir::Value reductionOp = createScalarCombiner(builder, loc, redId, type, op1, op2); - builder.create(loc, reductionOp); + if (isByRef) { + builder.create(loc, reductionOp, outAddr); + builder.create(loc, outAddr); + } else { + builder.create(loc, reductionOp); + } return decl; } +// TODO: By-ref vs by-val reductions are currently toggled for the whole +// operation (possibly effecting multiple reduction variables). +// This could cause a problem with openmp target reductions because +// by-ref trivial types may not be supported. +bool ReductionProcessor::doReductionByRef( + const llvm::SmallVectorImpl &reductionVars) { + if (reductionVars.empty()) + return false; + if (forceByrefReduction) + return true; + + for (mlir::Value reductionVar : reductionVars) { + if (auto declare = + mlir::dyn_cast(reductionVar.getDefiningOp())) + reductionVar = declare.getMemref(); + + if (!fir::isa_trivial(fir::unwrapRefType(reductionVar.getType()))) + return true; + } + return false; +} + void ReductionProcessor::addReductionDecl( mlir::Location currentLocation, Fortran::lower::AbstractConverter &converter, @@ -315,6 +374,37 @@ void ReductionProcessor::addReductionDecl( const auto &redOperator{ std::get(reduction.t)}; const auto &objectList{std::get(reduction.t)}; + + if (!std::holds_alternative( + redOperator.u)) { + if (const auto *reductionIntrinsic = + std::get_if(&redOperator.u)) { + if (!ReductionProcessor::supportedIntrinsicProcReduction( + *reductionIntrinsic)) { + return; + } + } else { + return; + } + } + + // initial pass to collect all recuction vars so we can figure out if this + // should happen byref + for (const Fortran::parser::OmpObject &ompObject : objectList.v) { + if (const auto *name{ + Fortran::parser::Unwrap(ompObject)}) { + if (const Fortran::semantics::Symbol * symbol{name->symbol}) { + if (reductionSymbols) + reductionSymbols->push_back(symbol); + mlir::Value symVal = converter.getSymbolAddress(*symbol); + if (auto declOp = symVal.getDefiningOp()) + symVal = declOp.getBase(); + reductionVars.push_back(symVal); + } + } + } + const bool isByRef = doReductionByRef(reductionVars); + if (const auto &redDefinedOp = std::get_if(&redOperator.u)) { const auto &intrinsicOp{ @@ -338,23 +428,20 @@ void ReductionProcessor::addReductionDecl( if (const auto *name{ Fortran::parser::Unwrap(ompObject)}) { if (const Fortran::semantics::Symbol * symbol{name->symbol}) { - if (reductionSymbols) - reductionSymbols->push_back(symbol); mlir::Value symVal = converter.getSymbolAddress(*symbol); if (auto declOp = symVal.getDefiningOp()) symVal = declOp.getBase(); - mlir::Type redType = - symVal.getType().cast().getEleTy(); - reductionVars.push_back(symVal); - if (redType.isa()) + auto redType = symVal.getType().cast(); + if (redType.getEleTy().isa()) decl = createReductionDecl( firOpBuilder, - getReductionName(intrinsicOp, firOpBuilder.getI1Type()), redId, - redType, currentLocation); - else if (redType.isIntOrIndexOrFloat()) { - decl = createReductionDecl(firOpBuilder, - getReductionName(intrinsicOp, redType), - redId, redType, currentLocation); + getReductionName(intrinsicOp, firOpBuilder.getI1Type(), + isByRef), + redId, redType, currentLocation, isByRef); + else if (redType.getEleTy().isIntOrIndexOrFloat()) { + decl = createReductionDecl( + firOpBuilder, getReductionName(intrinsicOp, redType, isByRef), + redId, redType, currentLocation, isByRef); } else { TODO(currentLocation, "Reduction of some types is not supported"); } @@ -374,21 +461,17 @@ void ReductionProcessor::addReductionDecl( if (const auto *name{ Fortran::parser::Unwrap(ompObject)}) { if (const Fortran::semantics::Symbol * symbol{name->symbol}) { - if (reductionSymbols) - reductionSymbols->push_back(symbol); mlir::Value symVal = converter.getSymbolAddress(*symbol); if (auto declOp = symVal.getDefiningOp()) symVal = declOp.getBase(); - mlir::Type redType = - symVal.getType().cast().getEleTy(); - reductionVars.push_back(symVal); - assert(redType.isIntOrIndexOrFloat() && + auto redType = symVal.getType().cast(); + assert(redType.getEleTy().isIntOrIndexOrFloat() && "Unsupported reduction type"); decl = createReductionDecl( firOpBuilder, getReductionName(getRealName(*reductionIntrinsic).ToString(), - redType), - redId, redType, currentLocation); + redType, isByRef), + redId, redType, currentLocation, isByRef); reductionDeclSymbols.push_back(mlir::SymbolRefAttr::get( firOpBuilder.getContext(), decl.getSymName())); } diff --git a/flang/lib/Lower/OpenMP/ReductionProcessor.h b/flang/lib/Lower/OpenMP/ReductionProcessor.h index 00770fe81d1e..679580f2a3ca 100644 --- a/flang/lib/Lower/OpenMP/ReductionProcessor.h +++ b/flang/lib/Lower/OpenMP/ReductionProcessor.h @@ -14,6 +14,7 @@ #define FORTRAN_LOWER_REDUCTIONPROCESSOR_H #include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/symbol.h" #include "flang/Semantics/type.h" @@ -71,11 +72,15 @@ public: static const Fortran::semantics::SourceName getRealName(const Fortran::parser::ProcedureDesignator &pd); - static std::string getReductionName(llvm::StringRef name, mlir::Type ty); + static bool + doReductionByRef(const llvm::SmallVectorImpl &reductionVars); + + static std::string getReductionName(llvm::StringRef name, mlir::Type ty, + bool isByRef); static std::string getReductionName( Fortran::parser::DefinedOperator::IntrinsicOperator intrinsicOp, - mlir::Type ty); + mlir::Type ty, bool isByRef); /// This function returns the identity value of the operator \p /// reductionOpName. For example: @@ -103,9 +108,11 @@ public: /// symbol table. The declaration has a constant initializer with the neutral /// value `initValue`, and the reduction combiner carried over from `reduce`. /// TODO: Generalize this for non-integer types, add atomic region. - static mlir::omp::ReductionDeclareOp createReductionDecl( - fir::FirOpBuilder &builder, llvm::StringRef reductionOpName, - const ReductionIdentifier redId, mlir::Type type, mlir::Location loc); + static mlir::omp::ReductionDeclareOp + createReductionDecl(fir::FirOpBuilder &builder, + llvm::StringRef reductionOpName, + const ReductionIdentifier redId, mlir::Type type, + mlir::Location loc, bool isByRef); /// Creates a reduction declaration and associates it with an OpenMP block /// directive. @@ -124,6 +131,7 @@ mlir::Value ReductionProcessor::getReductionOperation(fir::FirOpBuilder &builder, mlir::Type type, mlir::Location loc, mlir::Value op1, mlir::Value op2) { + type = fir::unwrapRefType(type); assert(type.isIntOrIndexOrFloat() && "only integer and float types are currently supported"); if (type.isIntOrIndex()) diff --git a/flang/test/Lower/OpenMP/FIR/parallel-reduction-add-byref.f90 b/flang/test/Lower/OpenMP/FIR/parallel-reduction-add-byref.f90 new file mode 100644 index 000000000000..ca432662b77c --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/parallel-reduction-add-byref.f90 @@ -0,0 +1,117 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +!CHECK-LABEL: omp.reduction.declare +!CHECK-SAME: @[[RED_F32_NAME:.*]] : !fir.ref +!CHECK-SAME: init { +!CHECK: ^bb0(%{{.*}}: !fir.ref): +!CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f32 +!CHECK: %[[REF:.*]] = fir.alloca f32 +!CHECKL fir.store [[%C0_1]] to %[[REF]] : !fir.ref +!CHECK: omp.yield(%[[REF]] : !fir.ref) +!CHECK: } combiner { +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +!CHECK: %[[RES:.*]] = arith.addf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +!CHECK: omp.yield(%[[ARG0]] : !fir.ref) +!CHECK: } + +!CHECK-LABEL: omp.reduction.declare +!CHECK-SAME: @[[RED_I32_NAME:.*]] : !fir.ref +!CHECK-SAME: init { +!CHECK: ^bb0(%{{.*}}: !fir.ref): +!CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +!CHECK: %[[REF:.*]] = fir.alloca i32 +!CHECKL fir.store [[%C0_1]] to %[[REF]] : !fir.ref +!CHECK: omp.yield(%[[REF]] : !fir.ref) +!CHECK: } combiner { +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +!CHECK: %[[RES:.*]] = arith.addi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +!CHECK: omp.yield(%[[ARG0]] : !fir.ref) +!CHECK: } + +!CHECK-LABEL: func.func @_QPsimple_int_add +!CHECK: %[[IREF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_addEi"} +!CHECK: %[[I_START:.*]] = arith.constant 0 : i32 +!CHECK: fir.store %[[I_START]] to %[[IREF]] : !fir.ref +!CHECK: omp.parallel byref reduction(@[[RED_I32_NAME]] %[[IREF]] -> %[[PRV:.+]] : !fir.ref) { +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref +!CHECK: %[[I_INCR:.+]] = arith.constant 1 : i32 +!CHECK: %[[RES:.+]] = arith.addi %[[LPRV]], %[[I_INCR]] +!CHECK: fir.store %[[RES]] to %[[PRV]] : !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +subroutine simple_int_add + integer :: i + i = 0 + + !$omp parallel reduction(+:i) + i = i + 1 + !$omp end parallel + + print *, i +end subroutine + +!CHECK-LABEL: func.func @_QPsimple_real_add +!CHECK: %[[RREF:.*]] = fir.alloca f32 {bindc_name = "r", uniq_name = "_QFsimple_real_addEr"} +!CHECK: %[[R_START:.*]] = arith.constant 0.000000e+00 : f32 +!CHECK: fir.store %[[R_START]] to %[[RREF]] : !fir.ref +!CHECK: omp.parallel byref reduction(@[[RED_F32_NAME]] %[[RREF]] -> %[[PRV:.+]] : !fir.ref) { +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref +!CHECK: %[[R_INCR:.+]] = arith.constant 1.500000e+00 : f32 +!CHECK: %[[RES]] = arith.addf %[[LPRV]], %[[R_INCR]] {{.*}} : f32 +!CHECK: fir.store %[[RES]] to %[[PRV]] : !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +subroutine simple_real_add + real :: r + r = 0.0 + + !$omp parallel reduction(+:r) + r = r + 1.5 + !$omp end parallel + + print *, r +end subroutine + +!CHECK-LABEL: func.func @_QPint_real_add +!CHECK: %[[IREF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFint_real_addEi"} +!CHECK: %[[RREF:.*]] = fir.alloca f32 {bindc_name = "r", uniq_name = "_QFint_real_addEr"} +!CHECK: %[[R_START:.*]] = arith.constant 0.000000e+00 : f32 +!CHECK: fir.store %[[R_START]] to %[[RREF]] : !fir.ref +!CHECK: %[[I_START:.*]] = arith.constant 0 : i32 +!CHECK: fir.store %[[I_START]] to %[[IREF]] : !fir.ref +!CHECK: omp.parallel byref reduction(@[[RED_I32_NAME]] %[[IREF]] -> %[[PRV0:.+]] : !fir.ref, @[[RED_F32_NAME]] %[[RREF]] -> %[[PRV1:.+]] : !fir.ref) { +!CHECK: %[[R_INCR:.*]] = arith.constant 1.500000e+00 : f32 +!CHECK: %[[LPRV1:.+]] = fir.load %[[PRV1]] : !fir.ref +!CHECK: %[[RES1:.+]] = arith.addf %[[R_INCR]], %[[LPRV1]] {{.*}} : f32 +!CHECK: fir.store %[[RES1]] to %[[PRV1]] +!CHECK: %[[LPRV0:.+]] = fir.load %[[PRV0]] : !fir.ref +!CHECK: %[[I_INCR:.*]] = arith.constant 3 : i32 +!CHECK: %[[RES0:.+]] = arith.addi %[[LPRV0]], %[[I_INCR]] +!CHECK: fir.store %[[RES0]] to %[[PRV0]] +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +subroutine int_real_add + real :: r + integer :: i + + r = 0.0 + i = 0 + + !$omp parallel reduction(+:i,r) + r = 1.5 + r + i = i + 3 + !$omp end parallel + + print *, r + print *, i +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-add-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-add-byref.f90 new file mode 100644 index 000000000000..d4d3452d3e86 --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-add-byref.f90 @@ -0,0 +1,392 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.reduction.declare @add_reduction_f_64_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f64 +! CHECK: %[[REF:.*]] = fir.alloca f64 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.addf %[[LD0]], %[[LD1]] fastmath : f64 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: omp.reduction.declare @add_reduction_i_64_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i64 +! CHECK: %[[REF:.*]] = fir.alloca i64 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.addi %[[LD0]], %[[LD1]] : i64 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: omp.reduction.declare @add_reduction_f_32_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[REF:.*]] = fir.alloca f32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.addf %[[LD0]], %[[LD1]] fastmath : f32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: omp.reduction.declare @add_reduction_i_32_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.addi %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_int_reduction() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_reductionEi"} +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_int_reductionEx"} +! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 +! CHECK: fir.store %[[VAL_2]] to %[[VAL_1]] : !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_i_32_byref %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { +! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_7]] : !fir.ref +! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_3]] : !fir.ref +! CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_9]], %[[VAL_10]] : i32 +! CHECK: fir.store %[[VAL_11]] to %[[VAL_7]] : !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_int_reduction + integer :: x + x = 0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = x + i + end do + !$omp end do + !$omp end parallel +end subroutine + + +! CHECK-LABEL: func.func @_QPsimple_real_reduction() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_real_reductionEi"} +! CHECK: %[[VAL_1:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFsimple_real_reductionEx"} +! CHECK: %[[VAL_2:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: fir.store %[[VAL_2]] to %[[VAL_1]] : !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_f_32_byref %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { +! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_7]] : !fir.ref +! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_3]] : !fir.ref +! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (i32) -> f32 +! CHECK: %[[VAL_12:.*]] = arith.addf %[[VAL_9]], %[[VAL_11]] fastmath : f32 +! CHECK: fir.store %[[VAL_12]] to %[[VAL_7]] : !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_real_reduction + real :: x + x = 0.0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = x + i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_int_reduction_switch_order() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_reduction_switch_orderEi"} +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_int_reduction_switch_orderEx"} +! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 +! CHECK: fir.store %[[VAL_2]] to %[[VAL_1]] : !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_i_32_byref %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { +! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_3]] : !fir.ref +! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_7]] : !fir.ref +! CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_9]], %[[VAL_10]] : i32 +! CHECK: fir.store %[[VAL_11]] to %[[VAL_7]] : !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_int_reduction_switch_order + integer :: x + x = 0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = i + x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_real_reduction_switch_order() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_real_reduction_switch_orderEi"} +! CHECK: %[[VAL_1:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFsimple_real_reduction_switch_orderEx"} +! CHECK: %[[VAL_2:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: fir.store %[[VAL_2]] to %[[VAL_1]] : !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_f_32_byref %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { +! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_3]] : !fir.ref +! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i32) -> f32 +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_7]] : !fir.ref +! CHECK: %[[VAL_12:.*]] = arith.addf %[[VAL_10]], %[[VAL_11]] fastmath : f32 +! CHECK: fir.store %[[VAL_12]] to %[[VAL_7]] : !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_real_reduction_switch_order + real :: x + x = 0.0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = i + x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_int_reductions_same_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_int_reductions_same_typeEi"} +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_int_reductions_same_typeEx"} +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFmultiple_int_reductions_same_typeEy"} +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFmultiple_int_reductions_same_typeEz"} +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i32 +! CHECK: fir.store %[[VAL_4]] to %[[VAL_1]] : !fir.ref +! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i32 +! CHECK: fir.store %[[VAL_5]] to %[[VAL_2]] : !fir.ref +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: fir.store %[[VAL_6]] to %[[VAL_3]] : !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_i_32_byref %[[VAL_1]] -> %[[VAL_11:.*]] : !fir.ref, @add_reduction_i_32_byref %[[VAL_2]] -> %[[VAL_12:.*]] : !fir.ref, @add_reduction_i_32_byref %[[VAL_3]] -> %[[VAL_13:.*]] : !fir.ref) for (%[[VAL_14:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { +! CHECK: fir.store %[[VAL_14]] to %[[VAL_7]] : !fir.ref +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_11]] : !fir.ref +! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_7]] : !fir.ref +! CHECK: %[[VAL_17:.*]] = arith.addi %[[VAL_15]], %[[VAL_16]] : i32 +! CHECK: fir.store %[[VAL_17]] to %[[VAL_11]] : !fir.ref +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_12]] : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_7]] : !fir.ref +! CHECK: %[[VAL_20:.*]] = arith.addi %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: fir.store %[[VAL_20]] to %[[VAL_12]] : !fir.ref +! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_13]] : !fir.ref +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_7]] : !fir.ref +! CHECK: %[[VAL_23:.*]] = arith.addi %[[VAL_21]], %[[VAL_22]] : i32 +! CHECK: fir.store %[[VAL_23]] to %[[VAL_13]] : !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine multiple_int_reductions_same_type + integer :: x,y,z + x = 0 + y = 0 + z = 0 + !$omp parallel + !$omp do reduction(+:x,y,z) + do i=1, 100 + x = x + i + y = y + i + z = z + i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_real_reductions_same_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_real_reductions_same_typeEi"} +! CHECK: %[[VAL_1:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFmultiple_real_reductions_same_typeEx"} +! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "y", uniq_name = "_QFmultiple_real_reductions_same_typeEy"} +! CHECK: %[[VAL_3:.*]] = fir.alloca f32 {bindc_name = "z", uniq_name = "_QFmultiple_real_reductions_same_typeEz"} +! CHECK: %[[VAL_4:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: fir.store %[[VAL_4]] to %[[VAL_1]] : !fir.ref +! CHECK: %[[VAL_5:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: fir.store %[[VAL_5]] to %[[VAL_2]] : !fir.ref +! CHECK: %[[VAL_6:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: fir.store %[[VAL_6]] to %[[VAL_3]] : !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_f_32_byref %[[VAL_1]] -> %[[VAL_11:.*]] : !fir.ref, @add_reduction_f_32_byref %[[VAL_2]] -> %[[VAL_12:.*]] : !fir.ref, @add_reduction_f_32_byref %[[VAL_3]] -> %[[VAL_13:.*]] : !fir.ref) for (%[[VAL_14:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { +! CHECK: fir.store %[[VAL_14]] to %[[VAL_7]] : !fir.ref +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_11]] : !fir.ref +! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_7]] : !fir.ref +! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (i32) -> f32 +! CHECK: %[[VAL_18:.*]] = arith.addf %[[VAL_15]], %[[VAL_17]] fastmath : f32 +! CHECK: fir.store %[[VAL_18]] to %[[VAL_11]] : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_12]] : !fir.ref +! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_7]] : !fir.ref +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i32) -> f32 +! CHECK: %[[VAL_22:.*]] = arith.addf %[[VAL_19]], %[[VAL_21]] fastmath : f32 +! CHECK: fir.store %[[VAL_22]] to %[[VAL_12]] : !fir.ref +! CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_13]] : !fir.ref +! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_7]] : !fir.ref +! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_24]] : (i32) -> f32 +! CHECK: %[[VAL_26:.*]] = arith.addf %[[VAL_23]], %[[VAL_25]] fastmath : f32 +! CHECK: fir.store %[[VAL_26]] to %[[VAL_13]] : !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine multiple_real_reductions_same_type + real :: x,y,z + x = 0.0 + y = 0.0 + z = 0.0 + !$omp parallel + !$omp do reduction(+:x,y,z) + do i=1, 100 + x = x + i + y = y + i + z = z + i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions_different_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductions_different_typeEi"} +! CHECK: %[[VAL_1:.*]] = fir.alloca f64 {bindc_name = "w", uniq_name = "_QFmultiple_reductions_different_typeEw"} +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_reductions_different_typeEx"} +! CHECK: %[[VAL_3:.*]] = fir.alloca i64 {bindc_name = "y", uniq_name = "_QFmultiple_reductions_different_typeEy"} +! CHECK: %[[VAL_4:.*]] = fir.alloca f32 {bindc_name = "z", uniq_name = "_QFmultiple_reductions_different_typeEz"} +! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i32 +! CHECK: fir.store %[[VAL_5]] to %[[VAL_2]] : !fir.ref +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i64 +! CHECK: fir.store %[[VAL_6]] to %[[VAL_3]] : !fir.ref +! CHECK: %[[VAL_7:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: fir.store %[[VAL_7]] to %[[VAL_4]] : !fir.ref +! CHECK: %[[VAL_8:.*]] = arith.constant 0.000000e+00 : f64 +! CHECK: fir.store %[[VAL_8]] to %[[VAL_1]] : !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_9:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_i_32_byref %[[VAL_2]] -> %[[VAL_13:.*]] : !fir.ref, @add_reduction_i_64_byref %[[VAL_3]] -> %[[VAL_14:.*]] : !fir.ref, @add_reduction_f_32_byref %[[VAL_4]] -> %[[VAL_15:.*]] : !fir.ref, @add_reduction_f_64_byref %[[VAL_1]] -> %[[VAL_16:.*]] : !fir.ref) for (%[[VAL_17:.*]]) : i32 = (%[[VAL_10]]) to (%[[VAL_11]]) inclusive step (%[[VAL_12]]) { +! CHECK: fir.store %[[VAL_17]] to %[[VAL_9]] : !fir.ref +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_13]] : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_9]] : !fir.ref +! CHECK: %[[VAL_20:.*]] = arith.addi %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: fir.store %[[VAL_20]] to %[[VAL_13]] : !fir.ref +! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_14]] : !fir.ref +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_9]] : !fir.ref +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_22]] : (i32) -> i64 +! CHECK: %[[VAL_24:.*]] = arith.addi %[[VAL_21]], %[[VAL_23]] : i64 +! CHECK: fir.store %[[VAL_24]] to %[[VAL_14]] : !fir.ref +! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_15]] : !fir.ref +! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_9]] : !fir.ref +! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_26]] : (i32) -> f32 +! CHECK: %[[VAL_28:.*]] = arith.addf %[[VAL_25]], %[[VAL_27]] fastmath : f32 +! CHECK: fir.store %[[VAL_28]] to %[[VAL_15]] : !fir.ref +! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_16]] : !fir.ref +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_9]] : !fir.ref +! CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_30]] : (i32) -> f64 +! CHECK: %[[VAL_32:.*]] = arith.addf %[[VAL_29]], %[[VAL_31]] fastmath : f64 +! CHECK: fir.store %[[VAL_32]] to %[[VAL_16]] : !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + + +subroutine multiple_reductions_different_type + integer :: x + integer(kind=8) :: y + real :: z + real(kind=8) :: w + x = 0 + y = 0 + z = 0.0 + w = 0.0 + !$omp parallel + !$omp do reduction(+:x,y,z,w) + do i=1, 100 + x = x + i + y = y + i + z = z + i + w = w + i + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-iand-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-iand-byref.f90 new file mode 100644 index 000000000000..00dfad69248b --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-iand-byref.f90 @@ -0,0 +1,46 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +!CHECK-LABEL: omp.reduction.declare @iand_i_32_byref : !fir.ref +!CHECK-SAME: init { +!CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +!CHECK: %[[C0_1:.*]] = arith.constant -1 : i32 +!CHECK: %[[REF:.*]] = fir.alloca i32 +!CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +!CHECK: omp.yield(%[[REF]] : !fir.ref) + +!CHECK-LABEL: } combiner { +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +!CHECK: %[[RES:.*]] = arith.andi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +!CHECK: omp.yield(%[[ARG0]] : !fir.ref) +!CHECK: } + + +!CHECK-LABEL: @_QPreduction_iand +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iandEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop byref reduction(@iand_i_32_byref %[[X_REF]] -> %[[PRV:.+]] : !fir.ref) for +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref +!CHECK: %[[RES:.+]] = arith.andi %[[LPRV]], %[[Y_I]] : i32 +!CHECK: fir.store %[[RES]] to %[[PRV]] : !fir.ref +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_iand(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(iand:x) + do i=1, 100 + x = iand(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ieor-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ieor-byref.f90 new file mode 100644 index 000000000000..fb35c405ca1d --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ieor-byref.f90 @@ -0,0 +1,45 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -mmlir --force-byref-reduction -fopenmp %s -o - | FileCheck %s + +! CHECK-LABEL: omp.reduction.declare @ieor_i_32_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.xori %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +!CHECK-LABEL: @_QPreduction_ieor +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_ieorEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop byref reduction(@ieor_i_32_byref %[[X_REF]] -> %[[PRV:.+]] : !fir.ref) for +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref +!CHECK: %[[RES:.+]] = arith.xori %[[LPRV]], %[[Y_I]] : i32 +!CHECK: fir.store %[[RES]] to %[[PRV]] : !fir.ref +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_ieor(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(ieor:x) + do i=1, 100 + x = ieor(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ior-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ior-byref.f90 new file mode 100644 index 000000000000..0365eff3fd81 --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ior-byref.f90 @@ -0,0 +1,45 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! CHECK-LABEL: omp.reduction.declare @ior_i_32_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.ori %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +!CHECK-LABEL: @_QPreduction_ior +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iorEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop byref reduction(@ior_i_32_byref %[[X_REF]] -> %[[PRV:.+]] : !fir.ref) for +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref +!CHECK: %[[RES:.+]] = arith.ori %[[LPRV]], %[[Y_I]] : i32 +!CHECK: fir.store %[[RES]] to %[[PRV]] : !fir.ref +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_ior(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(ior:x) + do i=1, 100 + x = ior(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-eqv-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-eqv-byref.f90 new file mode 100644 index 000000000000..84219b34f964 --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-eqv-byref.f90 @@ -0,0 +1,187 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.reduction.declare @eqv_reduction : !fir.ref> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>): +! CHECK: %[[VAL_1:.*]] = arith.constant true +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> +! CHECK: %[[REF:.*]] = fir.alloca !fir.logical<4> +! CHECK: fir.store %[[VAL_2]] to %[[REF]] : !fir.ref> +! CHECK: omp.yield(%[[REF]] : !fir.ref>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref> +! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[RES:.*]] = arith.cmpi eq, %[[VAL_2]], %[[VAL_3]] : i1 +! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_reduction( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reductionEi"} +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reductionEx"} +! CHECK: %[[VAL_3:.*]] = arith.constant true +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_4]] to %[[VAL_2]] : !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_7:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_2]] -> %[[VAL_9:.*]] : !fir.ref>) for (%[[VAL_10:.*]]) : i32 = (%[[VAL_6]]) to (%[[VAL_7]]) inclusive step (%[[VAL_8]]) { +! CHECK: fir.store %[[VAL_10]] to %[[VAL_5]] : !fir.ref +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_9]] : !fir.ref> +! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_5]] : !fir.ref +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i32) -> i64 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_13]], %[[VAL_14]] : i64 +! CHECK: %[[VAL_16:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_15]] : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_16]] : !fir.ref> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_17]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_20:.*]] = arith.cmpi eq, %[[VAL_18]], %[[VAL_19]] : i1 +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_21]] to %[[VAL_9]] : !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.eqv.:x) + do i=1, 100 + x = x .eqv. y(i) + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_reduction_switch_order( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reduction_switch_orderEi"} +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reduction_switch_orderEx"} +! CHECK: %[[VAL_3:.*]] = arith.constant true +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_4]] to %[[VAL_2]] : !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_7:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_2]] -> %[[VAL_9:.*]] : !fir.ref>) for (%[[VAL_10:.*]]) : i32 = (%[[VAL_6]]) to (%[[VAL_7]]) inclusive step (%[[VAL_8]]) { +! CHECK: fir.store %[[VAL_10]] to %[[VAL_5]] : !fir.ref +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_5]] : !fir.ref +! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (i32) -> i64 +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_14:.*]] = arith.subi %[[VAL_12]], %[[VAL_13]] : i64 +! CHECK: %[[VAL_15:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_14]] : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_15]] : !fir.ref> +! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_9]] : !fir.ref> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_16]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_17]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_20:.*]] = arith.cmpi eq, %[[VAL_18]], %[[VAL_19]] : i1 +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_21]] to %[[VAL_9]] : !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction_switch_order(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.eqv.:x) + do i=1, 100 + x = y(i) .eqv. x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "w"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductionsEi"} +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} +! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.logical<4> {bindc_name = "z", uniq_name = "_QFmultiple_reductionsEz"} +! CHECK: %[[VAL_5:.*]] = arith.constant true +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_6]] to %[[VAL_2]] : !fir.ref> +! CHECK: %[[VAL_7:.*]] = arith.constant true +! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref> +! CHECK: %[[VAL_9:.*]] = arith.constant true +! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_10]] to %[[VAL_4]] : !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_11:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_2]] -> %[[VAL_15:.*]] : !fir.ref>, @eqv_reduction %[[VAL_3]] -> %[[VAL_16:.*]] : !fir.ref>, @eqv_reduction %[[VAL_4]] -> %[[VAL_17:.*]] : !fir.ref>) for (%[[VAL_18:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_18]] to %[[VAL_11]] : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_15]] : !fir.ref> +! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_11]] : !fir.ref +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i32) -> i64 +! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_23:.*]] = arith.subi %[[VAL_21]], %[[VAL_22]] : i64 +! CHECK: %[[VAL_24:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_23]] : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_24]] : !fir.ref> +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_19]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_25]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_28:.*]] = arith.cmpi eq, %[[VAL_26]], %[[VAL_27]] : i1 +! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_28]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_29]] to %[[VAL_15]] : !fir.ref> +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_16]] : !fir.ref> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_11]] : !fir.ref +! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64 +! CHECK: %[[VAL_33:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_34:.*]] = arith.subi %[[VAL_32]], %[[VAL_33]] : i64 +! CHECK: %[[VAL_35:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_34]] : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_36:.*]] = fir.load %[[VAL_35]] : !fir.ref> +! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_36]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_39:.*]] = arith.cmpi eq, %[[VAL_37]], %[[VAL_38]] : i1 +! CHECK: %[[VAL_40:.*]] = fir.convert %[[VAL_39]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_40]] to %[[VAL_16]] : !fir.ref> +! CHECK: %[[VAL_41:.*]] = fir.load %[[VAL_17]] : !fir.ref> +! CHECK: %[[VAL_42:.*]] = fir.load %[[VAL_11]] : !fir.ref +! CHECK: %[[VAL_43:.*]] = fir.convert %[[VAL_42]] : (i32) -> i64 +! CHECK: %[[VAL_44:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_45:.*]] = arith.subi %[[VAL_43]], %[[VAL_44]] : i64 +! CHECK: %[[VAL_46:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_45]] : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_47:.*]] = fir.load %[[VAL_46]] : !fir.ref> +! CHECK: %[[VAL_48:.*]] = fir.convert %[[VAL_41]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_49:.*]] = fir.convert %[[VAL_47]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_50:.*]] = arith.cmpi eq, %[[VAL_48]], %[[VAL_49]] : i1 +! CHECK: %[[VAL_51:.*]] = fir.convert %[[VAL_50]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_51]] to %[[VAL_17]] : !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine multiple_reductions(w) + logical :: x,y,z,w(100) + x = .true. + y = .true. + z = .true. + !$omp parallel + !$omp do reduction(.eqv.:x,y,z) + do i=1, 100 + x = x .eqv. w(i) + y = y .eqv. w(i) + z = z .eqv. w(i) + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-neqv-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-neqv-byref.f90 new file mode 100644 index 000000000000..ec4d8500850b --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-neqv-byref.f90 @@ -0,0 +1,189 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + + +! CHECK-LABEL: omp.reduction.declare @neqv_reduction : !fir.ref> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>): +! CHECK: %[[VAL_1:.*]] = arith.constant false +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> +! CHECK: %[[REF:.*]] = fir.alloca !fir.logical<4> +! CHECK: fir.store %[[VAL_2]] to %[[REF]] : !fir.ref> +! CHECK: omp.yield(%[[REF]] : !fir.ref>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref> +! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[RES:.*]] = arith.cmpi ne, %[[VAL_2]], %[[VAL_3]] : i1 +! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_reduction( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reductionEi"} +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reductionEx"} +! CHECK: %[[VAL_3:.*]] = arith.constant true +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_4]] to %[[VAL_2]] : !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_7:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_2]] -> %[[VAL_9:.*]] : !fir.ref>) for (%[[VAL_10:.*]]) : i32 = (%[[VAL_6]]) to (%[[VAL_7]]) inclusive step (%[[VAL_8]]) { +! CHECK: fir.store %[[VAL_10]] to %[[VAL_5]] : !fir.ref +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_9]] : !fir.ref> +! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_5]] : !fir.ref +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i32) -> i64 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_13]], %[[VAL_14]] : i64 +! CHECK: %[[VAL_16:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_15]] : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_16]] : !fir.ref> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_17]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_20:.*]] = arith.cmpi ne, %[[VAL_18]], %[[VAL_19]] : i1 +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_21]] to %[[VAL_9]] : !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.neqv.:x) + do i=1, 100 + x = x .neqv. y(i) + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_reduction_switch_order( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reduction_switch_orderEi"} +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reduction_switch_orderEx"} +! CHECK: %[[VAL_3:.*]] = arith.constant true +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_4]] to %[[VAL_2]] : !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_7:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_2]] -> %[[VAL_9:.*]] : !fir.ref>) for (%[[VAL_10:.*]]) : i32 = (%[[VAL_6]]) to (%[[VAL_7]]) inclusive step (%[[VAL_8]]) { +! CHECK: fir.store %[[VAL_10]] to %[[VAL_5]] : !fir.ref +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_5]] : !fir.ref +! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (i32) -> i64 +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_14:.*]] = arith.subi %[[VAL_12]], %[[VAL_13]] : i64 +! CHECK: %[[VAL_15:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_14]] : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_15]] : !fir.ref> +! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_9]] : !fir.ref> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_16]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_17]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_20:.*]] = arith.cmpi ne, %[[VAL_18]], %[[VAL_19]] : i1 +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_21]] to %[[VAL_9]] : !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction_switch_order(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.neqv.:x) + do i=1, 100 + x = y(i) .neqv. x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "w"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductionsEi"} +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} +! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.logical<4> {bindc_name = "z", uniq_name = "_QFmultiple_reductionsEz"} +! CHECK: %[[VAL_5:.*]] = arith.constant true +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_6]] to %[[VAL_2]] : !fir.ref> +! CHECK: %[[VAL_7:.*]] = arith.constant true +! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref> +! CHECK: %[[VAL_9:.*]] = arith.constant true +! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_10]] to %[[VAL_4]] : !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_11:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_2]] -> %[[VAL_15:.*]] : !fir.ref>, @neqv_reduction %[[VAL_3]] -> %[[VAL_16:.*]] : !fir.ref>, @neqv_reduction %[[VAL_4]] -> %[[VAL_17:.*]] : !fir.ref>) for (%[[VAL_18:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_18]] to %[[VAL_11]] : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_15]] : !fir.ref> +! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_11]] : !fir.ref +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i32) -> i64 +! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_23:.*]] = arith.subi %[[VAL_21]], %[[VAL_22]] : i64 +! CHECK: %[[VAL_24:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_23]] : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_24]] : !fir.ref> +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_19]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_25]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_28:.*]] = arith.cmpi ne, %[[VAL_26]], %[[VAL_27]] : i1 +! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_28]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_29]] to %[[VAL_15]] : !fir.ref> +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_16]] : !fir.ref> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_11]] : !fir.ref +! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64 +! CHECK: %[[VAL_33:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_34:.*]] = arith.subi %[[VAL_32]], %[[VAL_33]] : i64 +! CHECK: %[[VAL_35:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_34]] : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_36:.*]] = fir.load %[[VAL_35]] : !fir.ref> +! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_36]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_39:.*]] = arith.cmpi ne, %[[VAL_37]], %[[VAL_38]] : i1 +! CHECK: %[[VAL_40:.*]] = fir.convert %[[VAL_39]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_40]] to %[[VAL_16]] : !fir.ref> +! CHECK: %[[VAL_41:.*]] = fir.load %[[VAL_17]] : !fir.ref> +! CHECK: %[[VAL_42:.*]] = fir.load %[[VAL_11]] : !fir.ref +! CHECK: %[[VAL_43:.*]] = fir.convert %[[VAL_42]] : (i32) -> i64 +! CHECK: %[[VAL_44:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_45:.*]] = arith.subi %[[VAL_43]], %[[VAL_44]] : i64 +! CHECK: %[[VAL_46:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_45]] : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_47:.*]] = fir.load %[[VAL_46]] : !fir.ref> +! CHECK: %[[VAL_48:.*]] = fir.convert %[[VAL_41]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_49:.*]] = fir.convert %[[VAL_47]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_50:.*]] = arith.cmpi ne, %[[VAL_48]], %[[VAL_49]] : i1 +! CHECK: %[[VAL_51:.*]] = fir.convert %[[VAL_50]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_51]] to %[[VAL_17]] : !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + + +subroutine multiple_reductions(w) + logical :: x,y,z,w(100) + x = .true. + y = .true. + z = .true. + !$omp parallel + !$omp do reduction(.neqv.:x,y,z) + do i=1, 100 + x = x .neqv. w(i) + y = y .neqv. w(i) + z = z .neqv. w(i) + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 new file mode 100644 index 000000000000..ddda24a17a83 --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 @@ -0,0 +1,90 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +!CHECK: omp.reduction.declare @max_f_32_byref : !fir.ref +!CHECK-SAME: init { +!CHECK: %[[MINIMUM_VAL:.*]] = arith.constant -3.40282347E+38 : f32 +!CHECK: %[[REF:.*]] = fir.alloca f32 +!CHECK: fir.store %[[MINIMUM_VAL]] to %[[REF]] : !fir.ref +!CHECK: omp.yield(%[[REF]] : !fir.ref) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +!CHECK: %[[RES:.*]] = arith.maximumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +!CHECK: omp.yield(%[[ARG0]] : !fir.ref) + +!CHECK-LABEL: omp.reduction.declare @max_i_32_byref : !fir.ref +!CHECK-SAME: init { +!CHECK: %[[MINIMUM_VAL:.*]] = arith.constant -2147483648 : i32 +!CHECK: fir.store %[[MINIMUM_VAL]] to %[[REF]] : !fir.ref +!CHECK: omp.yield(%[[REF]] : !fir.ref) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +!CHECK: %[[RES:.*]] = arith.maxsi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +!CHECK: omp.yield(%[[ARG0]] : !fir.ref) + +!CHECK-LABEL: @_QPreduction_max_int +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_max_intEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop byref reduction(@max_i_32_byref %[[X_REF]] -> %[[PRV:.+]] : !fir.ref) for +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref +!CHECK: %[[RES:.+]] = arith.cmpi sgt, %[[LPRV]], %[[Y_I]] : i32 +!CHECK: %[[SEL:.+]] = arith.select %[[RES]], %[[LPRV]], %[[Y_I]] +!CHECK: fir.store %[[SEL]] to %[[PRV]] : !fir.ref +!CHECK: omp.terminator + +!CHECK-LABEL: @_QPreduction_max_real +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box> +!CHECK: %[[X_REF:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFreduction_max_realEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop byref reduction(@max_f_32_byref %[[X_REF]] -> %[[PRV:.+]] : !fir.ref) for +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref +!CHECK: %[[RES:.+]] = arith.cmpf ogt, %[[Y_I]], %[[LPRV]] {{.*}} : f32 +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_max_int(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(max:x) + do i=1, 100 + x = max(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine + +subroutine reduction_max_real(y) + real :: x, y(:) + x = 0.0 + !$omp parallel + !$omp do reduction(max:x) + do i=1, 100 + x = max(y(i), x) + end do + !$omp end do + !$omp end parallel + print *, x + + !$omp parallel + !$omp do reduction(max:x) + do i=1, 100 + !CHECK-NOT: omp.reduction + if (y(i) .gt. x) x = y(i) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 new file mode 100644 index 000000000000..d767c54cdbc5 --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 @@ -0,0 +1,91 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -mmlir --force-byref-reduction -fopenmp -o - %s 2>&1 | FileCheck %s + +!CHECK: omp.reduction.declare @min_f_32_byref : !fir.ref +!CHECK-SAME: init { +!CHECK: %[[MAXIMUM_VAL:.*]] = arith.constant 3.40282347E+38 : f32 +!CHECK: %[[REF:.*]] = fir.alloca f32 +!CHECK: fir.store %[[MAXIMUM_VAL]] to %[[REF]] : !fir.ref +!CHECK: omp.yield(%[[REF]] : !fir.ref) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +!CHECK: %[[RES:.*]] = arith.minimumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +!CHECK: omp.yield(%[[ARG0]] : !fir.ref) + +!CHECK-LABEL: omp.reduction.declare @min_i_32_byref : !fir.ref +!CHECK-SAME: init { +!CHECK: %[[MAXIMUM_VAL:.*]] = arith.constant 2147483647 : i32 +!CHECK: fir.store %[[MAXIMUM_VAL]] to %[[REF]] : !fir.ref +!CHECK: omp.yield(%[[REF]] : !fir.ref) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +!CHECK: %[[RES:.*]] = arith.minsi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +!CHECK: omp.yield(%[[ARG0]] : !fir.ref) + +!CHECK-LABEL: @_QPreduction_min_int +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_min_intEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop byref reduction(@min_i_32_byref %[[X_REF]] -> %[[PRV:.+]] : !fir.ref) for +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref +!CHECK: %[[RES:.+]] = arith.cmpi slt, %[[LPRV]], %[[Y_I]] : i32 +!CHECK: %[[SEL:.+]] = arith.select %[[RES]], %[[LPRV]], %[[Y_I]] +!CHECK: fir.store %[[SEL]] to %[[PRV]] : !fir.ref +!CHECK: omp.yield +!CHECK: omp.terminator + +!CHECK-LABEL: @_QPreduction_min_real +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box> +!CHECK: %[[X_REF:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFreduction_min_realEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop byref reduction(@min_f_32_byref %[[X_REF]] -> %[[PRV:.+]] : !fir.ref) for +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref +!CHECK: %[[RES:.+]] = arith.cmpf ogt, %[[Y_I]], %[[LPRV]] {{.*}} : f32 +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_min_int(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(min:x) + do i=1, 100 + x = min(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine + +subroutine reduction_min_real(y) + real :: x, y(:) + x = 0.0 + !$omp parallel + !$omp do reduction(min:x) + do i=1, 100 + x = min(y(i), x) + end do + !$omp end do + !$omp end parallel + print *, x + + !$omp parallel + !$omp do reduction(min:x) + do i=1, 100 + !CHECK-NOT: omp.reduction + if (y(i) .gt. x) x = y(i) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/default-clause-byref.f90 b/flang/test/Lower/OpenMP/default-clause-byref.f90 new file mode 100644 index 000000000000..5d9538e53069 --- /dev/null +++ b/flang/test/Lower/OpenMP/default-clause-byref.f90 @@ -0,0 +1,385 @@ +! This test checks lowering of OpenMP parallel directive +! with `DEFAULT` clause present. + +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s +! RUN: bbc -fopenmp -emit-hlfir --force-byref-reduction %s -o - | FileCheck %s + + +!CHECK: func @_QQmain() attributes {fir.bindc_name = "default_clause_lowering"} { +!CHECK: %[[W:.*]] = fir.alloca i32 {bindc_name = "w", uniq_name = "_QFEw"} +!CHECK: %[[W_DECL:.*]]:2 = hlfir.declare %[[W]] {uniq_name = "_QFEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"} +!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[Y:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFEy"} +!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] {uniq_name = "_QFEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFEz"} +!CHECK: %[[Z_DECL:.*]]:2 = hlfir.declare %[[Z]] {uniq_name = "_QFEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[CONST:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[CONST]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[PRIVATE_W:.*]] = fir.alloca i32 {bindc_name = "w", pinned, uniq_name = "_QFEw"} +!CHECK: %[[PRIVATE_W_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_W]] {uniq_name = "_QFEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[CONST:.*]] = arith.constant 2 : i32 +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref +!CHECK: %[[RESULT:.*]] = arith.muli %[[CONST]], %[[TEMP]] : i32 +!CHECK: hlfir.assign %[[RESULT]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_W_DECL]]#0 : !fir.ref +!CHECK: %[[CONST:.*]] = arith.constant 45 : i32 +!CHECK: %[[RESULT:.*]] = arith.addi %[[TEMP]], %[[CONST]] : i32 +!CHECK: hlfir.assign %[[RESULT]] to %[[Z_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } + +program default_clause_lowering + integer :: x, y, z, w + + !$omp parallel default(private) firstprivate(x) shared(z) + x = y * 2 + z = w + 45 + !$omp end parallel + +!CHECK: omp.parallel { +!CHECK: %[[TEMP:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[X_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } + + !$omp parallel default(shared) + x = y + !$omp end parallel + +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } + + !$omp parallel default(none) private(x, y) + x = y + !$omp end parallel + +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_Y_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } + + !$omp parallel default(firstprivate) firstprivate(y) + x = y + !$omp end parallel + +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_Y_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[PRIVATE_W:.*]] = fir.alloca i32 {bindc_name = "w", pinned, uniq_name = "_QFEw"} +!CHECK: %[[PRIVATE_W_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_W]] {uniq_name = "_QFEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[W_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_W_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[CONST:.*]] = arith.constant 2 : i32 +!CHECK: %[[RESULT:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref +!CHECK: %[[TEMP:.*]] = arith.muli %[[CONST]], %[[RESULT]] : i32 +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_W_DECL]]#0 : !fir.ref +!CHECK: %[[CONST:.*]] = arith.constant 45 : i32 +!CHECK: %[[RESULT:.*]] = arith.addi %[[TEMP]], %[[CONST]] : i32 +!CHECK: hlfir.assign %[[RESULT]] to %[[Z_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } + + !$omp parallel default(firstprivate) private(x) shared(z) + x = y * 2 + z = w + 45 + !$omp end parallel + +!CHECK: omp.parallel { +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_W:.*]] = fir.alloca i32 {bindc_name = "w", pinned, uniq_name = "_QFEw"} +!CHECK: %[[PRIVATE_W_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_W]] {uniq_name = "_QFEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[W_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_W_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_W_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.terminator +!CHECK: } + !$omp parallel + !$omp parallel default(private) + x = y + !$omp end parallel + + !$omp parallel default(firstprivate) + w = x + !$omp end parallel + !$omp end parallel + +end program default_clause_lowering + +subroutine nested_default_clause_tests + integer :: x, y, z, w, k, a +!CHECK: %[[K:.*]] = fir.alloca i32 {bindc_name = "k", uniq_name = "_QFnested_default_clause_testsEk"} +!CHECK: %[[K_DECL:.*]]:2 = hlfir.declare %[[K]] {uniq_name = "_QFnested_default_clause_testsEk"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[W:.*]] = fir.alloca i32 {bindc_name = "w", uniq_name = "_QFnested_default_clause_testsEw"} +!CHECK: %[[W_DECL:.*]]:2 = hlfir.declare %[[W]] {uniq_name = "_QFnested_default_clause_testsEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[Y:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFnested_default_clause_testsEz"} +!CHECK: %[[Z_DECL:.*]]:2 = hlfir.declare %[[Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[PRIVATE_Z:.*]] = fir.alloca i32 {bindc_name = "z", pinned, uniq_name = "_QFnested_default_clause_testsEz"} +!CHECK: %[[PRIVATE_Z_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[PRIVATE_K:.*]] = fir.alloca i32 {bindc_name = "k", pinned, uniq_name = "_QFnested_default_clause_testsEk"} +!CHECK: %[[PRIVATE_K_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_K]] {uniq_name = "_QFnested_default_clause_testsEk"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: omp.parallel { +!CHECK: %[[INNER_PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[INNER_PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[INNER_PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[INNER_PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[CONST:.*]] = arith.constant 20 : i32 +!CHECK: hlfir.assign %[[CONST]] to %[[INNER_PRIVATE_Y_DECL]]#0 : i32, !fir.ref +!CHECK: %[[CONST:.*]] = arith.constant 10 : i32 +!CHECK: hlfir.assign %[[CONST]] to %[[INNER_PRIVATE_X_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.parallel { +!CHECK: %[[INNER_PRIVATE_W:.*]] = fir.alloca i32 {bindc_name = "w", pinned, uniq_name = "_QFnested_default_clause_testsEw"} +!CHECK: %[[INNER_PRIVATE_W_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_W]] {uniq_name = "_QFnested_default_clause_testsEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[INNER_PRIVATE_Z:.*]] = fir.alloca i32 {bindc_name = "z", pinned, uniq_name = "_QFnested_default_clause_testsEz"} +!CHECK: %[[INNER_PRIVATE_Z_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Z_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[INNER_PRIVATE_Z_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[INNER_PRIVATE_K:.*]] = fir.alloca i32 {bindc_name = "k", pinned, uniq_name = "_QFnested_default_clause_testsEk"} +!CHECK: %[[INNER_PRIVATE_K_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_K]] {uniq_name = "_QFnested_default_clause_testsEk"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_K_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[INNER_PRIVATE_K_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[CONST:.*]] = arith.constant 30 : i32 +!CHECK: hlfir.assign %[[CONST]] to %[[PRIVATE_Y_DECL]]#0 : i32, !fir.ref +!CHECK: %[[CONST:.*]] = arith.constant 40 : i32 +!CHECK: hlfir.assign %[[CONST]] to %[[INNER_PRIVATE_W_DECL]]#0 : i32, !fir.ref +!CHECK: %[[CONST:.*]] = arith.constant 50 : i32 +!CHECK: hlfir.assign %[[CONST]] to %[[INNER_PRIVATE_Z_DECL]]#0 : i32, !fir.ref +!CHECK: %[[CONST:.*]] = arith.constant 40 : i32 +!CHECK: hlfir.assign %[[CONST]] to %[[INNER_PRIVATE_K_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.terminator +!CHECK: } + !$omp parallel firstprivate(x) private(y) shared(w) default(private) + !$omp parallel default(private) + y = 20 + x = 10 + !$omp end parallel + + !$omp parallel default(firstprivate) shared(y) private(w) + y = 30 + w = 40 + z = 50 + k = 40 + !$omp end parallel + !$omp end parallel + + +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[PRIVATE_Z:.*]] = fir.alloca i32 {bindc_name = "z", pinned, uniq_name = "_QFnested_default_clause_testsEz"} +!CHECK: %[[PRIVATE_Z_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[PRIVATE_W:.*]] = fir.alloca i32 {bindc_name = "w", pinned, uniq_name = "_QFnested_default_clause_testsEw"} +!CHECK: %[[PRIVATE_W_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_W]] {uniq_name = "_QFnested_default_clause_testsEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_INNER_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[PRIVATE_INNER_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_INNER_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_INNER_X_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[INNER_PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[INNER_PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[INNER_PRIVATE_Y_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[TEMP:.*]] = fir.load %[[INNER_PRIVATE_Y_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_INNER_X_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_INNER_W:.*]] = fir.alloca i32 {bindc_name = "w", pinned, uniq_name = "_QFnested_default_clause_testsEw"} +!CHECK: %[[PRIVATE_INNER_W_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_INNER_W]] {uniq_name = "_QFnested_default_clause_testsEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[PRIVATE_INNER_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[PRIVATE_INNER_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_INNER_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP_1:.*]] = fir.load %[[PRIVATE_INNER_X_DECL]]#0 : !fir.ref +!CHECK: %[[TEMP_2:.*]] = fir.load %[[PRIVATE_Z_DECL]]#0 : !fir.ref +!CHECK: %[[RESULT:.*]] = arith.addi %{{.*}}, %{{.*}} : i32 +!CHECK: hlfir.assign %[[RESULT]] to %[[PRIVATE_INNER_W_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } + !$omp parallel default(private) + !$omp parallel default(firstprivate) + x = y + !$omp end parallel + + !$omp parallel default(private) shared(z) + w = x + z + !$omp end parallel + !$omp end parallel + +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[PRIVATE_W:.*]] = fir.alloca i32 {bindc_name = "w", pinned, uniq_name = "_QFnested_default_clause_testsEw"} +!CHECK: %[[PRIVATE_W_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_W]] {uniq_name = "_QFnested_default_clause_testsEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[PRIVATE_Z:.*]] = fir.alloca i32 {bindc_name = "z", pinned, uniq_name = "_QFnested_default_clause_testsEz"} +!CHECK: %[[PRIVATE_Z_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: omp.parallel { +!CHECK: %[[INNER_PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[INNER_PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[INNER_PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[INNER_PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[INNER_PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[INNER_PRIVATE_Y_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[TEMP:.*]] = fir.load %[[INNER_PRIVATE_Y_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[INNER_PRIVATE_X_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.parallel { +!CHECK: %[[TEMP_1:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref +!CHECK: %[[TEMP_2:.*]] = fir.load %[[PRIVATE_Z_DECL]]#0 : !fir.ref +!CHECK: %[[TEMP_3:.*]] = arith.addi %[[TEMP_1]], %[[TEMP_2]] : i32 +!CHECK: hlfir.assign %[[TEMP_3]] to %[[PRIVATE_W_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: } + !$omp parallel default(private) + !$omp parallel default(firstprivate) + x = y + !$omp end parallel + + !$omp parallel default(shared) + w = x + z + !$omp end parallel + !$omp end parallel + +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[TEMP:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_Y_DECL]]#0 temporary_lhs : i32, !fir.ref +!CHECK: omp.single { +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +!CHECK: } + !$omp parallel default(firstprivate) + !$omp single + x = y + !$omp end single + !$omp end parallel +end subroutine + +!CHECK: func.func @_QPskipped_default_clause_checks() { +!CHECK: %[[TYPE_ADDR:.*]] = fir.address_of(@_QFskipped_default_clause_checksE.n.i1) : !fir.ref> +!CHECK: %[[VAL_CONST_2:.*]] = arith.constant 2 : index +!CHECK: %[[VAL_I1_DECLARE:.*]]:2 = hlfir.declare %[[TYPE_ADDR]] typeparams %[[VAL_CONST_2]] {{.*}} +!CHECK: %[[TYPE_ADDR_IT:.*]] = fir.address_of(@_QFskipped_default_clause_checksE.n.it) : !fir.ref> +!CHECK: %[[VAL_CONST_2_0:.*]] = arith.constant 2 : index +!CHECK: %[[VAL_IT_DECLARE:.*]]:2 = hlfir.declare %[[TYPE_ADDR_IT]] typeparams %[[VAL_CONST_2_0]] {{.*}} +!CHECK: %[[VAL_I_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFskipped_default_clause_checksEi"} +!CHECK: %[[VAL_I_DECLARE:.*]]:2 = hlfir.declare %[[VAL_I_ALLOCA]] {{.*}} +!CHECK: %[[VAL_III_ALLOCA:.*]] = fir.alloca !fir.type<_QFskipped_default_clause_checksTit{i1:i32}> {bindc_name = "iii", uniq_name = "_QFskipped_default_clause_checksEiii"} +!CHECK: %[[VAL_III_DECLARE:.*]]:2 = hlfir.declare %[[VAL_III_ALLOCA]] {{.*}} +!CHECK: %[[VAL_X_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFskipped_default_clause_checksEx"} +!CHECK: %[[VAL_X_DECLARE:.*]]:2 = hlfir.declare %[[VAL_X_ALLOCA]] {{.*}} +!CHECK: %[[VAL_Y_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFskipped_default_clause_checksEy"} +!CHECK: %[[VAL_Y_DECLARE:.*]]:2 = hlfir.declare %[[VAL_Y_ALLOCA]] {{.*}} +!CHECK: %[[VAL_Z_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFskipped_default_clause_checksEz"} +!CHECK: %[[VAL_Z_DECLARE:.*]]:2 = hlfir.declare %[[VAL_Z_ALLOCA]] {{.*}} +subroutine skipped_default_clause_checks() + integer :: x,y,z + type it + integer::i1 + end type + type(it)::iii + +!CHECK: omp.parallel { +!CHECK: omp.wsloop byref reduction(@min_i_32_byref %[[VAL_Z_DECLARE]]#0 -> %[[PRV:.+]] : !fir.ref) for (%[[ARG:.*]]) {{.*}} { +!CHECK: omp.yield +!CHECK: } +!CHECK: omp.terminator +!CHECK: } + !$omp parallel do default(private) REDUCTION(MIN:z) + do i = 1, 10 + x = x + MIN(y,x) + enddo + !$omp end parallel do + +!CHECK: omp.parallel { +!CHECK: omp.terminator +!CHECK: } + namelist /nam/i + !$omp parallel default(private) + write(1,nam ) + !$omp endparallel + +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_III_ALLOCA:.*]] = fir.alloca !fir.type<_QFskipped_default_clause_checksTit{i1:i32}> {{.*}} +!CHECK: %[[PRIVATE_III_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_III_ALLOCA]] {{.*}} +!CHECK: %[[PRIVATE_ADDR:.*]] = fir.address_of(@_QQro._QFskipped_default_clause_checksTit.0) : !fir.ref> +!CHECK: %[[PRIVATE_PARAM:.*]]:2 = hlfir.declare %[[PRIVATE_ADDR]] {{.*}} +!CHECK: hlfir.assign %[[PRIVATE_PARAM]]#0 to %[[PRIVATE_III_DECLARE]]#0 {{.*}} +!CHECK: omp.terminator +!CHECK: } + !$omp parallel default(private) + iii=it(11) + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 b/flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 new file mode 100644 index 000000000000..067a71340b8d --- /dev/null +++ b/flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 @@ -0,0 +1,30 @@ +! Test that reductions and delayed privatization work properly togehter. Since +! both types of clauses add block arguments to the OpenMP region, we make sure +! that the block arguments are added in the proper order (reductions first and +! then delayed privatization. + +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction --openmp-enable-delayed-privatization -o - %s 2>&1 | FileCheck %s + +subroutine red_and_delayed_private + integer :: red + integer :: prv + + red = 0 + prv = 10 + + !$omp parallel reduction(+:red) private(prv) + red = red + 1 + prv = 20 + !$omp end parallel +end subroutine + +! CHECK-LABEL: omp.private {type = private} +! CHECK-SAME: @[[PRIVATIZER_SYM:.*]] : !fir.ref alloc { + +! CHECK-LABEL: omp.reduction.declare +! CHECK-SAME: @[[REDUCTION_SYM:.*]] : !fir.ref init + +! CHECK-LABEL: _QPred_and_delayed_private +! CHECK: omp.parallel +! CHECK-SAME: reduction(@[[REDUCTION_SYM]] %{{.*}} -> %arg0 : !fir.ref) +! CHECK-SAME: private(@[[PRIVATIZER_SYM]] %{{.*}} -> %arg1 : !fir.ref) { diff --git a/flang/test/Lower/OpenMP/parallel-reduction-add-byref.f90 b/flang/test/Lower/OpenMP/parallel-reduction-add-byref.f90 new file mode 100644 index 000000000000..c4a4695b8d9f --- /dev/null +++ b/flang/test/Lower/OpenMP/parallel-reduction-add-byref.f90 @@ -0,0 +1,125 @@ +! RUN: bbc -emit-hlfir --force-byref-reduction -fopenmp -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +!CHECK-LABEL: omp.reduction.declare +!CHECK-SAME: @[[RED_F32_NAME:.*]] : !fir.ref +!CHECK-SAME: init { +!CHECK: ^bb0(%{{.*}}: !fir.ref): +!CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f32 +!CHECK: %[[REF:.*]] = fir.alloca f32 +!CHECKL fir.store [[%C0_1]] to %[[REF]] : !fir.ref +!CHECK: omp.yield(%[[REF]] : !fir.ref) +!CHECK: } combiner { +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +!CHECK: %[[RES:.*]] = arith.addf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +!CHECK: omp.yield(%[[ARG0]] : !fir.ref) +!CHECK: } + +!CHECK-LABEL: omp.reduction.declare +!CHECK-SAME: @[[RED_I32_NAME:.*]] : !fir.ref +!CHECK-SAME: init { +!CHECK: ^bb0(%{{.*}}: !fir.ref): +!CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +!CHECK: %[[REF:.*]] = fir.alloca i32 +!CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +!CHECK: omp.yield(%[[REF]] : !fir.ref) +!CHECK: } combiner { +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +!CHECK: %[[RES:.*]] = arith.addi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +!CHECK: omp.yield(%[[ARG0]] : !fir.ref) +!CHECK: } + +!CHECK-LABEL: func.func @_QPsimple_int_add +!CHECK: %[[IREF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_addEi"} +!CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[IREF]] {uniq_name = "_QFsimple_int_addEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[I_START:.*]] = arith.constant 0 : i32 +!CHECK: hlfir.assign %[[I_START]] to %[[I_DECL]]#0 : i32, !fir.ref +!CHECK: omp.parallel byref reduction(@[[RED_I32_NAME]] %[[I_DECL]]#0 -> %[[PRV:.+]] : !fir.ref) { +!CHECK: %[[P_DECL:.+]]:2 = hlfir.declare %[[PRV]] {{.*}} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[LPRV:.+]] = fir.load %[[P_DECL]]#0 : !fir.ref +!CHECK: %[[I_INCR:.*]] = arith.constant 1 : i32 +!CHECK: %[[RES:.+]] = arith.addi %[[LPRV]], %[[I_INCR]] : i32 +!CHECK: hlfir.assign %[[RES]] to %[[P_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +subroutine simple_int_add + integer :: i + i = 0 + + !$omp parallel reduction(+:i) + i = i + 1 + !$omp end parallel + + print *, i +end subroutine + +!CHECK-LABEL: func.func @_QPsimple_real_add +!CHECK: %[[RREF:.*]] = fir.alloca f32 {bindc_name = "r", uniq_name = "_QFsimple_real_addEr"} +!CHECK: %[[R_DECL:.*]]:2 = hlfir.declare %[[RREF]] {uniq_name = "_QFsimple_real_addEr"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[R_START:.*]] = arith.constant 0.000000e+00 : f32 +!CHECK: hlfir.assign %[[R_START]] to %[[R_DECL]]#0 : f32, !fir.ref +!CHECK: omp.parallel byref reduction(@[[RED_F32_NAME]] %[[R_DECL]]#0 -> %[[PRV:.+]] : !fir.ref) { +!CHECK: %[[P_DECL:.+]]:2 = hlfir.declare %[[PRV]] {{.*}} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[LPRV:.+]] = fir.load %[[P_DECL]]#0 : !fir.ref +!CHECK: %[[R_INCR:.*]] = arith.constant 1.500000e+00 : f32 +!CHECK: %[[RES:.+]] = arith.addf %[[LPRV]], %[[R_INCR]] {{.*}} : f32 +!CHECK: hlfir.assign %[[RES]] to %[[P_DECL]]#0 : f32, !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +subroutine simple_real_add + real :: r + r = 0.0 + + !$omp parallel reduction(+:r) + r = r + 1.5 + !$omp end parallel + + print *, r +end subroutine + +!CHECK-LABEL: func.func @_QPint_real_add +!CHECK: %[[IREF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFint_real_addEi"} +!CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[IREF]] {uniq_name = "_QFint_real_addEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[RREF:.*]] = fir.alloca f32 {bindc_name = "r", uniq_name = "_QFint_real_addEr"} +!CHECK: %[[R_DECL:.*]]:2 = hlfir.declare %[[RREF]] {uniq_name = "_QFint_real_addEr"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[R_START:.*]] = arith.constant 0.000000e+00 : f32 +!CHECK: hlfir.assign %[[R_START]] to %[[R_DECL]]#0 : f32, !fir.ref +!CHECK: %[[I_START:.*]] = arith.constant 0 : i32 +!CHECK: hlfir.assign %[[I_START]] to %[[I_DECL]]#0 : i32, !fir.ref +!CHECK: omp.parallel byref reduction(@[[RED_I32_NAME]] %[[I_DECL]]#0 -> %[[IPRV:.+]] : !fir.ref, @[[RED_F32_NAME]] %[[R_DECL]]#0 -> %[[RPRV:.+]] : !fir.ref) { +!CHECK: %[[IP_DECL:.+]]:2 = hlfir.declare %[[IPRV]] {{.*}} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[RP_DECL:.+]]:2 = hlfir.declare %[[RPRV]] {{.*}} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[R_INCR:.*]] = arith.constant 1.500000e+00 : f32 +!CHECK: %[[R_LPRV:.+]] = fir.load %[[RP_DECL]]#0 : !fir.ref +!CHECK: %[[RES1:.+]] = arith.addf %[[R_INCR]], %[[R_LPRV]] {{.*}} : f32 +!CHECK: hlfir.assign %[[RES1]] to %[[RP_DECL]]#0 : f32, !fir.ref +!CHECK: %[[I_LPRV:.+]] = fir.load %[[IP_DECL]]#0 : !fir.ref +!CHECK: %[[I_INCR:.*]] = arith.constant 3 : i32 +!CHECK: %[[RES0:.+]] = arith.addi %[[I_LPRV]], %[[I_INCR]] : i32 +!CHECK: hlfir.assign %[[RES0]] to %[[IP_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +subroutine int_real_add + real :: r + integer :: i + + r = 0.0 + i = 0 + + !$omp parallel reduction(+:i,r) + r = 1.5 + r + i = i + 3 + !$omp end parallel + + print *, r + print *, i +end subroutine diff --git a/flang/test/Lower/OpenMP/parallel-reduction-byref.f90 b/flang/test/Lower/OpenMP/parallel-reduction-byref.f90 new file mode 100644 index 000000000000..a7c77c52674e --- /dev/null +++ b/flang/test/Lower/OpenMP/parallel-reduction-byref.f90 @@ -0,0 +1,44 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +!CHECK: omp.reduction.declare @[[REDUCTION_DECLARE:[_a-z0-9]+]] : !fir.ref +!CHECK-SAME: init { +!CHECK: ^bb0(%{{.*}}: !fir.ref): +!CHECK: %[[I0:[_a-z0-9]+]] = arith.constant 0 : i32 +!CHECK: %[[REF:.*]] = fir.alloca i32 +!CHECKL fir.store [[%I0]] to %[[REF]] : !fir.ref +!CHECK: omp.yield(%[[REF]] : !fir.ref) +!CHECK: } combiner { +!CHECK: ^bb0(%[[C0:[_a-z0-9]+]]: !fir.ref, %[[C1:[_a-z0-9]+]]: !fir.ref): +!CHECK: %[[LD0:.*]] = fir.load %[[C0]] : !fir.ref +!CHECK: %[[LD1:.*]] = fir.load %[[C1]] : !fir.ref +!CHECK: %[[CR:[_a-z0-9]+]] = arith.addi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[CR]] to %[[C0]] : !fir.ref +!CHECK: omp.yield(%[[C0]] : !fir.ref) +!CHECK: } +!CHECK: func.func @_QQmain() attributes {fir.bindc_name = "mn"} { +!CHECK: %[[RED_ACCUM_REF:[_a-z0-9]+]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} +!CHECK: %[[RED_ACCUM_DECL:[_a-z0-9]+]]:2 = hlfir.declare %[[RED_ACCUM_REF]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[C0:[_a-z0-9]+]] = arith.constant 0 : i32 +!CHECK: hlfir.assign %[[C0]] to %[[RED_ACCUM_DECL]]#0 : i32, !fir.ref +!CHECK: omp.parallel byref reduction(@[[REDUCTION_DECLARE]] %[[RED_ACCUM_DECL]]#0 -> %[[PRIVATE_RED:[a-z0-9]+]] : !fir.ref) { +!CHECK: %[[PRIVATE_DECL:[_a-z0-9]+]]:2 = hlfir.declare %[[PRIVATE_RED]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[C1:[_a-z0-9]+]] = arith.constant 1 : i32 +!CHECK: hlfir.assign %[[C1]] to %[[PRIVATE_DECL]]#0 : i32, !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: %[[RED_ACCUM_VAL:[_a-z0-9]+]] = fir.load %[[RED_ACCUM_DECL]]#0 : !fir.ref +!CHECK: {{.*}} = fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[RED_ACCUM_VAL]]) fastmath : (!fir.ref, i32) -> i1 +!CHECK: return +!CHECK: } + +program mn + integer :: i + i = 0 + + !$omp parallel reduction(+:i) + i = 1 + !$omp end parallel + + print *, i +end program diff --git a/flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 b/flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 new file mode 100644 index 000000000000..8492a69fed58 --- /dev/null +++ b/flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 @@ -0,0 +1,16 @@ +! Check that for parallel do, reduction is only processed for the loop + +! RUN: bbc -fopenmp --force-byref-reduction -emit-hlfir %s -o - | FileCheck %s +! RUN: flang-new -fc1 -fopenmp -mmlir --force-byref-reduction -emit-hlfir %s -o - | FileCheck %s + +! CHECK: omp.parallel { +! CHECK: omp.wsloop byref reduction(@add_reduction_i_32 +subroutine sb + integer :: x + x = 0 + !$omp parallel do reduction(+:x) + do i=1,100 + x = x + 1 + end do + !$omp end parallel do +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-add-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-add-byref.f90 new file mode 100644 index 000000000000..e8a04c23f4ea --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-add-byref.f90 @@ -0,0 +1,433 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! CHECK-LABEL: omp.reduction.declare @add_reduction_f_64_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f64 +! CHECK: %[[REF:.*]] = fir.alloca f64 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.addf %[[LD0]], %[[LD1]] fastmath : f64 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: omp.reduction.declare @add_reduction_i_64_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i64 +! CHECK: %[[REF:.*]] = fir.alloca i64 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.addi %[[LD0]], %[[LD1]] : i64 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: omp.reduction.declare @add_reduction_f_32_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[REF:.*]] = fir.alloca f32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.addf %[[LD0]], %[[LD1]] fastmath : f32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: omp.reduction.declare @add_reduction_i_32_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.addi %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_int_reduction() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_reductionEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_int_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_int_reductionEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : i32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_int_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_i_32_byref %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref +! CHECK: %[[VAL_15:.*]] = arith.addi %[[VAL_13]], %[[VAL_14]] : i32 +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_12]]#0 : i32, !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_int_reduction + integer :: x + x = 0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = x + i + end do + !$omp end do + !$omp end parallel +end subroutine + + +! CHECK-LABEL: func.func @_QPsimple_real_reduction() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_real_reductionEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_real_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFsimple_real_reductionEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_real_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : f32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_real_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_f_32_byref %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i32) -> f32 +! CHECK: %[[VAL_16:.*]] = arith.addf %[[VAL_13]], %[[VAL_15]] fastmath : f32 +! CHECK: hlfir.assign %[[VAL_16]] to %[[VAL_12]]#0 : f32, !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_real_reduction + real :: x + x = 0.0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = x + i + end do + !$omp end do + !$omp end parallel +end subroutine + + +! CHECK-LABEL: func.func @_QPsimple_int_reduction_switch_order() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_reduction_switch_orderEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_int_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_int_reduction_switch_orderEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_int_reduction_switch_orderEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : i32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_int_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_i_32_byref %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reduction_switch_orderEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_15:.*]] = arith.addi %[[VAL_13]], %[[VAL_14]] : i32 +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_12]]#0 : i32, !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_int_reduction_switch_order + integer :: x + x = 0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = i + x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_real_reduction_switch_order() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_real_reduction_switch_orderEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_real_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFsimple_real_reduction_switch_orderEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_real_reduction_switch_orderEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : f32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_real_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_f_32_byref %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reduction_switch_orderEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref +! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (i32) -> f32 +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_16:.*]] = arith.addf %[[VAL_14]], %[[VAL_15]] fastmath : f32 +! CHECK: hlfir.assign %[[VAL_16]] to %[[VAL_12]]#0 : f32, !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_real_reduction_switch_order + real :: x + x = 0.0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = i + x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_int_reductions_same_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_int_reductions_same_typeEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFmultiple_int_reductions_same_typeEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_int_reductions_same_typeEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFmultiple_int_reductions_same_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFmultiple_int_reductions_same_typeEy"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFmultiple_int_reductions_same_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFmultiple_int_reductions_same_typeEz"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_int_reductions_same_typeEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_8:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_8]] to %[[VAL_3]]#0 : i32, !fir.ref +! CHECK: %[[VAL_9:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_5]]#0 : i32, !fir.ref +! CHECK: %[[VAL_10:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_7]]#0 : i32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_11:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFmultiple_int_reductions_same_typeEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_i_32_byref %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref, @add_reduction_i_32_byref %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref, @add_reduction_i_32_byref %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { +! CHECK: fir.store %[[VAL_19]] to %[[VAL_12]]#1 : !fir.ref +! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_int_reductions_same_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_int_reductions_same_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_int_reductions_same_typeEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_20]]#0 : !fir.ref +! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_25:.*]] = arith.addi %[[VAL_23]], %[[VAL_24]] : i32 +! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_20]]#0 : i32, !fir.ref +! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_21]]#0 : !fir.ref +! CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_28:.*]] = arith.addi %[[VAL_26]], %[[VAL_27]] : i32 +! CHECK: hlfir.assign %[[VAL_28]] to %[[VAL_21]]#0 : i32, !fir.ref +! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_22]]#0 : !fir.ref +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_31:.*]] = arith.addi %[[VAL_29]], %[[VAL_30]] : i32 +! CHECK: hlfir.assign %[[VAL_31]] to %[[VAL_22]]#0 : i32, !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine multiple_int_reductions_same_type + integer :: x,y,z + x = 0 + y = 0 + z = 0 + !$omp parallel + !$omp do reduction(+:x,y,z) + do i=1, 100 + x = x + i + y = y + i + z = z + i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_real_reductions_same_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_real_reductions_same_typeEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFmultiple_real_reductions_same_typeEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFmultiple_real_reductions_same_typeEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFmultiple_real_reductions_same_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = fir.alloca f32 {bindc_name = "y", uniq_name = "_QFmultiple_real_reductions_same_typeEy"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFmultiple_real_reductions_same_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_6:.*]] = fir.alloca f32 {bindc_name = "z", uniq_name = "_QFmultiple_real_reductions_same_typeEz"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_real_reductions_same_typeEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_8:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_8]] to %[[VAL_3]]#0 : f32, !fir.ref +! CHECK: %[[VAL_9:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_5]]#0 : f32, !fir.ref +! CHECK: %[[VAL_10:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_7]]#0 : f32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_11:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFmultiple_real_reductions_same_typeEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_f_32_byref %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref, @add_reduction_f_32_byref %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref, @add_reduction_f_32_byref %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { +! CHECK: fir.store %[[VAL_19]] to %[[VAL_12]]#1 : !fir.ref +! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_real_reductions_same_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_real_reductions_same_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_real_reductions_same_typeEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_20]]#0 : !fir.ref +! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_24]] : (i32) -> f32 +! CHECK: %[[VAL_26:.*]] = arith.addf %[[VAL_23]], %[[VAL_25]] fastmath : f32 +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_20]]#0 : f32, !fir.ref +! CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_21]]#0 : !fir.ref +! CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_28]] : (i32) -> f32 +! CHECK: %[[VAL_30:.*]] = arith.addf %[[VAL_27]], %[[VAL_29]] fastmath : f32 +! CHECK: hlfir.assign %[[VAL_30]] to %[[VAL_21]]#0 : f32, !fir.ref +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_22]]#0 : !fir.ref +! CHECK: %[[VAL_32:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_32]] : (i32) -> f32 +! CHECK: %[[VAL_34:.*]] = arith.addf %[[VAL_31]], %[[VAL_33]] fastmath : f32 +! CHECK: hlfir.assign %[[VAL_34]] to %[[VAL_22]]#0 : f32, !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine multiple_real_reductions_same_type + real :: x,y,z + x = 0.0 + y = 0.0 + z = 0.0 + !$omp parallel + !$omp do reduction(+:x,y,z) + do i=1, 100 + x = x + i + y = y + i + z = z + i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions_different_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductions_different_typeEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFmultiple_reductions_different_typeEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca f64 {bindc_name = "w", uniq_name = "_QFmultiple_reductions_different_typeEw"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFmultiple_reductions_different_typeEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_reductions_different_typeEx"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFmultiple_reductions_different_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_6:.*]] = fir.alloca i64 {bindc_name = "y", uniq_name = "_QFmultiple_reductions_different_typeEy"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductions_different_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_8:.*]] = fir.alloca f32 {bindc_name = "z", uniq_name = "_QFmultiple_reductions_different_typeEz"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFmultiple_reductions_different_typeEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_10:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_5]]#0 : i32, !fir.ref +! CHECK: %[[VAL_11:.*]] = arith.constant 0 : i64 +! CHECK: hlfir.assign %[[VAL_11]] to %[[VAL_7]]#0 : i64, !fir.ref +! CHECK: %[[VAL_12:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_12]] to %[[VAL_9]]#0 : f32, !fir.ref +! CHECK: %[[VAL_13:.*]] = arith.constant 0.000000e+00 : f64 +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_3]]#0 : f64, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_14:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]] {uniq_name = "_QFmultiple_reductions_different_typeEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_17:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_i_32_byref %[[VAL_5]]#0 -> %[[VAL_19:.*]] : !fir.ref, @add_reduction_i_64_byref %[[VAL_7]]#0 -> %[[VAL_20:.*]] : !fir.ref, @add_reduction_f_32_byref %[[VAL_9]]#0 -> %[[VAL_21:.*]] : !fir.ref, @add_reduction_f_64_byref %[[VAL_3]]#0 -> %[[VAL_22:.*]] : !fir.ref) for (%[[VAL_23:.*]]) : i32 = (%[[VAL_16]]) to (%[[VAL_17]]) inclusive step (%[[VAL_18]]) { +! CHECK: fir.store %[[VAL_23]] to %[[VAL_15]]#1 : !fir.ref +! CHECK: %[[VAL_24:.*]]:2 = hlfir.declare %[[VAL_19]] {uniq_name = "_QFmultiple_reductions_different_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_25:.*]]:2 = hlfir.declare %[[VAL_20]] {uniq_name = "_QFmultiple_reductions_different_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_26:.*]]:2 = hlfir.declare %[[VAL_21]] {uniq_name = "_QFmultiple_reductions_different_typeEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_22]] {uniq_name = "_QFmultiple_reductions_different_typeEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_24]]#0 : !fir.ref +! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref +! CHECK: %[[VAL_30:.*]] = arith.addi %[[VAL_28]], %[[VAL_29]] : i32 +! CHECK: hlfir.assign %[[VAL_30]] to %[[VAL_24]]#0 : i32, !fir.ref +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_25]]#0 : !fir.ref +! CHECK: %[[VAL_32:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref +! CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_32]] : (i32) -> i64 +! CHECK: %[[VAL_34:.*]] = arith.addi %[[VAL_31]], %[[VAL_33]] : i64 +! CHECK: hlfir.assign %[[VAL_34]] to %[[VAL_25]]#0 : i64, !fir.ref +! CHECK: %[[VAL_35:.*]] = fir.load %[[VAL_26]]#0 : !fir.ref +! CHECK: %[[VAL_36:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref +! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_36]] : (i32) -> f32 +! CHECK: %[[VAL_38:.*]] = arith.addf %[[VAL_35]], %[[VAL_37]] fastmath : f32 +! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_26]]#0 : f32, !fir.ref +! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_27]]#0 : !fir.ref +! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref +! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> f64 +! CHECK: %[[VAL_42:.*]] = arith.addf %[[VAL_39]], %[[VAL_41]] fastmath : f64 +! CHECK: hlfir.assign %[[VAL_42]] to %[[VAL_27]]#0 : f64, !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine multiple_reductions_different_type + integer :: x + integer(kind=8) :: y + real :: z + real(kind=8) :: w + x = 0 + y = 0 + z = 0.0 + w = 0.0 + !$omp parallel + !$omp do reduction(+:x,y,z,w) + do i=1, 100 + x = x + i + y = y + i + z = z + i + w = w + i + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir-byref.f90 new file mode 100644 index 000000000000..3739b3ae36ea --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir-byref.f90 @@ -0,0 +1,58 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.reduction.declare @add_reduction_i_32_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.addi %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_int_reduction() +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_reductionEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_int_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_int_reductionEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : i32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_int_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_i_32_byref %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref +! CHECK: %[[VAL_15:.*]] = arith.addi %[[VAL_13]], %[[VAL_14]] : i32 +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_12]]#0 : i32, !fir.ref +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + + +subroutine simple_int_reduction + integer :: x + x = 0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = x + i + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 new file mode 100644 index 000000000000..15a6dde046fe --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 @@ -0,0 +1,64 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.reduction.declare @iand_i_32_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[C0_1:.*]] = arith.constant -1 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.andi %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: func.func @_QPreduction_iand( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFreduction_iandEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_iandEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iandEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_iandEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFreduction_iandEy"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFreduction_iandEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@iand_i_32_byref %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_iandEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_16]]) : (!fir.box>, i64) -> !fir.ref +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_17]] : !fir.ref +! CHECK: %[[VAL_20:.*]] = arith.andi %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: hlfir.assign %[[VAL_20]] to %[[VAL_14]]#0 : i32, !fir.ref +! CHECK: omp.yield +! CHECK: omp.terminator + + + +subroutine reduction_iand(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(iand:x) + do i=1, 100 + x = iand(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 new file mode 100644 index 000000000000..4e0957219fa5 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 @@ -0,0 +1,55 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! CHECK-LABEL: omp.reduction.declare @ieor_i_32_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.xori %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +!CHECK-LABEL: @_QPreduction_ieor +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_ieorEx"} +!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X_REF]] {uniq_name = "_QFreduction_ieorEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y_BOX]] {uniq_name = "_QFreduction_ieorEy"} : (!fir.box>) -> (!fir.box>, !fir.box>) + + +!CHECK: omp.parallel +!CHECK: %[[I_REF:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +!CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[I_REF]] {uniq_name = "_QFreduction_ieorEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: omp.wsloop byref reduction(@ieor_i_32_byref %[[X_DECL]]#0 -> %[[PRV:.+]] : !fir.ref) for +!CHECK: fir.store %{{.*}} to %[[I_DECL]]#1 : !fir.ref +!CHECK: %[[PRV_DECL:.+]]:2 = hlfir.declare %[[PRV]] {{.*}} : (!fir.ref) -> (!fir.ref, !fir.ref) +!CHECK: %[[I_32:.*]] = fir.load %[[I_DECL]]#0 : !fir.ref +!CHECK: %[[I_64:.*]] = fir.convert %[[I_32]] : (i32) -> i64 +!CHECK: %[[Y_I_REF:.*]] = hlfir.designate %[[Y_DECL]]#0 (%[[I_64]]) : (!fir.box>, i64) -> !fir.ref +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV_DECL]]#0 : !fir.ref +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref +!CHECK: %[[RES:.+]] = arith.xori %[[LPRV]], %[[Y_I]] : i32 +!CHECK: hlfir.assign %[[RES]] to %[[PRV_DECL]]#0 : i32, !fir.ref +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_ieor(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(ieor:x) + do i=1, 100 + x = ieor(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 new file mode 100644 index 000000000000..712edaf95575 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 @@ -0,0 +1,64 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.reduction.declare @ior_i_32_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.ori %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: func.func @_QPreduction_ior( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFreduction_iorEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_iorEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iorEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_iorEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFreduction_iorEy"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref +! CHECK: omp.parallel +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFreduction_iorEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@ior_i_32_byref %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) +! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_iorEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_16]]) : (!fir.box>, i64) -> !fir.ref +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_17]] : !fir.ref +! CHECK: %[[VAL_20:.*]] = arith.ori %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: hlfir.assign %[[VAL_20]] to %[[VAL_14]]#0 : i32, !fir.ref +! CHECK: omp.yield +! CHECK: omp.terminator + + + +subroutine reduction_ior(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(ior:x) + do i=1, 100 + x = ior(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 new file mode 100644 index 000000000000..4162626f926a --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 @@ -0,0 +1,206 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.reduction.declare @and_reduction : !fir.ref> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>): +! CHECK: %[[VAL_1:.*]] = arith.constant true +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> +! CHECK: %[[REF:.*]] = fir.alloca !fir.logical<4> +! CHECK: fir.store %[[VAL_2]] to %[[REF]] : !fir.ref> +! CHECK: omp.yield(%[[REF]] : !fir.ref>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref> +! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[RES:.*]] = arith.andi %[[VAL_2]], %[[VAL_3]] : i1 +! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_reduction( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reductionEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reductionEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref>>, !fir.shape<1>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@and_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref +! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64 +! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.andi %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.and.:x) + do i=1, 100 + x = x .and. y(i) + end do + !$omp end do + !$omp end parallel +end subroutine simple_reduction + + +! CHECK-LABEL: func.func @_QPsimple_reduction_switch_order( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reduction_switch_orderEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reduction_switch_orderEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref>>, !fir.shape<1>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@and_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_18]] : (i32) -> i64 +! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.andi %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction_switch_order(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.and.:x) + do i=1, 100 + x = y(i) .and. x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "w"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductionsEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref>>, !fir.shape<1>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.logical<4> {bindc_name = "z", uniq_name = "_QFmultiple_reductionsEz"} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_12:.*]] = arith.constant true +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_7]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_14:.*]] = arith.constant true +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_9]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_16:.*]] = arith.constant true +! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_17]] to %[[VAL_11]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_18:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@and_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref>, @and_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref>, @and_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref>) for (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) { +! CHECK: fir.store %[[VAL_26]] to %[[VAL_19]]#1 : !fir.ref +! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_29:.*]]:2 = hlfir.declare %[[VAL_25]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_27]]#0 : !fir.ref> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref +! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64 +! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref> +! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_37:.*]] = arith.andi %[[VAL_35]], %[[VAL_36]] : i1 +! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref> +! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref +! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64 +! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref> +! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_46:.*]] = arith.andi %[[VAL_44]], %[[VAL_45]] : i1 +! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref> +! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref +! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64 +! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref> +! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_55:.*]] = arith.andi %[[VAL_53]], %[[VAL_54]] : i1 +! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + + + +subroutine multiple_reductions(w) + logical :: x,y,z,w(100) + x = .true. + y = .true. + z = .true. + !$omp parallel + !$omp do reduction(.and.:x,y,z) + do i=1, 100 + x = x .and. w(i) + y = y .and. w(i) + z = z .and. w(i) + end do + !$omp end do + !$omp end parallel +end subroutine + diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 new file mode 100644 index 000000000000..4c159f3a69f9 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 @@ -0,0 +1,202 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.reduction.declare @eqv_reduction : !fir.ref> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>): +! CHECK: %[[VAL_1:.*]] = arith.constant true +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> +! CHECK: %[[REF:.*]] = fir.alloca !fir.logical<4> +! CHECK: fir.store %[[VAL_2]] to %[[REF]] : !fir.ref> +! CHECK: omp.yield(%[[REF]] : !fir.ref>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref> +! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[RES:.*]] = arith.cmpi eq, %[[VAL_2]], %[[VAL_3]] : i1 +! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_reduction( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reductionEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reductionEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref>>, !fir.shape<1>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref +! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64 +! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.cmpi eq, %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.eqv.:x) + do i=1, 100 + x = x .eqv. y(i) + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_reduction_switch_order( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reduction_switch_orderEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reduction_switch_orderEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref>>, !fir.shape<1>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_18]] : (i32) -> i64 +! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.cmpi eq, %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction_switch_order(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.eqv.:x) + do i=1, 100 + x = y(i) .eqv. x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "w"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductionsEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref>>, !fir.shape<1>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.logical<4> {bindc_name = "z", uniq_name = "_QFmultiple_reductionsEz"} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_12:.*]] = arith.constant true +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_7]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_14:.*]] = arith.constant true +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_9]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_16:.*]] = arith.constant true +! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_17]] to %[[VAL_11]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_18:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref>, @eqv_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref>, @eqv_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref>) for (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) { +! CHECK: fir.store %[[VAL_26]] to %[[VAL_19]]#1 : !fir.ref +! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_29:.*]]:2 = hlfir.declare %[[VAL_25]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_27]]#0 : !fir.ref> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref +! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64 +! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref> +! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_37:.*]] = arith.cmpi eq, %[[VAL_35]], %[[VAL_36]] : i1 +! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref> +! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref +! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64 +! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref> +! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_46:.*]] = arith.cmpi eq, %[[VAL_44]], %[[VAL_45]] : i1 +! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref> +! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref +! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64 +! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref> +! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_55:.*]] = arith.cmpi eq, %[[VAL_53]], %[[VAL_54]] : i1 +! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine multiple_reductions(w) + logical :: x,y,z,w(100) + x = .true. + y = .true. + z = .true. + !$omp parallel + !$omp do reduction(.eqv.:x,y,z) + do i=1, 100 + x = x .eqv. w(i) + y = y .eqv. w(i) + z = z .eqv. w(i) + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 new file mode 100644 index 000000000000..cfa8e47d3ca7 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 @@ -0,0 +1,207 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.reduction.declare @neqv_reduction : !fir.ref> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>): +! CHECK: %[[VAL_1:.*]] = arith.constant false +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> +! CHECK: %[[REF:.*]] = fir.alloca !fir.logical<4> +! CHECK: fir.store %[[VAL_2]] to %[[REF]] : !fir.ref> +! CHECK: omp.yield(%[[REF]] : !fir.ref>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref> +! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[RES:.*]] = arith.cmpi ne, %[[VAL_2]], %[[VAL_3]] : i1 +! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_reduction( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reductionEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reductionEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref>>, !fir.shape<1>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref +! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64 +! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.cmpi ne, %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.neqv.:x) + do i=1, 100 + x = x .neqv. y(i) + end do + !$omp end do + !$omp end parallel +end subroutine + + +! CHECK-LABEL: func.func @_QPsimple_reduction_switch_order( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reduction_switch_orderEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reduction_switch_orderEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref>>, !fir.shape<1>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_18]] : (i32) -> i64 +! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.cmpi ne, %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + + +subroutine simple_reduction_switch_order(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.neqv.:x) + do i=1, 100 + x = y(i) .neqv. x + end do + !$omp end do + !$omp end parallel +end subroutine + + +! CHECK-LABEL: func.func @_QPmultiple_reductions( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "w"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductionsEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref>>, !fir.shape<1>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.logical<4> {bindc_name = "z", uniq_name = "_QFmultiple_reductionsEz"} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_12:.*]] = arith.constant true +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_7]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_14:.*]] = arith.constant true +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_9]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_16:.*]] = arith.constant true +! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_17]] to %[[VAL_11]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_18:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref>, @neqv_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref>, @neqv_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref>) for (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) { +! CHECK: fir.store %[[VAL_26]] to %[[VAL_19]]#1 : !fir.ref +! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_29:.*]]:2 = hlfir.declare %[[VAL_25]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_27]]#0 : !fir.ref> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref +! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64 +! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref> +! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_37:.*]] = arith.cmpi ne, %[[VAL_35]], %[[VAL_36]] : i1 +! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref> +! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref +! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64 +! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref> +! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_46:.*]] = arith.cmpi ne, %[[VAL_44]], %[[VAL_45]] : i1 +! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref> +! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref +! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64 +! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref> +! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_55:.*]] = arith.cmpi ne, %[[VAL_53]], %[[VAL_54]] : i1 +! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return +! CHECK: } + + +subroutine multiple_reductions(w) + logical :: x,y,z,w(100) + x = .true. + y = .true. + z = .true. + !$omp parallel + !$omp do reduction(.neqv.:x,y,z) + do i=1, 100 + x = x .neqv. w(i) + y = y .neqv. w(i) + z = z .neqv. w(i) + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 new file mode 100644 index 000000000000..c71ea02f9373 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 @@ -0,0 +1,204 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.reduction.declare @or_reduction : !fir.ref> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref>): +! CHECK: %[[VAL_1:.*]] = arith.constant false +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> +! CHECK: %[[REF:.*]] = fir.alloca !fir.logical<4> +! CHECK: fir.store %[[VAL_2]] to %[[REF]] : !fir.ref> +! CHECK: omp.yield(%[[REF]] : !fir.ref>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: !fir.ref>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref> +! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[RES:.*]] = arith.ori %[[VAL_2]], %[[VAL_3]] : i1 +! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref>) + +! CHECK-LABEL: func.func @_QPsimple_reduction( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reductionEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reductionEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref>>, !fir.shape<1>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@or_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref +! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64 +! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.ori %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.or.:x) + do i=1, 100 + x = x .or. y(i) + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_reduction_switch_order( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reduction_switch_orderEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reduction_switch_orderEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref>>, !fir.shape<1>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@or_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_18]] : (i32) -> i64 +! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.ori %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction_switch_order(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.or.:x) + do i=1, 100 + x = y(i) .or. x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>> {fir.bindc_name = "w"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductionsEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref>>, !fir.shape<1>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.logical<4> {bindc_name = "z", uniq_name = "_QFmultiple_reductionsEz"} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_12:.*]] = arith.constant true +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_7]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_14:.*]] = arith.constant true +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_9]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_16:.*]] = arith.constant true +! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_17]] to %[[VAL_11]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.parallel { +! CHECK: %[[VAL_18:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@or_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref>, @or_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref>, @or_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref>) for (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) { +! CHECK: fir.store %[[VAL_26]] to %[[VAL_19]]#1 : !fir.ref +! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_29:.*]]:2 = hlfir.declare %[[VAL_25]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_27]]#0 : !fir.ref> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref +! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64 +! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref> +! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_37:.*]] = arith.ori %[[VAL_35]], %[[VAL_36]] : i1 +! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref> +! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref +! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64 +! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref> +! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_46:.*]] = arith.ori %[[VAL_44]], %[[VAL_45]] : i1 +! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref> +! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref +! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64 +! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref>>, i64) -> !fir.ref> +! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref> +! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_55:.*]] = arith.ori %[[VAL_53]], %[[VAL_54]] : i1 +! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + + + +subroutine multiple_reductions(w) + logical :: x,y,z,w(100) + x = .true. + y = .true. + z = .true. + !$omp parallel + !$omp do reduction(.or.:x,y,z) + do i=1, 100 + x = x .or. w(i) + y = y .or. w(i) + z = z .or. w(i) + end do + !$omp end do + !$omp end parallel +end subroutine + diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max-2-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max-2-byref.f90 new file mode 100644 index 000000000000..360cd34df2d1 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max-2-byref.f90 @@ -0,0 +1,20 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +! CHECK: omp.wsloop byref reduction(@max_i_32 +! CHECK: arith.cmpi sgt +! CHECK: arith.select + +module m1 + intrinsic max +end module m1 +program main + use m1, ren=>max + n=0 + !$omp parallel do reduction(ren:n) + do i=1,100 + n=max(n,i) + end do + if (n/=100) print *,101 + print *,'pass' +end program main diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 new file mode 100644 index 000000000000..f9bffc269bb8 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 @@ -0,0 +1,152 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +!CHECK: omp.reduction.declare @max_f_32_byref : !fir.ref +!CHECK-SAME: init { +!CHECK: %[[MINIMUM_VAL:.*]] = arith.constant -3.40282347E+38 : f32 +!CHECK: %[[REF:.*]] = fir.alloca f32 +!CHECK: fir.store %[[MINIMUM_VAL]] to %[[REF]] : !fir.ref +!CHECK: omp.yield(%[[REF]] : !fir.ref) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +!CHECK: %[[RES:.*]] = arith.maximumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +!CHECK: omp.yield(%[[ARG0]] : !fir.ref) + +!CHECK-LABEL: omp.reduction.declare @max_i_32_byref : !fir.ref +!CHECK-SAME: init { +!CHECK: %[[MINIMUM_VAL:.*]] = arith.constant -2147483648 : i32 +!CHECK: %[[REF:.*]] = fir.alloca i32 +!CHECK: fir.store %[[MINIMUM_VAL]] to %[[REF]] : !fir.ref +!CHECK: omp.yield(%[[REF]] : !fir.ref) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +!CHECK: %[[RES:.*]] = arith.maxsi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +!CHECK: omp.yield(%[[ARG0]] : !fir.ref) + +! CHECK-LABEL: func.func @_QPreduction_max_int( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFreduction_max_intEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_max_intEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_max_intEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_max_intEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFreduction_max_intEy"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFreduction_max_intEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@max_i_32_byref %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_max_intEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_16]]) : (!fir.box>, i64) -> !fir.ref +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_17]] : !fir.ref +! CHECK: %[[VAL_20:.*]] = arith.cmpi sgt, %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: %[[VAL_21:.*]] = arith.select %[[VAL_20]], %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: hlfir.assign %[[VAL_21]] to %[[VAL_14]]#0 : i32, !fir.ref +! CHECK: omp.yield +! CHECK: omp.terminator + +! CHECK-LABEL: func.func @_QPreduction_max_real( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFreduction_max_realEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_max_realEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFreduction_max_realEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_max_realEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFreduction_max_realEy"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : f32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFreduction_max_realEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@max_f_32_byref %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_max_realEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_16]]) : (!fir.box>, i64) -> !fir.ref +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]] : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref +! CHECK: %[[VAL_20:.*]] = arith.cmpf ogt, %[[VAL_18]], %[[VAL_19]] fastmath : f32 +! CHECK: %[[VAL_21:.*]] = arith.select %[[VAL_20]], %[[VAL_18]], %[[VAL_19]] : f32 +! CHECK: hlfir.assign %[[VAL_21]] to %[[VAL_14]]#0 : f32, !fir.ref +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: omp.parallel { +! CHECK: %[[VAL_30:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_31:.*]]:2 = hlfir.declare %[[VAL_30]] {uniq_name = "_QFreduction_max_realEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_32:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_33:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_34:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@max_f_32_byref %[[VAL_4]]#0 -> %[[VAL_35:.*]] : !fir.ref) for (%[[VAL_36:.*]]) : i32 = (%[[VAL_32]]) to (%[[VAL_33]]) inclusive step (%[[VAL_34]]) { +! CHECK: fir.store %[[VAL_36]] to %[[VAL_31]]#1 : !fir.ref +! CHECK: %[[VAL_37:.*]]:2 = hlfir.declare %[[VAL_35]] {uniq_name = "_QFreduction_max_realEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_38:.*]] = fir.load %[[VAL_31]]#0 : !fir.ref +! CHECK: %[[VAL_39:.*]] = fir.convert %[[VAL_38]] : (i32) -> i64 +! CHECK: %[[VAL_40:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_39]]) : (!fir.box>, i64) -> !fir.ref +! CHECK: %[[VAL_41:.*]] = fir.load %[[VAL_40]] : !fir.ref +! CHECK: %[[VAL_42:.*]] = fir.load %[[VAL_37]]#0 : !fir.ref +! CHECK: %[[VAL_43:.*]] = arith.cmpf ogt, %[[VAL_41]], %[[VAL_42]] fastmath : f32 +! CHECK: fir.if %[[VAL_43]] { +! CHECK: %[[VAL_44:.*]] = fir.load %[[VAL_31]]#0 : !fir.ref +! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_44]] : (i32) -> i64 +! CHECK: %[[VAL_46:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_45]]) : (!fir.box>, i64) -> !fir.ref +! CHECK: %[[VAL_47:.*]] = fir.load %[[VAL_46]] : !fir.ref +! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_37]]#0 : f32, !fir.ref +! CHECK: } else { +! CHECK: } +! CHECK: omp.yield +! CHECK: omp.terminator + + + +subroutine reduction_max_int(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(max:x) + do i=1, 100 + x = max(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine + +subroutine reduction_max_real(y) + real :: x, y(:) + x = 0.0 + !$omp parallel + !$omp do reduction(max:x) + do i=1, 100 + x = max(y(i), x) + end do + !$omp end do + !$omp end parallel + print *, x + + !$omp parallel + !$omp do reduction(max:x) + do i=1, 100 + if (y(i) .gt. x) x = y(i) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir-byref.f90 new file mode 100644 index 000000000000..a296ce47f20f --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir-byref.f90 @@ -0,0 +1,62 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.reduction.declare @max_i_32_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[MINIMUM_VAL:.*]] = arith.constant -2147483648 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[MINIMUM_VAL]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) +! CHECK: combiner +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.maxsi %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) + +! CHECK-LABEL: func.func @_QPreduction_max_int( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFreduction_max_intEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_max_intEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_max_intEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_max_intEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFreduction_max_intEy"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFreduction_max_intEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@max_i_32_byref %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_max_intEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_16]]) : (!fir.box>, i64) -> !fir.ref +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_17]] : !fir.ref +! CHECK: %[[VAL_20:.*]] = arith.cmpi sgt, %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: %[[VAL_21:.*]] = arith.select %[[VAL_20]], %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: hlfir.assign %[[VAL_21]] to %[[VAL_14]]#0 : i32, !fir.ref +! CHECK: omp.yield +! CHECK: omp.terminator + + +subroutine reduction_max_int(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(max:x) + do i=1, 100 + x = max(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 new file mode 100644 index 000000000000..da9e686362b6 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 @@ -0,0 +1,154 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +!CHECK: omp.reduction.declare @min_f_32_byref : !fir.ref +!CHECK-SAME: init { +!CHECK: %[[MAXIMUM_VAL:.*]] = arith.constant 3.40282347E+38 : f32 +!CHECK: %[[REF:.*]] = fir.alloca f32 +!CHECK: fir.store %[[MAXIMUM_VAL]] to %[[REF]] : !fir.ref +!CHECK: omp.yield(%[[REF]] : !fir.ref) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +!CHECK: %[[RES:.*]] = arith.minimumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +!CHECK: omp.yield(%[[ARG0]] : !fir.ref) + +!CHECK-LABEL: omp.reduction.declare @min_i_32_byref : !fir.ref +!CHECK-SAME: init { +!CHECK: %[[MAXIMUM_VAL:.*]] = arith.constant 2147483647 : i32 +!CHECK: %[[REF:.*]] = fir.alloca i32 +!CHECK: fir.store %[[MAXIMUM_VAL]] to %[[REF]] : !fir.ref +!CHECK: omp.yield(%[[REF]] : !fir.ref) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +!CHECK: %[[RES:.*]] = arith.minsi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +!CHECK: omp.yield(%[[ARG0]] : !fir.ref) + +! CHECK-LABEL: func.func @_QPreduction_min_int( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFreduction_min_intEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_min_intEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_min_intEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_min_intEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFreduction_min_intEy"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFreduction_min_intEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@min_i_32_byref %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_min_intEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_16]]) : (!fir.box>, i64) -> !fir.ref +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_17]] : !fir.ref +! CHECK: %[[VAL_20:.*]] = arith.cmpi slt, %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: %[[VAL_21:.*]] = arith.select %[[VAL_20]], %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: hlfir.assign %[[VAL_21]] to %[[VAL_14]]#0 : i32, !fir.ref +! CHECK: omp.yield +! CHECK: omp.terminator + +! CHECK-LABEL: func.func @_QPreduction_min_real( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFreduction_min_realEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_min_realEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_3:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFreduction_min_realEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_min_realEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFreduction_min_realEy"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : f32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFreduction_min_realEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@min_f_32_byref %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_min_realEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_16]]) : (!fir.box>, i64) -> !fir.ref +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]] : !fir.ref +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref +! CHECK: %[[VAL_20:.*]] = arith.cmpf olt, %[[VAL_18]], %[[VAL_19]] fastmath : f32 +! CHECK: %[[VAL_21:.*]] = arith.select %[[VAL_20]], %[[VAL_18]], %[[VAL_19]] : f32 +! CHECK: hlfir.assign %[[VAL_21]] to %[[VAL_14]]#0 : f32, !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: omp.parallel { +! CHECK: %[[VAL_30:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_31:.*]]:2 = hlfir.declare %[[VAL_30]] {uniq_name = "_QFreduction_min_realEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_32:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_33:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_34:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@min_f_32_byref %[[VAL_4]]#0 -> %[[VAL_35:.*]] : !fir.ref) for (%[[VAL_36:.*]]) : i32 = (%[[VAL_32]]) to (%[[VAL_33]]) inclusive step (%[[VAL_34]]) { +! CHECK: fir.store %[[VAL_36]] to %[[VAL_31]]#1 : !fir.ref +! CHECK: %[[VAL_37:.*]]:2 = hlfir.declare %[[VAL_35]] {uniq_name = "_QFreduction_min_realEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_38:.*]] = fir.load %[[VAL_31]]#0 : !fir.ref +! CHECK: %[[VAL_39:.*]] = fir.convert %[[VAL_38]] : (i32) -> i64 +! CHECK: %[[VAL_40:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_39]]) : (!fir.box>, i64) -> !fir.ref +! CHECK: %[[VAL_41:.*]] = fir.load %[[VAL_40]] : !fir.ref +! CHECK: %[[VAL_42:.*]] = fir.load %[[VAL_37]]#0 : !fir.ref +! CHECK: %[[VAL_43:.*]] = arith.cmpf ogt, %[[VAL_41]], %[[VAL_42]] fastmath : f32 +! CHECK: fir.if %[[VAL_43]] { +! CHECK: %[[VAL_44:.*]] = fir.load %[[VAL_31]]#0 : !fir.ref +! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_44]] : (i32) -> i64 +! CHECK: %[[VAL_46:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_45]]) : (!fir.box>, i64) -> !fir.ref +! CHECK: %[[VAL_47:.*]] = fir.load %[[VAL_46]] : !fir.ref +! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_37]]#0 : f32, !fir.ref +! CHECK: } else { +! CHECK: } +! CHECK: omp.yield +! CHECK: omp.terminator + + + +subroutine reduction_min_int(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(min:x) + do i=1, 100 + x = min(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine + +subroutine reduction_min_real(y) + real :: x, y(:) + x = 0.0 + !$omp parallel + !$omp do reduction(min:x) + do i=1, 100 + x = min(y(i), x) + end do + !$omp end do + !$omp end parallel + print *, x + + !$omp parallel + !$omp do reduction(min:x) + do i=1, 100 + if (y(i) .gt. x) x = y(i) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-min2.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-min2.f90 new file mode 100644 index 000000000000..9289973bae20 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-min2.f90 @@ -0,0 +1,41 @@ +! RUN: bbc -emit-hlfir -fopenmp -o - %s | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s | FileCheck %s + +! regression test for crash + +program reduce +integer :: i = 0 +integer :: r = 0 + +!$omp parallel do reduction(min:r) +do i=0,10 + r = i +enddo +!$omp end parallel do + +print *,r + +end program + +! TODO: the reduction is not curently lowered correctly. This test is checking +! that we do not crash and we still produce the same broken IR as before. + +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFEr) : !fir.ref +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFEr"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: omp.parallel { +! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_7:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop for (%[[VAL_9:.*]]) : i32 = (%[[VAL_6]]) to (%[[VAL_7]]) inclusive step (%[[VAL_8]]) { +! CHECK: fir.store %[[VAL_9]] to %[[VAL_5]]#1 : !fir.ref +! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref +! CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_3]]#0 : i32, !fir.ref +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-mul-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-mul-byref.f90 new file mode 100644 index 000000000000..00854281b87e --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-mul-byref.f90 @@ -0,0 +1,414 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.reduction.declare @multiply_reduction_f_64_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[VAL_1:.*]] = arith.constant 1.000000e+00 : f64 +! CHECK: %[[REF:.*]] = fir.alloca f64 +! CHECK: fir.store %[[VAL_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.mulf %[[LD0]], %[[LD1]] fastmath : f64 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: omp.reduction.declare @multiply_reduction_i_64_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[VAL_1:.*]] = arith.constant 1 : i64 +! CHECK: %[[REF:.*]] = fir.alloca i64 +! CHECK: fir.store %[[VAL_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.muli %[[LD0]], %[[LD1]] : i64 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: omp.reduction.declare @multiply_reduction_f_32_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[VAL_1:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[REF:.*]] = fir.alloca f32 +! CHECK: fir.store %[[VAL_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.mulf %[[LD0]], %[[LD1]] fastmath : f32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: omp.reduction.declare @multiply_reduction_i_32_byref : !fir.ref +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref): +! CHECK: %[[VAL_1:.*]] = arith.constant 1 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[VAL_1]] to %[[REF]] : !fir.ref +! CHECK: omp.yield(%[[REF]] : !fir.ref) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref, %[[ARG1:.*]]: !fir.ref): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref +! CHECK: %[[RES:.*]] = arith.muli %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref +! CHECK: omp.yield(%[[ARG0]] : !fir.ref) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_int_reduction() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_reductionEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_int_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_int_reductionEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : i32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_int_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@multiply_reduction_i_32_byref %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref +! CHECK: %[[VAL_15:.*]] = arith.muli %[[VAL_13]], %[[VAL_14]] : i32 +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_12]]#0 : i32, !fir.ref +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_int_reduction + integer :: x + x = 1 + !$omp parallel + !$omp do reduction(*:x) + do i=1, 10 + x = x * i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_real_reduction() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_real_reductionEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_real_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFsimple_real_reductionEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_real_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : f32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_real_reductionEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@multiply_reduction_f_32_byref %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reductionEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i32) -> f32 +! CHECK: %[[VAL_16:.*]] = arith.mulf %[[VAL_13]], %[[VAL_15]] fastmath : f32 +! CHECK: hlfir.assign %[[VAL_16]] to %[[VAL_12]]#0 : f32, !fir.ref +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_real_reduction + real :: x + x = 1.0 + !$omp parallel + !$omp do reduction(*:x) + do i=1, 10 + x = x * i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_int_reduction_switch_order() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_reduction_switch_orderEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_int_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_int_reduction_switch_orderEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_int_reduction_switch_orderEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : i32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_int_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@multiply_reduction_i_32_byref %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reduction_switch_orderEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_15:.*]] = arith.muli %[[VAL_13]], %[[VAL_14]] : i32 +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_12]]#0 : i32, !fir.ref +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_int_reduction_switch_order + integer :: x + x = 1 + !$omp parallel + !$omp do reduction(*:x) + do i=1, 10 + x = i * x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_real_reduction_switch_order() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_real_reduction_switch_orderEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_real_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFsimple_real_reduction_switch_orderEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_real_reduction_switch_orderEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : f32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_real_reduction_switch_orderEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@multiply_reduction_f_32_byref %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reduction_switch_orderEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref +! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (i32) -> f32 +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_16:.*]] = arith.mulf %[[VAL_14]], %[[VAL_15]] fastmath : f32 +! CHECK: hlfir.assign %[[VAL_16]] to %[[VAL_12]]#0 : f32, !fir.ref +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_real_reduction_switch_order + real :: x + x = 1.0 + !$omp parallel + !$omp do reduction(*:x) + do i=1, 10 + x = i * x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_int_reductions_same_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_int_reductions_same_typeEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFmultiple_int_reductions_same_typeEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_int_reductions_same_typeEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFmultiple_int_reductions_same_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFmultiple_int_reductions_same_typeEy"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFmultiple_int_reductions_same_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFmultiple_int_reductions_same_typeEz"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_int_reductions_same_typeEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: hlfir.assign %[[VAL_8]] to %[[VAL_3]]#0 : i32, !fir.ref +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_5]]#0 : i32, !fir.ref +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_7]]#0 : i32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_11:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFmultiple_int_reductions_same_typeEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@multiply_reduction_i_32_byref %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref, @multiply_reduction_i_32_byref %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref, @multiply_reduction_i_32_byref %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { +! CHECK: fir.store %[[VAL_19]] to %[[VAL_12]]#1 : !fir.ref +! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_int_reductions_same_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_int_reductions_same_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_int_reductions_same_typeEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_20]]#0 : !fir.ref +! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_25:.*]] = arith.muli %[[VAL_23]], %[[VAL_24]] : i32 +! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_20]]#0 : i32, !fir.ref +! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_21]]#0 : !fir.ref +! CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_28:.*]] = arith.muli %[[VAL_26]], %[[VAL_27]] : i32 +! CHECK: hlfir.assign %[[VAL_28]] to %[[VAL_21]]#0 : i32, !fir.ref +! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_22]]#0 : !fir.ref +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_31:.*]] = arith.muli %[[VAL_29]], %[[VAL_30]] : i32 +! CHECK: hlfir.assign %[[VAL_31]] to %[[VAL_22]]#0 : i32, !fir.ref +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine multiple_int_reductions_same_type + integer :: x,y,z + x = 1 + y = 1 + z = 1 + !$omp parallel + !$omp do reduction(*:x,y,z) + do i=1, 10 + x = x * i + y = y * i + z = z * i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_real_reductions_same_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_real_reductions_same_typeEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFmultiple_real_reductions_same_typeEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFmultiple_real_reductions_same_typeEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFmultiple_real_reductions_same_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = fir.alloca f32 {bindc_name = "y", uniq_name = "_QFmultiple_real_reductions_same_typeEy"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFmultiple_real_reductions_same_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_6:.*]] = fir.alloca f32 {bindc_name = "z", uniq_name = "_QFmultiple_real_reductions_same_typeEz"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_real_reductions_same_typeEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_8:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_8]] to %[[VAL_3]]#0 : f32, !fir.ref +! CHECK: %[[VAL_9:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_5]]#0 : f32, !fir.ref +! CHECK: %[[VAL_10:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_7]]#0 : f32, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_11:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFmultiple_real_reductions_same_typeEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@multiply_reduction_f_32_byref %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref, @multiply_reduction_f_32_byref %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref, @multiply_reduction_f_32_byref %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { +! CHECK: fir.store %[[VAL_19]] to %[[VAL_12]]#1 : !fir.ref +! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_real_reductions_same_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_real_reductions_same_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_real_reductions_same_typeEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_20]]#0 : !fir.ref +! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_24]] : (i32) -> f32 +! CHECK: %[[VAL_26:.*]] = arith.mulf %[[VAL_23]], %[[VAL_25]] fastmath : f32 +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_20]]#0 : f32, !fir.ref +! CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_21]]#0 : !fir.ref +! CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_28]] : (i32) -> f32 +! CHECK: %[[VAL_30:.*]] = arith.mulf %[[VAL_27]], %[[VAL_29]] fastmath : f32 +! CHECK: hlfir.assign %[[VAL_30]] to %[[VAL_21]]#0 : f32, !fir.ref +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_22]]#0 : !fir.ref +! CHECK: %[[VAL_32:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref +! CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_32]] : (i32) -> f32 +! CHECK: %[[VAL_34:.*]] = arith.mulf %[[VAL_31]], %[[VAL_33]] fastmath : f32 +! CHECK: hlfir.assign %[[VAL_34]] to %[[VAL_22]]#0 : f32, !fir.ref +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine multiple_real_reductions_same_type + real :: x,y,z + x = 1 + y = 1 + z = 1 + !$omp parallel + !$omp do reduction(*:x,y,z) + do i=1, 10 + x = x * i + y = y * i + z = z * i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions_different_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductions_different_typeEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFmultiple_reductions_different_typeEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_2:.*]] = fir.alloca f64 {bindc_name = "w", uniq_name = "_QFmultiple_reductions_different_typeEw"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFmultiple_reductions_different_typeEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_reductions_different_typeEx"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFmultiple_reductions_different_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_6:.*]] = fir.alloca i64 {bindc_name = "y", uniq_name = "_QFmultiple_reductions_different_typeEy"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductions_different_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_8:.*]] = fir.alloca f32 {bindc_name = "z", uniq_name = "_QFmultiple_reductions_different_typeEz"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFmultiple_reductions_different_typeEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_5]]#0 : i32, !fir.ref +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i64 +! CHECK: hlfir.assign %[[VAL_11]] to %[[VAL_7]]#0 : i64, !fir.ref +! CHECK: %[[VAL_12:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_12]] to %[[VAL_9]]#0 : f32, !fir.ref +! CHECK: %[[VAL_13:.*]] = arith.constant 1.000000e+00 : f64 +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_3]]#0 : f64, !fir.ref +! CHECK: omp.parallel { +! CHECK: %[[VAL_14:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]] {uniq_name = "_QFmultiple_reductions_different_typeEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_17:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@multiply_reduction_i_32_byref %[[VAL_5]]#0 -> %[[VAL_19:.*]] : !fir.ref, @multiply_reduction_i_64_byref %[[VAL_7]]#0 -> %[[VAL_20:.*]] : !fir.ref, @multiply_reduction_f_32_byref %[[VAL_9]]#0 -> %[[VAL_21:.*]] : !fir.ref, @multiply_reduction_f_64_byref %[[VAL_3]]#0 -> %[[VAL_22:.*]] : !fir.ref) for (%[[VAL_23:.*]]) : i32 = (%[[VAL_16]]) to (%[[VAL_17]]) inclusive step (%[[VAL_18]]) { +! CHECK: fir.store %[[VAL_23]] to %[[VAL_15]]#1 : !fir.ref +! CHECK: %[[VAL_24:.*]]:2 = hlfir.declare %[[VAL_19]] {uniq_name = "_QFmultiple_reductions_different_typeEx"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_25:.*]]:2 = hlfir.declare %[[VAL_20]] {uniq_name = "_QFmultiple_reductions_different_typeEy"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_26:.*]]:2 = hlfir.declare %[[VAL_21]] {uniq_name = "_QFmultiple_reductions_different_typeEz"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_22]] {uniq_name = "_QFmultiple_reductions_different_typeEw"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_24]]#0 : !fir.ref +! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref +! CHECK: %[[VAL_30:.*]] = arith.muli %[[VAL_28]], %[[VAL_29]] : i32 +! CHECK: hlfir.assign %[[VAL_30]] to %[[VAL_24]]#0 : i32, !fir.ref +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_25]]#0 : !fir.ref +! CHECK: %[[VAL_32:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref +! CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_32]] : (i32) -> i64 +! CHECK: %[[VAL_34:.*]] = arith.muli %[[VAL_31]], %[[VAL_33]] : i64 +! CHECK: hlfir.assign %[[VAL_34]] to %[[VAL_25]]#0 : i64, !fir.ref +! CHECK: %[[VAL_35:.*]] = fir.load %[[VAL_26]]#0 : !fir.ref +! CHECK: %[[VAL_36:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref +! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_36]] : (i32) -> f32 +! CHECK: %[[VAL_38:.*]] = arith.mulf %[[VAL_35]], %[[VAL_37]] fastmath : f32 +! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_26]]#0 : f32, !fir.ref +! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_27]]#0 : !fir.ref +! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref +! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> f64 +! CHECK: %[[VAL_42:.*]] = arith.mulf %[[VAL_39]], %[[VAL_41]] fastmath : f64 +! CHECK: hlfir.assign %[[VAL_42]] to %[[VAL_27]]#0 : f64, !fir.ref +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + + +subroutine multiple_reductions_different_type + integer :: x + integer(kind=8) :: y + real :: z + real(kind=8) :: w + x = 1 + y = 1 + z = 1 + w = 1 + !$omp parallel + !$omp do reduction(*:x,y,z,w) + do i=1, 10 + x = x * i + y = y * i + z = z * i + w = w * i + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h index 5bbaa8c208b8..c9ee0c25194c 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h @@ -1339,10 +1339,12 @@ public: /// in reductions. /// \param ReductionInfos A list of info on each reduction variable. /// \param IsNoWait A flag set if the reduction is marked as nowait. + /// \param IsByRef A flag set if the reduction is using reference + /// or direct value. InsertPointTy createReductions(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef ReductionInfos, - bool IsNoWait = false); + bool IsNoWait = false, bool IsByRef = false); ///} diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp index d65ed8c11d86..c74c898e1e88 100644 --- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -2110,7 +2110,7 @@ Function *getFreshReductionFunc(Module &M) { OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createReductions( const LocationDescription &Loc, InsertPointTy AllocaIP, - ArrayRef ReductionInfos, bool IsNoWait) { + ArrayRef ReductionInfos, bool IsNoWait, bool IsByRef) { for (const ReductionInfo &RI : ReductionInfos) { (void)RI; assert(RI.Variable && "expected non-null variable"); @@ -2197,17 +2197,29 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createReductions( for (auto En : enumerate(ReductionInfos)) { const ReductionInfo &RI = En.value(); Type *ValueType = RI.ElementType; - Value *RedValue = Builder.CreateLoad(ValueType, RI.Variable, - "red.value." + Twine(En.index())); + // We have one less load for by-ref case because that load is now inside of + // the reduction region + Value *RedValue = nullptr; + if (!IsByRef) { + RedValue = Builder.CreateLoad(ValueType, RI.Variable, + "red.value." + Twine(En.index())); + } Value *PrivateRedValue = Builder.CreateLoad(ValueType, RI.PrivateVariable, "red.private.value." + Twine(En.index())); Value *Reduced; - Builder.restoreIP( - RI.ReductionGen(Builder.saveIP(), RedValue, PrivateRedValue, Reduced)); + if (IsByRef) { + Builder.restoreIP(RI.ReductionGen(Builder.saveIP(), RI.Variable, + PrivateRedValue, Reduced)); + } else { + Builder.restoreIP(RI.ReductionGen(Builder.saveIP(), RedValue, + PrivateRedValue, Reduced)); + } if (!Builder.GetInsertBlock()) return InsertPointTy(); - Builder.CreateStore(Reduced, RI.Variable); + // for by-ref case, the load is inside of the reduction region + if (!IsByRef) + Builder.CreateStore(Reduced, RI.Variable); } Function *EndReduceFunc = getOrCreateRuntimeFunctionPtr( IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait @@ -2219,7 +2231,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createReductions( // function. There are no loads/stores here because they will be happening // inside the atomic elementwise reduction. Builder.SetInsertPoint(AtomicRedBlock); - if (CanGenerateAtomic) { + if (CanGenerateAtomic && !IsByRef) { for (const ReductionInfo &RI : ReductionInfos) { Builder.restoreIP(RI.AtomicReductionGen(Builder.saveIP(), RI.ElementType, RI.Variable, RI.PrivateVariable)); @@ -2257,7 +2269,9 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createReductions( Builder.restoreIP(RI.ReductionGen(Builder.saveIP(), LHS, RHS, Reduced)); if (!Builder.GetInsertBlock()) return InsertPointTy(); - Builder.CreateStore(Reduced, LHSPtr); + // store is inside of the reduction region when using by-ref + if (!IsByRef) + Builder.CreateStore(Reduced, LHSPtr); } Builder.CreateRetVoid(); diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td index 39ff49f0ccf5..0bd402d626dc 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -268,6 +268,9 @@ def ParallelOp : OpenMP_Op<"parallel", [ The optional $proc_bind_val attribute controls the thread affinity for the execution of the parallel region. + + The optional byref attribute controls whether reduction arguments are passed by + reference or by value. }]; let arguments = (ins Optional:$if_expr_var, @@ -278,7 +281,8 @@ def ParallelOp : OpenMP_Op<"parallel", [ OptionalAttr:$reductions, OptionalAttr:$proc_bind_val, Variadic:$private_vars, - OptionalAttr:$privatizers); + OptionalAttr:$privatizers, + UnitAttr:$byref); let regions = (region AnyRegion:$region); @@ -299,6 +303,7 @@ def ParallelOp : OpenMP_Op<"parallel", [ $allocators_vars, type($allocators_vars) ) `)` | `proc_bind` `(` custom($proc_bind_val) `)` + | `byref` $byref ) custom($region, $reduction_vars, type($reduction_vars), $reductions, $private_vars, type($private_vars), $privatizers) attr-dict @@ -570,6 +575,9 @@ def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, The optional `order` attribute specifies which order the iterations of the associate loops are executed in. Currently the only option for this attribute is "concurrent". + + The optional `byref` attribute indicates that reduction arguments should be + passed by reference. }]; let arguments = (ins Variadic:$lowerBound, @@ -584,6 +592,7 @@ def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, OptionalAttr:$schedule_modifier, UnitAttr:$simd_modifier, UnitAttr:$nowait, + UnitAttr:$byref, ConfinedAttr, [IntMinValue<0>]>:$ordered_val, OptionalAttr:$order_val, UnitAttr:$inclusive); @@ -613,6 +622,7 @@ def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, $schedule_val, $schedule_modifier, $simd_modifier, $schedule_chunk_var, type($schedule_chunk_var)) `)` |`nowait` $nowait + |`byref` $byref |`ordered` `(` $ordered_val `)` |`order` `(` custom($order_val) `)` ) custom($region, $lowerBound, $upperBound, $step, diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp index 8a6980e2c6a2..e7b899aec4af 100644 --- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -1209,7 +1209,7 @@ void ParallelOp::build(OpBuilder &builder, OperationState &state, /*allocate_vars=*/ValueRange(), /*allocators_vars=*/ValueRange(), /*reduction_vars=*/ValueRange(), /*reductions=*/nullptr, /*proc_bind_val=*/nullptr, /*private_vars=*/ValueRange(), - /*privatizers=*/nullptr); + /*privatizers=*/nullptr, /*byref=*/false); state.addAttributes(attributes); } @@ -1674,7 +1674,8 @@ void WsLoopOp::build(OpBuilder &builder, OperationState &state, /*linear_step_vars=*/ValueRange(), /*reduction_vars=*/ValueRange(), /*reductions=*/nullptr, /*schedule_val=*/nullptr, /*schedule_chunk_var=*/nullptr, /*schedule_modifier=*/nullptr, - /*simd_modifier=*/false, /*nowait=*/false, /*ordered_val=*/nullptr, + /*simd_modifier=*/false, /*nowait=*/false, /*byref=*/false, + /*ordered_val=*/nullptr, /*order_val=*/nullptr, /*inclusive=*/false); state.addAttributes(attributes); } diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index bef227f2c583..5027f2afe921 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -805,12 +805,12 @@ convertOmpTaskgroupOp(omp::TaskGroupOp tgOp, llvm::IRBuilderBase &builder, /// Allocate space for privatized reduction variables. template static void -allocReductionVars(T loop, llvm::IRBuilderBase &builder, - LLVM::ModuleTranslation &moduleTranslation, - llvm::OpenMPIRBuilder::InsertPointTy &allocaIP, - SmallVector &reductionDecls, - SmallVector &privateReductionVariables, - DenseMap &reductionVariableMap) { +allocByValReductionVars(T loop, llvm::IRBuilderBase &builder, + LLVM::ModuleTranslation &moduleTranslation, + llvm::OpenMPIRBuilder::InsertPointTy &allocaIP, + SmallVector &reductionDecls, + SmallVector &privateReductionVariables, + DenseMap &reductionVariableMap) { llvm::IRBuilderBase::InsertPointGuard guard(builder); builder.restoreIP(allocaIP); auto args = @@ -863,6 +863,7 @@ static LogicalResult convertOmpWsLoop(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { auto loop = cast(opInst); + const bool isByRef = loop.getByref(); // TODO: this should be in the op verifier instead. if (loop.getLowerBound().empty()) return failure(); @@ -888,18 +889,17 @@ convertOmpWsLoop(Operation &opInst, llvm::IRBuilderBase &builder, SmallVector privateReductionVariables; DenseMap reductionVariableMap; - allocReductionVars(loop, builder, moduleTranslation, allocaIP, reductionDecls, - privateReductionVariables, reductionVariableMap); - - // Store the mapping between reduction variables and their private copies on - // ModuleTranslation stack. It can be then recovered when translating - // omp.reduce operations in a separate call. - LLVM::ModuleTranslation::SaveStack mappingGuard( - moduleTranslation, reductionVariableMap); + if (!isByRef) { + allocByValReductionVars(loop, builder, moduleTranslation, allocaIP, + reductionDecls, privateReductionVariables, + reductionVariableMap); + } // Before the loop, store the initial values of reductions into reduction // variables. Although this could be done after allocas, we don't want to mess // up with the alloca insertion point. + MutableArrayRef reductionArgs = + loop.getRegion().getArguments().take_back(loop.getNumReductionVars()); for (unsigned i = 0; i < loop.getNumReductionVars(); ++i) { SmallVector phis; if (failed(inlineConvertOmpRegions(reductionDecls[i].getInitializerRegion(), @@ -908,9 +908,31 @@ convertOmpWsLoop(Operation &opInst, llvm::IRBuilderBase &builder, return failure(); assert(phis.size() == 1 && "expected one value to be yielded from the " "reduction neutral element declaration region"); - builder.CreateStore(phis[0], privateReductionVariables[i]); + if (isByRef) { + // Allocate reduction variable (which is a pointer to the real reduction + // variable allocated in the inlined region) + llvm::Value *var = builder.CreateAlloca( + moduleTranslation.convertType(reductionDecls[i].getType())); + // Store the result of the inlined region to the allocated reduction var + // ptr + builder.CreateStore(phis[0], var); + + privateReductionVariables.push_back(var); + moduleTranslation.mapValue(reductionArgs[i], phis[0]); + reductionVariableMap.try_emplace(loop.getReductionVars()[i], phis[0]); + } else { + // for by-ref case the store is inside of the reduction region + builder.CreateStore(phis[0], privateReductionVariables[i]); + // the rest was handled in allocByValReductionVars + } } + // Store the mapping between reduction variables and their private copies on + // ModuleTranslation stack. It can be then recovered when translating + // omp.reduce operations in a separate call. + LLVM::ModuleTranslation::SaveStack mappingGuard( + moduleTranslation, reductionVariableMap); + // Set up the source location value for OpenMP runtime. llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder); @@ -1014,7 +1036,7 @@ convertOmpWsLoop(Operation &opInst, llvm::IRBuilderBase &builder, builder.SetInsertPoint(tempTerminator); llvm::OpenMPIRBuilder::InsertPointTy contInsertPoint = ompBuilder->createReductions(builder.saveIP(), allocaIP, reductionInfos, - loop.getNowait()); + loop.getNowait(), isByRef); if (!contInsertPoint.getBlock()) return loop->emitOpError() << "failed to convert reductions"; auto nextInsertionPoint = @@ -1068,6 +1090,7 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy; OmpParallelOpConversionManager raii(opInst); + const bool isByRef = opInst.getByref(); // TODO: support error propagation in OpenMPIRBuilder and use it instead of // relying on captured variables. @@ -1082,18 +1105,17 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, // Allocate reduction vars SmallVector privateReductionVariables; DenseMap reductionVariableMap; - allocReductionVars(opInst, builder, moduleTranslation, allocaIP, - reductionDecls, privateReductionVariables, - reductionVariableMap); - - // Store the mapping between reduction variables and their private copies on - // ModuleTranslation stack. It can be then recovered when translating - // omp.reduce operations in a separate call. - LLVM::ModuleTranslation::SaveStack mappingGuard( - moduleTranslation, reductionVariableMap); + if (!isByRef) { + allocByValReductionVars(opInst, builder, moduleTranslation, allocaIP, + reductionDecls, privateReductionVariables, + reductionVariableMap); + } // Initialize reduction vars builder.restoreIP(allocaIP); + MutableArrayRef reductionArgs = + opInst.getRegion().getArguments().take_back( + opInst.getNumReductionVars()); for (unsigned i = 0; i < opInst.getNumReductionVars(); ++i) { SmallVector phis; if (failed(inlineConvertOmpRegions( @@ -1104,9 +1126,32 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, "expected one value to be yielded from the " "reduction neutral element declaration region"); builder.restoreIP(allocaIP); - builder.CreateStore(phis[0], privateReductionVariables[i]); + + if (isByRef) { + // Allocate reduction variable (which is a pointer to the real reduciton + // variable allocated in the inlined region) + llvm::Value *var = builder.CreateAlloca( + moduleTranslation.convertType(reductionDecls[i].getType())); + // Store the result of the inlined region to the allocated reduction var + // ptr + builder.CreateStore(phis[0], var); + + privateReductionVariables.push_back(var); + moduleTranslation.mapValue(reductionArgs[i], phis[0]); + reductionVariableMap.try_emplace(opInst.getReductionVars()[i], phis[0]); + } else { + // for by-ref case the store is inside of the reduction init region + builder.CreateStore(phis[0], privateReductionVariables[i]); + // the rest is done in allocByValReductionVars + } } + // Store the mapping between reduction variables and their private copies on + // ModuleTranslation stack. It can be then recovered when translating + // omp.reduce operations in a separate call. + LLVM::ModuleTranslation::SaveStack mappingGuard( + moduleTranslation, reductionVariableMap); + // Save the alloca insertion point on ModuleTranslation stack for use in // nested regions. LLVM::ModuleTranslation::SaveStack frame( @@ -1137,7 +1182,7 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy contInsertPoint = ompBuilder->createReductions(builder.saveIP(), allocaIP, - reductionInfos, false); + reductionInfos, false, isByRef); if (!contInsertPoint.getBlock()) { bodyGenStatus = opInst->emitOpError() << "failed to convert reductions"; return; diff --git a/mlir/test/Target/LLVMIR/openmp-reduction-byref.mlir b/mlir/test/Target/LLVMIR/openmp-reduction-byref.mlir new file mode 100644 index 000000000000..4ac1ebd43e1e --- /dev/null +++ b/mlir/test/Target/LLVMIR/openmp-reduction-byref.mlir @@ -0,0 +1,66 @@ +// RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s + + omp.reduction.declare @add_reduction_i_32 : !llvm.ptr init { + ^bb0(%arg0: !llvm.ptr): + %0 = llvm.mlir.constant(0 : i32) : i32 + %1 = llvm.mlir.constant(1 : i64) : i64 + %2 = llvm.alloca %1 x i32 : (i64) -> !llvm.ptr + llvm.store %0, %2 : i32, !llvm.ptr + omp.yield(%2 : !llvm.ptr) + } combiner { + ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr): + %0 = llvm.load %arg0 : !llvm.ptr -> i32 + %1 = llvm.load %arg1 : !llvm.ptr -> i32 + %2 = llvm.add %0, %1 : i32 + llvm.store %2, %arg0 : i32, !llvm.ptr + omp.yield(%arg0 : !llvm.ptr) + } + + // CHECK-LABEL: @main + llvm.func @main() { + %0 = llvm.mlir.constant(-1 : i32) : i32 + %1 = llvm.mlir.addressof @i : !llvm.ptr + omp.parallel byref reduction(@add_reduction_i_32 %1 -> %arg0 : !llvm.ptr) { + llvm.store %0, %arg0 : i32, !llvm.ptr + omp.terminator + } + llvm.return + } + llvm.mlir.global internal @i() {addr_space = 0 : i32} : i32 { + %0 = llvm.mlir.constant(0 : i32) : i32 + llvm.return %0 : i32 + } + +// CHECK: %{{.+}} = +// Call to the outlined function. +// CHECK: call void {{.*}} @__kmpc_fork_call +// CHECK-SAME: @[[OUTLINED:[A-Za-z_.][A-Za-z0-9_.]*]] + +// Outlined function. +// CHECK: define internal void @[[OUTLINED]] + +// Private reduction variable and its initialization. +// CHECK: %tid.addr.local = alloca i32 +// CHECK: %[[PRIVATE:.+]] = alloca i32 +// CHECK: store i32 0, ptr %[[PRIVATE]] +// CHECK: store ptr %[[PRIVATE]], ptr %[[PRIV_PTR:.+]], + +// Call to the reduction function. +// CHECK: call i32 @__kmpc_reduce +// CHECK-SAME: @[[REDFUNC:[A-Za-z_.][A-Za-z0-9_.]*]] + + +// Non-atomic reduction: +// CHECK: %[[PRIV_VAL_PTR:.+]] = load ptr, ptr %[[PRIV_PTR]] +// CHECK: %[[LOAD:.+]] = load i32, ptr @i +// CHECK: %[[PRIV_VAL:.+]] = load i32, ptr %[[PRIV_VAL_PTR]] +// CHECK: %[[SUM:.+]] = add i32 %[[LOAD]], %[[PRIV_VAL]] +// CHECK: store i32 %[[SUM]], ptr @i +// CHECK: call void @__kmpc_end_reduce +// CHECK: br label %[[FINALIZE:.+]] + +// CHECK: [[FINALIZE]]: + +// Reduction function. +// CHECK: define internal void @[[REDFUNC]] +// CHECK: add i32 -- GitLab From 3c227a31dd1046db02323868b9690a6152cfb3b8 Mon Sep 17 00:00:00 2001 From: Jon Roelofs Date: Wed, 13 Mar 2024 08:02:22 -0700 Subject: [PATCH 384/953] [cmake] Silence a duplicate libraries warning from Apple's linker (#85012) ld: warning: ignoring duplicate libraries: This triggers quite frequently in llvm's build because CMake's library depends mechanism doesn't de-duplicate libraries on the link line. Duplication is necessary for ELF platforms, but means something subtly different on Darwin platforms, hence the warning. Since we don't have much control over that from CMake, just disable the warning wholesale whenever the linker is detected to support it. --- llvm/cmake/modules/AddLLVM.cmake | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake index 374f5e085d91..eb9e6101bdce 100644 --- a/llvm/cmake/modules/AddLLVM.cmake +++ b/llvm/cmake/modules/AddLLVM.cmake @@ -257,6 +257,16 @@ if (NOT DEFINED LLVM_LINKER_DETECTED AND NOT WIN32) message(STATUS "Linker detection: unknown") endif() endif() + + # Apple's linker complains about duplicate libraries, which CMake likes to do + # to support ELF platforms. To silence that warning, we can use + # -no_warn_duplicate_libraries, but only in versions of the linker that + # support that flag. + if(NOT LLVM_USE_LINKER AND ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + check_linker_flag(C "-Wl,-no_warn_duplicate_libraries" LLVM_LINKER_SUPPORTS_NO_WARN_DUPLICATE_LIBRARIES) + else() + set(LLVM_LINKER_SUPPORTS_NO_WARN_DUPLICATE_LIBRARIES OFF CACHE INTERNAL "") + endif() endif() function(add_link_opts target_name) @@ -310,6 +320,11 @@ function(add_link_opts target_name) endif() endif() + if(LLVM_LINKER_SUPPORTS_NO_WARN_DUPLICATE_LIBRARIES) + set_property(TARGET ${target_name} APPEND_STRING PROPERTY + LINK_FLAGS " -Wl,-no_warn_duplicate_libraries") + endif() + if(ARG_SUPPORT_PLUGINS AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-brtl") -- GitLab From 628a79dad30befed82ee1c115b00fa9aca5305ed Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 13 Mar 2024 16:09:25 +0100 Subject: [PATCH 385/953] [InstCombine] Don't generate crash dialog for fixpoint verification failure (NFC) Fixpoint verification failures outside our tests are usually not indicative of a bug -- don't be pushy about having people report them. --- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 1688005de210..c9bbe437b368 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -5202,7 +5202,8 @@ static bool combineInstructionsOverFunction( if (Iteration > Opts.MaxIterations) { report_fatal_error( "Instruction Combining did not reach a fixpoint after " + - Twine(Opts.MaxIterations) + " iterations"); + Twine(Opts.MaxIterations) + " iterations", + /*GenCrashDiag=*/false); } } -- GitLab From 59ff907fc14aa2d02e57b4af4140949d4f8caca1 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 13 Mar 2024 07:45:14 -0700 Subject: [PATCH 386/953] [SLP]Fix PR85082: PHI node has multiple entries. Need to record casted extractelement for the externally used scalar, not original extract instruction. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 10 +-- .../X86/same-scalar-in-same-phi-extract.ll | 75 +++++++++++++++++++ 2 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index b8b67609d755..5e0f5b7efadc 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -12592,6 +12592,11 @@ Value *BoUpSLP::vectorizeTree( } else { Ex = Builder.CreateExtractElement(Vec, Lane); } + // If necessary, sign-extend or zero-extend ScalarRoot + // to the larger type. + if (Scalar->getType() != Ex->getType()) + Ex = Builder.CreateIntCast(Ex, Scalar->getType(), + MinBWs.find(E)->second.second); if (auto *I = dyn_cast(Ex)) ScalarToEEs[Scalar].try_emplace(Builder.GetInsertBlock(), I); } @@ -12601,11 +12606,6 @@ Value *BoUpSLP::vectorizeTree( GatherShuffleExtractSeq.insert(ExI); CSEBlocks.insert(ExI->getParent()); } - // If necessary, sign-extend or zero-extend ScalarRoot - // to the larger type. - if (Scalar->getType() != Ex->getType()) - return Builder.CreateIntCast(Ex, Scalar->getType(), - MinBWs.find(E)->second.second); return Ex; } assert(isa(Scalar->getType()) && diff --git a/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll b/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll new file mode 100644 index 000000000000..35f2f9e052e7 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll @@ -0,0 +1,75 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -slp-threshold=-99999 -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s + +define void @test(i32 %arg) { +; CHECK-LABEL: define void @test( +; CHECK-SAME: i32 [[ARG:%.*]]) { +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i32> , i32 [[ARG]], i32 0 +; CHECK-NEXT: br label [[BB2:%.*]] +; CHECK: bb2: +; CHECK-NEXT: switch i32 0, label [[BB10:%.*]] [ +; CHECK-NEXT: i32 0, label [[BB9:%.*]] +; CHECK-NEXT: i32 11, label [[BB9]] +; CHECK-NEXT: i32 1, label [[BB4:%.*]] +; CHECK-NEXT: ] +; CHECK: bb3: +; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x i32> [[TMP0]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[TMP1]] to i64 +; CHECK-NEXT: switch i32 0, label [[BB10]] [ +; CHECK-NEXT: i32 18, label [[BB7:%.*]] +; CHECK-NEXT: i32 1, label [[BB7]] +; CHECK-NEXT: i32 0, label [[BB10]] +; CHECK-NEXT: ] +; CHECK: bb4: +; CHECK-NEXT: [[TMP3:%.*]] = phi <2 x i32> [ [[TMP0]], [[BB2]] ] +; CHECK-NEXT: [[TMP4:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64> +; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i64> [[TMP4]], i32 0 +; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr i32, ptr null, i64 [[TMP5]] +; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i64> [[TMP4]], i32 1 +; CHECK-NEXT: [[GETELEMENTPTR6:%.*]] = getelementptr i32, ptr null, i64 [[TMP6]] +; CHECK-NEXT: ret void +; CHECK: bb7: +; CHECK-NEXT: [[PHI8:%.*]] = phi i64 [ [[TMP2]], [[BB3:%.*]] ], [ [[TMP2]], [[BB3]] ] +; CHECK-NEXT: br label [[BB9]] +; CHECK: bb9: +; CHECK-NEXT: ret void +; CHECK: bb10: +; CHECK-NEXT: ret void +; +bb: + %zext = zext i32 %arg to i64 + %zext1 = zext i32 0 to i64 + br label %bb2 + +bb2: + switch i32 0, label %bb10 [ + i32 0, label %bb9 + i32 11, label %bb9 + i32 1, label %bb4 + ] + +bb3: + switch i32 0, label %bb10 [ + i32 18, label %bb7 + i32 1, label %bb7 + i32 0, label %bb10 + ] + +bb4: + %phi = phi i64 [ %zext, %bb2 ] + %phi5 = phi i64 [ %zext1, %bb2 ] + %getelementptr = getelementptr i32, ptr null, i64 %phi + %getelementptr6 = getelementptr i32, ptr null, i64 %phi5 + ret void + +bb7: + %phi8 = phi i64 [ %zext, %bb3 ], [ %zext, %bb3 ] + br label %bb9 + +bb9: + ret void + +bb10: + ret void +} -- GitLab From 096ee4e16fd62cd578d20ec4e8ad4756f4e369ee Mon Sep 17 00:00:00 2001 From: agozillon Date: Wed, 13 Mar 2024 16:18:21 +0100 Subject: [PATCH 387/953] [Flang][OpenMP] Implement "promotion" of use_device_ptr non-cptr arguments to use_device_addr (#82834) This effectively implements some now deprecated OpenMP functionality that some applications (most notably at the moment GenASiS) unfortunately depend on (deprecated in specification version 5.2): "If a list item in a use_device_ptr clause is not of type C_PTR, the behavior is as if the list item appeared in a use_device_addr clause. Support for such list items in a use_device_ptr clause is deprecated." This PR downgrades the hard-error to a deprecated warning and "promotes" the above cases by simply moving the offending operands from the use_device_ptr value list to the back of the use_device_addr list (and moves the related symbols, locs and types that form the BlockArgs correspondingly) and then the generation of the target data construct proceeds as normal. --- flang/lib/Lower/OpenMP/OpenMP.cpp | 66 +++++++++++++++++ flang/lib/Semantics/check-omp-structure.cpp | 2 +- .../use-device-ptr-to-use-device-addr.f90 | 72 +++++++++++++++++++ .../test/Semantics/OpenMP/use_device_ptr1.f90 | 2 +- 4 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 flang/test/Lower/OpenMP/use-device-ptr-to-use-device-addr.f90 diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 1016c8389c6e..25bb4d9cff5d 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -798,6 +798,58 @@ genTaskGroupOp(Fortran::lower::AbstractConverter &converter, /*task_reductions=*/nullptr, allocateOperands, allocatorOperands); } +// This helper function implements the functionality of "promoting" +// non-CPTR arguments of use_device_ptr to use_device_addr +// arguments (automagic conversion of use_device_ptr -> +// use_device_addr in these cases). The way we do so currently is +// through the shuffling of operands from the devicePtrOperands to +// deviceAddrOperands where neccesary and re-organizing the types, +// locations and symbols to maintain the correct ordering of ptr/addr +// input -> BlockArg. +// +// This effectively implements some deprecated OpenMP functionality +// that some legacy applications unfortunately depend on +// (deprecated in specification version 5.2): +// +// "If a list item in a use_device_ptr clause is not of type C_PTR, +// the behavior is as if the list item appeared in a use_device_addr +// clause. Support for such list items in a use_device_ptr clause +// is deprecated." +static void promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr( + llvm::SmallVector &devicePtrOperands, + llvm::SmallVector &deviceAddrOperands, + llvm::SmallVector &useDeviceTypes, + llvm::SmallVector &useDeviceLocs, + llvm::SmallVector &useDeviceSymbols) { + auto moveElementToBack = [](size_t idx, auto &vector) { + auto *iter = std::next(vector.begin(), idx); + vector.push_back(*iter); + vector.erase(iter); + }; + + // Iterate over our use_device_ptr list and shift all non-cptr arguments into + // use_device_addr. + for (auto *it = devicePtrOperands.begin(); it != devicePtrOperands.end();) { + if (!fir::isa_builtin_cptr_type(fir::unwrapRefType(it->getType()))) { + deviceAddrOperands.push_back(*it); + // We have to shuffle the symbols around as well, to maintain + // the correct Input -> BlockArg for use_device_ptr/use_device_addr. + // NOTE: However, as map's do not seem to be included currently + // this isn't as pertinent, but we must try to maintain for + // future alterations. I believe the reason they are not currently + // is that the BlockArg assign/lowering needs to be extended + // to a greater set of types. + auto idx = std::distance(devicePtrOperands.begin(), it); + moveElementToBack(idx, useDeviceTypes); + moveElementToBack(idx, useDeviceLocs); + moveElementToBack(idx, useDeviceSymbols); + it = devicePtrOperands.erase(it); + continue; + } + ++it; + } +} + static mlir::omp::DataOp genDataOp(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, @@ -820,6 +872,20 @@ genDataOp(Fortran::lower::AbstractConverter &converter, useDeviceSymbols); cp.processUseDeviceAddr(deviceAddrOperands, useDeviceTypes, useDeviceLocs, useDeviceSymbols); + // This function implements the deprecated functionality of use_device_ptr + // that allows users to provide non-CPTR arguments to it with the caveat + // that the compiler will treat them as use_device_addr. A lot of legacy + // code may still depend on this functionality, so we should support it + // in some manner. We do so currently by simply shifting non-cptr operands + // from the use_device_ptr list into the front of the use_device_addr list + // whilst maintaining the ordering of useDeviceLocs, useDeviceSymbols and + // useDeviceTypes to use_device_ptr/use_device_addr input for BlockArg + // ordering. + // TODO: Perhaps create a user provideable compiler option that will + // re-introduce a hard-error rather than a warning in these cases. + promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr( + devicePtrOperands, deviceAddrOperands, useDeviceTypes, useDeviceLocs, + useDeviceSymbols); cp.processMap(currentLocation, llvm::omp::Directive::OMPD_target_data, stmtCtx, mapOperands); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 54101ab8a42b..bf4debee1df3 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -2948,7 +2948,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::UseDevicePtr &x) { if (name->symbol) { if (!(IsBuiltinCPtr(*(name->symbol)))) { context_.Say(itr->second->source, - "'%s' in USE_DEVICE_PTR clause must be of type C_PTR"_err_en_US, + "Use of non-C_PTR type '%s' in USE_DEVICE_PTR is deprecated, use USE_DEVICE_ADDR instead"_warn_en_US, name->ToString()); } else { useDevicePtrNameList.push_back(*name); diff --git a/flang/test/Lower/OpenMP/use-device-ptr-to-use-device-addr.f90 b/flang/test/Lower/OpenMP/use-device-ptr-to-use-device-addr.f90 new file mode 100644 index 000000000000..33b597165601 --- /dev/null +++ b/flang/test/Lower/OpenMP/use-device-ptr-to-use-device-addr.f90 @@ -0,0 +1,72 @@ +!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s +!RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s + +! This tests primary goal is to check the promotion of +! non-CPTR arguments from use_device_ptr to +! use_device_addr works, without breaking any +! functionality + +!CHECK: func.func @{{.*}}only_use_device_ptr() +!CHECK: omp.target_data use_device_ptr(%{{.*}} : !fir.ref>) use_device_addr(%{{.*}}, %{{.*}} : !fir.ref>>>, !fir.ref>>>) { +!CHECK: ^bb0(%{{.*}}: !fir.ref>, %{{.*}}: !fir.ref>>>, %{{.*}}: !fir.ref>>>): +subroutine only_use_device_ptr + use iso_c_binding + integer, pointer, dimension(:) :: array + real, pointer :: pa(:) + type(c_ptr) :: cptr + + !$omp target data use_device_ptr(pa, cptr, array) + !$omp end target data +end subroutine + +!CHECK: func.func @{{.*}}mix_use_device_ptr_and_addr() +!CHECK: omp.target_data use_device_ptr({{.*}} : !fir.ref>) use_device_addr(%{{.*}}, %{{.*}} : !fir.ref>>>, !fir.ref>>>) { +!CHECK: ^bb0(%{{.*}}: !fir.ref>, %{{.*}}: !fir.ref>>>, %{{.*}}: !fir.ref>>>): +subroutine mix_use_device_ptr_and_addr + use iso_c_binding + integer, pointer, dimension(:) :: array + real, pointer :: pa(:) + type(c_ptr) :: cptr + + !$omp target data use_device_ptr(pa, cptr) use_device_addr(array) + !$omp end target data +end subroutine + +!CHECK: func.func @{{.*}}only_use_device_addr() +!CHECK: omp.target_data use_device_addr(%{{.*}}, %{{.*}}, %{{.*}} : !fir.ref>>>, !fir.ref>, !fir.ref>>>) { +!CHECK: ^bb0(%{{.*}}: !fir.ref>>>, %{{.*}}: !fir.ref>, %{{.*}}: !fir.ref>>>): +subroutine only_use_device_addr + use iso_c_binding + integer, pointer, dimension(:) :: array + real, pointer :: pa(:) + type(c_ptr) :: cptr + + !$omp target data use_device_addr(pa, cptr, array) + !$omp end target data +end subroutine + +!CHECK: func.func @{{.*}}mix_use_device_ptr_and_addr_and_map() +!CHECK: omp.target_data map_entries(%{{.*}}, %{{.*}} : !fir.ref, !fir.ref) use_device_ptr(%{{.*}} : !fir.ref>) use_device_addr(%{{.*}}, %{{.*}} : !fir.ref>>>, !fir.ref>>>) { +!CHECK: ^bb0(%{{.*}}: !fir.ref>, %{{.*}}: !fir.ref>>>, %{{.*}}: !fir.ref>>>): +subroutine mix_use_device_ptr_and_addr_and_map + use iso_c_binding + integer :: i, j + integer, pointer, dimension(:) :: array + real, pointer :: pa(:) + type(c_ptr) :: cptr + + !$omp target data use_device_ptr(pa, cptr) use_device_addr(array) map(tofrom: i, j) + !$omp end target data +end subroutine + +!CHECK: func.func @{{.*}}only_use_map() +!CHECK: omp.target_data map_entries(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : !fir.llvm_ptr>>, !fir.ref>>>, !fir.ref>, !fir.llvm_ptr>>, !fir.ref>>>) { +subroutine only_use_map + use iso_c_binding + integer, pointer, dimension(:) :: array + real, pointer :: pa(:) + type(c_ptr) :: cptr + + !$omp target data map(pa, cptr, array) + !$omp end target data +end subroutine diff --git a/flang/test/Semantics/OpenMP/use_device_ptr1.f90 b/flang/test/Semantics/OpenMP/use_device_ptr1.f90 index af89698a5c5a..176fb5f35a84 100644 --- a/flang/test/Semantics/OpenMP/use_device_ptr1.f90 +++ b/flang/test/Semantics/OpenMP/use_device_ptr1.f90 @@ -27,7 +27,7 @@ subroutine omp_target_data a = arrayB !$omp end target data - !ERROR: 'a' in USE_DEVICE_PTR clause must be of type C_PTR + !WARNING: Use of non-C_PTR type 'a' in USE_DEVICE_PTR is deprecated, use USE_DEVICE_ADDR instead !$omp target data map(tofrom: a) use_device_ptr(a) a = 2 !$omp end target data -- GitLab From 732f5368cdc297e83f8720fb13a8c848ff116ccf Mon Sep 17 00:00:00 2001 From: Slava Zakharin Date: Wed, 13 Mar 2024 08:23:10 -0700 Subject: [PATCH 388/953] [RFC][mlir] Add profitability callback to the Inliner. (#84258) Discussion at https://discourse.llvm.org/t/inliner-cost-model/2992 This change adds a callback that reports whether inlining of the particular call site (communicated via ResolvedCall argument) is profitable or not. The default MLIR inliner pass behavior is unchanged, i.e. the callback always returns true. This callback may be used to customize the inliner behavior based on the target specifics (like target instructions costs), profitability of the inlining for further optimizations (e.g. if inlining may enable loop optimizations or scalar optimizations due to object shape propagation), optimization levels (e.g. -Os inlining may be quite different from -Ofast inlining), etc. One of the questions is whether the ResolvedCall entity represents enough of the context for the custom inlining models to come up with the profitability decision. I think we can start with this and extend it as necessary. --------- Co-authored-by: Mehdi Amini --- mlir/include/mlir/Transforms/Inliner.h | 43 +++++++++++-------- mlir/include/mlir/Transforms/Passes.td | 7 +++ mlir/lib/Transforms/InlinerPass.cpp | 38 +++++++++++++++- mlir/lib/Transforms/Utils/Inliner.cpp | 3 ++ .../inlining-dump-default-pipeline.mlir | 2 +- mlir/test/Transforms/inlining-threshold.mlir | 18 ++++++++ 6 files changed, 92 insertions(+), 19 deletions(-) create mode 100644 mlir/test/Transforms/inlining-threshold.mlir diff --git a/mlir/include/mlir/Transforms/Inliner.h b/mlir/include/mlir/Transforms/Inliner.h index 1fe61fb4bbe7..073b83f6f844 100644 --- a/mlir/include/mlir/Transforms/Inliner.h +++ b/mlir/include/mlir/Transforms/Inliner.h @@ -69,19 +69,6 @@ private: /// of inlining decisions from the leafs to the roots of the callgraph. class Inliner { public: - using RunPipelineHelperTy = std::function; - - Inliner(Operation *op, CallGraph &cg, Pass &pass, AnalysisManager am, - RunPipelineHelperTy runPipelineHelper, const InlinerConfig &config) - : op(op), cg(cg), pass(pass), am(am), - runPipelineHelper(std::move(runPipelineHelper)), config(config) {} - Inliner(Inliner &) = delete; - void operator=(const Inliner &) = delete; - - /// Perform inlining on a OpTrait::SymbolTable operation. - LogicalResult doInlining(); - /// This struct represents a resolved call to a given callgraph node. Given /// that the call does not actually contain a direct reference to the /// Region(CallGraphNode) that it is dispatching to, we need to resolve them @@ -94,7 +81,29 @@ public: CallGraphNode *sourceNode, *targetNode; }; -protected: + using RunPipelineHelperTy = std::function; + + /// Type of the callback answering if it is profitable + /// to inline a callable operation at a call site. + /// It might be the case that the ResolvedCall does not provide + /// enough context to make the profitability decision, so + /// this hook's interface might need to be extended in future. + using ProfitabilityCallbackTy = std::function; + + Inliner(Operation *op, CallGraph &cg, Pass &pass, AnalysisManager am, + RunPipelineHelperTy runPipelineHelper, const InlinerConfig &config, + ProfitabilityCallbackTy isProfitableToInline) + : op(op), cg(cg), pass(pass), am(am), + runPipelineHelper(std::move(runPipelineHelper)), config(config), + isProfitableToInline(std::move(isProfitableToInline)) {} + Inliner(Inliner &) = delete; + void operator=(const Inliner &) = delete; + + /// Perform inlining on a OpTrait::SymbolTable operation. + LogicalResult doInlining(); + +private: /// An OpTrait::SymbolTable operation to run the inlining on. Operation *op; /// A CallGraph analysis for the given operation. @@ -108,12 +117,12 @@ protected: const RunPipelineHelperTy runPipelineHelper; /// The inliner configuration parameters. const InlinerConfig &config; + /// Returns true, if it is profitable to inline the callable operation + /// at the call site. + ProfitabilityCallbackTy isProfitableToInline; -private: /// Forward declaration of the class providing the actual implementation. class Impl; - -public: }; } // namespace mlir diff --git a/mlir/include/mlir/Transforms/Passes.td b/mlir/include/mlir/Transforms/Passes.td index b8fdf7a58047..51b2a27da639 100644 --- a/mlir/include/mlir/Transforms/Passes.td +++ b/mlir/include/mlir/Transforms/Passes.td @@ -278,6 +278,13 @@ def Inliner : Pass<"inline"> { Option<"maxInliningIterations", "max-iterations", "unsigned", /*default=*/"4", "Maximum number of iterations when inlining within an SCC">, + Option<"inliningThreshold", "inlining-threshold", "unsigned", + /*default=*/"-1U", + "If the ratio between the number of the operations " + "in the callee and the number of the operations " + "in the caller exceeds this value (in percentage), " + "then the callee is not inlined even if it is legal " + "to inline it">, ]; } diff --git a/mlir/lib/Transforms/InlinerPass.cpp b/mlir/lib/Transforms/InlinerPass.cpp index c058e8050cd1..08d8dbf73a6a 100644 --- a/mlir/lib/Transforms/InlinerPass.cpp +++ b/mlir/lib/Transforms/InlinerPass.cpp @@ -24,6 +24,8 @@ namespace mlir { #include "mlir/Transforms/Passes.h.inc" } // namespace mlir +#define DEBUG_TYPE "inliner-pass" + using namespace mlir; /// This function implements the inliner optimization pipeline. @@ -88,6 +90,35 @@ InlinerPass::InlinerPass(std::function defaultPipeline, config.setOpPipelines(std::move(opPipelines)); } +// Return true if the inlining ratio does not exceed the threshold. +static bool isProfitableToInline(const Inliner::ResolvedCall &resolvedCall, + unsigned inliningThreshold) { + Region *callerRegion = resolvedCall.sourceNode->getCallableRegion(); + Region *calleeRegion = resolvedCall.targetNode->getCallableRegion(); + + // We should not get external nodes here, but just return true + // for now to preserve the original behavior of the inliner pass. + if (!calleeRegion || !calleeRegion) + return true; + + auto countOps = [](Region *region) { + unsigned count = 0; + region->walk([&](Operation *) { ++count; }); + return count; + }; + + unsigned callerOps = countOps(callerRegion); + + // Always inline empty callees (if it is possible at all). + if (callerOps == 0) + return true; + + unsigned ratio = countOps(calleeRegion) * 100 / callerOps; + LLVM_DEBUG(llvm::dbgs() << "Callee / caller operation ratio (max: " + << inliningThreshold << "%): " << ratio << "%\n"); + return ratio <= inliningThreshold; +} + void InlinerPass::runOnOperation() { CallGraph &cg = getAnalysis(); @@ -100,9 +131,14 @@ void InlinerPass::runOnOperation() { return signalPassFailure(); } + // By default, assume that any inlining is profitable. + auto profitabilityCb = [=](const Inliner::ResolvedCall &call) { + return isProfitableToInline(call, inliningThreshold); + }; + // Get an instance of the inliner. Inliner inliner(op, cg, *this, getAnalysisManager(), runPipelineHelper, - config); + config, profitabilityCb); // Run the inlining. if (failed(inliner.doInlining())) diff --git a/mlir/lib/Transforms/Utils/Inliner.cpp b/mlir/lib/Transforms/Utils/Inliner.cpp index f227cedb269d..8acfc96d2b61 100644 --- a/mlir/lib/Transforms/Utils/Inliner.cpp +++ b/mlir/lib/Transforms/Utils/Inliner.cpp @@ -741,6 +741,9 @@ bool Inliner::Impl::shouldInline(ResolvedCall &resolvedCall) { if (calleeHasMultipleBlocks && !callerRegionSupportsMultipleBlocks()) return false; + if (!inliner.isProfitableToInline(resolvedCall)) + return false; + // Otherwise, inline. return true; } diff --git a/mlir/test/Transforms/inlining-dump-default-pipeline.mlir b/mlir/test/Transforms/inlining-dump-default-pipeline.mlir index e2c31867a8e0..4f8638054206 100644 --- a/mlir/test/Transforms/inlining-dump-default-pipeline.mlir +++ b/mlir/test/Transforms/inlining-dump-default-pipeline.mlir @@ -1,2 +1,2 @@ // RUN: mlir-opt %s -pass-pipeline="builtin.module(inline)" -dump-pass-pipeline 2>&1 | FileCheck %s -// CHECK: builtin.module(inline{default-pipeline=canonicalize max-iterations=4 }) +// CHECK: builtin.module(inline{default-pipeline=canonicalize inlining-threshold=4294967295 max-iterations=4 }) diff --git a/mlir/test/Transforms/inlining-threshold.mlir b/mlir/test/Transforms/inlining-threshold.mlir new file mode 100644 index 000000000000..b94115d8f264 --- /dev/null +++ b/mlir/test/Transforms/inlining-threshold.mlir @@ -0,0 +1,18 @@ +// RUN: mlir-opt %s --mlir-disable-threading -inline='default-pipeline='' inlining-threshold=100' -debug-only=inliner-pass 2>&1 | FileCheck %s + +// Check that inlining does not happen when the threshold is exceeded. +func.func @callee1(%arg : i32) -> i32 { + %v1 = arith.addi %arg, %arg : i32 + %v2 = arith.addi %v1, %arg : i32 + %v3 = arith.addi %v2, %arg : i32 + return %v3 : i32 +} + +// CHECK-LABEL: func @caller1 +func.func @caller1(%arg0 : i32) -> i32 { + // CHECK-NEXT: call @callee1 + // CHECK-NEXT: return + + %0 = call @callee1(%arg0) : (i32) -> i32 + return %0 : i32 +} -- GitLab From e0738cc65865c31975b5bdbbf89c5a4dbbe06dc5 Mon Sep 17 00:00:00 2001 From: Slava Zakharin Date: Wed, 13 Mar 2024 08:26:33 -0700 Subject: [PATCH 389/953] [flang] Moved REAL(16) RANDOM_NUMBER to Float128Math library. (#85002) --- .../Optimizer/Builder/Runtime/Intrinsics.cpp | 29 ++++++- flang/runtime/Float128Math/CMakeLists.txt | 1 + flang/runtime/Float128Math/random.cpp | 23 +++++ flang/runtime/random-templates.h | 87 +++++++++++++++++++ flang/runtime/random.cpp | 81 ++--------------- .../Lower/Intrinsics/random_number_real16.f90 | 16 ++++ 6 files changed, 160 insertions(+), 77 deletions(-) create mode 100644 flang/runtime/Float128Math/random.cpp create mode 100644 flang/runtime/random-templates.h create mode 100644 flang/test/Lower/Intrinsics/random_number_real16.f90 diff --git a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp index 638bfd60a246..57c47da0f3f8 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp @@ -27,6 +27,24 @@ using namespace Fortran::runtime; +namespace { +/// Placeholder for real*16 version of RandomNumber Intrinsic +struct ForcedRandomNumberReal16 { + static constexpr const char *name = ExpandAndQuoteKey(RTNAME(RandomNumber16)); + static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { + return [](mlir::MLIRContext *ctx) { + auto boxTy = + fir::runtime::getModel()(ctx); + auto strTy = fir::runtime::getModel()(ctx); + auto intTy = fir::runtime::getModel()(ctx); + ; + return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy}, + mlir::NoneType::get(ctx)); + }; + } +}; +} // namespace + mlir::Value fir::runtime::genAssociated(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value pointer, mlir::Value target) { @@ -100,8 +118,15 @@ void fir::runtime::genRandomInit(fir::FirOpBuilder &builder, mlir::Location loc, void fir::runtime::genRandomNumber(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value harvest) { - mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc(loc, builder); + mlir::func::FuncOp func; + auto boxEleTy = fir::dyn_cast_ptrOrBoxEleTy(harvest.getType()); + auto eleTy = fir::unwrapSequenceType(boxEleTy); + if (eleTy.isF128()) { + func = fir::runtime::getRuntimeFunc(loc, builder); + } else { + func = fir::runtime::getRuntimeFunc(loc, builder); + } + mlir::FunctionType funcTy = func.getFunctionType(); mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); mlir::Value sourceLine = diff --git a/flang/runtime/Float128Math/CMakeLists.txt b/flang/runtime/Float128Math/CMakeLists.txt index 980356131b68..33f73a9c5445 100644 --- a/flang/runtime/Float128Math/CMakeLists.txt +++ b/flang/runtime/Float128Math/CMakeLists.txt @@ -48,6 +48,7 @@ set(sources nearest.cpp norm2.cpp pow.cpp + random.cpp round.cpp rrspacing.cpp scale.cpp diff --git a/flang/runtime/Float128Math/random.cpp b/flang/runtime/Float128Math/random.cpp new file mode 100644 index 000000000000..cda962b41614 --- /dev/null +++ b/flang/runtime/Float128Math/random.cpp @@ -0,0 +1,23 @@ +//===-- runtime/Float128Math/random.cpp -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "math-entries.h" +#include "numeric-template-specs.h" +#include "random-templates.h" + +using namespace Fortran::runtime::random; +extern "C" { + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +void RTDEF(RandomNumber16)( + const Descriptor &harvest, const char *source, int line) { + return Generate, 113>(harvest); +} +#endif + +} // extern "C" diff --git a/flang/runtime/random-templates.h b/flang/runtime/random-templates.h new file mode 100644 index 000000000000..ce64a94901a2 --- /dev/null +++ b/flang/runtime/random-templates.h @@ -0,0 +1,87 @@ +//===-- runtime/random-templates.h ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_RUNTIME_RANDOM_TEMPLATES_H_ +#define FORTRAN_RUNTIME_RANDOM_TEMPLATES_H_ + +#include "lock.h" +#include "numeric-templates.h" +#include "flang/Runtime/descriptor.h" +#include +#include + +namespace Fortran::runtime::random { + +// Newer "Minimum standard", recommended by Park, Miller, and Stockmeyer in +// 1993. Same as C++17 std::minstd_rand, but explicitly instantiated for +// permanence. +using Generator = + std::linear_congruential_engine; + +using GeneratedWord = typename Generator::result_type; +static constexpr std::uint64_t range{ + static_cast(Generator::max() - Generator::min() + 1)}; +static constexpr bool rangeIsPowerOfTwo{(range & (range - 1)) == 0}; +static constexpr int rangeBits{ + 64 - common::LeadingZeroBitCount(range) - !rangeIsPowerOfTwo}; + +extern Lock lock; +extern Generator generator; +extern std::optional nextValue; + +// Call only with lock held +static GeneratedWord GetNextValue() { + GeneratedWord result; + if (nextValue.has_value()) { + result = *nextValue; + nextValue.reset(); + } else { + result = generator(); + } + return result; +} + +template +inline void Generate(const Descriptor &harvest) { + static constexpr std::size_t minBits{ + std::max(PREC, 8 * sizeof(GeneratedWord))}; + using Int = common::HostUnsignedIntType; + static constexpr std::size_t words{ + static_cast(PREC + rangeBits - 1) / rangeBits}; + std::size_t elements{harvest.Elements()}; + SubscriptValue at[maxRank]; + harvest.GetLowerBounds(at); + { + CriticalSection critical{lock}; + for (std::size_t j{0}; j < elements; ++j) { + while (true) { + Int fraction{GetNextValue()}; + if constexpr (words > 1) { + for (std::size_t k{1}; k < words; ++k) { + static constexpr auto rangeMask{ + (GeneratedWord{1} << rangeBits) - 1}; + GeneratedWord word{(GetNextValue() - generator.min()) & rangeMask}; + fraction = (fraction << rangeBits) | word; + } + } + fraction >>= words * rangeBits - PREC; + REAL next{ + LDEXPTy::compute(static_cast(fraction), -(PREC + 1))}; + if (next >= 0.0 && next < 1.0) { + *harvest.Element(at) = next; + break; + } + } + harvest.IncrementSubscripts(at); + } + } +} + +} // namespace Fortran::runtime::random + +#endif // FORTRAN_RUNTIME_RANDOM_TEMPLATES_H_ diff --git a/flang/runtime/random.cpp b/flang/runtime/random.cpp index 642091a06aff..13bed1f0abe1 100644 --- a/flang/runtime/random.cpp +++ b/flang/runtime/random.cpp @@ -11,85 +11,24 @@ #include "flang/Runtime/random.h" #include "lock.h" +#include "random-templates.h" #include "terminator.h" #include "flang/Common/float128.h" #include "flang/Common/leading-zero-bit-count.h" #include "flang/Common/uint128.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" -#include #include #include #include #include -#include #include -namespace Fortran::runtime { +namespace Fortran::runtime::random { -// Newer "Minimum standard", recommended by Park, Miller, and Stockmeyer in -// 1993. Same as C++17 std::minstd_rand, but explicitly instantiated for -// permanence. -using Generator = - std::linear_congruential_engine; - -using GeneratedWord = typename Generator::result_type; -static constexpr std::uint64_t range{ - static_cast(Generator::max() - Generator::min() + 1)}; -static constexpr bool rangeIsPowerOfTwo{(range & (range - 1)) == 0}; -static constexpr int rangeBits{ - 64 - common::LeadingZeroBitCount(range) - !rangeIsPowerOfTwo}; - -static Lock lock; -static Generator generator; -static std::optional nextValue; - -// Call only with lock held -static GeneratedWord GetNextValue() { - GeneratedWord result; - if (nextValue.has_value()) { - result = *nextValue; - nextValue.reset(); - } else { - result = generator(); - } - return result; -} - -template -inline void Generate(const Descriptor &harvest) { - static constexpr std::size_t minBits{ - std::max(PREC, 8 * sizeof(GeneratedWord))}; - using Int = common::HostUnsignedIntType; - static constexpr std::size_t words{ - static_cast(PREC + rangeBits - 1) / rangeBits}; - std::size_t elements{harvest.Elements()}; - SubscriptValue at[maxRank]; - harvest.GetLowerBounds(at); - { - CriticalSection critical{lock}; - for (std::size_t j{0}; j < elements; ++j) { - while (true) { - Int fraction{GetNextValue()}; - if constexpr (words > 1) { - for (std::size_t k{1}; k < words; ++k) { - static constexpr auto rangeMask{ - (GeneratedWord{1} << rangeBits) - 1}; - GeneratedWord word{(GetNextValue() - generator.min()) & rangeMask}; - fraction = (fraction << rangeBits) | word; - } - } - fraction >>= words * rangeBits - PREC; - REAL next{std::ldexp(static_cast(fraction), -(PREC + 1))}; - if (next >= 0.0 && next < 1.0) { - *harvest.Element(at) = next; - break; - } - } - harvest.IncrementSubscripts(at); - } - } -} +Lock lock; +Generator generator; +std::optional nextValue; extern "C" { @@ -130,14 +69,6 @@ void RTNAME(RandomNumber)( #if LDBL_MANT_DIG == 64 Generate, 64>(harvest); return; -#endif - } - break; - case 16: - if constexpr (HasCppTypeFor) { -#if LDBL_MANT_DIG == 113 - Generate, 113>(harvest); - return; #endif } break; @@ -263,4 +194,4 @@ void RTNAME(RandomSeed)(const Descriptor *size, const Descriptor *put, } } // extern "C" -} // namespace Fortran::runtime +} // namespace Fortran::runtime::random diff --git a/flang/test/Lower/Intrinsics/random_number_real16.f90 b/flang/test/Lower/Intrinsics/random_number_real16.f90 new file mode 100644 index 000000000000..76fed258d8af --- /dev/null +++ b/flang/test/Lower/Intrinsics/random_number_real16.f90 @@ -0,0 +1,16 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: func @_QPtest_scalar +! CHECK: fir.call @_FortranARandomNumber16({{.*}}){{.*}}: (!fir.box, !fir.ref, i32) -> none +subroutine test_scalar + real(16) :: r + call random_number(r) +end + +! CHECK-LABEL: func @_QPtest_array +! CHECK: fir.call @_FortranARandomNumber16({{.*}}){{.*}}: (!fir.box, !fir.ref, i32) -> none +subroutine test_array(r) + real(16) :: r(:) + call random_number(r) +end -- GitLab From 286c3b500dc36b2451683bde5d681bf6efea3e63 Mon Sep 17 00:00:00 2001 From: Slava Zakharin Date: Wed, 13 Mar 2024 08:26:49 -0700 Subject: [PATCH 390/953] [flang] Enable REAL(16) MODULO lowering. (#85005) The lowering currently relies on the trivial operations, so we should just lower it for REAL(16) the same way we do this for other trivial operations. --- flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 5 +- flang/test/Lower/Intrinsics/modulo.f90 | 82 +++++++++++-------- 2 files changed, 52 insertions(+), 35 deletions(-) diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index ca5ab6fcea34..21d253624a1a 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -5208,6 +5208,8 @@ mlir::Value IntrinsicLibrary::genMod(mlir::Type resultType, // MODULO mlir::Value IntrinsicLibrary::genModulo(mlir::Type resultType, llvm::ArrayRef args) { + // TODO: we'd better generate a runtime call here, when runtime error + // checking is needed (to detect 0 divisor) or when precise math is requested. assert(args.size() == 2); // No floored modulo op in LLVM/MLIR yet. TODO: add one to MLIR. // In the meantime, use a simple inlined implementation based on truncated @@ -5233,10 +5235,7 @@ mlir::Value IntrinsicLibrary::genModulo(mlir::Type resultType, return builder.create(loc, mustAddP, remPlusP, remainder); } - // Real case - if (resultType == mlir::FloatType::getF128(builder.getContext())) - TODO(loc, "REAL(KIND=16): in MODULO intrinsic"); auto remainder = builder.create(loc, args[0], args[1]); mlir::Value zero = builder.createRealZeroConstant(loc, remainder.getType()); auto remainderIsNotZero = builder.create( diff --git a/flang/test/Lower/Intrinsics/modulo.f90 b/flang/test/Lower/Intrinsics/modulo.f90 index 64a6607a09cc..001e307aa077 100644 --- a/flang/test/Lower/Intrinsics/modulo.f90 +++ b/flang/test/Lower/Intrinsics/modulo.f90 @@ -3,36 +3,54 @@ ! CHECK-LABEL: func @_QPmodulo_testr( ! CHECK-SAME: %[[arg0:.*]]: !fir.ref{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}, %[[arg2:.*]]: !fir.ref{{.*}}) { subroutine modulo_testr(r, a, p) - real(8) :: r, a, p - ! CHECK-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref - ! CHECK-DAG: %[[p:.*]] = fir.load %[[arg2]] : !fir.ref - ! CHECK-DAG: %[[rem:.*]] = arith.remf %[[a]], %[[p]] {{.*}}: f64 - ! CHECK-DAG: %[[zero:.*]] = arith.constant 0.000000e+00 : f64 - ! CHECK-DAG: %[[remNotZero:.*]] = arith.cmpf une, %[[rem]], %[[zero]] {{.*}} : f64 - ! CHECK-DAG: %[[aNeg:.*]] = arith.cmpf olt, %[[a]], %[[zero]] {{.*}} : f64 - ! CHECK-DAG: %[[pNeg:.*]] = arith.cmpf olt, %[[p]], %[[zero]] {{.*}} : f64 - ! CHECK-DAG: %[[signDifferent:.*]] = arith.xori %[[aNeg]], %[[pNeg]] : i1 - ! CHECK-DAG: %[[mustAddP:.*]] = arith.andi %[[remNotZero]], %[[signDifferent]] : i1 - ! CHECK-DAG: %[[remPlusP:.*]] = arith.addf %[[rem]], %[[p]] {{.*}}: f64 - ! CHECK: %[[res:.*]] = arith.select %[[mustAddP]], %[[remPlusP]], %[[rem]] : f64 - ! CHECK: fir.store %[[res]] to %[[arg0]] : !fir.ref - r = modulo(a, p) - end subroutine - - ! CHECK-LABEL: func @_QPmodulo_testi( - ! CHECK-SAME: %[[arg0:.*]]: !fir.ref{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}, %[[arg2:.*]]: !fir.ref{{.*}}) { - subroutine modulo_testi(r, a, p) - integer(8) :: r, a, p - ! CHECK-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref - ! CHECK-DAG: %[[p:.*]] = fir.load %[[arg2]] : !fir.ref - ! CHECK-DAG: %[[rem:.*]] = arith.remsi %[[a]], %[[p]] : i64 - ! CHECK-DAG: %[[argXor:.*]] = arith.xori %[[a]], %[[p]] : i64 - ! CHECK-DAG: %[[signDifferent:.*]] = arith.cmpi slt, %[[argXor]], %c0{{.*}} : i64 - ! CHECK-DAG: %[[remNotZero:.*]] = arith.cmpi ne, %[[rem]], %c0{{.*}} : i64 - ! CHECK-DAG: %[[mustAddP:.*]] = arith.andi %[[remNotZero]], %[[signDifferent]] : i1 - ! CHECK-DAG: %[[remPlusP:.*]] = arith.addi %[[rem]], %[[p]] : i64 - ! CHECK: %[[res:.*]] = arith.select %[[mustAddP]], %[[remPlusP]], %[[rem]] : i64 - ! CHECK: fir.store %[[res]] to %[[arg0]] : !fir.ref - r = modulo(a, p) - end subroutine + real(8) :: r, a, p + ! CHECK-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref + ! CHECK-DAG: %[[p:.*]] = fir.load %[[arg2]] : !fir.ref + ! CHECK-DAG: %[[rem:.*]] = arith.remf %[[a]], %[[p]] {{.*}}: f64 + ! CHECK-DAG: %[[zero:.*]] = arith.constant 0.000000e+00 : f64 + ! CHECK-DAG: %[[remNotZero:.*]] = arith.cmpf une, %[[rem]], %[[zero]] {{.*}} : f64 + ! CHECK-DAG: %[[aNeg:.*]] = arith.cmpf olt, %[[a]], %[[zero]] {{.*}} : f64 + ! CHECK-DAG: %[[pNeg:.*]] = arith.cmpf olt, %[[p]], %[[zero]] {{.*}} : f64 + ! CHECK-DAG: %[[signDifferent:.*]] = arith.xori %[[aNeg]], %[[pNeg]] : i1 + ! CHECK-DAG: %[[mustAddP:.*]] = arith.andi %[[remNotZero]], %[[signDifferent]] : i1 + ! CHECK-DAG: %[[remPlusP:.*]] = arith.addf %[[rem]], %[[p]] {{.*}}: f64 + ! CHECK: %[[res:.*]] = arith.select %[[mustAddP]], %[[remPlusP]], %[[rem]] : f64 + ! CHECK: fir.store %[[res]] to %[[arg0]] : !fir.ref + r = modulo(a, p) +end subroutine +! CHECK-LABEL: func @_QPmodulo_testi( +! CHECK-SAME: %[[arg0:.*]]: !fir.ref{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}, %[[arg2:.*]]: !fir.ref{{.*}}) { +subroutine modulo_testi(r, a, p) + integer(8) :: r, a, p + ! CHECK-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref + ! CHECK-DAG: %[[p:.*]] = fir.load %[[arg2]] : !fir.ref + ! CHECK-DAG: %[[rem:.*]] = arith.remsi %[[a]], %[[p]] : i64 + ! CHECK-DAG: %[[argXor:.*]] = arith.xori %[[a]], %[[p]] : i64 + ! CHECK-DAG: %[[signDifferent:.*]] = arith.cmpi slt, %[[argXor]], %c0{{.*}} : i64 + ! CHECK-DAG: %[[remNotZero:.*]] = arith.cmpi ne, %[[rem]], %c0{{.*}} : i64 + ! CHECK-DAG: %[[mustAddP:.*]] = arith.andi %[[remNotZero]], %[[signDifferent]] : i1 + ! CHECK-DAG: %[[remPlusP:.*]] = arith.addi %[[rem]], %[[p]] : i64 + ! CHECK: %[[res:.*]] = arith.select %[[mustAddP]], %[[remPlusP]], %[[rem]] : i64 + ! CHECK: fir.store %[[res]] to %[[arg0]] : !fir.ref + r = modulo(a, p) +end subroutine + +! CHECK-LABEL: func @_QPmodulo_testr16( +! CHECK-SAME: %[[arg0:.*]]: !fir.ref{{.*}}, %[[arg1:.*]]: !fir.ref{{.*}}, %[[arg2:.*]]: !fir.ref{{.*}}) { +subroutine modulo_testr16(r, a, p) + real(16) :: r, a, p + ! CHECK-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref + ! CHECK-DAG: %[[p:.*]] = fir.load %[[arg2]] : !fir.ref + ! CHECK-DAG: %[[rem:.*]] = arith.remf %[[a]], %[[p]] {{.*}}: f128 + ! CHECK-DAG: %[[zero:.*]] = arith.constant 0.000000e+00 : f128 + ! CHECK-DAG: %[[remNotZero:.*]] = arith.cmpf une, %[[rem]], %[[zero]] {{.*}} : f128 + ! CHECK-DAG: %[[aNeg:.*]] = arith.cmpf olt, %[[a]], %[[zero]] {{.*}} : f128 + ! CHECK-DAG: %[[pNeg:.*]] = arith.cmpf olt, %[[p]], %[[zero]] {{.*}} : f128 + ! CHECK-DAG: %[[signDifferent:.*]] = arith.xori %[[aNeg]], %[[pNeg]] : i1 + ! CHECK-DAG: %[[mustAddP:.*]] = arith.andi %[[remNotZero]], %[[signDifferent]] : i1 + ! CHECK-DAG: %[[remPlusP:.*]] = arith.addf %[[rem]], %[[p]] {{.*}}: f128 + ! CHECK: %[[res:.*]] = arith.select %[[mustAddP]], %[[remPlusP]], %[[rem]] : f128 + ! CHECK: fir.store %[[res]] to %[[arg0]] : !fir.ref + r = modulo(a, p) +end subroutine -- GitLab From d24ff9aec4f2741804268a66d711d6d31cd06138 Mon Sep 17 00:00:00 2001 From: Slava Zakharin Date: Wed, 13 Mar 2024 08:27:15 -0700 Subject: [PATCH 391/953] [flang][runtime] Added lowering and runtime for REAL(16) IEEE_FMA. (#85017) --- flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 4 ++++ flang/runtime/Float128Math/CMakeLists.txt | 1 + flang/runtime/Float128Math/fma.cpp | 23 +++++++++++++++++++ flang/runtime/Float128Math/math-entries.h | 3 +++ flang/test/Lower/Intrinsics/fma_real16.f90 | 9 ++++++++ 5 files changed, 40 insertions(+) create mode 100644 flang/runtime/Float128Math/fma.cpp create mode 100644 flang/test/Lower/Intrinsics/fma_real16.f90 diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index 21d253624a1a..94fcfa350311 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -922,6 +922,8 @@ mlir::Value genComplexMathOp(fir::FirOpBuilder &builder, mlir::Location loc, constexpr auto FuncTypeReal16Real16 = genFuncType, Ty::Real<16>>; constexpr auto FuncTypeReal16Real16Real16 = genFuncType, Ty::Real<16>, Ty::Real<16>>; +constexpr auto FuncTypeReal16Real16Real16Real16 = + genFuncType, Ty::Real<16>, Ty::Real<16>, Ty::Real<16>>; constexpr auto FuncTypeReal16Integer4Real16 = genFuncType, Ty::Integer<4>, Ty::Real<16>>; constexpr auto FuncTypeInteger4Real16 = @@ -1143,6 +1145,8 @@ static constexpr MathOperation mathOperations[] = { {"fma", "llvm.fma.f64", genFuncType, Ty::Real<8>, Ty::Real<8>, Ty::Real<8>>, genMathOp}, + {"fma", RTNAME_STRING(FmaF128), FuncTypeReal16Real16Real16Real16, + genLibF128Call}, {"gamma", "tgammaf", genFuncType, Ty::Real<4>>, genLibCall}, {"gamma", "tgamma", genFuncType, Ty::Real<8>>, genLibCall}, {"gamma", RTNAME_STRING(TgammaF128), FuncTypeReal16Real16, genLibF128Call}, diff --git a/flang/runtime/Float128Math/CMakeLists.txt b/flang/runtime/Float128Math/CMakeLists.txt index 33f73a9c5445..a5f5bec1e7e4 100644 --- a/flang/runtime/Float128Math/CMakeLists.txt +++ b/flang/runtime/Float128Math/CMakeLists.txt @@ -33,6 +33,7 @@ set(sources exp.cpp exponent.cpp floor.cpp + fma.cpp fraction.cpp hypot.cpp j0.cpp diff --git a/flang/runtime/Float128Math/fma.cpp b/flang/runtime/Float128Math/fma.cpp new file mode 100644 index 000000000000..ec67e8e6fba2 --- /dev/null +++ b/flang/runtime/Float128Math/fma.cpp @@ -0,0 +1,23 @@ +//===-- runtime/Float128Math/fma.cpp --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "math-entries.h" + +namespace Fortran::runtime { +extern "C" { + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +CppTypeFor RTDEF(FmaF128)( + CppTypeFor x, CppTypeFor y, + CppTypeFor z) { + return Fma::invoke(x, y, z); +} +#endif + +} // extern "C" +} // namespace Fortran::runtime diff --git a/flang/runtime/Float128Math/math-entries.h b/flang/runtime/Float128Math/math-entries.h index 1eab7c86f2ed..13fdab264700 100644 --- a/flang/runtime/Float128Math/math-entries.h +++ b/flang/runtime/Float128Math/math-entries.h @@ -77,6 +77,7 @@ DEFINE_FALLBACK_F128(Erf) DEFINE_FALLBACK_F128(Erfc) DEFINE_FALLBACK_F128(Exp) DEFINE_FALLBACK_F128(Floor) +DEFINE_FALLBACK_F128(Fma) DEFINE_FALLBACK_F128(Frexp) DEFINE_FALLBACK_F128(Hypot) DEFINE_FALLBACK_I32(Ilogb) @@ -124,6 +125,7 @@ DEFINE_SIMPLE_ALIAS(Erf, erfq) DEFINE_SIMPLE_ALIAS(Erfc, erfcq) DEFINE_SIMPLE_ALIAS(Exp, expq) DEFINE_SIMPLE_ALIAS(Floor, floorq) +DEFINE_SIMPLE_ALIAS(Fma, fmaq) DEFINE_SIMPLE_ALIAS(Frexp, frexpq) DEFINE_SIMPLE_ALIAS(Hypot, hypotq) DEFINE_SIMPLE_ALIAS(Ilogb, ilogbq) @@ -177,6 +179,7 @@ DEFINE_SIMPLE_ALIAS(Erf, std::erf) DEFINE_SIMPLE_ALIAS(Erfc, std::erfc) DEFINE_SIMPLE_ALIAS(Exp, std::exp) DEFINE_SIMPLE_ALIAS(Floor, std::floor) +DEFINE_SIMPLE_ALIAS(Fma, std::fma) DEFINE_SIMPLE_ALIAS(Frexp, std::frexp) DEFINE_SIMPLE_ALIAS(Hypot, std::hypot) DEFINE_SIMPLE_ALIAS(Ilogb, std::ilogb) diff --git a/flang/test/Lower/Intrinsics/fma_real16.f90 b/flang/test/Lower/Intrinsics/fma_real16.f90 new file mode 100644 index 000000000000..62cf2fbcefbf --- /dev/null +++ b/flang/test/Lower/Intrinsics/fma_real16.f90 @@ -0,0 +1,9 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranAFmaF128({{.*}}){{.*}}: (f128, f128, f128) -> f128 + use ieee_arithmetic, only: ieee_fma + real(16) :: x, y, z + x = ieee_fma(x, y, z) +end -- GitLab From 9a3000cf6700a711f3d81d071e0b6933cef46c36 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Wed, 13 Mar 2024 08:36:49 -0700 Subject: [PATCH 392/953] [libc] roll out rest of stdbit.h entrypoints to gpu,linux,baremetal (#84938) --- libc/config/gpu/entrypoints.txt | 30 +++++++++++++++++++++++ libc/config/linux/aarch64/entrypoints.txt | 30 +++++++++++++++++++++++ libc/config/linux/arm/entrypoints.txt | 30 +++++++++++++++++++++++ libc/config/linux/riscv/entrypoints.txt | 30 +++++++++++++++++++++++ 4 files changed, 120 insertions(+) diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt index fca5315fc4f0..4fb87cb9f5a3 100644 --- a/libc/config/gpu/entrypoints.txt +++ b/libc/config/gpu/entrypoints.txt @@ -106,6 +106,36 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdbit.stdc_first_trailing_one_ui libc.src.stdbit.stdc_first_trailing_one_ul libc.src.stdbit.stdc_first_trailing_one_ull + libc.src.stdbit.stdc_count_zeros_uc + libc.src.stdbit.stdc_count_zeros_us + libc.src.stdbit.stdc_count_zeros_ui + libc.src.stdbit.stdc_count_zeros_ul + libc.src.stdbit.stdc_count_zeros_ull + libc.src.stdbit.stdc_count_ones_uc + libc.src.stdbit.stdc_count_ones_us + libc.src.stdbit.stdc_count_ones_ui + libc.src.stdbit.stdc_count_ones_ul + libc.src.stdbit.stdc_count_ones_ull + libc.src.stdbit.stdc_has_single_bit_uc + libc.src.stdbit.stdc_has_single_bit_us + libc.src.stdbit.stdc_has_single_bit_ui + libc.src.stdbit.stdc_has_single_bit_ul + libc.src.stdbit.stdc_has_single_bit_ull + libc.src.stdbit.stdc_bit_width_uc + libc.src.stdbit.stdc_bit_width_us + libc.src.stdbit.stdc_bit_width_ui + libc.src.stdbit.stdc_bit_width_ul + libc.src.stdbit.stdc_bit_width_ull + libc.src.stdbit.stdc_bit_floor_uc + libc.src.stdbit.stdc_bit_floor_us + libc.src.stdbit.stdc_bit_floor_ui + libc.src.stdbit.stdc_bit_floor_ul + libc.src.stdbit.stdc_bit_floor_ull + libc.src.stdbit.stdc_bit_ceil_uc + libc.src.stdbit.stdc_bit_ceil_us + libc.src.stdbit.stdc_bit_ceil_ui + libc.src.stdbit.stdc_bit_ceil_ul + libc.src.stdbit.stdc_bit_ceil_ull # stdlib.h entrypoints libc.src.stdlib.abs diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index abd1f83794ed..7d69099e3cb9 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -131,6 +131,36 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdbit.stdc_first_trailing_one_ui libc.src.stdbit.stdc_first_trailing_one_ul libc.src.stdbit.stdc_first_trailing_one_ull + libc.src.stdbit.stdc_count_zeros_uc + libc.src.stdbit.stdc_count_zeros_us + libc.src.stdbit.stdc_count_zeros_ui + libc.src.stdbit.stdc_count_zeros_ul + libc.src.stdbit.stdc_count_zeros_ull + libc.src.stdbit.stdc_count_ones_uc + libc.src.stdbit.stdc_count_ones_us + libc.src.stdbit.stdc_count_ones_ui + libc.src.stdbit.stdc_count_ones_ul + libc.src.stdbit.stdc_count_ones_ull + libc.src.stdbit.stdc_has_single_bit_uc + libc.src.stdbit.stdc_has_single_bit_us + libc.src.stdbit.stdc_has_single_bit_ui + libc.src.stdbit.stdc_has_single_bit_ul + libc.src.stdbit.stdc_has_single_bit_ull + libc.src.stdbit.stdc_bit_width_uc + libc.src.stdbit.stdc_bit_width_us + libc.src.stdbit.stdc_bit_width_ui + libc.src.stdbit.stdc_bit_width_ul + libc.src.stdbit.stdc_bit_width_ull + libc.src.stdbit.stdc_bit_floor_uc + libc.src.stdbit.stdc_bit_floor_us + libc.src.stdbit.stdc_bit_floor_ui + libc.src.stdbit.stdc_bit_floor_ul + libc.src.stdbit.stdc_bit_floor_ull + libc.src.stdbit.stdc_bit_ceil_uc + libc.src.stdbit.stdc_bit_ceil_us + libc.src.stdbit.stdc_bit_ceil_ui + libc.src.stdbit.stdc_bit_ceil_ul + libc.src.stdbit.stdc_bit_ceil_ull # stdlib.h entrypoints libc.src.stdlib.abs diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index 2fca96c5601b..bf1559b2f023 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -108,6 +108,36 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdbit.stdc_first_trailing_one_ui libc.src.stdbit.stdc_first_trailing_one_ul libc.src.stdbit.stdc_first_trailing_one_ull + libc.src.stdbit.stdc_count_zeros_uc + libc.src.stdbit.stdc_count_zeros_us + libc.src.stdbit.stdc_count_zeros_ui + libc.src.stdbit.stdc_count_zeros_ul + libc.src.stdbit.stdc_count_zeros_ull + libc.src.stdbit.stdc_count_ones_uc + libc.src.stdbit.stdc_count_ones_us + libc.src.stdbit.stdc_count_ones_ui + libc.src.stdbit.stdc_count_ones_ul + libc.src.stdbit.stdc_count_ones_ull + libc.src.stdbit.stdc_has_single_bit_uc + libc.src.stdbit.stdc_has_single_bit_us + libc.src.stdbit.stdc_has_single_bit_ui + libc.src.stdbit.stdc_has_single_bit_ul + libc.src.stdbit.stdc_has_single_bit_ull + libc.src.stdbit.stdc_bit_width_uc + libc.src.stdbit.stdc_bit_width_us + libc.src.stdbit.stdc_bit_width_ui + libc.src.stdbit.stdc_bit_width_ul + libc.src.stdbit.stdc_bit_width_ull + libc.src.stdbit.stdc_bit_floor_uc + libc.src.stdbit.stdc_bit_floor_us + libc.src.stdbit.stdc_bit_floor_ui + libc.src.stdbit.stdc_bit_floor_ul + libc.src.stdbit.stdc_bit_floor_ull + libc.src.stdbit.stdc_bit_ceil_uc + libc.src.stdbit.stdc_bit_ceil_us + libc.src.stdbit.stdc_bit_ceil_ui + libc.src.stdbit.stdc_bit_ceil_ul + libc.src.stdbit.stdc_bit_ceil_ull # stdlib.h entrypoints libc.src.stdlib.abs diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 006aa787ea6a..b1c9dd0428ee 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -132,6 +132,36 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdbit.stdc_first_trailing_one_ui libc.src.stdbit.stdc_first_trailing_one_ul libc.src.stdbit.stdc_first_trailing_one_ull + libc.src.stdbit.stdc_count_zeros_uc + libc.src.stdbit.stdc_count_zeros_us + libc.src.stdbit.stdc_count_zeros_ui + libc.src.stdbit.stdc_count_zeros_ul + libc.src.stdbit.stdc_count_zeros_ull + libc.src.stdbit.stdc_count_ones_uc + libc.src.stdbit.stdc_count_ones_us + libc.src.stdbit.stdc_count_ones_ui + libc.src.stdbit.stdc_count_ones_ul + libc.src.stdbit.stdc_count_ones_ull + libc.src.stdbit.stdc_has_single_bit_uc + libc.src.stdbit.stdc_has_single_bit_us + libc.src.stdbit.stdc_has_single_bit_ui + libc.src.stdbit.stdc_has_single_bit_ul + libc.src.stdbit.stdc_has_single_bit_ull + libc.src.stdbit.stdc_bit_width_uc + libc.src.stdbit.stdc_bit_width_us + libc.src.stdbit.stdc_bit_width_ui + libc.src.stdbit.stdc_bit_width_ul + libc.src.stdbit.stdc_bit_width_ull + libc.src.stdbit.stdc_bit_floor_uc + libc.src.stdbit.stdc_bit_floor_us + libc.src.stdbit.stdc_bit_floor_ui + libc.src.stdbit.stdc_bit_floor_ul + libc.src.stdbit.stdc_bit_floor_ull + libc.src.stdbit.stdc_bit_ceil_uc + libc.src.stdbit.stdc_bit_ceil_us + libc.src.stdbit.stdc_bit_ceil_ui + libc.src.stdbit.stdc_bit_ceil_ul + libc.src.stdbit.stdc_bit_ceil_ull # stdlib.h entrypoints libc.src.stdlib.abs -- GitLab From bb82092de71466728630050691fa9c20796b3cbc Mon Sep 17 00:00:00 2001 From: Han-Chung Wang Date: Wed, 13 Mar 2024 08:52:05 -0700 Subject: [PATCH 393/953] [mlir][tensor] Make getMixedPadImpl return static values when possible. (#85016) If low and high are constants (i.e., not attributes), users still prefer attributes. Otherwise, there could be failures in type inference. A failure is introduced by https://github.com/llvm/llvm-project/commit/60e562d11aeca8020de8d50ded7f0ba9e10e8843, see the drop_known_unit_constant_low_high test for more details. --- .../mlir/Dialect/Tensor/IR/TensorOps.td | 2 +- .../TensorToLinalg/tensor-ops-to-linalg.mlir | 3 +-- .../Dialect/Linalg/drop-unit-extent-dims.mlir | 20 +++++++++++++++++++ .../Dialect/Linalg/generalize-pad-tensor.mlir | 3 +-- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td b/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td index 670202fe4372..cf7f3e89079c 100644 --- a/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td +++ b/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td @@ -1364,7 +1364,7 @@ def Tensor_PadOp : Tensor_Op<"pad", [ unsigned count = staticAttrs.size(); for (unsigned idx = 0; idx < count; ++idx) { if (ShapedType::isDynamic(staticAttrs[idx])) - res.push_back(values[numDynamic++]); + res.push_back(getAsOpFoldResult(values[numDynamic++])); else res.push_back(builder.getI64IntegerAttr(staticAttrs[idx])); } diff --git a/mlir/test/Conversion/TensorToLinalg/tensor-ops-to-linalg.mlir b/mlir/test/Conversion/TensorToLinalg/tensor-ops-to-linalg.mlir index 238c0c51312a..a0a676edceb7 100644 --- a/mlir/test/Conversion/TensorToLinalg/tensor-ops-to-linalg.mlir +++ b/mlir/test/Conversion/TensorToLinalg/tensor-ops-to-linalg.mlir @@ -22,7 +22,6 @@ func.func @generalize_pad_tensor_static_shape(%arg0: tensor<1x28x28x1xf32>) -> t // CHECK-LABEL: func @generalize_pad_tensor_dynamic_shape( // CHECK-SAME: %[[IN:.*]]: tensor<4x?x2x?xf32>, // CHECK-SAME: %[[OFFSET:.*]]: index) -> tensor<4x?x?x?xf32> { -// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index // CHECK-DAG: %[[CST:.*]] = arith.constant 0.000000e+00 : f32 // CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index // CHECK: %[[DIM1:.*]] = tensor.dim %[[IN]], %[[C1]] : tensor<4x?x2x?xf32> @@ -33,7 +32,7 @@ func.func @generalize_pad_tensor_static_shape(%arg0: tensor<1x28x28x1xf32>) -> t // CHECK: %[[OUT_DIM3:.*]] = arith.addi %[[DIM3]], %[[OFFSET]] : index // CHECK: %[[INIT:.*]] = tensor.empty(%[[DIM1]], %[[OUT_DIM2]], %[[OUT_DIM3]]) : tensor<4x?x?x?xf32> // CHECK: %[[FILL:.*]] = linalg.fill ins(%[[CST]] : f32) outs(%[[INIT]] : tensor<4x?x?x?xf32>) -> tensor<4x?x?x?xf32> -// CHECK: %[[PADDED:.*]] = tensor.insert_slice %[[IN]] into %[[FILL]]{{\[}}%[[C0]], %[[C0]], %[[OFFSET]], %[[C0]]] [4, %[[DIM1]], 2, %[[DIM3]]] [1, 1, 1, 1] : tensor<4x?x2x?xf32> into tensor<4x?x?x?xf32> +// CHECK: %[[PADDED:.*]] = tensor.insert_slice %[[IN]] into %[[FILL]][0, 0, %[[OFFSET]], 0] [4, %[[DIM1]], 2, %[[DIM3]]] [1, 1, 1, 1] : tensor<4x?x2x?xf32> into tensor<4x?x?x?xf32> // CHECK: return %[[PADDED]] : tensor<4x?x?x?xf32> // CHECK: } func.func @generalize_pad_tensor_dynamic_shape(%arg0: tensor<4x?x2x?xf32>, %arg1: index) -> tensor<4x?x?x?xf32> { diff --git a/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir b/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir index f2c490b83207..c140b6abcc37 100644 --- a/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir +++ b/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir @@ -1033,3 +1033,23 @@ func.func @do_not_drop_non_constant_padding(%arg0: tensor<1x1x3x1x1xf32>, %pad: // CHECK-SLICES-LABEL: func @do_not_drop_non_constant_padding // CHECK-SLICES: tensor.pad %{{.*}} low[0, 1, 0, %c0, 0] high[0, 0, 0, %c0, 2] // CHECK-SLICES: } : tensor<1x1x3x1x1xf32> to tensor<1x2x3x1x3xf32> + +// ----- + +func.func @drop_known_unit_constant_low_high(%arg0: tensor<1x383x128xf32>) -> tensor<1x384x128xf32> { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %cst = arith.constant 0.000000e+00 : f32 + %padded = tensor.pad %arg0 low[%c0, %c1, %c0] high[%c0, %c0, %c0] { + ^bb0(%arg1: index, %arg2: index, %arg3: index): + tensor.yield %cst : f32 + } : tensor<1x383x128xf32> to tensor<1x384x128xf32> + return %padded : tensor<1x384x128xf32> +} +// CHECK-LABEL: func @drop_known_unit_constant_low_high +// CHECK: %[[COLLAPSE:.+]] = tensor.collapse_shape +// CHECK-SAME: {{\[}}[0, 1], [2]] : tensor<1x383x128xf32> into tensor<383x128xf32> +// CHECK: %[[PADDED:.+]] = tensor.pad %[[COLLAPSE]] low[1, 0] high[0, 0] +// CHECK: } : tensor<383x128xf32> to tensor<384x128xf32> +// CHECK: tensor.expand_shape %[[PADDED]] +// CHECK-SAME: {{\[}}[0, 1], [2]] : tensor<384x128xf32> into tensor<1x384x128xf32> diff --git a/mlir/test/Dialect/Linalg/generalize-pad-tensor.mlir b/mlir/test/Dialect/Linalg/generalize-pad-tensor.mlir index ac0eb48fb379..2beab31b613d 100644 --- a/mlir/test/Dialect/Linalg/generalize-pad-tensor.mlir +++ b/mlir/test/Dialect/Linalg/generalize-pad-tensor.mlir @@ -19,7 +19,6 @@ func.func @generalize_pad_tensor_static_shape(%arg0: tensor<1x28x28x1xf32>) -> t // CHECK-LABEL: func @generalize_pad_tensor_dynamic_shape( // CHECK-SAME: %[[IN:.*]]: tensor<4x?x2x?xf32>, // CHECK-SAME: %[[OFFSET:.*]]: index) -> tensor<4x?x?x?xf32> { -// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index // CHECK-DAG: %[[CST:.*]] = arith.constant 0.000000e+00 : f32 // CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index // CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index @@ -32,7 +31,7 @@ func.func @generalize_pad_tensor_static_shape(%arg0: tensor<1x28x28x1xf32>) -> t // CHECK: %[[FILL:.*]] = linalg.fill ins(%[[CST]] : f32) outs(%[[INIT]] : tensor<4x?x?x?xf32>) -> tensor<4x?x?x?xf32> // CHECK: %[[DIM1_1:.*]] = tensor.dim %[[IN]], %[[C1]] : tensor<4x?x2x?xf32> // CHECK: %[[DIM3_1:.*]] = tensor.dim %[[IN]], %[[C3]] : tensor<4x?x2x?xf32> -// CHECK: %[[PADDED:.*]] = tensor.insert_slice %[[IN]] into %[[FILL]]{{\[}}%[[C0]], %[[C0]], %[[OFFSET]], %[[C0]]] [4, %[[DIM1_1]], 2, %[[DIM3_1]]] [1, 1, 1, 1] : tensor<4x?x2x?xf32> into tensor<4x?x?x?xf32> +// CHECK: %[[PADDED:.*]] = tensor.insert_slice %[[IN]] into %[[FILL]][0, 0, %[[OFFSET]], 0] [4, %[[DIM1_1]], 2, %[[DIM3_1]]] [1, 1, 1, 1] : tensor<4x?x2x?xf32> into tensor<4x?x?x?xf32> // CHECK: return %[[PADDED]] : tensor<4x?x?x?xf32> // CHECK: } func.func @generalize_pad_tensor_dynamic_shape(%arg0: tensor<4x?x2x?xf32>, %arg1: index) -> tensor<4x?x?x?xf32> { -- GitLab From c3eccf03b365a705bc8dc043217478a82bc37a4d Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 13 Mar 2024 08:53:13 -0700 Subject: [PATCH 394/953] Avoid a potential exit(1) in LLVMContext::diagnose() (#84992) by handling *all* errors in IRExecDiagnosticHandler. The function that call this handles all unhandled errors with an `exit(1)`. rdar://124459751 I don't really have a testcase for this, since the crash report I got for this involved the Swift language plugin. --- lldb/source/Expression/IRExecutionUnit.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index e4e131d70d43..cb9bee8733e1 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -212,18 +212,17 @@ struct IRExecDiagnosticHandler : public llvm::DiagnosticHandler { Status *err; IRExecDiagnosticHandler(Status *err) : err(err) {} bool handleDiagnostics(const llvm::DiagnosticInfo &DI) override { - if (DI.getKind() == llvm::DK_SrcMgr) { + if (DI.getSeverity() == llvm::DS_Error) { const auto &DISM = llvm::cast(DI); if (err && err->Success()) { err->SetErrorToGenericError(); err->SetErrorStringWithFormat( - "Inline assembly error: %s", + "IRExecution error: %s", DISM.getSMDiag().getMessage().str().c_str()); } - return true; } - return false; + return true; } }; } // namespace -- GitLab From cc761a7c356178009d186e70740ccb53bf0c6deb Mon Sep 17 00:00:00 2001 From: Zaara Syeda Date: Wed, 13 Mar 2024 11:57:07 -0400 Subject: [PATCH 395/953] [PowerPC][NFC] Rename ADDItocL to match the 64-bit naming convention (#85099) In preparation of adding a similar instruction for large code model on AIX for 32-bit, rename the exisitng ADDItocL 64-instruction to ADDItocL8 to match the naming convention of other instructions with 32-bit and 64-bit variants. --- .../Target/PowerPC/GISel/PPCInstructionSelector.cpp | 4 ++-- llvm/lib/Target/PowerPC/P10InstrResources.td | 2 +- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 6 +++--- llvm/lib/Target/PowerPC/PPCBack2BackFusion.def | 4 ++-- llvm/lib/Target/PowerPC/PPCFastISel.cpp | 10 ++++++---- llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 10 +++++----- llvm/lib/Target/PowerPC/PPCInstr64Bit.td | 4 ++-- llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 12 ++++++------ llvm/lib/Target/PowerPC/PPCMacroFusion.def | 6 +++--- llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp | 3 +-- .../CodeGen/PowerPC/remove-copy-crunsetcrbit.mir | 2 +- 11 files changed, 32 insertions(+), 31 deletions(-) diff --git a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp index 3fd7a1ad9efa..98cd3a82a6e0 100644 --- a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp +++ b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp @@ -695,8 +695,8 @@ bool PPCInstructionSelector::selectConstantPool( .addReg(HaAddrReg) .addMemOperand(MMO); else - // For medium code model, generate ADDItocL(CPI, ADDIStocHA8(X2, CPI)) - MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::ADDItocL), DstReg) + // For medium code model, generate ADDItocL8(CPI, ADDIStocHA8(X2, CPI)) + MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::ADDItocL8), DstReg) .addReg(HaAddrReg) .addConstantPoolIndex(CPI); } diff --git a/llvm/lib/Target/PowerPC/P10InstrResources.td b/llvm/lib/Target/PowerPC/P10InstrResources.td index 3bbc5a63ca7a..5015ba887d0b 100644 --- a/llvm/lib/Target/PowerPC/P10InstrResources.td +++ b/llvm/lib/Target/PowerPC/P10InstrResources.td @@ -881,7 +881,7 @@ def : InstRW<[P10W_FX_3C, P10W_DISP_ANY], // 3 Cycles ALU operations, 1 input operands def : InstRW<[P10W_FX_3C, P10W_DISP_ANY, P10FX_Read], (instrs - ADDI, ADDI8, ADDIdtprelL32, ADDItlsldLADDR32, ADDItocL, LI, LI8, + ADDI, ADDI8, ADDIdtprelL32, ADDItlsldLADDR32, ADDItocL8, LI, LI8, ADDIC, ADDIC8, ADDIS, ADDIS8, ADDISdtprelHA32, ADDIStocHA, ADDIStocHA8, LIS, LIS8, ADDME, ADDME8, diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 6f33b16f045a..542854ec9b99 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1236,8 +1236,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { EmitToStreamer(*OutStreamer, TmpInst); return; } - case PPC::ADDItocL: { - // Transform %xd = ADDItocL %xs, @sym + case PPC::ADDItocL8: { + // Transform %xd = ADDItocL8 %xs, @sym LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); // Change the opcode to ADDI8. If the global address is external, then @@ -1246,7 +1246,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { TmpInst.setOpcode(PPC::ADDI8); const MachineOperand &MO = MI->getOperand(2); - assert((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL."); + assert((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL8."); LLVM_DEBUG(assert( !(MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal())) && diff --git a/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def b/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def index 8bbe315a2bb9..6bb66bcc6c21 100644 --- a/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def +++ b/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def @@ -29,7 +29,7 @@ FUSION_FEATURE(GeneralBack2Back, hasBack2BackFusion, -1, ADDIStocHA8, ADDIdtprelL32, ADDItlsldLADDR32, - ADDItocL, + ADDItocL8, ADDME, ADDME8, ADDME8O, @@ -518,7 +518,7 @@ FUSION_FEATURE(GeneralBack2Back, hasBack2BackFusion, -1, ADDIStocHA8, ADDIdtprelL32, ADDItlsldLADDR32, - ADDItocL, + ADDItocL8, ADDME, ADDME8, ADDME8O, diff --git a/llvm/lib/Target/PowerPC/PPCFastISel.cpp b/llvm/lib/Target/PowerPC/PPCFastISel.cpp index 56af80f9cede..6e31cdae8476 100644 --- a/llvm/lib/Target/PowerPC/PPCFastISel.cpp +++ b/llvm/lib/Target/PowerPC/PPCFastISel.cpp @@ -2094,7 +2094,7 @@ unsigned PPCFastISel::PPCMaterializeGV(const GlobalValue *GV, MVT VT) { // for large code model, we generate: // LDtocL(GV, ADDIStocHA8(%x2, GV)) // Otherwise we generate: - // ADDItocL(ADDIStocHA8(%x2, GV), GV) + // ADDItocL8(ADDIStocHA8(%x2, GV), GV) // Either way, start with the ADDIStocHA8: Register HighPartReg = createResultReg(RC); BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(PPC::ADDIStocHA8), @@ -2104,9 +2104,11 @@ unsigned PPCFastISel::PPCMaterializeGV(const GlobalValue *GV, MVT VT) { BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(PPC::LDtocL), DestReg).addGlobalAddress(GV).addReg(HighPartReg); } else { - // Otherwise generate the ADDItocL. - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(PPC::ADDItocL), - DestReg).addReg(HighPartReg).addGlobalAddress(GV); + // Otherwise generate the ADDItocL8. + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(PPC::ADDItocL8), + DestReg) + .addReg(HighPartReg) + .addGlobalAddress(GV); } } diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 2462cbb19282..0c25accd1d6c 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -6134,7 +6134,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) { // [64-bit ELF/AIX] // LDtocL(@sym, ADDIStocHA8(%x2, @sym)) // Otherwise we generate: - // ADDItocL(ADDIStocHA8(%x2, @sym), @sym) + // ADDItocL8(ADDIStocHA8(%x2, @sym), @sym) SDValue GA = N->getOperand(0); SDValue TOCbase = N->getOperand(1); @@ -6154,7 +6154,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) { } // Build the address relative to the TOC-pointer. - ReplaceNode(N, CurDAG->getMachineNode(PPC::ADDItocL, dl, MVT::i64, + ReplaceNode(N, CurDAG->getMachineNode(PPC::ADDItocL8, dl, MVT::i64, SDValue(Tmp, 0), GA)); return; } @@ -7707,7 +7707,7 @@ void PPCDAGToDAGISel::PeepholePPC64() { // target flags on the immediate operand when we fold it into the // load instruction. // - // For something like ADDItocL, the relocation information is + // For something like ADDItocL8, the relocation information is // inferred from the opcode; when we process it in the AsmPrinter, // we add the necessary relocation there. A load, though, can receive // relocation from various flavors of ADDIxxx, so we need to carry @@ -7728,7 +7728,7 @@ void PPCDAGToDAGISel::PeepholePPC64() { case PPC::ADDItlsldL: Flags = PPCII::MO_TLSLD_LO; break; - case PPC::ADDItocL: + case PPC::ADDItocL8: Flags = PPCII::MO_TOC_LO; break; } @@ -7755,7 +7755,7 @@ void PPCDAGToDAGISel::PeepholePPC64() { // If we have a addi(toc@l)/addis(toc@ha) pair, and the addis has only // one use, then we can do this for any offset, we just need to also // update the offset (i.e. the symbol addend) on the addis also. - if (Base.getMachineOpcode() != PPC::ADDItocL) + if (Base.getMachineOpcode() != PPC::ADDItocL8) continue; if (!HBase.isMachineOpcode() || diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td index 2949d58ab664..a9359794a641 100644 --- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -1480,8 +1480,8 @@ let hasSideEffects = 0 in { let isReMaterializable = 1 in { def ADDIStocHA8: PPCEmitTimePseudo<(outs g8rc:$rD), (ins g8rc_nox0:$reg, tocentry:$disp), "#ADDIStocHA8", []>, isPPC64; -def ADDItocL: PPCEmitTimePseudo<(outs g8rc:$rD), (ins g8rc_nox0:$reg, tocentry:$disp), - "#ADDItocL", []>, isPPC64; +def ADDItocL8: PPCEmitTimePseudo<(outs g8rc:$rD), (ins g8rc_nox0:$reg, tocentry:$disp), + "#ADDItocL8", []>, isPPC64; } // Local Data Transform diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp index 5d37e929f875..5f5eb31a5a85 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -1077,7 +1077,7 @@ bool PPCInstrInfo::isReallyTriviallyReMaterializable( case PPC::LIS8: case PPC::ADDIStocHA: case PPC::ADDIStocHA8: - case PPC::ADDItocL: + case PPC::ADDItocL8: case PPC::LOAD_STACK_GUARD: case PPC::PPCLdFixedAddr: case PPC::XXLXORz: @@ -3453,7 +3453,7 @@ MachineInstr *PPCInstrInfo::getForwardingDefMI( break; case PPC::LI: case PPC::LI8: - case PPC::ADDItocL: + case PPC::ADDItocL8: case PPC::ADDI: case PPC::ADDI8: OpNoForForwarding = i; @@ -4420,7 +4420,7 @@ bool PPCInstrInfo::isDefMIElgibleForForwarding(MachineInstr &DefMI, MachineOperand *&ImmMO, MachineOperand *&RegMO) const { unsigned Opc = DefMI.getOpcode(); - if (Opc != PPC::ADDItocL && Opc != PPC::ADDI && Opc != PPC::ADDI8) + if (Opc != PPC::ADDItocL8 && Opc != PPC::ADDI && Opc != PPC::ADDI8) return false; assert(DefMI.getNumOperands() >= 3 && @@ -4485,8 +4485,8 @@ bool PPCInstrInfo::isImmElgibleForForwarding(const MachineOperand &ImmMO, int64_t &Imm, int64_t BaseImm) const { assert(isAnImmediateOperand(ImmMO) && "ImmMO is NOT an immediate"); - if (DefMI.getOpcode() == PPC::ADDItocL) { - // The operand for ADDItocL is CPI, which isn't imm at compiling time, + if (DefMI.getOpcode() == PPC::ADDItocL8) { + // The operand for ADDItocL8 is CPI, which isn't imm at compiling time, // However, we know that, it is 16-bit width, and has the alignment of 4. // Check if the instruction met the requirement. if (III.ImmMustBeMultipleOf > 4 || @@ -4899,7 +4899,7 @@ bool PPCInstrInfo::transformToImmFormFedByAdd( // register with ImmMO. // Before that, we need to fixup the target flags for imm. // For some reason, we miss to set the flag for the ImmMO if it is CPI. - if (DefMI.getOpcode() == PPC::ADDItocL) + if (DefMI.getOpcode() == PPC::ADDItocL8) ImmMO->setTargetFlags(PPCII::MO_TOC_LO); // MI didn't have the interface such as MI.setOperand(i) though diff --git a/llvm/lib/Target/PowerPC/PPCMacroFusion.def b/llvm/lib/Target/PowerPC/PPCMacroFusion.def index 6b8ad22639c8..fb6e656edb8b 100644 --- a/llvm/lib/Target/PowerPC/PPCMacroFusion.def +++ b/llvm/lib/Target/PowerPC/PPCMacroFusion.def @@ -32,7 +32,7 @@ // {addi} followed by one of these {lxvd2x, lxvw4x, lxvdsx, lvebx, lvehx, // lvewx, lvx, lxsdx} FUSION_FEATURE(AddiLoad, hasAddiLoadFusion, 2, \ - FUSION_OP_SET(ADDI, ADDI8, ADDItocL), \ + FUSION_OP_SET(ADDI, ADDI8, ADDItocL8), \ FUSION_OP_SET(LXVD2X, LXVW4X, LXVDSX, LVEBX, LVEHX, LVEWX, \ LVX, LXSDX)) @@ -135,11 +135,11 @@ FUSION_FEATURE(XorisXori, hasWideImmFusion, 1, FUSION_OP_SET(XORIS, XORIS8), // addis rx,ra,si - addi rt,rx,SI, SI >= 0 FUSION_FEATURE(AddisAddi, hasWideImmFusion, 1, FUSION_OP_SET(ADDIS, ADDIS8, ADDIStocHA8), - FUSION_OP_SET(ADDI, ADDI8, ADDItocL)) + FUSION_OP_SET(ADDI, ADDI8, ADDItocL8)) // addi rx,ra,si - addis rt,rx,SI, ra > 0, SI >= 2 FUSION_FEATURE(AddiAddis, hasWideImmFusion, 1, - FUSION_OP_SET(ADDI, ADDI8, ADDItocL), + FUSION_OP_SET(ADDI, ADDI8, ADDItocL8), FUSION_OP_SET(ADDIS, ADDIS8, ADDIStocHA8)) // mtctr - { bcctr,bcctrl } diff --git a/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp b/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp index 81f078ab246e..0527991b58ba 100644 --- a/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp +++ b/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp @@ -94,8 +94,7 @@ namespace { protected: bool hasTOCLoReloc(const MachineInstr &MI) { - if (MI.getOpcode() == PPC::LDtocL || - MI.getOpcode() == PPC::ADDItocL || + if (MI.getOpcode() == PPC::LDtocL || MI.getOpcode() == PPC::ADDItocL8 || MI.getOpcode() == PPC::LWZtocL) return true; diff --git a/llvm/test/CodeGen/PowerPC/remove-copy-crunsetcrbit.mir b/llvm/test/CodeGen/PowerPC/remove-copy-crunsetcrbit.mir index 3a312d2f4a8b..f3ef95bbb79a 100644 --- a/llvm/test/CodeGen/PowerPC/remove-copy-crunsetcrbit.mir +++ b/llvm/test/CodeGen/PowerPC/remove-copy-crunsetcrbit.mir @@ -130,7 +130,7 @@ body: | %22:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @c %10:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @e %13:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @a - %14:g8rc_and_g8rc_nox0 = ADDItocL killed %13, @a, implicit $x2 + %14:g8rc_and_g8rc_nox0 = ADDItocL8 killed %13, @a, implicit $x2 bb.2.while.body: successors: %bb.4(0x30000000), %bb.3(0x50000000) -- GitLab From f15a790fd383665ec4defa0711e975476fd8b18b Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Wed, 13 Mar 2024 15:55:18 +0000 Subject: [PATCH 396/953] Remove use of reference lifetime extension introduced in cdde0d9 Rather than dealing with which is more readable, the named variable doesn't seem to add value here - so omit it. --- clang/lib/AST/Interp/Interp.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index bb220657c2da..db80e2d59753 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -846,8 +846,7 @@ bool CMP3(InterpState &S, CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo) { CmpInfo->getValueInfo(CmpInfo->makeWeakResult(CmpResult)); assert(CmpValueInfo); assert(CmpValueInfo->hasValidIntValue()); - const APSInt &IntValue = CmpValueInfo->getIntValue(); - return SetThreeWayComparisonField(S, OpPC, P, IntValue); + return SetThreeWayComparisonField(S, OpPC, P, CmpValueInfo->getIntValue()); } template ::T> -- GitLab From 57b991ab39348d91d8552787958ba7db1e7ceb8a Mon Sep 17 00:00:00 2001 From: Usman Nadeem Date: Wed, 13 Mar 2024 09:05:55 -0700 Subject: [PATCH 397/953] [AArch64] Improve lowering of truncating uzp1 (#82457) There were two existing patterns: `concat_vectors(trunc(x), trunc(y)) -> uzp1(x, y)` `concat_vectors(assertzext(trunc(x)), assertzext(trunc(y))) -> uzp1(x, y)` Move them into a class and add the following `assertsext` pattern to it: `concat_vectors(assertsext(trunc(x)), assertsext(trunc(y))) -> uzp1(x, y)` Add the following transform for v8i8 and v4i16 result types to help with pattern matching: `truncating uzp1(x, y) -> trunc(concat(x, y))` And a pattern to go with it: `trunc(concat_vectors(x, y)) -> uzp1 (x, y)` Add another isel pattern for v8i8 and v4i16 result vector types, similar to the existing concat pattern, but with a trunc node in the begining: `trunc(concat_vectors(assertext_trunc(x), assertext_trunc(y))) -> xtn(uzp1(x, y))` --- .../Target/AArch64/AArch64ISelLowering.cpp | 39 +-- llvm/lib/Target/AArch64/AArch64InstrInfo.td | 53 ++-- .../CodeGen/AArch64/arm64-convert-v4f64.ll | 21 +- llvm/test/CodeGen/AArch64/extbinopload.ll | 31 ++- .../CodeGen/AArch64/fp-conversion-to-tbl.ll | 5 +- llvm/test/CodeGen/AArch64/fptoi.ll | 256 ++++++------------ llvm/test/CodeGen/AArch64/neon-truncstore.ll | 5 +- llvm/test/CodeGen/AArch64/sadd_sat_vec.ll | 2 +- llvm/test/CodeGen/AArch64/shuffle-tbl34.ll | 14 +- llvm/test/CodeGen/AArch64/ssub_sat_vec.ll | 2 +- llvm/test/CodeGen/AArch64/tbl-loops.ll | 4 +- llvm/test/CodeGen/AArch64/trunc-to-tbl.ll | 28 +- llvm/test/CodeGen/AArch64/uadd_sat_vec.ll | 2 +- llvm/test/CodeGen/AArch64/usub_sat_vec.ll | 2 +- llvm/test/CodeGen/AArch64/vcvt-oversize.ll | 5 +- .../vec-combine-compare-truncate-store.ll | 2 +- .../AArch64/vec3-loads-ext-trunc-stores.ll | 22 +- 17 files changed, 209 insertions(+), 284 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 5b7a36d2eba7..9665ae5ceb90 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -21423,12 +21423,8 @@ static SDValue performUzpCombine(SDNode *N, SelectionDAG &DAG, } } - // uzp1(xtn x, xtn y) -> xtn(uzp1 (x, y)) - // Only implemented on little-endian subtargets. - bool IsLittleEndian = DAG.getDataLayout().isLittleEndian(); - - // This optimization only works on little endian. - if (!IsLittleEndian) + // These optimizations only work on little endian. + if (!DAG.getDataLayout().isLittleEndian()) return SDValue(); // uzp1(bitcast(x), bitcast(y)) -> uzp1(x, y) @@ -21447,21 +21443,28 @@ static SDValue performUzpCombine(SDNode *N, SelectionDAG &DAG, if (ResVT != MVT::v2i32 && ResVT != MVT::v4i16 && ResVT != MVT::v8i8) return SDValue(); - auto getSourceOp = [](SDValue Operand) -> SDValue { - const unsigned Opcode = Operand.getOpcode(); - if (Opcode == ISD::TRUNCATE) - return Operand->getOperand(0); - if (Opcode == ISD::BITCAST && - Operand->getOperand(0).getOpcode() == ISD::TRUNCATE) - return Operand->getOperand(0)->getOperand(0); - return SDValue(); - }; + SDValue SourceOp0 = peekThroughBitcasts(Op0); + SDValue SourceOp1 = peekThroughBitcasts(Op1); - SDValue SourceOp0 = getSourceOp(Op0); - SDValue SourceOp1 = getSourceOp(Op1); + // truncating uzp1(x, y) -> xtn(concat (x, y)) + if (SourceOp0.getValueType() == SourceOp1.getValueType()) { + EVT Op0Ty = SourceOp0.getValueType(); + if ((ResVT == MVT::v4i16 && Op0Ty == MVT::v2i32) || + (ResVT == MVT::v8i8 && Op0Ty == MVT::v4i16)) { + SDValue Concat = + DAG.getNode(ISD::CONCAT_VECTORS, DL, + Op0Ty.getDoubleNumVectorElementsVT(*DAG.getContext()), + SourceOp0, SourceOp1); + return DAG.getNode(ISD::TRUNCATE, DL, ResVT, Concat); + } + } - if (!SourceOp0 || !SourceOp1) + // uzp1(xtn x, xtn y) -> xtn(uzp1 (x, y)) + if (SourceOp0.getOpcode() != ISD::TRUNCATE || + SourceOp1.getOpcode() != ISD::TRUNCATE) return SDValue(); + SourceOp0 = SourceOp0.getOperand(0); + SourceOp1 = SourceOp1.getOperand(0); if (SourceOp0.getValueType() != SourceOp1.getValueType() || !SourceOp0.getValueType().isSimple()) diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 6254e68326f7..b4b975cce007 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -6153,26 +6153,39 @@ defm UZP2 : SIMDZipVector<0b101, "uzp2", AArch64uzp2>; defm ZIP1 : SIMDZipVector<0b011, "zip1", AArch64zip1>; defm ZIP2 : SIMDZipVector<0b111, "zip2", AArch64zip2>; -def : Pat<(v16i8 (concat_vectors (v8i8 (trunc (v8i16 V128:$Vn))), - (v8i8 (trunc (v8i16 V128:$Vm))))), - (UZP1v16i8 V128:$Vn, V128:$Vm)>; -def : Pat<(v8i16 (concat_vectors (v4i16 (trunc (v4i32 V128:$Vn))), - (v4i16 (trunc (v4i32 V128:$Vm))))), - (UZP1v8i16 V128:$Vn, V128:$Vm)>; -def : Pat<(v4i32 (concat_vectors (v2i32 (trunc (v2i64 V128:$Vn))), - (v2i32 (trunc (v2i64 V128:$Vm))))), - (UZP1v4i32 V128:$Vn, V128:$Vm)>; -// These are the same as above, with an optional assertzext node that can be -// generated from fptoi lowering. -def : Pat<(v16i8 (concat_vectors (v8i8 (assertzext (trunc (v8i16 V128:$Vn)))), - (v8i8 (assertzext (trunc (v8i16 V128:$Vm)))))), - (UZP1v16i8 V128:$Vn, V128:$Vm)>; -def : Pat<(v8i16 (concat_vectors (v4i16 (assertzext (trunc (v4i32 V128:$Vn)))), - (v4i16 (assertzext (trunc (v4i32 V128:$Vm)))))), - (UZP1v8i16 V128:$Vn, V128:$Vm)>; -def : Pat<(v4i32 (concat_vectors (v2i32 (assertzext (trunc (v2i64 V128:$Vn)))), - (v2i32 (assertzext (trunc (v2i64 V128:$Vm)))))), - (UZP1v4i32 V128:$Vn, V128:$Vm)>; +def trunc_optional_assert_ext : PatFrags<(ops node:$op0), + [(trunc node:$op0), + (assertzext (trunc node:$op0)), + (assertsext (trunc node:$op0))]>; + +// concat_vectors(trunc(x), trunc(y)) -> uzp1(x, y) +// concat_vectors(assertzext(trunc(x)), assertzext(trunc(y))) -> uzp1(x, y) +// concat_vectors(assertsext(trunc(x)), assertsext(trunc(y))) -> uzp1(x, y) +class concat_trunc_to_uzp1_pat + : Pat<(ConcatTy (concat_vectors (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vn))), + (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vm))))), + (!cast("UZP1"#ConcatTy) V128:$Vn, V128:$Vm)>; +def : concat_trunc_to_uzp1_pat; +def : concat_trunc_to_uzp1_pat; +def : concat_trunc_to_uzp1_pat; + +// trunc(concat_vectors(trunc(x), trunc(y))) -> xtn(uzp1(x, y)) +// trunc(concat_vectors(assertzext(trunc(x)), assertzext(trunc(y)))) -> xtn(uzp1(x, y)) +// trunc(concat_vectors(assertsext(trunc(x)), assertsext(trunc(y)))) -> xtn(uzp1(x, y)) +class trunc_concat_trunc_to_xtn_uzp1_pat + : Pat<(Ty (trunc_optional_assert_ext + (ConcatTy (concat_vectors + (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vn))), + (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vm))))))), + (!cast("XTN"#Ty) (!cast("UZP1"#ConcatTy) V128:$Vn, V128:$Vm))>; +def : trunc_concat_trunc_to_xtn_uzp1_pat; +def : trunc_concat_trunc_to_xtn_uzp1_pat; + +def : Pat<(v8i8 (trunc (concat_vectors (v4i16 V64:$Vn), (v4i16 V64:$Vm)))), + (UZP1v8i8 V64:$Vn, V64:$Vm)>; +def : Pat<(v4i16 (trunc (concat_vectors (v2i32 V64:$Vn), (v2i32 V64:$Vm)))), + (UZP1v4i16 V64:$Vn, V64:$Vm)>; def : Pat<(v16i8 (concat_vectors (v8i8 (trunc (AArch64vlshr (v8i16 V128:$Vn), (i32 8)))), diff --git a/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll b/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll index 49325299f74a..3007e7ce771e 100644 --- a/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll +++ b/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll @@ -8,9 +8,8 @@ define <4 x i16> @fptosi_v4f64_to_v4i16(ptr %ptr) { ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-NEXT: xtn v1.2s, v1.2d -; CHECK-NEXT: xtn v0.2s, v0.2d -; CHECK-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-NEXT: xtn v0.4h, v0.4s ; CHECK-NEXT: ret %tmp1 = load <4 x double>, ptr %ptr %tmp2 = fptosi <4 x double> %tmp1 to <4 x i16> @@ -26,13 +25,10 @@ define <8 x i8> @fptosi_v4f64_to_v4i8(ptr %ptr) { ; CHECK-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-NEXT: fcvtzs v3.2d, v3.2d ; CHECK-NEXT: fcvtzs v2.2d, v2.2d -; CHECK-NEXT: xtn v0.2s, v0.2d -; CHECK-NEXT: xtn v1.2s, v1.2d -; CHECK-NEXT: xtn v3.2s, v3.2d -; CHECK-NEXT: xtn v2.2s, v2.2d -; CHECK-NEXT: uzp1 v0.4h, v1.4h, v0.4h -; CHECK-NEXT: uzp1 v1.4h, v2.4h, v3.4h -; CHECK-NEXT: uzp1 v0.8b, v1.8b, v0.8b +; CHECK-NEXT: uzp1 v0.4s, v1.4s, v0.4s +; CHECK-NEXT: uzp1 v1.4s, v2.4s, v3.4s +; CHECK-NEXT: uzp1 v0.8h, v1.8h, v0.8h +; CHECK-NEXT: xtn v0.8b, v0.8h ; CHECK-NEXT: ret %tmp1 = load <8 x double>, ptr %ptr %tmp2 = fptosi <8 x double> %tmp1 to <8 x i8> @@ -96,9 +92,8 @@ define <4 x i16> @fptoui_v4f64_to_v4i16(ptr %ptr) { ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-NEXT: xtn v1.2s, v1.2d -; CHECK-NEXT: xtn v0.2s, v0.2d -; CHECK-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-NEXT: xtn v0.4h, v0.4s ; CHECK-NEXT: ret %tmp1 = load <4 x double>, ptr %ptr %tmp2 = fptoui <4 x double> %tmp1 to <4 x i16> diff --git a/llvm/test/CodeGen/AArch64/extbinopload.ll b/llvm/test/CodeGen/AArch64/extbinopload.ll index 1f68c77611e1..dff4831330de 100644 --- a/llvm/test/CodeGen/AArch64/extbinopload.ll +++ b/llvm/test/CodeGen/AArch64/extbinopload.ll @@ -650,7 +650,7 @@ define <16 x i32> @extrause_load(ptr %p, ptr %q, ptr %r, ptr %s, ptr %z) { ; CHECK-NEXT: add x11, x3, #12 ; CHECK-NEXT: str s1, [x4] ; CHECK-NEXT: ushll v1.8h, v1.8b, #0 -; CHECK-NEXT: ldp s0, s5, [x2] +; CHECK-NEXT: ldp s0, s4, [x2] ; CHECK-NEXT: ushll v2.8h, v0.8b, #0 ; CHECK-NEXT: umov w9, v2.h[0] ; CHECK-NEXT: umov w10, v2.h[1] @@ -662,24 +662,25 @@ define <16 x i32> @extrause_load(ptr %p, ptr %q, ptr %r, ptr %s, ptr %z) { ; CHECK-NEXT: ushll v2.8h, v2.8b, #0 ; CHECK-NEXT: mov v0.b[10], w9 ; CHECK-NEXT: add x9, x1, #4 -; CHECK-NEXT: uzp1 v1.8b, v1.8b, v2.8b +; CHECK-NEXT: mov v1.d[1], v2.d[0] ; CHECK-NEXT: mov v0.b[11], w10 ; CHECK-NEXT: add x10, x1, #12 +; CHECK-NEXT: bic v1.8h, #255, lsl #8 ; CHECK-NEXT: ld1 { v0.s }[3], [x3], #4 -; CHECK-NEXT: ldr s4, [x0, #12] -; CHECK-NEXT: ldp s3, s16, [x0, #4] -; CHECK-NEXT: ld1 { v5.s }[1], [x3] -; CHECK-NEXT: ldp s6, s7, [x2, #8] -; CHECK-NEXT: ld1 { v4.s }[1], [x10] -; CHECK-NEXT: ld1 { v3.s }[1], [x9] -; CHECK-NEXT: ld1 { v6.s }[1], [x8] -; CHECK-NEXT: ld1 { v7.s }[1], [x11] +; CHECK-NEXT: ldr s3, [x0, #12] +; CHECK-NEXT: ldp s2, s7, [x0, #4] +; CHECK-NEXT: ld1 { v4.s }[1], [x3] +; CHECK-NEXT: ldp s5, s6, [x2, #8] +; CHECK-NEXT: ld1 { v3.s }[1], [x10] +; CHECK-NEXT: ld1 { v2.s }[1], [x9] +; CHECK-NEXT: ld1 { v5.s }[1], [x8] +; CHECK-NEXT: ld1 { v6.s }[1], [x11] ; CHECK-NEXT: add x8, x1, #8 -; CHECK-NEXT: ld1 { v16.s }[1], [x8] -; CHECK-NEXT: uaddl v2.8h, v3.8b, v4.8b -; CHECK-NEXT: ushll v3.8h, v6.8b, #0 -; CHECK-NEXT: uaddl v4.8h, v5.8b, v7.8b -; CHECK-NEXT: uaddl v1.8h, v1.8b, v16.8b +; CHECK-NEXT: ld1 { v7.s }[1], [x8] +; CHECK-NEXT: uaddl v2.8h, v2.8b, v3.8b +; CHECK-NEXT: ushll v3.8h, v5.8b, #0 +; CHECK-NEXT: uaddl v4.8h, v4.8b, v6.8b +; CHECK-NEXT: uaddw v1.8h, v1.8h, v7.8b ; CHECK-NEXT: uaddw2 v5.8h, v3.8h, v0.16b ; CHECK-NEXT: ushll v0.4s, v2.4h, #3 ; CHECK-NEXT: ushll2 v2.4s, v2.8h, #3 diff --git a/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll b/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll index 1ea87bb6b04b..0a3b9a070c2b 100644 --- a/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll +++ b/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll @@ -73,9 +73,8 @@ define void @fptoui_v8f32_to_v8i8_no_loop(ptr %A, ptr %dst) { ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: fcvtzs.4s v1, v1 ; CHECK-NEXT: fcvtzs.4s v0, v0 -; CHECK-NEXT: xtn.4h v1, v1 -; CHECK-NEXT: xtn.4h v0, v0 -; CHECK-NEXT: uzp1.8b v0, v0, v1 +; CHECK-NEXT: uzp1.8h v0, v0, v1 +; CHECK-NEXT: xtn.8b v0, v0 ; CHECK-NEXT: str d0, [x1] ; CHECK-NEXT: ret entry: diff --git a/llvm/test/CodeGen/AArch64/fptoi.ll b/llvm/test/CodeGen/AArch64/fptoi.ll index 67190e8596c4..7af01b53dae7 100644 --- a/llvm/test/CodeGen/AArch64/fptoi.ll +++ b/llvm/test/CodeGen/AArch64/fptoi.ll @@ -1096,30 +1096,17 @@ entry: } define <3 x i16> @fptos_v3f64_v3i16(<3 x double> %a) { -; CHECK-SD-LABEL: fptos_v3f64_v3i16: -; CHECK-SD: // %bb.0: // %entry -; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1 -; CHECK-SD-NEXT: // kill: def $d2 killed $d2 def $q2 -; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] -; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d -; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: fptos_v3f64_v3i16: -; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 -; CHECK-GI-NEXT: // kill: def $d2 killed $d2 def $q2 -; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] -; CHECK-GI-NEXT: fcvtzs v1.2d, v2.2d -; CHECK-GI-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: fptos_v3f64_v3i16: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: // kill: def $d2 killed $d2 def $q2 +; CHECK-NEXT: mov v0.d[1], v1.d[0] +; CHECK-NEXT: fcvtzs v1.2d, v2.2d +; CHECK-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret entry: %c = fptosi <3 x double> %a to <3 x i16> ret <3 x i16> %c @@ -1134,9 +1121,8 @@ define <3 x i16> @fptou_v3f64_v3i16(<3 x double> %a) { ; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] ; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v3f64_v3i16: @@ -1160,9 +1146,8 @@ define <4 x i16> @fptos_v4f64_v4i16(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v4f64_v4i16: @@ -1182,9 +1167,8 @@ define <4 x i16> @fptou_v4f64_v4i16(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v4f64_v4i16: @@ -1600,9 +1584,8 @@ define <3 x i8> @fptos_v3f64_v3i8(<3 x double> %a) { ; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] ; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: umov w0, v0.h[0] ; CHECK-SD-NEXT: umov w1, v0.h[1] ; CHECK-SD-NEXT: umov w2, v0.h[2] @@ -1638,9 +1621,8 @@ define <3 x i8> @fptou_v3f64_v3i8(<3 x double> %a) { ; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] ; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: umov w0, v0.h[0] ; CHECK-SD-NEXT: umov w1, v0.h[1] ; CHECK-SD-NEXT: umov w2, v0.h[2] @@ -1672,9 +1654,8 @@ define <4 x i8> @fptos_v4f64_v4i8(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v4f64_v4i8: @@ -1694,9 +1675,8 @@ define <4 x i8> @fptou_v4f64_v4i8(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v4f64_v4i8: @@ -1718,13 +1698,10 @@ define <8 x i8> @fptos_v8f64_v8i8(<8 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v2.8b +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: xtn v0.8b, v0.8h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v8f64_v8i8: @@ -1750,13 +1727,10 @@ define <8 x i8> @fptou_v8f64_v8i8(<8 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v2.8b +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: xtn v0.8b, v0.8h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v8f64_v8i8: @@ -1786,21 +1760,13 @@ define <16 x i8> @fptos_v16f64_v16i8(<16 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v7.2s, v7.2d -; CHECK-SD-NEXT: xtn v6.2s, v6.2d -; CHECK-SD-NEXT: xtn v5.2s, v5.2d -; CHECK-SD-NEXT: xtn v4.2s, v4.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h -; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] -; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b +; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s +; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v1.8h, v4.8h, v6.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v16f64_v16i8: @@ -1837,21 +1803,13 @@ define <16 x i8> @fptou_v16f64_v16i8(<16 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v7.2s, v7.2d -; CHECK-SD-NEXT: xtn v6.2s, v6.2d -; CHECK-SD-NEXT: xtn v5.2s, v5.2d -; CHECK-SD-NEXT: xtn v4.2s, v4.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h -; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] -; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b +; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s +; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v1.8h, v4.8h, v6.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v16f64_v16i8: @@ -1900,36 +1858,20 @@ define <32 x i8> @fptos_v32f64_v32i8(<32 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v18.2d, v18.2d ; CHECK-SD-NEXT: fcvtzs v17.2d, v17.2d ; CHECK-SD-NEXT: fcvtzs v16.2d, v16.2d -; CHECK-SD-NEXT: xtn v7.2s, v7.2d -; CHECK-SD-NEXT: xtn v6.2s, v6.2d -; CHECK-SD-NEXT: xtn v5.2s, v5.2d -; CHECK-SD-NEXT: xtn v4.2s, v4.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: xtn v23.2s, v23.2d -; CHECK-SD-NEXT: xtn v22.2s, v22.2d -; CHECK-SD-NEXT: xtn v21.2s, v21.2d -; CHECK-SD-NEXT: xtn v20.2s, v20.2d -; CHECK-SD-NEXT: xtn v19.2s, v19.2d -; CHECK-SD-NEXT: xtn v18.2s, v18.2d -; CHECK-SD-NEXT: xtn v17.2s, v17.2d -; CHECK-SD-NEXT: xtn v16.2s, v16.2d -; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h -; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: uzp1 v1.4h, v22.4h, v23.4h -; CHECK-SD-NEXT: uzp1 v3.4h, v20.4h, v21.4h -; CHECK-SD-NEXT: uzp1 v5.4h, v18.4h, v19.4h -; CHECK-SD-NEXT: uzp1 v7.4h, v16.4h, v17.4h -; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] -; CHECK-SD-NEXT: mov v3.d[1], v1.d[0] -; CHECK-SD-NEXT: mov v7.d[1], v5.d[0] +; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s +; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v3.4s, v20.4s, v21.4s +; CHECK-SD-NEXT: uzp1 v1.4s, v22.4s, v23.4s +; CHECK-SD-NEXT: uzp1 v5.4s, v18.4s, v19.4s +; CHECK-SD-NEXT: uzp1 v7.4s, v16.4s, v17.4s +; CHECK-SD-NEXT: uzp1 v4.8h, v4.8h, v6.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: uzp1 v1.8h, v3.8h, v1.8h +; CHECK-SD-NEXT: uzp1 v2.8h, v7.8h, v5.8h ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b -; CHECK-SD-NEXT: uzp1 v1.16b, v7.16b, v3.16b +; CHECK-SD-NEXT: uzp1 v1.16b, v2.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v32f64_v32i8: @@ -1997,36 +1939,20 @@ define <32 x i8> @fptou_v32f64_v32i8(<32 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v18.2d, v18.2d ; CHECK-SD-NEXT: fcvtzs v17.2d, v17.2d ; CHECK-SD-NEXT: fcvtzs v16.2d, v16.2d -; CHECK-SD-NEXT: xtn v7.2s, v7.2d -; CHECK-SD-NEXT: xtn v6.2s, v6.2d -; CHECK-SD-NEXT: xtn v5.2s, v5.2d -; CHECK-SD-NEXT: xtn v4.2s, v4.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: xtn v23.2s, v23.2d -; CHECK-SD-NEXT: xtn v22.2s, v22.2d -; CHECK-SD-NEXT: xtn v21.2s, v21.2d -; CHECK-SD-NEXT: xtn v20.2s, v20.2d -; CHECK-SD-NEXT: xtn v19.2s, v19.2d -; CHECK-SD-NEXT: xtn v18.2s, v18.2d -; CHECK-SD-NEXT: xtn v17.2s, v17.2d -; CHECK-SD-NEXT: xtn v16.2s, v16.2d -; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h -; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: uzp1 v1.4h, v22.4h, v23.4h -; CHECK-SD-NEXT: uzp1 v3.4h, v20.4h, v21.4h -; CHECK-SD-NEXT: uzp1 v5.4h, v18.4h, v19.4h -; CHECK-SD-NEXT: uzp1 v7.4h, v16.4h, v17.4h -; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] -; CHECK-SD-NEXT: mov v3.d[1], v1.d[0] -; CHECK-SD-NEXT: mov v7.d[1], v5.d[0] +; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s +; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v3.4s, v20.4s, v21.4s +; CHECK-SD-NEXT: uzp1 v1.4s, v22.4s, v23.4s +; CHECK-SD-NEXT: uzp1 v5.4s, v18.4s, v19.4s +; CHECK-SD-NEXT: uzp1 v7.4s, v16.4s, v17.4s +; CHECK-SD-NEXT: uzp1 v4.8h, v4.8h, v6.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: uzp1 v1.8h, v3.8h, v1.8h +; CHECK-SD-NEXT: uzp1 v2.8h, v7.8h, v5.8h ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b -; CHECK-SD-NEXT: uzp1 v1.16b, v7.16b, v3.16b +; CHECK-SD-NEXT: uzp1 v1.16b, v2.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v32f64_v32i8: @@ -3026,9 +2952,8 @@ define <8 x i8> @fptos_v8f32_v8i8(<8 x float> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.4s, v1.4s ; CHECK-SD-NEXT: fcvtzs v0.4s, v0.4s -; CHECK-SD-NEXT: xtn v1.4h, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v1.8b +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h +; CHECK-SD-NEXT: xtn v0.8b, v0.8h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v8f32_v8i8: @@ -3048,9 +2973,8 @@ define <8 x i8> @fptou_v8f32_v8i8(<8 x float> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.4s, v1.4s ; CHECK-SD-NEXT: fcvtzs v0.4s, v0.4s -; CHECK-SD-NEXT: xtn v1.4h, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v1.8b +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h +; CHECK-SD-NEXT: xtn v0.8b, v0.8h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v8f32_v8i8: @@ -3072,12 +2996,8 @@ define <16 x i8> @fptos_v16f32_v16i8(<16 x float> %a) { ; CHECK-SD-NEXT: fcvtzs v2.4s, v2.4s ; CHECK-SD-NEXT: fcvtzs v1.4s, v1.4s ; CHECK-SD-NEXT: fcvtzs v0.4s, v0.4s -; CHECK-SD-NEXT: xtn v3.4h, v3.4s -; CHECK-SD-NEXT: xtn v2.4h, v2.4s -; CHECK-SD-NEXT: xtn v1.4h, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: mov v2.d[1], v3.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] +; CHECK-SD-NEXT: uzp1 v2.8h, v2.8h, v3.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v2.16b ; CHECK-SD-NEXT: ret ; @@ -3134,20 +3054,12 @@ define <32 x i8> @fptos_v32f32_v32i8(<32 x float> %a) { ; CHECK-SD-NEXT: fcvtzs v6.4s, v6.4s ; CHECK-SD-NEXT: fcvtzs v5.4s, v5.4s ; CHECK-SD-NEXT: fcvtzs v4.4s, v4.4s -; CHECK-SD-NEXT: xtn v3.4h, v3.4s -; CHECK-SD-NEXT: xtn v2.4h, v2.4s -; CHECK-SD-NEXT: xtn v1.4h, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: xtn v7.4h, v7.4s -; CHECK-SD-NEXT: xtn v6.4h, v6.4s -; CHECK-SD-NEXT: xtn v5.4h, v5.4s -; CHECK-SD-NEXT: xtn v4.4h, v4.4s -; CHECK-SD-NEXT: mov v2.d[1], v3.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] -; CHECK-SD-NEXT: mov v6.d[1], v7.d[0] -; CHECK-SD-NEXT: mov v4.d[1], v5.d[0] +; CHECK-SD-NEXT: uzp1 v2.8h, v2.8h, v3.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h +; CHECK-SD-NEXT: uzp1 v1.8h, v6.8h, v7.8h +; CHECK-SD-NEXT: uzp1 v3.8h, v4.8h, v5.8h ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v2.16b -; CHECK-SD-NEXT: uzp1 v1.16b, v4.16b, v6.16b +; CHECK-SD-NEXT: uzp1 v1.16b, v3.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v32f32_v32i8: diff --git a/llvm/test/CodeGen/AArch64/neon-truncstore.ll b/llvm/test/CodeGen/AArch64/neon-truncstore.ll index b677d077b98c..5d78ad24eb33 100644 --- a/llvm/test/CodeGen/AArch64/neon-truncstore.ll +++ b/llvm/test/CodeGen/AArch64/neon-truncstore.ll @@ -104,7 +104,7 @@ define void @v4i32_v4i8(<4 x i32> %a, ptr %result) { ; CHECK-LABEL: v4i32_v4i8: ; CHECK: // %bb.0: ; CHECK-NEXT: xtn v0.4h, v0.4s -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x0] ; CHECK-NEXT: ret %b = trunc <4 x i32> %a to <4 x i8> @@ -170,8 +170,7 @@ define void @v2i16_v2i8(<2 x i16> %a, ptr %result) { define void @v4i16_v4i8(<4 x i16> %a, ptr %result) { ; CHECK-LABEL: v4i16_v4i8: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x0] ; CHECK-NEXT: ret %b = trunc <4 x i16> %a to <4 x i8> diff --git a/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll b/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll index 5f905d94e357..6f1ae023bf25 100644 --- a/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll @@ -145,7 +145,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-NEXT: sqadd v0.4h, v0.4h, v1.4h ; CHECK-NEXT: sshr v0.4h, v0.4h, #8 -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll b/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll index 0ef64789ad97..fb571eff39fe 100644 --- a/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll +++ b/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll @@ -353,13 +353,17 @@ define <8 x i8> @shuffle4_v8i8_v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c, <8 x define <8 x i16> @shuffle4_v4i8_zext(<4 x i8> %a, <4 x i8> %b, <4 x i8> %c, <4 x i8> %d) { ; CHECK-LABEL: shuffle4_v4i8_zext: ; CHECK: // %bb.0: -; CHECK-NEXT: uzp1 v0.8b, v0.8b, v1.8b -; CHECK-NEXT: uzp1 v1.8b, v2.8b, v3.8b +; CHECK-NEXT: fmov d5, d2 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: // kill: def $d3 killed $d3 def $q3 ; CHECK-NEXT: adrp x8, .LCPI8_0 -; CHECK-NEXT: ushll v2.8h, v0.8b, #0 +; CHECK-NEXT: fmov d4, d0 ; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI8_0] -; CHECK-NEXT: ushll v3.8h, v1.8b, #0 -; CHECK-NEXT: tbl v0.16b, { v2.16b, v3.16b }, v0.16b +; CHECK-NEXT: mov v4.d[1], v1.d[0] +; CHECK-NEXT: mov v5.d[1], v3.d[0] +; CHECK-NEXT: bic v4.8h, #255, lsl #8 +; CHECK-NEXT: bic v5.8h, #255, lsl #8 +; CHECK-NEXT: tbl v0.16b, { v4.16b, v5.16b }, v0.16b ; CHECK-NEXT: ret %x = shufflevector <4 x i8> %a, <4 x i8> %b, <8 x i32> %y = shufflevector <4 x i8> %c, <4 x i8> %d, <8 x i32> diff --git a/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll b/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll index acec3e74d3e9..d1f843a09f74 100644 --- a/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll @@ -146,7 +146,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-NEXT: sqsub v0.4h, v0.4h, v1.4h ; CHECK-NEXT: sshr v0.4h, v0.4h, #8 -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/tbl-loops.ll b/llvm/test/CodeGen/AArch64/tbl-loops.ll index 4f8a4f7aede3..0ad990086551 100644 --- a/llvm/test/CodeGen/AArch64/tbl-loops.ll +++ b/llvm/test/CodeGen/AArch64/tbl-loops.ll @@ -41,8 +41,8 @@ define void @loop1(ptr noalias nocapture noundef writeonly %dst, ptr nocapture n ; CHECK-NEXT: fcvtzs v2.4s, v2.4s ; CHECK-NEXT: xtn v1.4h, v1.4s ; CHECK-NEXT: xtn v2.4h, v2.4s -; CHECK-NEXT: xtn v1.8b, v1.8h -; CHECK-NEXT: xtn v2.8b, v2.8h +; CHECK-NEXT: uzp1 v1.8b, v1.8b, v0.8b +; CHECK-NEXT: uzp1 v2.8b, v2.8b, v0.8b ; CHECK-NEXT: mov v1.s[1], v2.s[0] ; CHECK-NEXT: stur d1, [x12, #-4] ; CHECK-NEXT: add x12, x12, #8 diff --git a/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll b/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll index ba367b0dbfde..18cd4cc2111a 100644 --- a/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll +++ b/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll @@ -710,23 +710,23 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) { ; CHECK-NEXT: LBB6_1: ; %loop ; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: ldp q4, q1, [x0, #48] -; CHECK-NEXT: add x9, x1, #8 -; CHECK-NEXT: ldp q3, q2, [x0] -; CHECK-NEXT: subs x8, x8, #1 +; CHECK-NEXT: add x9, x1, #10 ; CHECK-NEXT: ldr d0, [x0, #80] +; CHECK-NEXT: ldp q3, q2, [x0] ; CHECK-NEXT: ldr q5, [x0, #32] +; CHECK-NEXT: subs x8, x8, #1 ; CHECK-NEXT: add x0, x0, #128 -; CHECK-NEXT: uzp1.4s v4, v5, v4 -; CHECK-NEXT: uzp1.4s v2, v3, v2 ; CHECK-NEXT: uzp1.4s v0, v1, v0 -; CHECK-NEXT: uzp1.8h v1, v2, v4 +; CHECK-NEXT: uzp1.4s v1, v5, v4 +; CHECK-NEXT: uzp1.4s v2, v3, v2 ; CHECK-NEXT: xtn.4h v0, v0 -; CHECK-NEXT: uzp1.16b v1, v1, v0 -; CHECK-NEXT: xtn.8b v0, v0 -; CHECK-NEXT: st1.h { v1 }[4], [x9] -; CHECK-NEXT: add x9, x1, #10 -; CHECK-NEXT: st1.b { v0 }[2], [x9] -; CHECK-NEXT: str d1, [x1], #16 +; CHECK-NEXT: uzp1.8h v1, v2, v1 +; CHECK-NEXT: uzp1.8b v2, v0, v0 +; CHECK-NEXT: uzp1.16b v0, v1, v0 +; CHECK-NEXT: st1.b { v2 }[2], [x9] +; CHECK-NEXT: add x9, x1, #8 +; CHECK-NEXT: st1.h { v0 }[4], [x9] +; CHECK-NEXT: str d0, [x1], #16 ; CHECK-NEXT: b.eq LBB6_1 ; CHECK-NEXT: ; %bb.2: ; %exit ; CHECK-NEXT: ret @@ -755,7 +755,7 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) { ; CHECK-BE-NEXT: xtn v0.4h, v0.4s ; CHECK-BE-NEXT: uzp1 v1.8h, v1.8h, v2.8h ; CHECK-BE-NEXT: uzp1 v1.16b, v1.16b, v0.16b -; CHECK-BE-NEXT: xtn v0.8b, v0.8h +; CHECK-BE-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-BE-NEXT: rev16 v2.16b, v1.16b ; CHECK-BE-NEXT: rev64 v1.16b, v1.16b ; CHECK-BE-NEXT: st1 { v0.b }[2], [x9] @@ -790,7 +790,7 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) { ; CHECK-DISABLE-NEXT: xtn v0.4h, v0.4s ; CHECK-DISABLE-NEXT: uzp1 v1.8h, v1.8h, v2.8h ; CHECK-DISABLE-NEXT: uzp1 v1.16b, v1.16b, v0.16b -; CHECK-DISABLE-NEXT: xtn v0.8b, v0.8h +; CHECK-DISABLE-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-DISABLE-NEXT: rev16 v2.16b, v1.16b ; CHECK-DISABLE-NEXT: rev64 v1.16b, v1.16b ; CHECK-DISABLE-NEXT: st1 { v0.b }[2], [x9] diff --git a/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll b/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll index e05c65daf50a..f0bbed59405e 100644 --- a/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll @@ -142,7 +142,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: movi d0, #0xff00ff00ff00ff ; CHECK-NEXT: uaddl v1.8h, v1.8b, v2.8b ; CHECK-NEXT: umin v0.4h, v1.4h, v0.4h -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/usub_sat_vec.ll b/llvm/test/CodeGen/AArch64/usub_sat_vec.ll index 05f43e7d8427..82c0327219f5 100644 --- a/llvm/test/CodeGen/AArch64/usub_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/usub_sat_vec.ll @@ -143,7 +143,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: ushll v0.8h, v0.8b, #0 ; CHECK-NEXT: ushll v1.8h, v1.8b, #0 ; CHECK-NEXT: uqsub v0.4h, v0.4h, v1.4h -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/vcvt-oversize.ll b/llvm/test/CodeGen/AArch64/vcvt-oversize.ll index 380bdbcc7f74..611940546bc1 100644 --- a/llvm/test/CodeGen/AArch64/vcvt-oversize.ll +++ b/llvm/test/CodeGen/AArch64/vcvt-oversize.ll @@ -9,9 +9,8 @@ define <8 x i8> @float_to_i8(ptr %in) { ; CHECK-NEXT: fadd v0.4s, v0.4s, v0.4s ; CHECK-NEXT: fcvtzs v0.4s, v0.4s ; CHECK-NEXT: fcvtzs v1.4s, v1.4s -; CHECK-NEXT: xtn v0.4h, v0.4s -; CHECK-NEXT: xtn v1.4h, v1.4s -; CHECK-NEXT: uzp1 v0.8b, v1.8b, v0.8b +; CHECK-NEXT: uzp1 v0.8h, v1.8h, v0.8h +; CHECK-NEXT: xtn v0.8b, v0.8h ; CHECK-NEXT: ret %l = load <8 x float>, ptr %in %scale = fmul <8 x float> %l, diff --git a/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll b/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll index 9c6ab8da0fa7..dd7a9c6d7768 100644 --- a/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll +++ b/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll @@ -210,7 +210,7 @@ define void @no_combine_for_non_bool_truncate(<4 x i32> %vec, ptr %out) { ; CHECK-LABEL: no_combine_for_non_bool_truncate: ; CHECK: ; %bb.0: ; CHECK-NEXT: xtn.4h v0, v0 -; CHECK-NEXT: xtn.8b v0, v0 +; CHECK-NEXT: uzp1.8b v0, v0, v0 ; CHECK-NEXT: str s0, [x0] ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll b/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll index 90328f73f86b..71d55df66517 100644 --- a/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll +++ b/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll @@ -410,7 +410,7 @@ define void @store_trunc_from_64bits(ptr %src, ptr %dst) { ; BE-NEXT: ldrh w8, [x0, #4] ; BE-NEXT: rev32 v0.4h, v0.4h ; BE-NEXT: mov v0.h[2], w8 -; BE-NEXT: xtn v0.8b, v0.8h +; BE-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; BE-NEXT: rev32 v0.16b, v0.16b ; BE-NEXT: str s0, [sp, #12] ; BE-NEXT: ldrh w9, [sp, #12] @@ -456,7 +456,7 @@ define void @store_trunc_add_from_64bits(ptr %src, ptr %dst) { ; BE-NEXT: add x8, x8, :lo12:.LCPI11_0 ; BE-NEXT: ld1 { v1.4h }, [x8] ; BE-NEXT: add v0.4h, v0.4h, v1.4h -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -638,7 +638,7 @@ define void @shift_trunc_store(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -672,7 +672,7 @@ define void @shift_trunc_store_default_align(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -706,7 +706,7 @@ define void @shift_trunc_store_align_4(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -741,7 +741,7 @@ define void @shift_trunc_store_const_offset_1(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -777,7 +777,7 @@ define void @shift_trunc_store_const_offset_3(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -801,7 +801,7 @@ define void @shift_trunc_volatile_store(ptr %src, ptr %dst) { ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: ldr q0, [x0] ; CHECK-NEXT: shrn.4h v0, v0, #16 -; CHECK-NEXT: xtn.8b v1, v0 +; CHECK-NEXT: uzp1.8b v1, v0, v0 ; CHECK-NEXT: umov.h w8, v0[2] ; CHECK-NEXT: str s1, [sp, #12] ; CHECK-NEXT: ldrh w9, [sp, #12] @@ -816,7 +816,7 @@ define void @shift_trunc_volatile_store(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -868,7 +868,7 @@ define void @load_v3i8_zext_to_3xi32_add_trunc_store(ptr %src) { ; BE-NEXT: ushll v0.8h, v0.8b, #0 ; BE-NEXT: ld1 { v0.b }[4], [x9] ; BE-NEXT: add v0.4h, v0.4h, v1.4h -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #8] @@ -921,7 +921,7 @@ define void @load_v3i8_sext_to_3xi32_add_trunc_store(ptr %src) { ; BE-NEXT: ushll v0.8h, v0.8b, #0 ; BE-NEXT: ld1 { v0.b }[4], [x9] ; BE-NEXT: add v0.4h, v0.4h, v1.4h -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #8] -- GitLab From f1015d1701d86c4e640cdbfd1928a958aea921d6 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 13 Mar 2024 16:08:01 +0000 Subject: [PATCH 398/953] [VPlan] Use VPBuilder to create ActiveLaneMask (NFC). --- .../Vectorize/LoopVectorizationPlanner.h | 16 ++++++++++++---- .../lib/Transforms/Vectorize/VPlanTransforms.cpp | 8 ++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h index a7ebf78e54ce..e86705e89889 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h +++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h @@ -79,6 +79,13 @@ public: VPBasicBlock *getInsertBlock() const { return BB; } VPBasicBlock::iterator getInsertPoint() const { return InsertPt; } + /// Create a VPBuilder to insert after \p R. + static VPBuilder getToInsertAfter(VPRecipeBase *R) { + VPBuilder B; + B.setInsertPoint(R->getParent(), std::next(R->getIterator())); + return B; + } + /// InsertPoint - A saved insertion point. class VPInsertPoint { VPBasicBlock *Block = nullptr; @@ -131,8 +138,9 @@ public: /// Create an N-ary operation with \p Opcode, \p Operands and set \p Inst as /// its underlying Instruction. - VPValue *createNaryOp(unsigned Opcode, ArrayRef Operands, - Instruction *Inst = nullptr, const Twine &Name = "") { + VPInstruction *createNaryOp(unsigned Opcode, ArrayRef Operands, + Instruction *Inst = nullptr, + const Twine &Name = "") { DebugLoc DL; if (Inst) DL = Inst->getDebugLoc(); @@ -140,8 +148,8 @@ public: NewVPInst->setUnderlyingValue(Inst); return NewVPInst; } - VPValue *createNaryOp(unsigned Opcode, ArrayRef Operands, - DebugLoc DL, const Twine &Name = "") { + VPInstruction *createNaryOp(unsigned Opcode, ArrayRef Operands, + DebugLoc DL, const Twine &Name = "") { return createInstruction(Opcode, Operands, DL, Name); } diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp index f6b564ad931c..3b19db9f0d30 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp @@ -1192,10 +1192,10 @@ void VPlanTransforms::addActiveLaneMask( LaneMask = addVPLaneMaskPhiAndUpdateExitBranch( Plan, DataAndControlFlowWithoutRuntimeCheck); } else { - LaneMask = new VPInstruction(VPInstruction::ActiveLaneMask, - {WideCanonicalIV, Plan.getTripCount()}, - nullptr, "active.lane.mask"); - LaneMask->insertAfter(WideCanonicalIV); + VPBuilder B = VPBuilder::getToInsertAfter(WideCanonicalIV); + LaneMask = B.createNaryOp(VPInstruction::ActiveLaneMask, + {WideCanonicalIV, Plan.getTripCount()}, nullptr, + "active.lane.mask"); } // Walk users of WideCanonicalIV and replace all compares of the form -- GitLab From 8a8ef1cacfcd7745d2b6ad00431e6fa9ab9a2fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?= =?UTF-8?q?=E3=83=B3=29?= Date: Wed, 13 Mar 2024 09:14:40 -0700 Subject: [PATCH 399/953] [flang][cuda] Enable cuda with -x cuda option (#84944) Flang driver was already able to enable the CUDA language feature base on the file extension but there was no command line option. This PR adds one. --- flang/lib/Frontend/CompilerInvocation.cpp | 9 +++++++++ flang/lib/Frontend/FrontendAction.cpp | 11 ++++++++--- flang/test/Driver/cuda-option.f90 | 15 +++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 flang/test/Driver/cuda-option.f90 diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 4707de0e976c..2e3fa1f6e660 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -581,6 +581,8 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, // pre-processed inputs. .Case("f95", Language::Fortran) .Case("f95-cpp-input", Language::Fortran) + // CUDA Fortran + .Case("cuda", Language::Fortran) .Default(Language::Unknown); // Flang's intermediate representations. @@ -877,6 +879,13 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args, if (args.hasArg(clang::driver::options::OPT_flarge_sizes)) res.getDefaultKinds().set_sizeIntegerKind(8); + // -x cuda + auto language = args.getLastArgValue(clang::driver::options::OPT_x); + if (language.equals("cuda")) { + res.getFrontendOpts().features.Enable( + Fortran::common::LanguageFeature::CUDA); + } + // -fopenmp and -fopenacc if (args.hasArg(clang::driver::options::OPT_fopenacc)) { res.getFrontendOpts().features.Enable( diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp index 599b4e11f0cf..bb1c239540d9 100644 --- a/flang/lib/Frontend/FrontendAction.cpp +++ b/flang/lib/Frontend/FrontendAction.cpp @@ -86,9 +86,14 @@ bool FrontendAction::beginSourceFile(CompilerInstance &ci, invoc.collectMacroDefinitions(); } - // Enable CUDA Fortran if source file is *.cuf/*.CUF. - invoc.getFortranOpts().features.Enable(Fortran::common::LanguageFeature::CUDA, - getCurrentInput().getIsCUDAFortran()); + if (!invoc.getFortranOpts().features.IsEnabled( + Fortran::common::LanguageFeature::CUDA)) { + // Enable CUDA Fortran if source file is *.cuf/*.CUF and not already + // enabled. + invoc.getFortranOpts().features.Enable( + Fortran::common::LanguageFeature::CUDA, + getCurrentInput().getIsCUDAFortran()); + } // Decide between fixed and free form (if the user didn't express any // preference, use the file extension to decide) diff --git a/flang/test/Driver/cuda-option.f90 b/flang/test/Driver/cuda-option.f90 new file mode 100644 index 000000000000..112e1cb6c77f --- /dev/null +++ b/flang/test/Driver/cuda-option.f90 @@ -0,0 +1,15 @@ +! Test -fcuda option +! RUN: %flang -fc1 -cpp -x cuda -fdebug-unparse %s -o - | FileCheck %s +! RUN: not %flang -fc1 -cpp %s -o - 2>&1 | FileCheck %s --check-prefix=ERROR +program main +#if _CUDA + integer :: var = _CUDA +#endif + integer, device :: dvar +end program + +! CHECK-LABEL: PROGRAM main +! CHECK: INTEGER :: var = 1 +! CHECK: INTEGER, DEVICE :: dvar + +! ERROR: cuda-option.f90:8:19: error: expected end of statement -- GitLab From 5facb406e6417987ac5dfabd8f04510d7bc3fbc6 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Wed, 13 Mar 2024 09:26:36 -0700 Subject: [PATCH 400/953] [libc][docs] document gpu support for stdbit.h (#85103) Via: https://github.com/llvm/llvm-project/pull/84938#issuecomment-1992120095 --------- Co-authored-by: Joseph Huber --- libc/docs/gpu/support.rst | 73 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/libc/docs/gpu/support.rst b/libc/docs/gpu/support.rst index 250f0a7794de..31bbdc41090b 100644 --- a/libc/docs/gpu/support.rst +++ b/libc/docs/gpu/support.rst @@ -89,6 +89,79 @@ strtok_r |check| strxfrm |check| ============= ========= ============ +stdbit.h +-------- + +============================ ========= ============ +Function Name Available RPC Required +============================ ========= ============ +stdc_leading_zeros_uc |check| +stdc_leading_zeros_us |check| +stdc_leading_zeros_ui |check| +stdc_leading_zeros_ul |check| +stdc_leading_zeros_ull |check| +stdc_trailing_zeros_uc |check| +stdc_trailing_zeros_us |check| +stdc_trailing_zeros_ui |check| +stdc_trailing_zeros_ul |check| +stdc_trailing_zeros_ull |check| +stdc_trailing_ones_uc |check| +stdc_trailing_ones_us |check| +stdc_trailing_ones_ui |check| +stdc_trailing_ones_ul |check| +stdc_trailing_ones_ull |check| +stdc_first_leading_zero_uc |check| +stdc_first_leading_zero_us |check| +stdc_first_leading_zero_ui |check| +stdc_first_leading_zero_ul |check| +stdc_first_leading_zero_ull |check| +stdc_first_leading_one_uc |check| +stdc_first_leading_one_us |check| +stdc_first_leading_one_ui |check| +stdc_first_leading_one_ul |check| +stdc_first_leading_one_ull |check| +stdc_first_trailing_zero_uc |check| +stdc_first_trailing_zero_us |check| +stdc_first_trailing_zero_ui |check| +stdc_first_trailing_zero_ul |check| +stdc_first_trailing_zero_ull |check| +stdc_first_trailing_one_uc |check| +stdc_first_trailing_one_us |check| +stdc_first_trailing_one_ui |check| +stdc_first_trailing_one_ul |check| +stdc_first_trailing_one_ull |check| +stdc_count_zeros_uc |check| +stdc_count_zeros_us |check| +stdc_count_zeros_ui |check| +stdc_count_zeros_ul |check| +stdc_count_zeros_ull |check| +stdc_count_ones_uc |check| +stdc_count_ones_us |check| +stdc_count_ones_ui |check| +stdc_count_ones_ul |check| +stdc_count_ones_ull |check| +stdc_has_single_bit_uc |check| +stdc_has_single_bit_us |check| +stdc_has_single_bit_ui |check| +stdc_has_single_bit_ul |check| +stdc_has_single_bit_ull |check| +stdc_bit_width_uc |check| +stdc_bit_width_us |check| +stdc_bit_width_ui |check| +stdc_bit_width_ul |check| +stdc_bit_width_ull |check| +stdc_bit_floor_uc |check| +stdc_bit_floor_us |check| +stdc_bit_floor_ui |check| +stdc_bit_floor_ul |check| +stdc_bit_floor_ull |check| +stdc_bit_ceil_uc |check| +stdc_bit_ceil_us |check| +stdc_bit_ceil_ui |check| +stdc_bit_ceil_ul |check| +stdc_bit_ceil_ull |check| +============================ ========= ============ + stdlib.h -------- -- GitLab From bb893fa23f6c851d957d82e14bc1aa6fbbffcaaa Mon Sep 17 00:00:00 2001 From: Christian Sigg Date: Wed, 13 Mar 2024 17:26:50 +0100 Subject: [PATCH 401/953] [mlir] Fix inlining-threshold.mlir test for NDEBUG builds. --- mlir/test/Transforms/inlining-threshold.mlir | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/test/Transforms/inlining-threshold.mlir b/mlir/test/Transforms/inlining-threshold.mlir index b94115d8f264..649408aab577 100644 --- a/mlir/test/Transforms/inlining-threshold.mlir +++ b/mlir/test/Transforms/inlining-threshold.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt %s --mlir-disable-threading -inline='default-pipeline='' inlining-threshold=100' -debug-only=inliner-pass 2>&1 | FileCheck %s +// RUN: mlir-opt %s -inline='default-pipeline= inlining-threshold=100' | FileCheck %s // Check that inlining does not happen when the threshold is exceeded. func.func @callee1(%arg : i32) -> i32 { -- GitLab From ccd16085f70105d457f052543d731dd51089945b Mon Sep 17 00:00:00 2001 From: Bhuminjay Soni Date: Wed, 13 Mar 2024 21:58:25 +0530 Subject: [PATCH 402/953] Diagnose misuse of the cleanup attribute (#80040) This pull request fixes #79443 when the cleanup attribute is intended to be applied to a variable declaration, passing its address to a specified function. The problem arises when standard functions like free, closedir, fclose, etc., are used incorrectly with this attribute, leading to incorrect behavior. Fixes #79443 --- clang/docs/ReleaseNotes.rst | 4 ++++ clang/include/clang/Sema/Sema.h | 5 +++-- clang/lib/Sema/SemaDeclAttr.cpp | 24 ++++++++++++++++++++++++ clang/test/Sema/attr-cleanup.c | 28 ++++++++++++++++++++++++++-- 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 64a9fe0d8bcc..7173c1400f53 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -237,6 +237,10 @@ Improvements to Clang's diagnostics - Clang now diagnoses lambda function expressions being implicitly cast to boolean values, under ``-Wpointer-bool-conversion``. Fixes #GH82512. +- Clang now provides improved warnings for the ``cleanup`` attribute to detect misuse scenarios, + such as attempting to call ``free`` on an unallocated object. Fixes + `#79443 `_. + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d6ab2b0c2def..4a853119a2bb 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2152,14 +2152,15 @@ public: bool IsLayoutCompatible(QualType T1, QualType T2) const; + bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, + const FunctionProtoType *Proto); + private: void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, const ArraySubscriptExpr *ASE = nullptr, bool AllowOnePastEnd = true, bool IndexNegated = false); void CheckArrayAccess(const Expr *E); - bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, - const FunctionProtoType *Proto); bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc, ArrayRef Args); bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index e3da3e606435..ec00fdf3f88d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3787,6 +3787,30 @@ static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) { << NI.getName() << ParamTy << Ty; return; } + VarDecl *VD = cast(D); + // Create a reference to the variable declaration. This is a fake/dummy + // reference. + DeclRefExpr *VariableReference = DeclRefExpr::Create( + S.Context, NestedNameSpecifierLoc{}, FD->getLocation(), VD, false, + DeclarationNameInfo{VD->getDeclName(), VD->getLocation()}, VD->getType(), + VK_LValue); + + // Create a unary operator expression that represents taking the address of + // the variable. This is a fake/dummy expression. + Expr *AddressOfVariable = UnaryOperator::Create( + S.Context, VariableReference, UnaryOperatorKind::UO_AddrOf, + S.Context.getPointerType(VD->getType()), VK_PRValue, OK_Ordinary, Loc, + +false, FPOptionsOverride{}); + + // Create a function call expression. This is a fake/dummy call expression. + CallExpr *FunctionCallExpression = + CallExpr::Create(S.Context, E, ArrayRef{AddressOfVariable}, + S.Context.VoidTy, VK_PRValue, Loc, FPOptionsOverride{}); + + if (S.CheckFunctionCall(FD, FunctionCallExpression, + FD->getType()->getAs())) { + return; + } D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD)); } diff --git a/clang/test/Sema/attr-cleanup.c b/clang/test/Sema/attr-cleanup.c index 2c38687622c2..95baf2e675a0 100644 --- a/clang/test/Sema/attr-cleanup.c +++ b/clang/test/Sema/attr-cleanup.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 %s -verify -fsyntax-only +// RUN: %clang_cc1 -Wfree-nonheap-object -fsyntax-only -verify %s void c1(int *a); - +typedef __typeof__(sizeof(0)) size_t; extern int g1 __attribute((cleanup(c1))); // expected-warning {{'cleanup' attribute only applies to local variables}} int g2 __attribute((cleanup(c1))); // expected-warning {{'cleanup' attribute only applies to local variables}} static int g3 __attribute((cleanup(c1))); // expected-warning {{'cleanup' attribute only applies to local variables}} @@ -48,3 +48,27 @@ void t6(void) { } void t7(__attribute__((cleanup(c4))) int a) {} // expected-warning {{'cleanup' attribute only applies to local variables}} + +extern void free(void *); +extern void *malloc(size_t size); +void t8(void) { + void *p + __attribute__(( + cleanup( + free // expected-warning{{attempt to call free on non-heap object 'p'}} + ) + )) + = malloc(10); +} +typedef __attribute__((aligned(2))) int Aligned2Int; +void t9(void){ + Aligned2Int __attribute__((cleanup(c1))) xwarn; // expected-warning{{passing 2-byte aligned argument to 4-byte aligned parameter 1 of 'c1' may result in an unaligned pointer access}} +} + +__attribute__((enforce_tcb("TCB1"))) void func1(int *x) { + *x = 5; +} +__attribute__((enforce_tcb("TCB2"))) void t10() { + int __attribute__((cleanup(func1))) x = 5; // expected-warning{{calling 'func1' is a violation of trusted computing base 'TCB2'}} +} + -- GitLab From 69afb9d7875d79fdacaaa2f22b5ee3a06faf5373 Mon Sep 17 00:00:00 2001 From: Sirraide Date: Wed, 13 Mar 2024 17:39:23 +0100 Subject: [PATCH 403/953] [Clang] [Sema] Fix bug in `_Complex float`+`int` arithmetic (#83063) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C23 6.3.1.8 ‘Usual arithmetic conversions’ p1 states (emphasis mine): > Otherwise, if the corresponding real type of either operand is `float`, the other operand is converted, *without change of type domain*, to a type whose corresponding real type is `float`. ‘type domain’ here refers to `_Complex` vs real (i.e. non-`_Complex`); there is another clause that states the same for `double`. Consider the following code: ```c++ _Complex float f; int x; f / x; ``` After talking this over with @AaronBallman, we came to the conclusion that `x` should be converted to `float` and *not* `_Complex float` (that is, we should perform a division of `_Complex float / float`, and *not* `_Complex float / _Complex float`; the same also applies to `-+*`). This was already being done correctly for cases where `x` was already a `float`; it’s just mixed `_Complex float`+`int` operations that currently suffer from this problem. This pr removes the extra `FloatingRealToComplex` conversion that we were erroneously inserting and adds some tests to make sure we’re actually doing `_Complex float / float` and not `_Complex float / _Complex float` (and analogously for `double` and `-+*`). The only exception here is `float / _Complex float`, which calls a library function (`__divsc3`) that takes 4 `float`s, so we end up having to convert the `float` to a `_Complex float` after all (and analogously for `double`); I don’t believe there is a way around this. Lastly, we were also missing tests for `_Complex` arithmetic at compile time, so this adds some tests for that as well. --- clang/docs/ReleaseNotes.rst | 7 ++ clang/lib/Sema/SemaExpr.cpp | 15 ++- clang/test/CodeGen/complex-math-mixed.c | 146 ++++++++++++++++++++++++ clang/test/CodeGen/volatile.cpp | 48 ++++---- clang/test/Sema/complex-arithmetic.c | 115 +++++++++++++++++++ 5 files changed, 298 insertions(+), 33 deletions(-) create mode 100644 clang/test/CodeGen/complex-math-mixed.c create mode 100644 clang/test/Sema/complex-arithmetic.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7173c1400f53..c5488e8742f6 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -278,6 +278,13 @@ Bug Fixes in This Version - Clang now correctly generates overloads for bit-precise integer types for builtin operators in C++. Fixes #GH82998. +- When performing mixed arithmetic between ``_Complex`` floating-point types and integers, + Clang now correctly promotes the integer to its corresponding real floating-point + type only rather than to the complex type (e.g. ``_Complex float / int`` is now evaluated + as ``_Complex float / float`` rather than ``_Complex float / _Complex float``), as mandated + by the C standard. This significantly improves codegen of `*` and `/` especially. + Fixes (`#31205 `_). + Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 93f82e68ab64..8725b09f8546 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1099,12 +1099,13 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, return E; } -/// Converts an integer to complex float type. Helper function of +/// Convert complex integers to complex floats and real integers to +/// real floats as required for complex arithmetic. Helper function of /// UsualArithmeticConversions() /// /// \return false if the integer expression is an integer type and is -/// successfully converted to the complex type. -static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr, +/// successfully converted to the (complex) float type. +static bool handleComplexIntegerToFloatConversion(Sema &S, ExprResult &IntExpr, ExprResult &ComplexExpr, QualType IntTy, QualType ComplexTy, @@ -1114,8 +1115,6 @@ static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr, if (IntTy->isIntegerType()) { QualType fpTy = ComplexTy->castAs()->getElementType(); IntExpr = S.ImpCastExprToType(IntExpr.get(), fpTy, CK_IntegralToFloating); - IntExpr = S.ImpCastExprToType(IntExpr.get(), ComplexTy, - CK_FloatingRealToComplex); } else { assert(IntTy->isComplexIntegerType()); IntExpr = S.ImpCastExprToType(IntExpr.get(), ComplexTy, @@ -1160,11 +1159,11 @@ static QualType handleComplexFloatConversion(Sema &S, ExprResult &Shorter, static QualType handleComplexConversion(Sema &S, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign) { - // if we have an integer operand, the result is the complex type. - if (!handleIntegerToComplexFloatConversion(S, RHS, LHS, RHSType, LHSType, + // Handle (complex) integer types. + if (!handleComplexIntegerToFloatConversion(S, RHS, LHS, RHSType, LHSType, /*SkipCast=*/false)) return LHSType; - if (!handleIntegerToComplexFloatConversion(S, LHS, RHS, LHSType, RHSType, + if (!handleComplexIntegerToFloatConversion(S, LHS, RHS, LHSType, RHSType, /*SkipCast=*/IsCompAssign)) return RHSType; diff --git a/clang/test/CodeGen/complex-math-mixed.c b/clang/test/CodeGen/complex-math-mixed.c new file mode 100644 index 000000000000..050163cca80a --- /dev/null +++ b/clang/test/CodeGen/complex-math-mixed.c @@ -0,0 +1,146 @@ +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown -o - | FileCheck %s --check-prefix=X86 +// RUN: %clang_cc1 %s -O0 -triple x86_64-unknown-unknown -fsyntax-only -ast-dump | FileCheck %s --check-prefix=AST + +// Check that for 'F _Complex + int' (F = real floating-point type), we emit an +// implicit cast from 'int' to 'F', but NOT to 'F _Complex' (i.e. that we do +// 'F _Complex + F', NOT 'F _Complex + F _Complex'), and likewise for -/*. + +// AST-NOT: FloatingRealToComplex + +float _Complex add_float_ci(float _Complex a, int b) { + // X86-LABEL: @add_float_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: fadd float {{.*}}, [[I]] + // X86-NOT: fadd + return a + b; +} + +float _Complex add_float_ic(int a, float _Complex b) { + // X86-LABEL: @add_float_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: fadd float [[I]] + // X86-NOT: fadd + return a + b; +} + +float _Complex sub_float_ci(float _Complex a, int b) { + // X86-LABEL: @sub_float_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: fsub float {{.*}}, [[I]] + // X86-NOT: fsub + return a - b; +} + +float _Complex sub_float_ic(int a, float _Complex b) { + // X86-LABEL: @sub_float_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: fsub float [[I]] + // X86: fneg + // X86-NOT: fsub + return a - b; +} + +float _Complex mul_float_ci(float _Complex a, int b) { + // X86-LABEL: @mul_float_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: fmul float {{.*}}, [[I]] + // X86: fmul float {{.*}}, [[I]] + // X86-NOT: fmul + return a * b; +} + +float _Complex mul_float_ic(int a, float _Complex b) { + // X86-LABEL: @mul_float_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: fmul float [[I]] + // X86: fmul float [[I]] + // X86-NOT: fmul + return a * b; +} + +float _Complex div_float_ci(float _Complex a, int b) { + // X86-LABEL: @div_float_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: fdiv float {{.*}}, [[I]] + // X86: fdiv float {{.*}}, [[I]] + // X86-NOT: @__divsc3 + return a / b; +} + +// There is no good way of doing this w/o converting the 'int' to a complex +// number, so we expect complex division here. +float _Complex div_float_ic(int a, float _Complex b) { + // X86-LABEL: @div_float_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: call {{.*}} @__divsc3(float {{.*}} [[I]], float noundef 0.{{0+}}e+00, float {{.*}}, float {{.*}}) + return a / b; +} + +double _Complex add_double_ci(double _Complex a, int b) { + // X86-LABEL: @add_double_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: fadd double {{.*}}, [[I]] + // X86-NOT: fadd + return a + b; +} + +double _Complex add_double_ic(int a, double _Complex b) { + // X86-LABEL: @add_double_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: fadd double [[I]] + // X86-NOT: fadd + return a + b; +} + +double _Complex sub_double_ci(double _Complex a, int b) { + // X86-LABEL: @sub_double_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: fsub double {{.*}}, [[I]] + // X86-NOT: fsub + return a - b; +} + +double _Complex sub_double_ic(int a, double _Complex b) { + // X86-LABEL: @sub_double_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: fsub double [[I]] + // X86: fneg + // X86-NOT: fsub + return a - b; +} + +double _Complex mul_double_ci(double _Complex a, int b) { + // X86-LABEL: @mul_double_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: fmul double {{.*}}, [[I]] + // X86: fmul double {{.*}}, [[I]] + // X86-NOT: fmul + return a * b; +} + +double _Complex mul_double_ic(int a, double _Complex b) { + // X86-LABEL: @mul_double_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: fmul double [[I]] + // X86: fmul double [[I]] + // X86-NOT: fmul + return a * b; +} + +double _Complex div_double_ci(double _Complex a, int b) { + // X86-LABEL: @div_double_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: fdiv double {{.*}}, [[I]] + // X86: fdiv double {{.*}}, [[I]] + // X86-NOT: @__divdc3 + return a / b; +} + +// There is no good way of doing this w/o converting the 'int' to a complex +// number, so we expect complex division here. +double _Complex div_double_ic(int a, double _Complex b) { + // X86-LABEL: @div_double_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: call {{.*}} @__divdc3(double {{.*}} [[I]], double noundef 0.{{0+}}e+00, double {{.*}}, double {{.*}}) + return a / b; +} diff --git a/clang/test/CodeGen/volatile.cpp b/clang/test/CodeGen/volatile.cpp index 38724659ad8a..70f523b93852 100644 --- a/clang/test/CodeGen/volatile.cpp +++ b/clang/test/CodeGen/volatile.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -O2 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK +// RUN: %clang_cc1 -O2 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s struct agg { int a ; @@ -10,34 +10,32 @@ _Complex float cf; int volatile vol =10; void f0() { const_cast(cf) = const_cast(cf) + 1; -// CHECK: %cf.real = load volatile float, ptr @cf -// CHECK: %cf.imag = load volatile float, ptr getelementptr -// CHECK: %add.r = fadd float %cf.real, 1.000000e+00 -// CHECK: %add.i = fadd float %cf.imag, 0.000000e+00 -// CHECK: store volatile float %add.r -// CHECK: store volatile float %add.i, ptr getelementptr +// CHECK: [[Re1:%.*]] = load volatile float, ptr @cf +// CHECK: [[Im1:%.*]] = load volatile float, ptr getelementptr +// CHECK: [[Add1:%.*]] = fadd float [[Re1]], 1.000000e+00 +// CHECK: store volatile float [[Add1]], ptr @cf +// CHECK: store volatile float [[Im1]], ptr getelementptr static_cast(cf) = static_cast(cf) + 1; -// CHECK: %cf.real1 = load volatile float, ptr @cf -// CHECK: %cf.imag2 = load volatile float, ptr getelementptr -// CHECK: %add.r3 = fadd float %cf.real1, 1.000000e+00 -// CHECK: %add.i4 = fadd float %cf.imag2, 0.000000e+00 -// CHECK: store volatile float %add.r3, ptr @cf -// CHECK: store volatile float %add.i4, ptr getelementptr +// CHECK: [[Re2:%.*]] = load volatile float, ptr @cf +// CHECK: [[Im2:%.*]] = load volatile float, ptr getelementptr +// CHECK: [[Add2:%.*]] = fadd float [[Re2]], 1.000000e+00 +// CHECK: store volatile float [[Add2]], ptr @cf +// CHECK: store volatile float [[Im2]], ptr getelementptr const_cast(a.a) = const_cast(t.a) ; -// CHECK: %0 = load volatile i32, ptr @t -// CHECK: store volatile i32 %0, ptr @a +// CHECK: [[I1:%.*]] = load volatile i32, ptr @t +// CHECK: store volatile i32 [[I1]], ptr @a static_cast(a.b) = static_cast(t.a) ; -// CHECK: %1 = load volatile i32, ptr @t -// CHECK: store volatile i32 %1, ptr getelementptr +// CHECK: [[I2:%.*]] = load volatile i32, ptr @t +// CHECK: store volatile i32 [[I2]], ptr getelementptr const_cast(vt) = const_cast(vt) + 1; -// CHECK: %2 = load volatile i32, ptr @vt -// CHECK: %add = add nsw i32 %2, 1 -// CHECK: store volatile i32 %add, ptr @vt +// CHECK: [[I3:%.*]] = load volatile i32, ptr @vt +// CHECK: [[Add3:%.*]] = add nsw i32 [[I3]], 1 +// CHECK: store volatile i32 [[Add3]], ptr @vt static_cast(vt) = static_cast(vt) + 1; -// CHECK: %3 = load volatile i32, ptr @vt -// CHECK: %add5 = add nsw i32 %3, 1 -// CHECK: store volatile i32 %add5, ptr @vt +// CHECK: [[I4:%.*]] = load volatile i32, ptr @vt +// CHECK: [[Add4:%.*]] = add nsw i32 [[I4]], 1 +// CHECK: store volatile i32 [[Add4]], ptr @vt vt = const_cast(vol); -// %4 = load i32, ptr @vol -// store i32 %4, ptr @vt +// [[I5:%.*]] = load i32, ptr @vol +// store i32 [[I5]], ptr @vt } diff --git a/clang/test/Sema/complex-arithmetic.c b/clang/test/Sema/complex-arithmetic.c new file mode 100644 index 000000000000..c9e84da6daa9 --- /dev/null +++ b/clang/test/Sema/complex-arithmetic.c @@ -0,0 +1,115 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +// This tests evaluation of _Complex arithmetic at compile time. + +#define APPROX_EQ(a, b) ( \ + __builtin_fabs(__real (a) - __real (b)) < 0.0001 && \ + __builtin_fabs(__imag (a) - __imag (b)) < 0.0001 \ +) + +#define EVAL(a, b) _Static_assert(a == b, "") +#define EVALF(a, b) _Static_assert(APPROX_EQ(a, b), "") + +// _Complex float + _Complex float +void a() { + EVALF((2.f + 3i) + (4.f + 5i), 6.f + 8i); + EVALF((2.f + 3i) - (4.f + 5i), -2.f - 2i); + EVALF((2.f + 3i) * (4.f + 5i), -7.f + 22i); + EVALF((2.f + 3i) / (4.f + 5i), 0.5609f + 0.0487i); + + EVALF((2. + 3i) + (4. + 5i), 6. + 8i); + EVALF((2. + 3i) - (4. + 5i), -2. - 2i); + EVALF((2. + 3i) * (4. + 5i), -7. + 22i); + EVALF((2. + 3i) / (4. + 5i), .5609 + .0487i); +} + +// _Complex int + _Complex int +void b() { + EVAL((2 + 3i) + (4 + 5i), 6 + 8i); + EVAL((2 + 3i) - (4 + 5i), -2 - 2i); + EVAL((2 + 3i) * (4 + 5i), -7 + 22i); + EVAL((8 + 30i) / (4 + 5i), 4 + 1i); +} + +// _Complex float + float +void c() { + EVALF((2.f + 4i) + 3.f, 5.f + 4i); + EVALF((2.f + 4i) - 3.f, -1.f + 4i); + EVALF((2.f + 4i) * 3.f, 6.f + 12i); + EVALF((2.f + 4i) / 2.f, 1.f + 2i); + + EVALF(3.f + (2.f + 4i), 5.f + 4i); + EVALF(3.f - (2.f + 4i), 1.f - 4i); + EVALF(3.f * (2.f + 4i), 6.f + 12i); + EVALF(3.f / (2.f + 4i), .3f - 0.6i); + + EVALF((2. + 4i) + 3., 5. + 4i); + EVALF((2. + 4i) - 3., -1. + 4i); + EVALF((2. + 4i) * 3., 6. + 12i); + EVALF((2. + 4i) / 2., 1. + 2i); + + EVALF(3. + (2. + 4i), 5. + 4i); + EVALF(3. - (2. + 4i), 1. - 4i); + EVALF(3. * (2. + 4i), 6. + 12i); + EVALF(3. / (2. + 4i), .3 - 0.6i); +} + +// _Complex int + int +void d() { + EVAL((2 + 4i) + 3, 5 + 4i); + EVAL((2 + 4i) - 3, -1 + 4i); + EVAL((2 + 4i) * 3, 6 + 12i); + EVAL((2 + 4i) / 2, 1 + 2i); + + EVAL(3 + (2 + 4i), 5 + 4i); + EVAL(3 - (2 + 4i), 1 - 4i); + EVAL(3 * (2 + 4i), 6 + 12i); + EVAL(20 / (2 + 4i), 2 - 4i); +} + +// _Complex float + int +void e() { + EVALF((2.f + 4i) + 3, 5.f + 4i); + EVALF((2.f + 4i) - 3, -1.f + 4i); + EVALF((2.f + 4i) * 3, 6.f + 12i); + EVALF((2.f + 4i) / 2, 1.f + 2i); + + EVALF(3 + (2.f + 4i), 5.f + 4i); + EVALF(3 - (2.f + 4i), 1.f - 4i); + EVALF(3 * (2.f + 4i), 6.f + 12i); + EVALF(3 / (2.f + 4i), .3f - 0.6i); + + EVALF((2. + 4i) + 3, 5. + 4i); + EVALF((2. + 4i) - 3, -1. + 4i); + EVALF((2. + 4i) * 3, 6. + 12i); + EVALF((2. + 4i) / 2, 1. + 2i); + + EVALF(3 + (2. + 4i), 5. + 4i); + EVALF(3 - (2. + 4i), 1. - 4i); + EVALF(3 * (2. + 4i), 6. + 12i); + EVALF(3 / (2. + 4i), .3 - 0.6i); +} + +// _Complex int + float +void f() { + EVALF((2 + 4i) + 3.f, 5.f + 4i); + EVALF((2 + 4i) - 3.f, -1.f + 4i); + EVALF((2 + 4i) * 3.f, 6.f + 12i); + EVALF((2 + 4i) / 2.f, 1.f + 2i); + + EVALF(3.f + (2 + 4i), 5.f + 4i); + EVALF(3.f - (2 + 4i), 1.f - 4i); + EVALF(3.f * (2 + 4i), 6.f + 12i); + EVALF(3.f / (2 + 4i), .3f - 0.6i); + + EVALF((2 + 4i) + 3., 5. + 4i); + EVALF((2 + 4i) - 3., -1. + 4i); + EVALF((2 + 4i) * 3., 6. + 12i); + EVALF((2 + 4i) / 2., 1. + 2i); + + EVALF(3. + (2 + 4i), 5. + 4i); + EVALF(3. - (2 + 4i), 1. - 4i); + EVALF(3. * (2 + 4i), 6. + 12i); + EVALF(3. / (2 + 4i), .3 - 0.6i); +} -- GitLab From 360da83858655ad8297f3c0467c8c97ebedab5ed Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Wed, 13 Mar 2024 16:39:35 +0000 Subject: [PATCH 404/953] [RemoveDI][NFC] Rename DPValue->DbgRecord in comments and varnames (#84939) This patch continues the ongoing rename work, replacing DPValue with DbgRecord in comments and the names of variables, both members and fn-local. This is the most labour-intensive part of the rename, as it is where the most decisions have to be made about whether a given comment or variable is referring to DPValues (equivalent to debug variable intrinsics) or DbgRecords (a catch-all for all debug intrinsics); these decisions are not individually difficult, but comprise a fairly large amount of text to review. This patch still largely performs basic string substitutions followed by clang-format; there are almost* no places where, for example, a comment has been expanded or modified to reflect the semantic difference between DPValues and DbgRecords. I don't believe such a change is generally necessary in LLVM, but it may be useful in the docs, and so I'll be submitting docs changes as a separate patch. *In a few places, `dbg.values` was replaced with `debug intrinsics`. --- .../llvm/CodeGen/GlobalISel/IRTranslator.h | 2 +- llvm/include/llvm/IR/BasicBlock.h | 32 ++-- .../include/llvm/IR/DebugProgramInstruction.h | 62 +++--- llvm/include/llvm/IR/Instruction.h | 31 +-- llvm/include/llvm/IR/PassManager.h | 2 +- llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp | 6 +- .../CodeGen/AssignmentTrackingAnalysis.cpp | 35 ++-- llvm/lib/CodeGen/CodeGenPrepare.cpp | 8 +- llvm/lib/CodeGen/MIRPrinter.cpp | 4 +- llvm/lib/CodeGen/SelectOptimize.cpp | 15 +- llvm/lib/IR/AsmWriter.cpp | 2 +- llvm/lib/IR/BasicBlock.cpp | 176 +++++++++--------- llvm/lib/IR/DebugInfo.cpp | 2 +- llvm/lib/IR/DebugProgramInstruction.cpp | 70 +++---- llvm/lib/IR/Instruction.cpp | 37 ++-- llvm/lib/IR/LLVMContextImpl.cpp | 2 +- llvm/lib/IR/LLVMContextImpl.h | 12 +- llvm/lib/Transforms/Utils/Local.cpp | 2 +- .../Transforms/Utils/LoopRotationUtils.cpp | 28 +-- llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 9 +- llvm/lib/Transforms/Utils/ValueMapper.cpp | 8 +- llvm/unittests/IR/BasicBlockDbgInfoTest.cpp | 76 ++++---- llvm/unittests/IR/DebugInfoTest.cpp | 26 +-- .../Transforms/Utils/DebugifyTest.cpp | 2 +- 24 files changed, 330 insertions(+), 319 deletions(-) diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h index bfac54a65c5b..29f675b2203b 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -205,7 +205,7 @@ private: bool translate(const Constant &C, Register Reg); /// Examine any debug-info attached to the instruction (in the form of - /// DPValues) and translate it. + /// DbgRecords) and translate it. void translateDbgInfo(const Instruction &Inst, MachineIRBuilder &MIRBuilder); diff --git a/llvm/include/llvm/IR/BasicBlock.h b/llvm/include/llvm/IR/BasicBlock.h index 5bac113c9b7b..71c1a8394896 100644 --- a/llvm/include/llvm/IR/BasicBlock.h +++ b/llvm/include/llvm/IR/BasicBlock.h @@ -78,13 +78,13 @@ public: DPMarker *createMarker(InstListType::iterator It); /// Convert variable location debugging information stored in dbg.value - /// intrinsics into DPMarker / DPValue records. Deletes all dbg.values in + /// intrinsics into DPMarkers / DbgRecords. Deletes all dbg.values in /// the process and sets IsNewDbgInfoFormat = true. Only takes effect if /// the UseNewDbgInfoFormat LLVM command line option is given. void convertToNewDbgValues(); /// Convert variable location debugging information stored in DPMarkers and - /// DPValues into the dbg.value intrinsic representation. Sets + /// DbgRecords into the dbg.value intrinsic representation. Sets /// IsNewDbgInfoFormat = false. void convertFromNewDbgValues(); @@ -93,50 +93,50 @@ public: /// if necessary. void setIsNewDbgInfoFormat(bool NewFlag); - /// Record that the collection of DPValues in \p M "trails" after the last + /// Record that the collection of DbgRecords in \p M "trails" after the last /// instruction of this block. These are equivalent to dbg.value intrinsics /// that exist at the end of a basic block with no terminator (a transient /// state that occurs regularly). void setTrailingDbgRecords(DPMarker *M); - /// Fetch the collection of DPValues that "trail" after the last instruction + /// Fetch the collection of DbgRecords that "trail" after the last instruction /// of this block, see \ref setTrailingDbgRecords. If there are none, returns /// nullptr. DPMarker *getTrailingDbgRecords(); - /// Delete any trailing DPValues at the end of this block, see + /// Delete any trailing DbgRecords at the end of this block, see /// \ref setTrailingDbgRecords. void deleteTrailingDbgRecords(); void dumpDbgValues() const; - /// Return the DPMarker for the position given by \p It, so that DPValues can - /// be inserted there. This will either be nullptr if not present, a DPMarker, - /// or TrailingDPValues if It is end(). + /// Return the DPMarker for the position given by \p It, so that DbgRecords + /// can be inserted there. This will either be nullptr if not present, a + /// DPMarker, or TrailingDbgRecords if It is end(). DPMarker *getMarker(InstListType::iterator It); /// Return the DPMarker for the position that comes after \p I. \see /// BasicBlock::getMarker, this can be nullptr, a DPMarker, or - /// TrailingDPValues if there is no next instruction. + /// TrailingDbgRecords if there is no next instruction. DPMarker *getNextMarker(Instruction *I); - /// Insert a DPValue into a block at the position given by \p I. + /// Insert a DbgRecord into a block at the position given by \p I. void insertDbgRecordAfter(DbgRecord *DPV, Instruction *I); - /// Insert a DPValue into a block at the position given by \p Here. + /// Insert a DbgRecord into a block at the position given by \p Here. void insertDbgRecordBefore(DbgRecord *DPV, InstListType::iterator Here); - /// Eject any debug-info trailing at the end of a block. DPValues can + /// Eject any debug-info trailing at the end of a block. DbgRecords can /// transiently be located "off the end" of a block if the blocks terminator /// is temporarily removed. Once a terminator is re-inserted this method will - /// move such DPValues back to the right place (ahead of the terminator). - void flushTerminatorDbgValues(); + /// move such DbgRecords back to the right place (ahead of the terminator). + void flushTerminatorDbgRecords(); /// In rare circumstances instructions can be speculatively removed from /// blocks, and then be re-inserted back into that position later. When this /// happens in RemoveDIs debug-info mode, some special patching-up needs to /// occur: inserting into the middle of a sequence of dbg.value intrinsics - /// does not have an equivalent with DPValues. + /// does not have an equivalent with DbgRecords. void reinsertInstInDbgRecords(Instruction *I, std::optional Pos); @@ -522,7 +522,7 @@ private: BasicBlock::iterator FromEndIt); /// Perform any debug-info specific maintenence for the given splice - /// activity. In the DPValue debug-info representation, debug-info is not + /// activity. In the DbgRecord debug-info representation, debug-info is not /// in instructions, and so it does not automatically move from one block /// to another. void spliceDebugInfo(BasicBlock::iterator ToIt, BasicBlock *FromBB, diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h index 507b652feeb0..1afc9259241d 100644 --- a/llvm/include/llvm/IR/DebugProgramInstruction.h +++ b/llvm/include/llvm/IR/DebugProgramInstruction.h @@ -1,4 +1,4 @@ -//===-- llvm/DebugProgramInstruction.h - Stream of debug info -------*- C++ -*-===// +//===-- llvm/DebugProgramInstruction.h - Stream of debug info ---*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -15,10 +15,10 @@ // %bar = void call @ext(%foo); // // and all information is stored in the Value / Metadata hierachy defined -// elsewhere in LLVM. In the "DPValue" design, each instruction /may/ have a -// connection with a DPMarker, which identifies a position immediately before the -// instruction, and each DPMarker /may/ then have connections to DPValues which -// record the variable assignment information. To illustrate: +// elsewhere in LLVM. In the "DbgRecord" design, each instruction /may/ have a +// connection with a DPMarker, which identifies a position immediately before +// the instruction, and each DPMarker /may/ then have connections to DbgRecords +// which record the variable assignment information. To illustrate: // // %foo = add i32 1, %0 // ; foo->DbgMarker == nullptr @@ -26,7 +26,7 @@ // ;; the instruction for %foo, therefore it has no DbgMarker. // %bar = void call @ext(%foo) // ; bar->DbgMarker = { -// ; StoredDPValues = { +// ; StoredDbgRecords = { // ; DPValue(metadata i32 %foo, ...) // ; } // ; } @@ -119,7 +119,7 @@ public: /// Base class for non-instruction debug metadata records that have positions /// within IR. Features various methods copied across from the Instruction /// class to aid ease-of-use. DbgRecords should always be linked into a -/// DPMarker's StoredDPValues list. The marker connects a DbgRecord back to +/// DPMarker's StoredDbgRecords list. The marker connects a DbgRecord back to /// it's position in the BasicBlock. /// /// We need a discriminator for dyn/isa casts. In order to avoid paying for a @@ -557,8 +557,8 @@ public: /// intrinsics. There is a one-to-one relationship between each debug /// intrinsic in a block and each DbgRecord once the representation has been /// converted, and the ordering is meaningful in the same way. - simple_ilist StoredDPValues; - bool empty() const { return StoredDPValues.empty(); } + simple_ilist StoredDbgRecords; + bool empty() const { return StoredDbgRecords.empty(); } const BasicBlock *getParent() const; BasicBlock *getParent(); @@ -576,54 +576,56 @@ public: void print(raw_ostream &O, bool IsForDebug = false) const; void print(raw_ostream &ROS, ModuleSlotTracker &MST, bool IsForDebug) const; - /// Produce a range over all the DPValues in this Marker. + /// Produce a range over all the DbgRecords in this Marker. iterator_range::iterator> getDbgRecordRange(); iterator_range::const_iterator> getDbgRecordRange() const; - /// Transfer any DPValues from \p Src into this DPMarker. If \p InsertAtHead - /// is true, place them before existing DPValues, otherwise afterwards. + /// Transfer any DbgRecords from \p Src into this DPMarker. If \p InsertAtHead + /// is true, place them before existing DbgRecords, otherwise afterwards. void absorbDebugValues(DPMarker &Src, bool InsertAtHead); - /// Transfer the DPValues in \p Range from \p Src into this DPMarker. If - /// \p InsertAtHead is true, place them before existing DPValues, otherwise + /// Transfer the DbgRecords in \p Range from \p Src into this DPMarker. If + /// \p InsertAtHead is true, place them before existing DbgRecords, otherwise // afterwards. void absorbDebugValues(iterator_range Range, DPMarker &Src, bool InsertAtHead); - /// Insert a DPValue into this DPMarker, at the end of the list. If + /// Insert a DbgRecord into this DPMarker, at the end of the list. If /// \p InsertAtHead is true, at the start. void insertDbgRecord(DbgRecord *New, bool InsertAtHead); - /// Insert a DPValue prior to a DPValue contained within this marker. + /// Insert a DbgRecord prior to a DbgRecord contained within this marker. void insertDbgRecord(DbgRecord *New, DbgRecord *InsertBefore); - /// Insert a DPValue after a DPValue contained within this marker. + /// Insert a DbgRecord after a DbgRecord contained within this marker. void insertDbgRecordAfter(DbgRecord *New, DbgRecord *InsertAfter); /// Clone all DPMarkers from \p From into this marker. There are numerous /// options to customise the source/destination, due to gnarliness, see class /// comment. - /// \p FromHere If non-null, copy from FromHere to the end of From's DPValues - /// \p InsertAtHead Place the cloned DPValues at the start of StoredDPValues - /// \returns Range over all the newly cloned DPValues + /// \p FromHere If non-null, copy from FromHere to the end of From's + /// DbgRecords + /// \p InsertAtHead Place the cloned DbgRecords at the start of + /// StoredDbgRecords + /// \returns Range over all the newly cloned DbgRecords iterator_range::iterator> cloneDebugInfoFrom(DPMarker *From, std::optional::iterator> FromHere, bool InsertAtHead = false); - /// Erase all DPValues in this DPMarker. + /// Erase all DbgRecords in this DPMarker. void dropDbgRecords(); /// Erase a single DbgRecord from this marker. In an ideal future, we would /// never erase an assignment in this way, but it's the equivalent to /// erasing a debug intrinsic from a block. void dropOneDbgRecord(DbgRecord *DR); - /// We generally act like all llvm Instructions have a range of DPValues + /// We generally act like all llvm Instructions have a range of DbgRecords /// attached to them, but in reality sometimes we don't allocate the DPMarker - /// to save time and memory, but still have to return ranges of DPValues. When - /// we need to describe such an unallocated DPValue range, use this static - /// markers range instead. This will bite us if someone tries to insert a - /// DPValue in that range, but they should be using the Official (TM) API for - /// that. + /// to save time and memory, but still have to return ranges of DbgRecords. + /// When we need to describe such an unallocated DbgRecord range, use this + /// static markers range instead. This will bite us if someone tries to insert + /// a DbgRecord in that range, but they should be using the Official (TM) API + /// for that. static DPMarker EmptyDPMarker; static iterator_range::iterator> getEmptyDbgRecordRange() { - return make_range(EmptyDPMarker.StoredDPValues.end(), - EmptyDPMarker.StoredDPValues.end()); + return make_range(EmptyDPMarker.StoredDbgRecords.end(), + EmptyDPMarker.StoredDbgRecords.end()); } }; @@ -632,7 +634,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const DPMarker &Marker) { return OS; } -/// Inline helper to return a range of DPValues attached to a marker. It needs +/// Inline helper to return a range of DbgRecords attached to a marker. It needs /// to be inlined as it's frequently called, but also come after the declaration /// of DPMarker. Thus: it's pre-declared by users like Instruction, then an /// inlineable body defined here. diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h index 817abd6afbca..d6cf15577523 100644 --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -64,47 +64,48 @@ public: /// Clone any debug-info attached to \p From onto this instruction. Used to /// copy debugging information from one block to another, when copying entire - /// blocks. \see DebugProgramInstruction.h , because the ordering of DPValues - /// is still important, fine grain control of which instructions are moved and - /// where they go is necessary. + /// blocks. \see DebugProgramInstruction.h , because the ordering of + /// DbgRecords is still important, fine grain control of which instructions + /// are moved and where they go is necessary. /// \p From The instruction to clone debug-info from. - /// \p from_here Optional iterator to limit DPValues cloned to be a range from + /// \p from_here Optional iterator to limit DbgRecords cloned to be a range + /// from /// from_here to end(). - /// \p InsertAtHead Whether the cloned DPValues should be placed at the end - /// or the beginning of existing DPValues attached to this. - /// \returns A range over the newly cloned DPValues. + /// \p InsertAtHead Whether the cloned DbgRecords should be placed at the end + /// or the beginning of existing DbgRecords attached to this. + /// \returns A range over the newly cloned DbgRecords. iterator_range::iterator> cloneDebugInfoFrom( const Instruction *From, std::optional::iterator> FromHere = std::nullopt, bool InsertAtHead = false); - /// Return a range over the DPValues attached to this instruction. + /// Return a range over the DbgRecords attached to this instruction. iterator_range::iterator> getDbgRecordRange() const { return llvm::getDbgRecordRange(DbgMarker); } - /// Return an iterator to the position of the "Next" DPValue after this + /// Return an iterator to the position of the "Next" DbgRecord after this /// instruction, or std::nullopt. This is the position to pass to /// BasicBlock::reinsertInstInDbgRecords when re-inserting an instruction. std::optional::iterator> getDbgReinsertionPosition(); - /// Returns true if any DPValues are attached to this instruction. + /// Returns true if any DbgRecords are attached to this instruction. bool hasDbgRecords() const; - /// Transfer any DPValues on the position \p It onto this instruction, - /// by simply adopting the sequence of DPValues (which is efficient) if + /// Transfer any DbgRecords on the position \p It onto this instruction, + /// by simply adopting the sequence of DbgRecords (which is efficient) if /// possible, by merging two sequences otherwise. void adoptDbgRecords(BasicBlock *BB, InstListType::iterator It, bool InsertAtHead); - /// Erase any DPValues attached to this instruction. + /// Erase any DbgRecords attached to this instruction. void dropDbgRecords(); - /// Erase a single DPValue \p I that is attached to this instruction. + /// Erase a single DbgRecord \p I that is attached to this instruction. void dropOneDbgRecord(DbgRecord *I); /// Handle the debug-info implications of this instruction being removed. Any - /// attached DPValues need to "fall" down onto the next instruction. + /// attached DbgRecords need to "fall" down onto the next instruction. void handleMarkerRemoval(); protected: diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h index c03d49c3b7b9..ec8b809d40bf 100644 --- a/llvm/include/llvm/IR/PassManager.h +++ b/llvm/include/llvm/IR/PassManager.h @@ -227,7 +227,7 @@ public: detail::getAnalysisResult( AM, IR, std::tuple(ExtraArgs...)); - // RemoveDIs: if requested, convert debug-info to DPValue representation + // RemoveDIs: if requested, convert debug-info to DbgRecord representation // for duration of these passes. bool ShouldConvertDbgInfo = shouldConvertDbgInfo(IR); if (ShouldConvertDbgInfo) diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp index 93fb2a821dee..0eb9c246f2a9 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp @@ -19,7 +19,7 @@ using namespace llvm; PreservedAnalyses BitcodeWriterPass::run(Module &M, ModuleAnalysisManager &AM) { - // RemoveDIs: there's no bitcode representation of the DPValue debug-info, + // RemoveDIs: there's no bitcode representation of the DbgRecord debug-info, // convert to dbg.values before writing out. bool IsNewDbgInfoFormat = M.IsNewDbgInfoFormat; if (IsNewDbgInfoFormat) @@ -56,8 +56,8 @@ namespace { StringRef getPassName() const override { return "Bitcode Writer"; } bool runOnModule(Module &M) override { - // RemoveDIs: there's no bitcode representation of the DPValue debug-info, - // convert to dbg.values before writing out. + // RemoveDIs: there's no bitcode representation of the DbgRecord + // debug-info, convert to dbg.values before writing out. bool IsNewDbgInfoFormat = M.IsNewDbgInfoFormat; if (IsNewDbgInfoFormat) M.convertFromNewDbgValues(); diff --git a/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp b/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp index a4b819a735c6..746926e56f2e 100644 --- a/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp +++ b/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp @@ -217,13 +217,14 @@ void FunctionVarLocs::init(FunctionVarLocsBuilder &Builder) { // to the start and end position in the vector with VarLocsBeforeInst. This // block includes VarLocs for any DPValues attached to that instruction. for (auto &P : Builder.VarLocsBeforeInst) { - // Process VarLocs attached to a DPValue alongside their marker Instruction. + // Process VarLocs attached to a DbgRecord alongside their marker + // Instruction. if (isa(P.first)) continue; const Instruction *I = cast(P.first); unsigned BlockStart = VarLocRecords.size(); - // Any VarLocInfos attached to a DPValue should now be remapped to their - // marker Instruction, in order of DPValue appearance and prior to any + // Any VarLocInfos attached to a DbgRecord should now be remapped to their + // marker Instruction, in order of DbgRecord appearance and prior to any // VarLocInfos attached directly to that instruction. for (const DPValue &DPV : DPValue::filter(I->getDbgRecordRange())) { // Even though DPV defines a variable location, VarLocsBeforeInst can @@ -1649,7 +1650,7 @@ void AssignmentTrackingLowering::processUntaggedInstruction( Ops.push_back(dwarf::DW_OP_deref); DIE = DIExpression::prependOpcodes(DIE, Ops, /*StackValue=*/false, /*EntryValue=*/false); - // Find a suitable insert point, before the next instruction or DPValue + // Find a suitable insert point, before the next instruction or DbgRecord // after I. auto InsertBefore = getNextNode(&I); assert(InsertBefore && "Shouldn't be inserting after a terminator"); @@ -1886,21 +1887,21 @@ void AssignmentTrackingLowering::resetInsertionPoint(DPValue &After) { } void AssignmentTrackingLowering::process(BasicBlock &BB, BlockInfo *LiveSet) { - // If the block starts with DPValues, we need to process those DPValues as + // If the block starts with DbgRecords, we need to process those DbgRecords as // their own frame without processing any instructions first. - bool ProcessedLeadingDPValues = !BB.begin()->hasDbgRecords(); + bool ProcessedLeadingDbgRecords = !BB.begin()->hasDbgRecords(); for (auto II = BB.begin(), EI = BB.end(); II != EI;) { assert(VarsTouchedThisFrame.empty()); // Process the instructions in "frames". A "frame" includes a single // non-debug instruction followed any debug instructions before the // next non-debug instruction. - // Skip the current instruction if it has unprocessed DPValues attached (see - // comment above `ProcessedLeadingDPValues`). - if (ProcessedLeadingDPValues) { + // Skip the current instruction if it has unprocessed DbgRecords attached + // (see comment above `ProcessedLeadingDbgRecords`). + if (ProcessedLeadingDbgRecords) { // II is now either a debug intrinsic, a non-debug instruction with no - // attached DPValues, or a non-debug instruction with attached processed - // DPValues. + // attached DbgRecords, or a non-debug instruction with attached processed + // DbgRecords. // II has not been processed. if (!isa(&*II)) { if (II->isTerminator()) @@ -1912,8 +1913,8 @@ void AssignmentTrackingLowering::process(BasicBlock &BB, BlockInfo *LiveSet) { } } // II is now either a debug intrinsic, a non-debug instruction with no - // attached DPValues, or a non-debug instruction with attached unprocessed - // DPValues. + // attached DbgRecords, or a non-debug instruction with attached unprocessed + // DbgRecords. if (II != EI && II->hasDbgRecords()) { // Skip over non-variable debug records (i.e., labels). They're going to // be read from IR (possibly re-ordering them within the debug record @@ -1924,7 +1925,7 @@ void AssignmentTrackingLowering::process(BasicBlock &BB, BlockInfo *LiveSet) { assert(LiveSet->isValid()); } } - ProcessedLeadingDPValues = true; + ProcessedLeadingDbgRecords = true; while (II != EI) { auto *Dbg = dyn_cast(&*II); if (!Dbg) @@ -1934,9 +1935,9 @@ void AssignmentTrackingLowering::process(BasicBlock &BB, BlockInfo *LiveSet) { assert(LiveSet->isValid()); ++II; } - // II is now a non-debug instruction either with no attached DPValues, or - // with attached processed DPValues. II has not been processed, and all - // debug instructions or DPValues in the frame preceding II have been + // II is now a non-debug instruction either with no attached DbgRecords, or + // with attached processed DbgRecords. II has not been processed, and all + // debug instructions or DbgRecords in the frame preceding II have been // processed. // We've processed everything in the "frame". Now determine which variables diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 59a0c64d3c9f..055e275e143d 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -2946,7 +2946,7 @@ class TypePromotionTransaction { Instruction *PrevInst; BasicBlock *BB; } Point; - std::optional BeforeDPValue = std::nullopt; + std::optional BeforeDbgRecord = std::nullopt; /// Remember whether or not the instruction had a previous instruction. bool HasPrevInstruction; @@ -2958,9 +2958,9 @@ class TypePromotionTransaction { BasicBlock *BB = Inst->getParent(); // Record where we would have to re-insert the instruction in the sequence - // of DPValues, if we ended up reinserting. + // of DbgRecords, if we ended up reinserting. if (BB->IsNewDbgInfoFormat) - BeforeDPValue = Inst->getDbgReinsertionPosition(); + BeforeDbgRecord = Inst->getDbgReinsertionPosition(); if (HasPrevInstruction) { Point.PrevInst = &*std::prev(Inst->getIterator()); @@ -2983,7 +2983,7 @@ class TypePromotionTransaction { Inst->insertBefore(*Point.BB, Position); } - Inst->getParent()->reinsertInstInDbgRecords(Inst, BeforeDPValue); + Inst->getParent()->reinsertInstInDbgRecords(Inst, BeforeDbgRecord); } }; diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index 4ed44d1c06f4..8efe67a9a72b 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -982,7 +982,7 @@ void MIRFormatter::printIRValue(raw_ostream &OS, const Value &V, } void llvm::printMIR(raw_ostream &OS, const Module &M) { - // RemoveDIs: as there's no textual form for DPValues yet, print debug-info + // RemoveDIs: as there's no textual form for DbgRecords yet, print debug-info // in dbg.value format. bool IsNewDbgInfoFormat = M.IsNewDbgInfoFormat; if (IsNewDbgInfoFormat) @@ -996,7 +996,7 @@ void llvm::printMIR(raw_ostream &OS, const Module &M) { } void llvm::printMIR(raw_ostream &OS, const MachineFunction &MF) { - // RemoveDIs: as there's no textual form for DPValues yet, print debug-info + // RemoveDIs: as there's no textual form for DbgRecords yet, print debug-info // in dbg.value format. bool IsNewDbgInfoFormat = MF.getFunction().IsNewDbgInfoFormat; if (IsNewDbgInfoFormat) diff --git a/llvm/lib/CodeGen/SelectOptimize.cpp b/llvm/lib/CodeGen/SelectOptimize.cpp index 40898d284a09..f65d5320bab9 100644 --- a/llvm/lib/CodeGen/SelectOptimize.cpp +++ b/llvm/lib/CodeGen/SelectOptimize.cpp @@ -645,12 +645,13 @@ void SelectOptimizeImpl::convertProfitableSIGroups(SelectGroups &ProfSIGroups) { DI->moveBeforePreserving(&*EndBlock->getFirstInsertionPt()); } - // Duplicate implementation for DPValues, the non-instruction debug-info - // record. Helper lambda for moving DPValues to the end block. - auto TransferDPValues = [&](Instruction &I) { - for (auto &DPValue : llvm::make_early_inc_range(I.getDbgRecordRange())) { - DPValue.removeFromParent(); - EndBlock->insertDbgRecordBefore(&DPValue, + // Duplicate implementation for DbgRecords, the non-instruction debug-info + // format. Helper lambda for moving DbgRecords to the end block. + auto TransferDbgRecords = [&](Instruction &I) { + for (auto &DbgRecord : + llvm::make_early_inc_range(I.getDbgRecordRange())) { + DbgRecord.removeFromParent(); + EndBlock->insertDbgRecordBefore(&DbgRecord, EndBlock->getFirstInsertionPt()); } }; @@ -660,7 +661,7 @@ void SelectOptimizeImpl::convertProfitableSIGroups(SelectGroups &ProfSIGroups) { // middle" of the select group. auto R = make_range(std::next(SI.getI()->getIterator()), std::next(LastSI.getI()->getIterator())); - llvm::for_each(R, TransferDPValues); + llvm::for_each(R, TransferDbgRecords); // These are the new basic blocks for the conditional branch. // At least one will become an actual new basic block. diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 1beb4c069a69..11383ea6214b 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -4592,7 +4592,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { void AssemblyWriter::printDPMarker(const DPMarker &Marker) { // There's no formal representation of a DPMarker -- print purely as a // debugging aid. - for (const DbgRecord &DPR : Marker.StoredDPValues) { + for (const DbgRecord &DPR : Marker.StoredDbgRecords) { printDbgRecord(DPR); Out << "\n"; } diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp index 7ead7ce3bf08..4dd1bdd6e2f4 100644 --- a/llvm/lib/IR/BasicBlock.cpp +++ b/llvm/lib/IR/BasicBlock.cpp @@ -63,9 +63,9 @@ DPMarker *BasicBlock::createMarker(InstListType::iterator It) { void BasicBlock::convertToNewDbgValues() { IsNewDbgInfoFormat = true; - // Iterate over all instructions in the instruction list, collecting dbg.value - // instructions and converting them to DPValues. Once we find a "real" - // instruction, attach all those DPValues to a DPMarker in that instruction. + // Iterate over all instructions in the instruction list, collecting debug + // info intrinsics and converting them to DbgRecords. Once we find a "real" + // instruction, attach all those DbgRecords to a DPMarker in that instruction. SmallVector DPVals; for (Instruction &I : make_early_inc_range(InstList)) { assert(!I.DbgMarker && "DbgMarker already set on old-format instrs?"); @@ -86,7 +86,7 @@ void BasicBlock::convertToNewDbgValues() { if (DPVals.empty()) continue; - // Create a marker to store DPValues in. + // Create a marker to store DbgRecords in. createMarker(&I); DPMarker *Marker = I.DbgMarker; @@ -102,7 +102,7 @@ void BasicBlock::convertFromNewDbgValues() { IsNewDbgInfoFormat = false; // Iterate over the block, finding instructions annotated with DPMarkers. - // Convert any attached DPValues to dbg.values and insert ahead of the + // Convert any attached DbgRecords to debug intrinsics and insert ahead of the // instruction. for (auto &Inst : *this) { if (!Inst.DbgMarker) @@ -116,7 +116,7 @@ void BasicBlock::convertFromNewDbgValues() { Marker.eraseFromParent(); } - // Assume no trailing DPValues: we could technically create them at the end + // Assume no trailing DbgRecords: we could technically create them at the end // of the block, after a terminator, but this would be non-cannonical and // indicates that something else is broken somewhere. assert(!getTrailingDbgRecords()); @@ -691,15 +691,15 @@ void BasicBlock::renumberInstructions() { NumInstrRenumberings++; } -void BasicBlock::flushTerminatorDbgValues() { - // If we erase the terminator in a block, any DPValues will sink and "fall +void BasicBlock::flushTerminatorDbgRecords() { + // If we erase the terminator in a block, any DbgRecords will sink and "fall // off the end", existing after any terminator that gets inserted. With // dbg.value intrinsics we would just insert the terminator at end() and - // the dbg.values would come before the terminator. With DPValues, we must + // the dbg.values would come before the terminator. With DbgRecords, we must // do this manually. // To get out of this unfortunate form, whenever we insert a terminator, - // check whether there's anything trailing at the end and move those DPValues - // in front of the terminator. + // check whether there's anything trailing at the end and move those + // DbgRecords in front of the terminator. // Do nothing if we're not in new debug-info format. if (!IsNewDbgInfoFormat) @@ -710,15 +710,15 @@ void BasicBlock::flushTerminatorDbgValues() { if (!Term) return; - // Are there any dangling DPValues? - DPMarker *TrailingDPValues = getTrailingDbgRecords(); - if (!TrailingDPValues) + // Are there any dangling DbgRecords? + DPMarker *TrailingDbgRecords = getTrailingDbgRecords(); + if (!TrailingDbgRecords) return; - // Transfer DPValues from the trailing position onto the terminator. + // Transfer DbgRecords from the trailing position onto the terminator. createMarker(Term); - Term->DbgMarker->absorbDebugValues(*TrailingDPValues, false); - TrailingDPValues->eraseFromParent(); + Term->DbgMarker->absorbDebugValues(*TrailingDbgRecords, false); + TrailingDbgRecords->eraseFromParent(); deleteTrailingDbgRecords(); } @@ -735,7 +735,7 @@ void BasicBlock::spliceDebugInfoEmptyBlock(BasicBlock::iterator Dest, // If an optimisation pass attempts to splice the contents of the block from // BB1->begin() to BB1->getTerminator(), then the dbg.value will be // transferred to the destination. - // However, in the "new" DPValue format for debug-info, that range is empty: + // However, in the "new" DbgRecord format for debug-info, that range is empty: // begin() returns an iterator to the terminator, as there will only be a // single instruction in the block. We must piece together from the bits set // in the iterators whether there was the intention to transfer any debug @@ -750,16 +750,16 @@ void BasicBlock::spliceDebugInfoEmptyBlock(BasicBlock::iterator Dest, bool ReadFromHead = First.getHeadBit(); // If the source block is completely empty, including no terminator, then - // transfer any trailing DPValues that are still hanging around. This can + // transfer any trailing DbgRecords that are still hanging around. This can // occur when a block is optimised away and the terminator has been moved // somewhere else. if (Src->empty()) { - DPMarker *SrcTrailingDPValues = Src->getTrailingDbgRecords(); - if (!SrcTrailingDPValues) + DPMarker *SrcTrailingDbgRecords = Src->getTrailingDbgRecords(); + if (!SrcTrailingDbgRecords) return; Dest->adoptDbgRecords(Src, Src->end(), InsertAtHead); - // adoptDbgRecords should have released the trailing DPValues. + // adoptDbgRecords should have released the trailing DbgRecords. assert(!Src->getTrailingDbgRecords()); return; } @@ -785,8 +785,8 @@ void BasicBlock::spliceDebugInfo(BasicBlock::iterator Dest, BasicBlock *Src, /* Do a quick normalisation before calling the real splice implementation. We might be operating on a degenerate basic block that has no instructions in it, a legitimate transient state. In that case, Dest will be end() and - any DPValues temporarily stored in the TrailingDPValues map in LLVMContext. - We might illustrate it thus: + any DbgRecords temporarily stored in the TrailingDbgRecords map in + LLVMContext. We might illustrate it thus: Dest | @@ -795,35 +795,35 @@ void BasicBlock::spliceDebugInfo(BasicBlock::iterator Dest, BasicBlock *Src, | | First Last - However: does the caller expect the "~" DPValues to end up before or after - the spliced segment? This is communciated in the "Head" bit of Dest, which - signals whether the caller called begin() or end() on this block. + However: does the caller expect the "~" DbgRecords to end up before or + after the spliced segment? This is communciated in the "Head" bit of Dest, + which signals whether the caller called begin() or end() on this block. - If the head bit is set, then all is well, we leave DPValues trailing just + If the head bit is set, then all is well, we leave DbgRecords trailing just like how dbg.value instructions would trail after instructions spliced to the beginning of this block. - If the head bit isn't set, then try to jam the "~" DPValues onto the front - of the First instruction, then splice like normal, which joins the "~" - DPValues with the "+" DPValues. However if the "+" DPValues are supposed to - be left behind in Src, then: - * detach the "+" DPValues, - * move the "~" DPValues onto First, + If the head bit isn't set, then try to jam the "~" DbgRecords onto the + front of the First instruction, then splice like normal, which joins the + "~" DbgRecords with the "+" DbgRecords. However if the "+" DbgRecords are + supposed to be left behind in Src, then: + * detach the "+" DbgRecords, + * move the "~" DbgRecords onto First, * splice like normal, - * replace the "+" DPValues onto the Last position. + * replace the "+" DbgRecords onto the Last position. Complicated, but gets the job done. */ - // If we're inserting at end(), and not in front of dangling DPValues, then - // move the DPValues onto "First". They'll then be moved naturally in the + // If we're inserting at end(), and not in front of dangling DbgRecords, then + // move the DbgRecords onto "First". They'll then be moved naturally in the // splice process. - DPMarker *MoreDanglingDPValues = nullptr; - DPMarker *OurTrailingDPValues = getTrailingDbgRecords(); - if (Dest == end() && !Dest.getHeadBit() && OurTrailingDPValues) { - // Are the "+" DPValues not supposed to move? If so, detach them + DPMarker *MoreDanglingDbgRecords = nullptr; + DPMarker *OurTrailingDbgRecords = getTrailingDbgRecords(); + if (Dest == end() && !Dest.getHeadBit() && OurTrailingDbgRecords) { + // Are the "+" DbgRecords not supposed to move? If so, detach them // temporarily. if (!First.getHeadBit() && First->hasDbgRecords()) { - MoreDanglingDPValues = Src->getMarker(First); - MoreDanglingDPValues->removeFromParent(); + MoreDanglingDbgRecords = Src->getMarker(First); + MoreDanglingDbgRecords->removeFromParent(); } if (First->hasDbgRecords()) { @@ -839,8 +839,8 @@ void BasicBlock::spliceDebugInfo(BasicBlock::iterator Dest, BasicBlock *Src, // No current marker, create one and absorb in. (FIXME: we can avoid an // allocation in the future). DPMarker *CurMarker = Src->createMarker(&*First); - CurMarker->absorbDebugValues(*OurTrailingDPValues, false); - OurTrailingDPValues->eraseFromParent(); + CurMarker->absorbDebugValues(*OurTrailingDbgRecords, false); + OurTrailingDbgRecords->eraseFromParent(); } deleteTrailingDbgRecords(); First.setHeadBit(true); @@ -849,16 +849,16 @@ void BasicBlock::spliceDebugInfo(BasicBlock::iterator Dest, BasicBlock *Src, // Call the main debug-info-splicing implementation. spliceDebugInfoImpl(Dest, Src, First, Last); - // Do we have some "+" DPValues hanging around that weren't supposed to move, - // and we detached to make things easier? - if (!MoreDanglingDPValues) + // Do we have some "+" DbgRecords hanging around that weren't supposed to + // move, and we detached to make things easier? + if (!MoreDanglingDbgRecords) return; // FIXME: we could avoid an allocation here sometimes. (adoptDbgRecords // requires an iterator). DPMarker *LastMarker = Src->createMarker(Last); - LastMarker->absorbDebugValues(*MoreDanglingDPValues, true); - MoreDanglingDPValues->eraseFromParent(); + LastMarker->absorbDebugValues(*MoreDanglingDbgRecords, true); + MoreDanglingDbgRecords->eraseFromParent(); } void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, @@ -870,15 +870,16 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, bool InsertAtHead = Dest.getHeadBit(); bool ReadFromHead = First.getHeadBit(); // Use this flag to signal the abnormal case, where we don't want to copy the - // DPValues ahead of the "Last" position. + // DbgRecords ahead of the "Last" position. bool ReadFromTail = !Last.getTailBit(); bool LastIsEnd = (Last == Src->end()); /* Here's an illustration of what we're about to do. We have two blocks, this and Src, and two segments of list. Each instruction is marked by a capital - while potential DPValue debug-info is marked out by "-" characters and a few - other special characters (+:=) where I want to highlight what's going on. + while potential DbgRecord debug-info is marked out by "-" characters and a + few other special characters (+:=) where I want to highlight what's going + on. Dest | @@ -889,18 +890,18 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, The splice method is going to take all the instructions from First up to (but not including) Last and insert them in _front_ of Dest, forming one - long list. All the DPValues attached to instructions _between_ First and + long list. All the DbgRecords attached to instructions _between_ First and Last need no maintenence. However, we have to do special things with the - DPValues marked with the +:= characters. We only have three positions: - should the "+" DPValues be transferred, and if so to where? Do we move the - ":" DPValues? Would they go in front of the "=" DPValues, or should the "=" - DPValues go before "+" DPValues? + DbgRecords marked with the +:= characters. We only have three positions: + should the "+" DbgRecords be transferred, and if so to where? Do we move the + ":" DbgRecords? Would they go in front of the "=" DbgRecords, or should the + "=" DbgRecords go before "+" DbgRecords? We're told which way it should be by the bits carried in the iterators. The "Head" bit indicates whether the specified position is supposed to be at the - front of the attached DPValues (true) or not (false). The Tail bit is true - on the other end of a range: is the range intended to include DPValues up to - the end (false) or not (true). + front of the attached DbgRecords (true) or not (false). The Tail bit is true + on the other end of a range: is the range intended to include DbgRecords up + to the end (false) or not (true). FIXME: the tail bit doesn't need to be distinct from the head bit, we could combine them. @@ -934,15 +935,16 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, */ - // Detach the marker at Dest -- this lets us move the "====" DPValues around. + // Detach the marker at Dest -- this lets us move the "====" DbgRecords + // around. DPMarker *DestMarker = nullptr; if (Dest != end()) { if ((DestMarker = getMarker(Dest))) DestMarker->removeFromParent(); } - // If we're moving the tail range of DPValues (":::"), absorb them into the - // front of the DPValues at Dest. + // If we're moving the tail range of DbgRecords (":::"), absorb them into the + // front of the DbgRecords at Dest. if (ReadFromTail && Src->getMarker(Last)) { DPMarker *FromLast = Src->getMarker(Last); if (LastIsEnd) { @@ -956,7 +958,7 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, } } - // If we're _not_ reading from the head of First, i.e. the "++++" DPValues, + // If we're _not_ reading from the head of First, i.e. the "++++" DbgRecords, // move their markers onto Last. They remain in the Src block. No action // needed. if (!ReadFromHead && First->hasDbgRecords()) { @@ -970,16 +972,16 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, } } - // Finally, do something with the "====" DPValues we detached. + // Finally, do something with the "====" DbgRecords we detached. if (DestMarker) { if (InsertAtHead) { - // Insert them at the end of the DPValues at Dest. The "::::" DPValues + // Insert them at the end of the DbgRecords at Dest. The "::::" DbgRecords // might be in front of them. DPMarker *NewDestMarker = createMarker(Dest); NewDestMarker->absorbDebugValues(*DestMarker, false); } else { // Insert them right at the start of the range we moved, ahead of First - // and the "++++" DPValues. + // and the "++++" DbgRecords. DPMarker *FirstMarker = createMarker(First); FirstMarker->absorbDebugValues(*DestMarker, true); } @@ -990,10 +992,10 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, // any trailing debug-info at the end of the block would "normally" have // been pushed in front of "First". Move it there now. DPMarker *FirstMarker = getMarker(First); - DPMarker *TrailingDPValues = getTrailingDbgRecords(); - if (TrailingDPValues) { - FirstMarker->absorbDebugValues(*TrailingDPValues, true); - TrailingDPValues->eraseFromParent(); + DPMarker *TrailingDbgRecords = getTrailingDbgRecords(); + if (TrailingDbgRecords) { + FirstMarker->absorbDebugValues(*TrailingDbgRecords, true); + TrailingDbgRecords->eraseFromParent(); deleteTrailingDbgRecords(); } } @@ -1024,7 +1026,7 @@ void BasicBlock::splice(iterator Dest, BasicBlock *Src, iterator First, // And move the instructions. getInstList().splice(Dest, Src->getInstList(), First, Last); - flushTerminatorDbgValues(); + flushTerminatorDbgRecords(); } void BasicBlock::insertDbgRecordAfter(DbgRecord *DPV, Instruction *I) { @@ -1057,38 +1059,40 @@ DPMarker *BasicBlock::getMarker(InstListType::iterator It) { } void BasicBlock::reinsertInstInDbgRecords( - Instruction *I, std::optional Pos) { + Instruction *I, std::optional Pos) { // "I" was originally removed from a position where it was - // immediately in front of Pos. Any DPValues on that position then "fell down" - // onto Pos. "I" has been re-inserted at the front of that wedge of DPValues, - // shuffle them around to represent the original positioning. To illustrate: + // immediately in front of Pos. Any DbgRecords on that position then "fell + // down" onto Pos. "I" has been re-inserted at the front of that wedge of + // DbgRecords, shuffle them around to represent the original positioning. To + // illustrate: // // Instructions: I1---I---I0 - // DPValues: DDD DDD + // DbgRecords: DDD DDD // // Instruction "I" removed, // // Instructions: I1------I0 - // DPValues: DDDDDD + // DbgRecords: DDDDDD // ^Pos // // Instruction "I" re-inserted (now): // // Instructions: I1---I------I0 - // DPValues: DDDDDD + // DbgRecords: DDDDDD // ^Pos // // After this method completes: // // Instructions: I1---I---I0 - // DPValues: DDD DDD + // DbgRecords: DDD DDD - // This happens if there were no DPValues on I0. Are there now DPValues there? + // This happens if there were no DbgRecords on I0. Are there now DbgRecords + // there? if (!Pos) { DPMarker *NextMarker = getNextMarker(I); if (!NextMarker) return; - if (NextMarker->StoredDPValues.empty()) + if (NextMarker->StoredDbgRecords.empty()) return; // There are DPMarkers there now -- they fell down from "I". DPMarker *ThisMarker = createMarker(I); @@ -1096,15 +1100,15 @@ void BasicBlock::reinsertInstInDbgRecords( return; } - // Is there even a range of DPValues to move? + // Is there even a range of DbgRecords to move? DPMarker *DPM = (*Pos)->getMarker(); - auto Range = make_range(DPM->StoredDPValues.begin(), (*Pos)); + auto Range = make_range(DPM->StoredDbgRecords.begin(), (*Pos)); if (Range.begin() == Range.end()) return; // Otherwise: splice. DPMarker *ThisMarker = createMarker(I); - assert(ThisMarker->StoredDPValues.empty()); + assert(ThisMarker->StoredDbgRecords.empty()); ThisMarker->absorbDebugValues(Range, *DPM, true); } diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index e63b1e67dad7..d16895058ba2 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -895,7 +895,7 @@ bool llvm::stripNonLineTableDebugInfo(Module &M) { if (I.hasMetadataOtherThanDebugLoc()) I.setMetadata("heapallocsite", nullptr); - // Strip any DPValues attached. + // Strip any DbgRecords attached. I.dropDbgRecords(); } } diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index 019b00c2e208..f34d3aecfa0a 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -1,4 +1,4 @@ -//======-- DebugProgramInstruction.cpp - Implement DPValues/DPMarkers --======// +//=====-- DebugProgramInstruction.cpp - Implement DbgRecords/DPMarkers --=====// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -541,21 +541,21 @@ void DbgRecord::moveAfter(DbgRecord *MoveAfter) { /////////////////////////////////////////////////////////////////////////////// // An empty, global, DPMarker for the purpose of describing empty ranges of -// DPValues. +// DbgRecords. DPMarker DPMarker::EmptyDPMarker; void DPMarker::dropDbgRecords() { - while (!StoredDPValues.empty()) { - auto It = StoredDPValues.begin(); + while (!StoredDbgRecords.empty()) { + auto It = StoredDbgRecords.begin(); DbgRecord *DR = &*It; - StoredDPValues.erase(It); + StoredDbgRecords.erase(It); DR->deleteRecord(); } } void DPMarker::dropOneDbgRecord(DbgRecord *DR) { assert(DR->getMarker() == this); - StoredDPValues.erase(DR->getIterator()); + StoredDbgRecords.erase(DR->getIterator()); DR->deleteRecord(); } @@ -566,15 +566,15 @@ const BasicBlock *DPMarker::getParent() const { BasicBlock *DPMarker::getParent() { return MarkedInstr->getParent(); } void DPMarker::removeMarker() { - // Are there any DPValues in this DPMarker? If not, nothing to preserve. + // Are there any DbgRecords in this DPMarker? If not, nothing to preserve. Instruction *Owner = MarkedInstr; - if (StoredDPValues.empty()) { + if (StoredDbgRecords.empty()) { eraseFromParent(); Owner->DbgMarker = nullptr; return; } - // The attached DPValues need to be preserved; attach them to the next + // The attached DbgRecords need to be preserved; attach them to the next // instruction. If there isn't a next instruction, put them on the // "trailing" list. DPMarker *NextMarker = Owner->getParent()->getNextMarker(Owner); @@ -610,15 +610,15 @@ void DPMarker::eraseFromParent() { } iterator_range DPMarker::getDbgRecordRange() { - return make_range(StoredDPValues.begin(), StoredDPValues.end()); + return make_range(StoredDbgRecords.begin(), StoredDbgRecords.end()); } iterator_range DPMarker::getDbgRecordRange() const { - return make_range(StoredDPValues.begin(), StoredDPValues.end()); + return make_range(StoredDbgRecords.begin(), StoredDbgRecords.end()); } void DbgRecord::removeFromParent() { - getMarker()->StoredDPValues.erase(getIterator()); + getMarker()->StoredDbgRecords.erase(getIterator()); Marker = nullptr; } @@ -628,29 +628,29 @@ void DbgRecord::eraseFromParent() { } void DPMarker::insertDbgRecord(DbgRecord *New, bool InsertAtHead) { - auto It = InsertAtHead ? StoredDPValues.begin() : StoredDPValues.end(); - StoredDPValues.insert(It, *New); + auto It = InsertAtHead ? StoredDbgRecords.begin() : StoredDbgRecords.end(); + StoredDbgRecords.insert(It, *New); New->setMarker(this); } void DPMarker::insertDbgRecord(DbgRecord *New, DbgRecord *InsertBefore) { assert(InsertBefore->getMarker() == this && - "DPValue 'InsertBefore' must be contained in this DPMarker!"); - StoredDPValues.insert(InsertBefore->getIterator(), *New); + "DbgRecord 'InsertBefore' must be contained in this DPMarker!"); + StoredDbgRecords.insert(InsertBefore->getIterator(), *New); New->setMarker(this); } void DPMarker::insertDbgRecordAfter(DbgRecord *New, DbgRecord *InsertAfter) { assert(InsertAfter->getMarker() == this && - "DPValue 'InsertAfter' must be contained in this DPMarker!"); - StoredDPValues.insert(++(InsertAfter->getIterator()), *New); + "DbgRecord 'InsertAfter' must be contained in this DPMarker!"); + StoredDbgRecords.insert(++(InsertAfter->getIterator()), *New); New->setMarker(this); } void DPMarker::absorbDebugValues(DPMarker &Src, bool InsertAtHead) { - auto It = InsertAtHead ? StoredDPValues.begin() : StoredDPValues.end(); - for (DbgRecord &DPV : Src.StoredDPValues) + auto It = InsertAtHead ? StoredDbgRecords.begin() : StoredDbgRecords.end(); + for (DbgRecord &DPV : Src.StoredDbgRecords) DPV.setMarker(this); - StoredDPValues.splice(It, Src.StoredDPValues); + StoredDbgRecords.splice(It, Src.StoredDbgRecords); } void DPMarker::absorbDebugValues(iterator_range Range, @@ -659,45 +659,45 @@ void DPMarker::absorbDebugValues(iterator_range Range, DR.setMarker(this); auto InsertPos = - (InsertAtHead) ? StoredDPValues.begin() : StoredDPValues.end(); + (InsertAtHead) ? StoredDbgRecords.begin() : StoredDbgRecords.end(); - StoredDPValues.splice(InsertPos, Src.StoredDPValues, Range.begin(), - Range.end()); + StoredDbgRecords.splice(InsertPos, Src.StoredDbgRecords, Range.begin(), + Range.end()); } iterator_range::iterator> DPMarker::cloneDebugInfoFrom( DPMarker *From, std::optional::iterator> from_here, bool InsertAtHead) { DbgRecord *First = nullptr; - // Work out what range of DPValues to clone: normally all the contents of the - // "From" marker, optionally we can start from the from_here position down to - // end(). + // Work out what range of DbgRecords to clone: normally all the contents of + // the "From" marker, optionally we can start from the from_here position down + // to end(). auto Range = - make_range(From->StoredDPValues.begin(), From->StoredDPValues.end()); + make_range(From->StoredDbgRecords.begin(), From->StoredDbgRecords.end()); if (from_here.has_value()) - Range = make_range(*from_here, From->StoredDPValues.end()); + Range = make_range(*from_here, From->StoredDbgRecords.end()); // Clone each DPValue and insert into StoreDPValues; optionally place them at // the start or the end of the list. - auto Pos = (InsertAtHead) ? StoredDPValues.begin() : StoredDPValues.end(); + auto Pos = (InsertAtHead) ? StoredDbgRecords.begin() : StoredDbgRecords.end(); for (DbgRecord &DR : Range) { DbgRecord *New = DR.clone(); New->setMarker(this); - StoredDPValues.insert(Pos, *New); + StoredDbgRecords.insert(Pos, *New); if (!First) First = New; } if (!First) - return {StoredDPValues.end(), StoredDPValues.end()}; + return {StoredDbgRecords.end(), StoredDbgRecords.end()}; if (InsertAtHead) // If InsertAtHead is set, we cloned a range onto the front of of the - // StoredDPValues collection, return that range. - return {StoredDPValues.begin(), Pos}; + // StoredDbgRecords collection, return that range. + return {StoredDbgRecords.begin(), Pos}; else // We inserted a block at the end, return that range. - return {First->getIterator(), StoredDPValues.end()}; + return {First->getIterator(), StoredDbgRecords.end()}; } } // end namespace llvm diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index e0892398f434..7a677d7f3c2b 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -143,7 +143,7 @@ void Instruction::insertBefore(BasicBlock &BB, return; // We've inserted "this": if InsertAtHead is set then it comes before any - // DPValues attached to InsertPos. But if it's not set, then any DPValues + // DPValues attached to InsertPos. But if it's not set, then any DbgRecords // should now come before "this". bool InsertAtHead = InsertPos.getHeadBit(); if (!InsertAtHead) { @@ -166,10 +166,10 @@ void Instruction::insertBefore(BasicBlock &BB, } // If we're inserting a terminator, check if we need to flush out - // TrailingDPValues. Inserting instructions at the end of an incomplete + // TrailingDbgRecords. Inserting instructions at the end of an incomplete // block is handled by the code block above. if (isTerminator()) - getParent()->flushTerminatorDbgValues(); + getParent()->flushTerminatorDbgRecords(); } /// Unlink this instruction from its current basic block and insert it into the @@ -212,12 +212,12 @@ void Instruction::moveBeforeImpl(BasicBlock &BB, InstListType::iterator I, assert(I == BB.end() || I->getParent() == &BB); bool InsertAtHead = I.getHeadBit(); - // If we've been given the "Preserve" flag, then just move the DPValues with + // If we've been given the "Preserve" flag, then just move the DbgRecords with // the instruction, no more special handling needed. if (BB.IsNewDbgInfoFormat && DbgMarker && !Preserve) { if (I != this->getIterator() || InsertAtHead) { // "this" is definitely moving in the list, or it's moving ahead of its - // attached DPValues. Detach any existing DPValues. + // attached DPValues. Detach any existing DbgRecords. handleMarkerRemoval(); } } @@ -229,15 +229,15 @@ void Instruction::moveBeforeImpl(BasicBlock &BB, InstListType::iterator I, if (BB.IsNewDbgInfoFormat && !Preserve) { DPMarker *NextMarker = getParent()->getNextMarker(this); - // If we're inserting at point I, and not in front of the DPValues attached - // there, then we should absorb the DPValues attached to I. + // If we're inserting at point I, and not in front of the DbgRecords + // attached there, then we should absorb the DbgRecords attached to I. if (!InsertAtHead && NextMarker && !NextMarker->empty()) { adoptDbgRecords(&BB, I, false); } } if (isTerminator()) - getParent()->flushTerminatorDbgValues(); + getParent()->flushTerminatorDbgRecords(); } iterator_range Instruction::cloneDebugInfoFrom( @@ -263,11 +263,11 @@ Instruction::getDbgReinsertionPosition() { if (!NextMarker) return std::nullopt; - // Are there any DPValues in the next marker? - if (NextMarker->StoredDPValues.empty()) + // Are there any DbgRecords in the next marker? + if (NextMarker->StoredDbgRecords.empty()) return std::nullopt; - return NextMarker->StoredDPValues.begin(); + return NextMarker->StoredDbgRecords.begin(); } bool Instruction::hasDbgRecords() const { return !getDbgRecordRange().empty(); } @@ -275,20 +275,20 @@ bool Instruction::hasDbgRecords() const { return !getDbgRecordRange().empty(); } void Instruction::adoptDbgRecords(BasicBlock *BB, BasicBlock::iterator It, bool InsertAtHead) { DPMarker *SrcMarker = BB->getMarker(It); - auto ReleaseTrailingDPValues = [BB, It, SrcMarker]() { + auto ReleaseTrailingDbgRecords = [BB, It, SrcMarker]() { if (BB->end() == It) { SrcMarker->eraseFromParent(); BB->deleteTrailingDbgRecords(); } }; - if (!SrcMarker || SrcMarker->StoredDPValues.empty()) { - ReleaseTrailingDPValues(); + if (!SrcMarker || SrcMarker->StoredDbgRecords.empty()) { + ReleaseTrailingDbgRecords(); return; } // If we have DPMarkers attached to this instruction, we have to honour the - // ordering of DPValues between this and the other marker. Fall back to just + // ordering of DbgRecords between this and the other marker. Fall back to just // absorbing from the source. if (DbgMarker || It == BB->end()) { // Ensure we _do_ have a marker. @@ -304,10 +304,11 @@ void Instruction::adoptDbgRecords(BasicBlock *BB, BasicBlock::iterator It, // block, it's important to not leave the empty marker trailing. It will // give a misleading impression that some debug records have been left // trailing. - ReleaseTrailingDPValues(); + ReleaseTrailingDbgRecords(); } else { - // Optimisation: we're transferring all the DPValues from the source marker - // onto this empty location: just adopt the other instructions marker. + // Optimisation: we're transferring all the DbgRecords from the source + // marker onto this empty location: just adopt the other instructions + // marker. DbgMarker = SrcMarker; DbgMarker->MarkedInstr = this; It->DbgMarker = nullptr; diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp index a0bf9cae7926..a471314ccb94 100644 --- a/llvm/lib/IR/LLVMContextImpl.cpp +++ b/llvm/lib/IR/LLVMContextImpl.cpp @@ -50,7 +50,7 @@ LLVMContextImpl::~LLVMContextImpl() { // when it's terminator was removed were eventually replaced. This assertion // firing indicates that DPValues went missing during the lifetime of the // LLVMContext. - assert(TrailingDPValues.empty() && "DPValue records in blocks not cleaned"); + assert(TrailingDbgRecords.empty() && "DbgRecords in blocks not cleaned"); #endif // NOTE: We need to delete the contents of OwnedModules, but Module's dtor diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index c841b28ca438..b1dcb262fb65 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -1684,19 +1684,19 @@ public: /// such a way. These are stored in LLVMContext because typically LLVM only /// edits a small number of blocks at a time, so there's no need to bloat /// BasicBlock with such a data structure. - SmallDenseMap TrailingDPValues; + SmallDenseMap TrailingDbgRecords; - // Set, get and delete operations for TrailingDPValues. + // Set, get and delete operations for TrailingDbgRecords. void setTrailingDbgRecords(BasicBlock *B, DPMarker *M) { - assert(!TrailingDPValues.count(B)); - TrailingDPValues[B] = M; + assert(!TrailingDbgRecords.count(B)); + TrailingDbgRecords[B] = M; } DPMarker *getTrailingDbgRecords(BasicBlock *B) { - return TrailingDPValues.lookup(B); + return TrailingDbgRecords.lookup(B); } - void deleteTrailingDbgRecords(BasicBlock *B) { TrailingDPValues.erase(B); } + void deleteTrailingDbgRecords(BasicBlock *B) { TrailingDbgRecords.erase(B); } }; } // end namespace llvm diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index 7b74caac9e08..a87e5a3a923a 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -2848,7 +2848,7 @@ unsigned llvm::changeToUnreachable(Instruction *I, bool PreserveLCSSA, Updates.push_back({DominatorTree::Delete, BB, UniqueSuccessor}); DTU->applyUpdates(Updates); } - BB->flushTerminatorDbgValues(); + BB->flushTerminatorDbgRecords(); return NumInstrsRemoved; } diff --git a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp index 8c6af7afa875..acfd87c64b79 100644 --- a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp @@ -577,28 +577,28 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { Module *M = OrigHeader->getModule(); - // Track the next DPValue to clone. If we have a sequence where an + // Track the next DbgRecord to clone. If we have a sequence where an // instruction is hoisted instead of being cloned: - // DPValue blah + // DbgRecord blah // %foo = add i32 0, 0 - // DPValue xyzzy + // DbgRecord xyzzy // %bar = call i32 @foobar() - // where %foo is hoisted, then the DPValue "blah" will be seen twice, once + // where %foo is hoisted, then the DbgRecord "blah" will be seen twice, once // attached to %foo, then when %foo his hoisted it will "fall down" onto the // function call: - // DPValue blah - // DPValue xyzzy + // DbgRecord blah + // DbgRecord xyzzy // %bar = call i32 @foobar() // causing it to appear attached to the call too. // // To avoid this, cloneDebugInfoFrom takes an optional "start cloning from - // here" position to account for this behaviour. We point it at any DPValues - // on the next instruction, here labelled xyzzy, before we hoist %foo. - // Later, we only only clone DPValues from that position (xyzzy) onwards, - // which avoids cloning DPValue "blah" multiple times. - // (Stored as a range because it gives us a natural way of testing whether - // there were DPValues on the next instruction before we hoisted things). - iterator_range NextDbgInsts = + // here" position to account for this behaviour. We point it at any + // DbgRecords on the next instruction, here labelled xyzzy, before we hoist + // %foo. Later, we only only clone DbgRecords from that position (xyzzy) + // onwards, which avoids cloning DbgRecord "blah" multiple times. (Stored as + // a range because it gives us a natural way of testing whether + // there were DbgRecords on the next instruction before we hoisted things). + iterator_range NextDbgInsts = (I != E) ? I->getDbgRecordRange() : DPMarker::getEmptyDbgRecordRange(); while (I != E) { @@ -777,7 +777,7 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { // OrigPreHeader's old terminator (the original branch into the loop), and // remove the corresponding incoming values from the PHI nodes in OrigHeader. LoopEntryBranch->eraseFromParent(); - OrigPreheader->flushTerminatorDbgValues(); + OrigPreheader->flushTerminatorDbgRecords(); // Update MemorySSA before the rewrite call below changes the 1:1 // instruction:cloned_instruction_or_value mapping. diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 0f3d1403481d..6d2a6a3e7f11 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1572,7 +1572,8 @@ hoistLockstepIdenticalDPValues(Instruction *TI, Instruction *I1, while (none_of(Itrs, atEnd)) { bool HoistDPVs = allIdentical(Itrs); for (CurrentAndEndIt &Pair : Itrs) { - // Increment Current iterator now as we may be about to move the DPValue. + // Increment Current iterator now as we may be about to move the + // DbgRecord. DbgRecord &DR = *Pair.first++; if (HoistDPVs) { DR.removeFromParent(); @@ -5304,7 +5305,7 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) { // Ensure that any debug-info records that used to occur after the Unreachable // are moved to in front of it -- otherwise they'll "dangle" at the end of // the block. - BB->flushTerminatorDbgValues(); + BB->flushTerminatorDbgRecords(); // Debug-info records on the unreachable inst itself should be deleted, as // below we delete everything past the final executable instruction. @@ -5326,8 +5327,8 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) { // block will be the unwind edges of Invoke/CatchSwitch/CleanupReturn, // and we can therefore guarantee this block will be erased. - // If we're deleting this, we're deleting any subsequent dbg.values, so - // delete DPValue records of variable information. + // If we're deleting this, we're deleting any subsequent debug info, so + // delete DbgRecords. BBI->dropDbgRecords(); // Delete this instruction (any uses are guaranteed to be dead) diff --git a/llvm/lib/Transforms/Utils/ValueMapper.cpp b/llvm/lib/Transforms/Utils/ValueMapper.cpp index 3da161043d6c..abb7a4452a37 100644 --- a/llvm/lib/Transforms/Utils/ValueMapper.cpp +++ b/llvm/lib/Transforms/Utils/ValueMapper.cpp @@ -146,7 +146,7 @@ public: Value *mapValue(const Value *V); void remapInstruction(Instruction *I); void remapFunction(Function &F); - void remapDPValue(DbgRecord &DPV); + void remapDbgRecord(DbgRecord &DPV); Constant *mapConstant(const Constant *C) { return cast_or_null(mapValue(C)); @@ -537,7 +537,7 @@ Value *Mapper::mapValue(const Value *V) { return getVM()[V] = ConstantPointerNull::get(cast(NewTy)); } -void Mapper::remapDPValue(DbgRecord &DR) { +void Mapper::remapDbgRecord(DbgRecord &DR) { if (DPLabel *DPL = dyn_cast(&DR)) { DPL->setLabel(cast(mapMetadata(DPL->getLabel()))); return; @@ -1067,7 +1067,7 @@ void Mapper::remapFunction(Function &F) { for (Instruction &I : BB) { remapInstruction(&I); for (DbgRecord &DR : I.getDbgRecordRange()) - remapDPValue(DR); + remapDbgRecord(DR); } } } @@ -1234,7 +1234,7 @@ void ValueMapper::remapInstruction(Instruction &I) { } void ValueMapper::remapDPValue(Module *M, DPValue &V) { - FlushingMapper(pImpl)->remapDPValue(V); + FlushingMapper(pImpl)->remapDbgRecord(V); } void ValueMapper::remapDPValueRange( diff --git a/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp b/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp index e23c7eaa4930..bfc64cb84143 100644 --- a/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp +++ b/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp @@ -149,7 +149,7 @@ TEST(BasicBlockDbgInfoTest, MarkerOperations) { Instruction *Instr2 = Instr1->getNextNode(); DPMarker *Marker1 = Instr1->DbgMarker; DPMarker *Marker2 = Instr2->DbgMarker; - // There's no TrailingDPValues marker allocated yet. + // There's no TrailingDbgRecords marker allocated yet. DPMarker *EndMarker = nullptr; // Check that the "getMarker" utilities operate as expected. @@ -159,26 +159,26 @@ TEST(BasicBlockDbgInfoTest, MarkerOperations) { EXPECT_EQ(BB.getNextMarker(Instr2), EndMarker); // Is nullptr. // There should be two DPValues, - EXPECT_EQ(Marker1->StoredDPValues.size(), 1u); - EXPECT_EQ(Marker2->StoredDPValues.size(), 1u); + EXPECT_EQ(Marker1->StoredDbgRecords.size(), 1u); + EXPECT_EQ(Marker2->StoredDbgRecords.size(), 1u); // Unlink them and try to re-insert them through the basic block. - DbgRecord *DPV1 = &*Marker1->StoredDPValues.begin(); - DbgRecord *DPV2 = &*Marker2->StoredDPValues.begin(); + DbgRecord *DPV1 = &*Marker1->StoredDbgRecords.begin(); + DbgRecord *DPV2 = &*Marker2->StoredDbgRecords.begin(); DPV1->removeFromParent(); DPV2->removeFromParent(); - EXPECT_TRUE(Marker1->StoredDPValues.empty()); - EXPECT_TRUE(Marker2->StoredDPValues.empty()); + EXPECT_TRUE(Marker1->StoredDbgRecords.empty()); + EXPECT_TRUE(Marker2->StoredDbgRecords.empty()); // This should appear in Marker1. BB.insertDbgRecordBefore(DPV1, BB.begin()); - EXPECT_EQ(Marker1->StoredDPValues.size(), 1u); - EXPECT_EQ(DPV1, &*Marker1->StoredDPValues.begin()); + EXPECT_EQ(Marker1->StoredDbgRecords.size(), 1u); + EXPECT_EQ(DPV1, &*Marker1->StoredDbgRecords.begin()); // This should attach to Marker2. BB.insertDbgRecordAfter(DPV2, &*BB.begin()); - EXPECT_EQ(Marker2->StoredDPValues.size(), 1u); - EXPECT_EQ(DPV2, &*Marker2->StoredDPValues.begin()); + EXPECT_EQ(Marker2->StoredDbgRecords.size(), 1u); + EXPECT_EQ(DPV2, &*Marker2->StoredDbgRecords.begin()); // Now, how about removing instructions? That should cause any DPValues to // "fall down". @@ -186,7 +186,7 @@ TEST(BasicBlockDbgInfoTest, MarkerOperations) { Marker1 = nullptr; // DPValues should now be in Marker2. EXPECT_EQ(BB.size(), 1u); - EXPECT_EQ(Marker2->StoredDPValues.size(), 2u); + EXPECT_EQ(Marker2->StoredDbgRecords.size(), 2u); // They should also be in the correct order. SmallVector DPVs; for (DbgRecord &DPV : Marker2->getDbgRecordRange()) @@ -201,7 +201,7 @@ TEST(BasicBlockDbgInfoTest, MarkerOperations) { EXPECT_TRUE(BB.empty()); EndMarker = BB.getTrailingDbgRecords(); ASSERT_NE(EndMarker, nullptr); - EXPECT_EQ(EndMarker->StoredDPValues.size(), 2u); + EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u); // Again, these should arrive in the correct order. DPVs.clear(); @@ -213,13 +213,13 @@ TEST(BasicBlockDbgInfoTest, MarkerOperations) { // Inserting a normal instruction at the beginning: shouldn't dislodge the // DPValues. It's intended to not go at the start. Instr1->insertBefore(BB, BB.begin()); - EXPECT_EQ(EndMarker->StoredDPValues.size(), 2u); + EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u); Instr1->removeFromParent(); // Inserting at end(): should dislodge the DPValues, if they were dbg.values // then they would sit "above" the new instruction. Instr1->insertBefore(BB, BB.end()); - EXPECT_EQ(Instr1->DbgMarker->StoredDPValues.size(), 2u); + EXPECT_EQ(Instr1->DbgMarker->StoredDbgRecords.size(), 2u); // We should de-allocate the trailing marker when something is inserted // at end(). EXPECT_EQ(BB.getTrailingDbgRecords(), nullptr); @@ -227,14 +227,14 @@ TEST(BasicBlockDbgInfoTest, MarkerOperations) { // Remove Instr1: now the DPValues will fall down again, Instr1->removeFromParent(); EndMarker = BB.getTrailingDbgRecords(); - EXPECT_EQ(EndMarker->StoredDPValues.size(), 2u); + EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u); // Inserting a terminator, however it's intended, should dislodge the // trailing DPValues, as it's the clear intention of the caller that this be // the final instr in the block, and DPValues aren't allowed to live off the // end forever. Instr2->insertBefore(BB, BB.begin()); - EXPECT_EQ(Instr2->DbgMarker->StoredDPValues.size(), 2u); + EXPECT_EQ(Instr2->DbgMarker->StoredDbgRecords.size(), 2u); EXPECT_EQ(BB.getTrailingDbgRecords(), nullptr); // Teardown, @@ -298,24 +298,24 @@ TEST(BasicBlockDbgInfoTest, HeadBitOperations) { Instruction *DInst = CInst->getNextNode(); // CInst should have debug-info. ASSERT_TRUE(CInst->DbgMarker); - EXPECT_FALSE(CInst->DbgMarker->StoredDPValues.empty()); + EXPECT_FALSE(CInst->DbgMarker->StoredDbgRecords.empty()); // If we move "c" to the start of the block, just normally, then the DPValues // should fall down to "d". CInst->moveBefore(BB, BeginIt2); - EXPECT_TRUE(!CInst->DbgMarker || CInst->DbgMarker->StoredDPValues.empty()); + EXPECT_TRUE(!CInst->DbgMarker || CInst->DbgMarker->StoredDbgRecords.empty()); ASSERT_TRUE(DInst->DbgMarker); - EXPECT_FALSE(DInst->DbgMarker->StoredDPValues.empty()); + EXPECT_FALSE(DInst->DbgMarker->StoredDbgRecords.empty()); // Wheras if we move D to the start of the block with moveBeforePreserving, // the DPValues should move with it. DInst->moveBeforePreserving(BB, BB.begin()); - EXPECT_FALSE(DInst->DbgMarker->StoredDPValues.empty()); + EXPECT_FALSE(DInst->DbgMarker->StoredDbgRecords.empty()); EXPECT_EQ(&*BB.begin(), DInst); // Similarly, moveAfterPreserving "D" to "C" should move DPValues with "D". DInst->moveAfterPreserving(CInst); - EXPECT_FALSE(DInst->DbgMarker->StoredDPValues.empty()); + EXPECT_FALSE(DInst->DbgMarker->StoredDbgRecords.empty()); // (move back to the start...) DInst->moveBeforePreserving(BB, BB.begin()); @@ -324,8 +324,8 @@ TEST(BasicBlockDbgInfoTest, HeadBitOperations) { // If we move "C" to the beginning of the block, it should go before the // DPValues. They'll stay on "D". CInst->moveBefore(BB, BB.begin()); - EXPECT_TRUE(!CInst->DbgMarker || CInst->DbgMarker->StoredDPValues.empty()); - EXPECT_FALSE(DInst->DbgMarker->StoredDPValues.empty()); + EXPECT_TRUE(!CInst->DbgMarker || CInst->DbgMarker->StoredDbgRecords.empty()); + EXPECT_FALSE(DInst->DbgMarker->StoredDbgRecords.empty()); EXPECT_EQ(&*BB.begin(), CInst); EXPECT_EQ(CInst->getNextNode(), DInst); @@ -341,8 +341,8 @@ TEST(BasicBlockDbgInfoTest, HeadBitOperations) { // run of dbg.values and the next instruction. CInst->moveBefore(BB, DInst->getIterator()); // CInst gains the DPValues. - EXPECT_TRUE(!DInst->DbgMarker || DInst->DbgMarker->StoredDPValues.empty()); - EXPECT_FALSE(CInst->DbgMarker->StoredDPValues.empty()); + EXPECT_TRUE(!DInst->DbgMarker || DInst->DbgMarker->StoredDbgRecords.empty()); + EXPECT_FALSE(CInst->DbgMarker->StoredDbgRecords.empty()); EXPECT_EQ(&*BB.begin(), CInst); UseNewDbgInfoFormat = false; @@ -390,16 +390,16 @@ TEST(BasicBlockDbgInfoTest, InstrDbgAccess) { ASSERT_FALSE(BInst->DbgMarker); ASSERT_TRUE(CInst->DbgMarker); - ASSERT_EQ(CInst->DbgMarker->StoredDPValues.size(), 1u); - DbgRecord *DPV1 = &*CInst->DbgMarker->StoredDPValues.begin(); + ASSERT_EQ(CInst->DbgMarker->StoredDbgRecords.size(), 1u); + DbgRecord *DPV1 = &*CInst->DbgMarker->StoredDbgRecords.begin(); ASSERT_TRUE(DPV1); EXPECT_FALSE(BInst->hasDbgRecords()); // Clone DPValues from one inst to another. Other arguments to clone are // tested in DPMarker test. auto Range1 = BInst->cloneDebugInfoFrom(CInst); - EXPECT_EQ(BInst->DbgMarker->StoredDPValues.size(), 1u); - DbgRecord *DPV2 = &*BInst->DbgMarker->StoredDPValues.begin(); + EXPECT_EQ(BInst->DbgMarker->StoredDbgRecords.size(), 1u); + DbgRecord *DPV2 = &*BInst->DbgMarker->StoredDbgRecords.begin(); EXPECT_EQ(std::distance(Range1.begin(), Range1.end()), 1u); EXPECT_EQ(&*Range1.begin(), DPV2); EXPECT_NE(DPV1, DPV2); @@ -417,12 +417,12 @@ TEST(BasicBlockDbgInfoTest, InstrDbgAccess) { // Dropping should be easy, BInst->dropDbgRecords(); EXPECT_FALSE(BInst->hasDbgRecords()); - EXPECT_EQ(BInst->DbgMarker->StoredDPValues.size(), 0u); + EXPECT_EQ(BInst->DbgMarker->StoredDbgRecords.size(), 0u); // And we should be able to drop individual DPValues. CInst->dropOneDbgRecord(DPV1); EXPECT_FALSE(CInst->hasDbgRecords()); - EXPECT_EQ(CInst->DbgMarker->StoredDPValues.size(), 0u); + EXPECT_EQ(CInst->DbgMarker->StoredDbgRecords.size(), 0u); UseNewDbgInfoFormat = false; } @@ -531,9 +531,9 @@ protected: Branch = &*Last; CInst = &*Dest; - DPVA = cast(&*BInst->DbgMarker->StoredDPValues.begin()); - DPVB = cast(&*Branch->DbgMarker->StoredDPValues.begin()); - DPVConst = cast(&*CInst->DbgMarker->StoredDPValues.begin()); + DPVA = cast(&*BInst->DbgMarker->StoredDbgRecords.begin()); + DPVB = cast(&*Branch->DbgMarker->StoredDbgRecords.begin()); + DPVConst = cast(&*CInst->DbgMarker->StoredDbgRecords.begin()); } void TearDown() override { UseNewDbgInfoFormat = false; } @@ -1171,7 +1171,7 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceTrailing) { // spliced in. Instruction *BInst = &*Entry.begin(); ASSERT_TRUE(BInst->DbgMarker); - EXPECT_EQ(BInst->DbgMarker->StoredDPValues.size(), 1u); + EXPECT_EQ(BInst->DbgMarker->StoredDbgRecords.size(), 1u); UseNewDbgInfoFormat = false; } @@ -1387,7 +1387,7 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty1) { // should be in the correct order of %a, then 0. Instruction *BInst = &*Entry.begin(); ASSERT_TRUE(BInst->hasDbgRecords()); - EXPECT_EQ(BInst->DbgMarker->StoredDPValues.size(), 2u); + EXPECT_EQ(BInst->DbgMarker->StoredDbgRecords.size(), 2u); SmallVector DPValues; for (DbgRecord &DPV : BInst->getDbgRecordRange()) DPValues.push_back(cast(&DPV)); @@ -1457,7 +1457,7 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty2) { // We should now have one dbg.values on the first instruction, %a. Instruction *BInst = &*Entry.begin(); ASSERT_TRUE(BInst->hasDbgRecords()); - EXPECT_EQ(BInst->DbgMarker->StoredDPValues.size(), 1u); + EXPECT_EQ(BInst->DbgMarker->StoredDbgRecords.size(), 1u); SmallVector DPValues; for (DbgRecord &DPV : BInst->getDbgRecordRange()) DPValues.push_back(cast(&DPV)); diff --git a/llvm/unittests/IR/DebugInfoTest.cpp b/llvm/unittests/IR/DebugInfoTest.cpp index 0b019c26148b..4bd11d26071b 100644 --- a/llvm/unittests/IR/DebugInfoTest.cpp +++ b/llvm/unittests/IR/DebugInfoTest.cpp @@ -951,7 +951,7 @@ TEST(MetadataTest, ConvertDbgToDPValue) { ExitBlock->createMarker(FirstInst); ExitBlock->createMarker(RetInst); - // Insert DPValues into markers, order should come out DPV2, DPV1. + // Insert DbgRecords into markers, order should come out DPV2, DPV1. FirstInst->DbgMarker->insertDbgRecord(DPV1, false); FirstInst->DbgMarker->insertDbgRecord(DPV2, true); unsigned int ItCount = 0; @@ -964,7 +964,7 @@ TEST(MetadataTest, ConvertDbgToDPValue) { // Clone them onto the second marker -- should allocate new DPVs. RetInst->DbgMarker->cloneDebugInfoFrom(FirstInst->DbgMarker, std::nullopt, false); - EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 2u); + EXPECT_EQ(RetInst->DbgMarker->StoredDbgRecords.size(), 2u); ItCount = 0; // Check these things store the same information; but that they're not the same // objects. @@ -980,25 +980,25 @@ TEST(MetadataTest, ConvertDbgToDPValue) { } RetInst->DbgMarker->dropDbgRecords(); - EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 0u); + EXPECT_EQ(RetInst->DbgMarker->StoredDbgRecords.size(), 0u); // Try cloning one single DPValue. auto DIIt = std::next(FirstInst->DbgMarker->getDbgRecordRange().begin()); RetInst->DbgMarker->cloneDebugInfoFrom(FirstInst->DbgMarker, DIIt, false); - EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 1u); + EXPECT_EQ(RetInst->DbgMarker->StoredDbgRecords.size(), 1u); // The second DPValue should have been cloned; it should have the same values // as DPV1. - EXPECT_EQ(cast(RetInst->DbgMarker->StoredDPValues.begin()) + EXPECT_EQ(cast(RetInst->DbgMarker->StoredDbgRecords.begin()) ->getRawLocation(), DPV1->getRawLocation()); - // We should be able to drop individual DPValues. + // We should be able to drop individual DbgRecords. RetInst->DbgMarker->dropOneDbgRecord( - &*RetInst->DbgMarker->StoredDPValues.begin()); + &*RetInst->DbgMarker->StoredDbgRecords.begin()); // "Aborb" a DPMarker: this means pretend that the instruction it's attached // to is disappearing so it needs to be transferred into "this" marker. RetInst->DbgMarker->absorbDebugValues(*FirstInst->DbgMarker, true); - EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 2u); + EXPECT_EQ(RetInst->DbgMarker->StoredDbgRecords.size(), 2u); // Should be the DPV1 and DPV2 objects. ItCount = 0; for (DbgRecord &Item : RetInst->DbgMarker->getDbgRecordRange()) { @@ -1009,7 +1009,7 @@ TEST(MetadataTest, ConvertDbgToDPValue) { } // Finally -- there are two DPValues left over. If we remove evrything in the - // basic block, then they should sink down into the "TrailingDPValues" + // basic block, then they should sink down into the "TrailingDbgRecords" // container for dangling debug-info. Future facilities will restore them // back when a terminator is inserted. FirstInst->DbgMarker->removeMarker(); @@ -1019,7 +1019,7 @@ TEST(MetadataTest, ConvertDbgToDPValue) { DPMarker *EndMarker = ExitBlock->getTrailingDbgRecords(); ASSERT_NE(EndMarker, nullptr); - EXPECT_EQ(EndMarker->StoredDPValues.size(), 2u); + EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u); // Test again that it's those two DPValues, DPV1 and DPV2. ItCount = 0; for (DbgRecord &Item : EndMarker->getDbgRecordRange()) { @@ -1115,14 +1115,14 @@ TEST(MetadataTest, DPValueConversionRoutines) { EXPECT_EQ(FirstInst, FirstInst->DbgMarker->MarkedInstr); EXPECT_EQ(SecondInst, SecondInst->DbgMarker->MarkedInstr); - EXPECT_EQ(FirstInst->DbgMarker->StoredDPValues.size(), 1u); + EXPECT_EQ(FirstInst->DbgMarker->StoredDbgRecords.size(), 1u); DPValue *DPV1 = cast(&*FirstInst->DbgMarker->getDbgRecordRange().begin()); EXPECT_EQ(DPV1->getMarker(), FirstInst->DbgMarker); // Should point at %a, an argument. EXPECT_TRUE(isa(DPV1->getVariableLocationOp(0))); - EXPECT_EQ(SecondInst->DbgMarker->StoredDPValues.size(), 1u); + EXPECT_EQ(SecondInst->DbgMarker->StoredDbgRecords.size(), 1u); DPValue *DPV2 = cast(&*SecondInst->DbgMarker->getDbgRecordRange().begin()); EXPECT_EQ(DPV2->getMarker(), SecondInst->DbgMarker); @@ -1135,7 +1135,7 @@ TEST(MetadataTest, DPValueConversionRoutines) { EXPECT_TRUE(BB2->IsNewDbgInfoFormat); for (auto &Inst : *BB2) // Either there should be no marker, or it should be empty. - EXPECT_TRUE(!Inst.DbgMarker || Inst.DbgMarker->StoredDPValues.empty()); + EXPECT_TRUE(!Inst.DbgMarker || Inst.DbgMarker->StoredDbgRecords.empty()); // Validating the first block should continue to not be a problem, Error = verifyModule(*M, &errs(), &BrokenDebugInfo); diff --git a/llvm/unittests/Transforms/Utils/DebugifyTest.cpp b/llvm/unittests/Transforms/Utils/DebugifyTest.cpp index 89fa1334b427..0b00734fc4d7 100644 --- a/llvm/unittests/Transforms/Utils/DebugifyTest.cpp +++ b/llvm/unittests/Transforms/Utils/DebugifyTest.cpp @@ -60,7 +60,7 @@ struct DebugValueDrop : public FunctionPass { for (Instruction &I : BB) { if (auto *DVI = dyn_cast(&I)) Dbgs.push_back(DVI); - // If there are any non-intrinsic records (DPValues), drop those too. + // If there are any non-intrinsic records (DbgRecords), drop those too. I.dropDbgRecords(); } } -- GitLab From e703c735df1257022bcb6ca9de857e20e671392f Mon Sep 17 00:00:00 2001 From: Changpeng Fang Date: Wed, 13 Mar 2024 09:49:30 -0700 Subject: [PATCH 405/953] AMDGPU: Remove incorrect uses of SubtaretPredicate around DS_Reals (#85001) SubtargetPredicate is copied from DS_Pseudo to DS_Real. We should not use another SubtargetPredicate assignment around DS_Real, because doing so will override the predicate from DS_Pseudo. For example, for DS_ADD_RTN_F64, SubtargetPredicate was set to HasLdsAtomicAddF64 in Pseudo. And it will be overridden to isGFX90APlus if we assign isGFX90APlus to SubtargetPredicate in Real definition. --- llvm/lib/Target/AMDGPU/DSInstructions.td | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/DSInstructions.td b/llvm/lib/Target/AMDGPU/DSInstructions.td index 87ace01a6d0e..e944dde15990 100644 --- a/llvm/lib/Target/AMDGPU/DSInstructions.td +++ b/llvm/lib/Target/AMDGPU/DSInstructions.td @@ -1735,14 +1735,12 @@ def DS_WRITE_B128_vi : DS_Real_vi<0xdf, DS_WRITE_B128>; def DS_READ_B96_vi : DS_Real_vi<0xfe, DS_READ_B96>; def DS_READ_B128_vi : DS_Real_vi<0xff, DS_READ_B128>; -let SubtargetPredicate = isGFX90APlus in { - def DS_ADD_F64_vi : DS_Real_vi<0x5c, DS_ADD_F64>; - def DS_ADD_RTN_F64_vi : DS_Real_vi<0x7c, DS_ADD_RTN_F64>; -} // End SubtargetPredicate = isGFX90APlus - -let SubtargetPredicate = isGFX940Plus in { - def DS_PK_ADD_F16_vi : DS_Real_vi<0x17, DS_PK_ADD_F16>; - def DS_PK_ADD_RTN_F16_vi : DS_Real_vi<0xb7, DS_PK_ADD_RTN_F16>; - def DS_PK_ADD_BF16_vi : DS_Real_vi<0x18, DS_PK_ADD_BF16>; - def DS_PK_ADD_RTN_BF16_vi : DS_Real_vi<0xb8, DS_PK_ADD_RTN_BF16>; -} // End SubtargetPredicate = isGFX940Plus +// GFX90A+. +def DS_ADD_F64_vi : DS_Real_vi<0x5c, DS_ADD_F64>; +def DS_ADD_RTN_F64_vi : DS_Real_vi<0x7c, DS_ADD_RTN_F64>; + +// GFX940+. +def DS_PK_ADD_F16_vi : DS_Real_vi<0x17, DS_PK_ADD_F16>; +def DS_PK_ADD_RTN_F16_vi : DS_Real_vi<0xb7, DS_PK_ADD_RTN_F16>; +def DS_PK_ADD_BF16_vi : DS_Real_vi<0x18, DS_PK_ADD_BF16>; +def DS_PK_ADD_RTN_BF16_vi : DS_Real_vi<0xb8, DS_PK_ADD_RTN_BF16>; -- GitLab From 3b2694853e361d2221ec8071f815d9f5eef35b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Warzy=C5=84ski?= Date: Wed, 13 Mar 2024 16:53:26 +0000 Subject: [PATCH 406/953] [mlir][nfc] Update Linalg matmul -> Vector OP test (#81416) Updates "transform-op-matmul-to-outerproduct.mlir". Summary: * refines TD sequence so that it's easier to reason about the compilation pipeline (e.g. `transform.structured.vectorize_children_and_apply_patterns` is replaced with`transform.structured.vectorize `), * new input dims to be able to distinguish parallel from reduction dims, * updates LIT variable names (makes the output easier to follow), * removes "noise" from the expected LIT output (e.g. types). These Linalg -> Vector tests using Transform Dialect are great reference points for constructing lowering pipelines. This simplification + clean-up will hopefully make it easier to follow. --- .../transform-op-matmul-to-outerproduct.mlir | 67 +++++++++++-------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/mlir/test/Dialect/Linalg/transform-op-matmul-to-outerproduct.mlir b/mlir/test/Dialect/Linalg/transform-op-matmul-to-outerproduct.mlir index ee66073a9a41..a1a0c413da0c 100644 --- a/mlir/test/Dialect/Linalg/transform-op-matmul-to-outerproduct.mlir +++ b/mlir/test/Dialect/Linalg/transform-op-matmul-to-outerproduct.mlir @@ -1,38 +1,51 @@ // RUN: mlir-opt %s -transform-interpreter | FileCheck %s -func.func @outerproduct_matmul(%A: memref<3x3xf32>, %B: memref<3x3xf32>, %C: memref<3x3xf32>) { - linalg.matmul ins(%A, %B: memref<3x3xf32>, memref<3x3xf32>) +func.func @matmul_to_outerproduct(%A: memref<3x4xf32>, %B: memref<4x3xf32>, %C: memref<3x3xf32>) { + linalg.matmul ins(%A, %B: memref<3x4xf32>, memref<4x3xf32>) outs(%C: memref<3x3xf32>) return } -// CHECK-LABEL: func.func @outerproduct_matmul( -// CHECK-SAME: %[[VAL_0:.*]]: memref<3x3xf32>, %[[VAL_1:.*]]: memref<3x3xf32>, %[[VAL_2:.*]]: memref<3x3xf32>) { -// CHECK: %[[VAL_3:.*]] = arith.constant 0 : index -// CHECK: %[[VAL_4:.*]] = arith.constant 0.000000e+00 : f32 -// CHECK: %[[VAL_5:.*]] = vector.transfer_read %[[VAL_0]]{{\[}}%[[VAL_3]], %[[VAL_3]]], %[[VAL_4]] {in_bounds = [true, true]} : memref<3x3xf32>, vector<3x3xf32> -// CHECK: %[[VAL_6:.*]] = vector.transfer_read %[[VAL_1]]{{\[}}%[[VAL_3]], %[[VAL_3]]], %[[VAL_4]] {in_bounds = [true, true]} : memref<3x3xf32>, vector<3x3xf32> -// CHECK: %[[VAL_7:.*]] = vector.transfer_read %[[VAL_2]]{{\[}}%[[VAL_3]], %[[VAL_3]]], %[[VAL_4]] {in_bounds = [true, true]} : memref<3x3xf32>, vector<3x3xf32> -// CHECK: %[[VAL_8:.*]] = vector.transpose %[[VAL_5]], [1, 0] : vector<3x3xf32> to vector<3x3xf32> -// CHECK: %[[VAL_9:.*]] = vector.extract %[[VAL_8]][0] : vector<3xf32> from vector<3x3xf32> -// CHECK: %[[VAL_10:.*]] = vector.extract %[[VAL_6]][0] : vector<3xf32> from vector<3x3xf32> -// CHECK: %[[VAL_11:.*]] = vector.outerproduct %[[VAL_9]], %[[VAL_10]], %[[VAL_7]] {kind = #vector.kind} : vector<3xf32>, vector<3xf32> -// CHECK: %[[VAL_12:.*]] = vector.extract %[[VAL_8]][1] : vector<3xf32> from vector<3x3xf32> -// CHECK: %[[VAL_13:.*]] = vector.extract %[[VAL_6]][1] : vector<3xf32> from vector<3x3xf32> -// CHECK: %[[VAL_14:.*]] = vector.outerproduct %[[VAL_12]], %[[VAL_13]], %[[VAL_11]] {kind = #vector.kind} : vector<3xf32>, vector<3xf32> -// CHECK: %[[VAL_15:.*]] = vector.extract %[[VAL_8]][2] : vector<3xf32> from vector<3x3xf32> -// CHECK: %[[VAL_16:.*]] = vector.extract %[[VAL_6]][2] : vector<3xf32> from vector<3x3xf32> -// CHECK: %[[VAL_17:.*]] = vector.outerproduct %[[VAL_15]], %[[VAL_16]], %[[VAL_14]] {kind = #vector.kind} : vector<3xf32>, vector<3xf32> -// CHECK: vector.transfer_write %[[VAL_17]], %[[VAL_2]]{{\[}}%[[VAL_3]], %[[VAL_3]]] {in_bounds = [true, true]} : vector<3x3xf32>, memref<3x3xf32> -// CHECK: return -// CHECK: } +// CHECK-LABEL: func.func @matmul_to_outerproduct( +// CHECK-SAME: %[[A:.*]]: memref<3x4xf32>, +// CHECK-SAME: %[[B:.*]]: memref<4x3xf32>, +// CHECK-SAME: %[[C:.*]]: memref<3x3xf32>) { +// CHECK: %[[VEC_A:.*]] = vector.transfer_read %[[A]] +// CHECK: %[[VEC_B:.*]] = vector.transfer_read %[[B]] +// CHECK: %[[VEC_C:.*]] = vector.transfer_read %[[C]] +// CHECK: %[[VEC_A_T:.*]] = vector.transpose %[[VEC_A]], [1, 0] : vector<3x4xf32> to vector<4x3xf32> +// CHECK: %[[A0:.*]] = vector.extract %[[VEC_A_T]][0] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[B0:.*]] = vector.extract %[[VEC_B]][0] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[OP_0:.*]] = vector.outerproduct %[[A0]], %[[B0]], %[[VEC_C]] +// CHECK: %[[A1:.*]] = vector.extract %[[VEC_A_T]][1] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[B1:.*]] = vector.extract %[[VEC_B]][1] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[OP_1:.*]] = vector.outerproduct %[[A1]], %[[B1]], %[[OP_0]] +// CHECK: %[[A_2:.*]] = vector.extract %[[VEC_A_T]][2] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[B_2:.*]] = vector.extract %[[VEC_B]][2] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[OP_2:.*]] = vector.outerproduct %[[A_2]], %[[B_2]], %[[OP_1]] +// CHECK: %[[A_3:.*]] = vector.extract %[[VEC_A_T]][3] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[B_3:.*]] = vector.extract %[[VEC_B]][3] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[RES:.*]] = vector.outerproduct %[[A_3]], %[[B_3]], %[[OP_2]] +// CHECK: vector.transfer_write %[[RES]], %[[C]]{{.*}} : vector<3x3xf32>, memref<3x3xf32> module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { - %0 = transform.structured.match ops{["linalg.matmul"]} in %arg1 : (!transform.any_op) -> !transform.any_op - %1 = transform.get_parent_op %0 {isolated_from_above} : (!transform.any_op) -> !transform.any_op - %2 = transform.structured.vectorize_children_and_apply_patterns %1 : (!transform.any_op) -> !transform.any_op - transform.apply_patterns to %2 { + transform.named_sequence @__transform_main(%module: !transform.any_op {transform.readonly}) { + %func = transform.structured.match ops{["func.func"]} in %module : (!transform.any_op) -> !transform.any_op + + // Vectorize: linalg.matmul -> vector.multi_reduction + %matmul = transform.structured.match ops{["linalg.matmul"]} in %func : (!transform.any_op) -> !transform.any_op + transform.structured.vectorize %matmul : !transform.any_op + + // vector.multi_reduction --> vector.contract + transform.apply_patterns to %func { + transform.apply_patterns.vector.reduction_to_contract + // Reduce the rank of xfer ops. This transform vector.contract to be more + // more matmul-like and to enable the lowering to outer product Ops. + transform.apply_patterns.vector.transfer_permutation_patterns + } : !transform.any_op + + // vector.contract --> vector.outerproduct + transform.apply_patterns to %func { transform.apply_patterns.vector.lower_contraction lowering_strategy = "outerproduct" } : !transform.any_op transform.yield -- GitLab From 79cd2c0bb9acb4685094d6b3bf21c758aa51d3df Mon Sep 17 00:00:00 2001 From: "Nadeem, Usman" Date: Wed, 13 Mar 2024 09:54:30 -0700 Subject: [PATCH 407/953] [AArch64] Fix tests after PR82457 Change-Id: I44a7e4a10af750b3339d6564c6ce6c2e5c17778e --- llvm/test/CodeGen/AArch64/bitcast.ll | 4 ++-- llvm/test/CodeGen/AArch64/shufflevector.ll | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/test/CodeGen/AArch64/bitcast.ll b/llvm/test/CodeGen/AArch64/bitcast.ll index bccfdb93d786..9ebd570e687a 100644 --- a/llvm/test/CodeGen/AArch64/bitcast.ll +++ b/llvm/test/CodeGen/AArch64/bitcast.ll @@ -59,7 +59,7 @@ define i32 @bitcast_v4i8_i32(<4 x i8> %a, <4 x i8> %b){ ; CHECK-NEXT: sub sp, sp, #16 ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: add v0.4h, v0.4h, v1.4h -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: fmov w0, s0 ; CHECK-NEXT: add sp, sp, #16 ; CHECK-NEXT: ret @@ -388,7 +388,7 @@ define <2 x i16> @bitcast_v4i8_v2i16(<4 x i8> %a, <4 x i8> %b){ ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: add v0.4h, v0.4h, v1.4h ; CHECK-NEXT: add x8, sp, #12 -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [sp, #12] ; CHECK-NEXT: ld1 { v0.h }[0], [x8] ; CHECK-NEXT: orr x8, x8, #0x2 diff --git a/llvm/test/CodeGen/AArch64/shufflevector.ll b/llvm/test/CodeGen/AArch64/shufflevector.ll index d79f3ae11167..b1131f287fe9 100644 --- a/llvm/test/CodeGen/AArch64/shufflevector.ll +++ b/llvm/test/CodeGen/AArch64/shufflevector.ll @@ -202,7 +202,7 @@ define i32 @shufflevector_v4i8(<4 x i8> %a, <4 x i8> %b){ ; CHECK-SD-NEXT: ext v0.8b, v1.8b, v0.8b, #6 ; CHECK-SD-NEXT: zip1 v1.4h, v1.4h, v0.4h ; CHECK-SD-NEXT: ext v0.8b, v0.8b, v1.8b, #4 -; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-SD-NEXT: fmov w0, s0 ; CHECK-SD-NEXT: add sp, sp, #16 ; CHECK-SD-NEXT: ret @@ -390,7 +390,7 @@ define i32 @shufflevector_v4i8_zeroes(<4 x i8> %a, <4 x i8> %b){ ; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 ; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-SD-NEXT: dup v0.4h, v0.h[0] -; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-SD-NEXT: fmov w0, s0 ; CHECK-SD-NEXT: add sp, sp, #16 ; CHECK-SD-NEXT: ret -- GitLab From 122d368b2b120ff233e66658862b90f185f65c6e Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 13 Mar 2024 10:13:21 -0700 Subject: [PATCH 408/953] [llvm-objcopy] --[de]compress-debug-sections: don't compress SHF_ALLOC sections, only decompress .debug sections Simplify --[de]compress-debug-sections to make it easier to add custom section [de]compression. Change the following two behaviors to match GNU objcopy. * --compress-debug-sections compresses SHF_ALLOC sections while GNU doesn't. * --decompress-debug-sections decompresses non-debug sections while GNU doesn't. Pull Request: https://github.com/llvm/llvm-project/pull/84885 --- llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp | 63 +++++++------------ llvm/lib/ObjCopy/ELF/ELFObject.h | 1 + .../ELF/Inputs/compress-debug-sections.yaml | 4 ++ .../ELF/compress-debug-sections-zlib.test | 2 + .../ELF/compress-debug-sections-zstd.test | 2 + .../llvm-objcopy/ELF/decompress-sections.test | 36 +++++++++++ 6 files changed, 68 insertions(+), 40 deletions(-) create mode 100644 llvm/test/tools/llvm-objcopy/ELF/decompress-sections.test diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp index f52bcb74938d..e4d6e02f3aa6 100644 --- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp +++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp @@ -214,33 +214,32 @@ static Error dumpSectionToFile(StringRef SecName, StringRef Filename, SecName.str().c_str()); } -static bool isCompressable(const SectionBase &Sec) { - return !(Sec.Flags & ELF::SHF_COMPRESSED) && - StringRef(Sec.Name).starts_with(".debug"); -} - -static Error replaceDebugSections( - Object &Obj, function_ref ShouldReplace, - function_ref(const SectionBase *)> AddSection) { +Error Object::compressOrDecompressSections(const CommonConfig &Config) { // Build a list of the debug sections we are going to replace. // We can't call `AddSection` while iterating over sections, // because it would mutate the sections array. - SmallVector ToReplace; - for (auto &Sec : Obj.sections()) - if (ShouldReplace(Sec)) - ToReplace.push_back(&Sec); - - // Build a mapping from original section to a new one. - DenseMap FromTo; - for (SectionBase *S : ToReplace) { - Expected NewSection = AddSection(S); - if (!NewSection) - return NewSection.takeError(); - - FromTo[S] = *NewSection; + SmallVector>, 0> + ToReplace; + for (SectionBase &Sec : sections()) { + if ((Sec.Flags & SHF_ALLOC) || !StringRef(Sec.Name).starts_with(".debug")) + continue; + if (auto *CS = dyn_cast(&Sec)) { + if (Config.DecompressDebugSections) { + ToReplace.emplace_back( + &Sec, [=] { return &addSection(*CS); }); + } + } else if (Config.CompressionType != DebugCompressionType::None) { + ToReplace.emplace_back(&Sec, [&, S = &Sec] { + return &addSection( + CompressedSection(*S, Config.CompressionType, Is64Bits)); + }); + } } - return Obj.replaceSections(FromTo); + DenseMap FromTo; + for (auto [S, Func] : ToReplace) + FromTo[S] = Func(); + return replaceSections(FromTo); } static bool isAArch64MappingSymbol(const Symbol &Sym) { @@ -534,24 +533,8 @@ static Error replaceAndRemoveSections(const CommonConfig &Config, if (Error E = Obj.removeSections(ELFConfig.AllowBrokenLinks, RemovePred)) return E; - if (Config.CompressionType != DebugCompressionType::None) { - if (Error Err = replaceDebugSections( - Obj, isCompressable, - [&Config, &Obj](const SectionBase *S) -> Expected { - return &Obj.addSection( - CompressedSection(*S, Config.CompressionType, Obj.Is64Bits)); - })) - return Err; - } else if (Config.DecompressDebugSections) { - if (Error Err = replaceDebugSections( - Obj, - [](const SectionBase &S) { return isa(&S); }, - [&Obj](const SectionBase *S) { - const CompressedSection *CS = cast(S); - return &Obj.addSection(*CS); - })) - return Err; - } + if (Error E = Obj.compressOrDecompressSections(Config)) + return E; return Error::success(); } diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h index 7a2e20d82d11..f72c109b6009 100644 --- a/llvm/lib/ObjCopy/ELF/ELFObject.h +++ b/llvm/lib/ObjCopy/ELF/ELFObject.h @@ -1210,6 +1210,7 @@ public: Error removeSections(bool AllowBrokenLinks, std::function ToRemove); + Error compressOrDecompressSections(const CommonConfig &Config); Error replaceSections(const DenseMap &FromTo); Error removeSymbols(function_ref ToRemove); template T &addSection(Ts &&...Args) { diff --git a/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml b/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml index 67d8435fa486..e2dfee9163a2 100644 --- a/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml +++ b/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml @@ -43,6 +43,10 @@ Sections: Type: SHT_PROGBITS Flags: [ SHF_GROUP ] Content: '00' + - Name: .debug_alloc + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Content: 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f Symbols: - Type: STT_SECTION Section: .debug_foo diff --git a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test index e1ebeed8d4fc..056ae84ce491 100644 --- a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test +++ b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test @@ -12,8 +12,10 @@ # CHECK: Name Type Address Off Size ES Flg Lk Inf Al # COMPRESSED: .debug_foo PROGBITS 0000000000000000 000040 {{.*}} 00 C 0 0 8 # COMPRESSED-NEXT: .notdebug_foo PROGBITS 0000000000000000 {{.*}} 000008 00 0 0 0 +# COMPRESSED: .debug_alloc PROGBITS 0000000000000000 {{.*}} 000040 00 A 0 0 0 # UNCOMPRESSED: .debug_foo PROGBITS 0000000000000000 000040 000008 00 0 0 0 # UNCOMPRESSED-NEXT: .notdebug_foo PROGBITS 0000000000000000 {{.*}} 000008 00 0 0 0 +# UNCOMPRESSED: .debug_alloc PROGBITS 0000000000000000 {{.*}} 000040 00 A 0 0 0 ## Relocations do not change. # CHECK: Relocation section '.rela.debug_foo' at offset {{.*}} contains 2 entries: diff --git a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zstd.test b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zstd.test index d763131c4067..bde1c2f311d0 100644 --- a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zstd.test +++ b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zstd.test @@ -12,8 +12,10 @@ # CHECK: Name Type Address Off Size ES Flg Lk Inf Al # COMPRESSED: .debug_foo PROGBITS 0000000000000000 000040 {{.*}} 00 C 0 0 8 # COMPRESSED-NEXT: .notdebug_foo PROGBITS 0000000000000000 {{.*}} 000008 00 0 0 0 +# COMPRESSED: .debug_alloc PROGBITS 0000000000000000 {{.*}} 000040 00 A 0 0 0 # DECOMPRESSED: .debug_foo PROGBITS 0000000000000000 000040 000008 00 0 0 0 # DECOMPRESSED-NEXT: .notdebug_foo PROGBITS 0000000000000000 {{.*}} 000008 00 0 0 0 +# DECOMPRESSED: .debug_alloc PROGBITS 0000000000000000 {{.*}} 000040 00 A 0 0 0 ## Relocations do not change. # CHECK: Relocation section '.rela.debug_foo' at offset {{.*}} contains 2 entries: diff --git a/llvm/test/tools/llvm-objcopy/ELF/decompress-sections.test b/llvm/test/tools/llvm-objcopy/ELF/decompress-sections.test new file mode 100644 index 000000000000..4258ddbe66a3 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/ELF/decompress-sections.test @@ -0,0 +1,36 @@ +# REQUIRES: zlib +## Test decompression for different sections. + +# RUN: yaml2obj %s -o %t +# RUN: llvm-objcopy --decompress-debug-sections %t %t.de +# RUN: llvm-readelf -S %t.de | FileCheck %s + +# CHECK: Name Type Address Off Size ES Flg Lk Inf Al +# CHECK: .debug_alloc PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 AC 0 0 0 +# CHECK-NEXT: .debug_nonalloc PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 1 +# CHECK-NEXT: .debugx PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 1 +# CHECK-NEXT: nodebug PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 C 0 0 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .debug_alloc + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_COMPRESSED ] + Content: 010000000000000040000000000000000100000000000000789cd36280002d3269002f800151 + - Name: .debug_nonalloc + Type: SHT_PROGBITS + Flags: [ SHF_COMPRESSED ] + Content: 010000000000000040000000000000000100000000000000789cd36280002d3269002f800151 + - Name: .debugx + Type: SHT_PROGBITS + Flags: [ SHF_COMPRESSED ] + Content: 010000000000000040000000000000000100000000000000789cd36280002d3269002f800151 + - Name: nodebug + Type: SHT_PROGBITS + Flags: [ SHF_COMPRESSED ] + Content: 010000000000000040000000000000000100000000000000789cd36280002d3269002f800151 -- GitLab From 35f5caea5115d7dabf0c1a92c8627069d6dbd556 Mon Sep 17 00:00:00 2001 From: Chen Cheng <110446443+ChengChen002@users.noreply.github.com> Date: Thu, 14 Mar 2024 01:16:42 +0800 Subject: [PATCH 409/953] [NFC] Corrected data type (#84880) On windows, "&Method.first" is of type "unsigned long long *", and a type conversion error occurs. --- llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp index d346214d3ae2..57ac991ee37f 100644 --- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp +++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp @@ -87,7 +87,7 @@ static void registerJITLoaderVTuneUnregisterImpl( for (auto &Method : UM) { JITEventWrapper::Wrapper->iJIT_NotifyEvent( iJVM_EVENT_TYPE_METHOD_UNLOAD_START, - const_cast(&Method.first)); + const_cast(&Method.first)); } } -- GitLab From 13ccaf9b9d4400bb128b35ff4ac733e4afc3ad1c Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Wed, 13 Mar 2024 10:12:16 -0700 Subject: [PATCH 410/953] Revert "Reapply "[analyzer] Accept C library functions from the `std` namespace"" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e48d5a838f69e0a8e0ae95a8aed1a8809f45465a. Fails to build on x86-64 w/gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) with the following message: ../llvm-project/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp:41:28: error: declaration of ‘std::unique_ptr IsCLibraryFunctionTest::ASTUnit’ changes meaning of ‘ASTUnit’ [-fpermissive] 41 | std::unique_ptr ASTUnit; | ^~~~~~~ In file included from ../llvm-project/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp:4: ../llvm-project/clang/include/clang/Frontend/ASTUnit.h:89:7: note: ‘ASTUnit’ declared here as ‘class clang::ASTUnit’ 89 | class ASTUnit { | ^~~~~~~ --- .../Core/PathSensitive/CallDescription.h | 8 +- .../StaticAnalyzer/Core/CheckerContext.cpp | 8 +- clang/unittests/StaticAnalyzer/CMakeLists.txt | 1 - .../StaticAnalyzer/IsCLibraryFunctionTest.cpp | 84 ------------------- .../clang/unittests/StaticAnalyzer/BUILD.gn | 1 - 5 files changed, 9 insertions(+), 93 deletions(-) delete mode 100644 clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h index b4e1636130ca..3432d2648633 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h @@ -41,8 +41,12 @@ public: /// - We also accept calls where the number of arguments or parameters is /// greater than the specified value. /// For the exact heuristics, see CheckerContext::isCLibraryFunction(). - /// (This mode only matches functions that are declared either directly - /// within a TU or in the namespace `std`.) + /// Note that functions whose declaration context is not a TU (e.g. + /// methods, functions in namespaces) are not accepted as C library + /// functions. + /// FIXME: If I understand it correctly, this discards calls where C++ code + /// refers a C library function through the namespace `std::` via headers + /// like . CLibrary, /// Matches "simple" functions that are not methods. (Static methods are diff --git a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp index 1a9bff529e9b..d6d4cec9dd3d 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp @@ -87,11 +87,9 @@ bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD, if (!II) return false; - // C library functions are either declared directly within a TU (the common - // case) or they are accessed through the namespace `std` (when they are used - // in C++ via headers like ). - const DeclContext *DC = FD->getDeclContext()->getRedeclContext(); - if (!(DC->isTranslationUnit() || DC->isStdNamespace())) + // Look through 'extern "C"' and anything similar invented in the future. + // If this function is not in TU directly, it is not a C library function. + if (!FD->getDeclContext()->getRedeclContext()->isTranslationUnit()) return false; // If this function is not externally visible, it is not a C library function. diff --git a/clang/unittests/StaticAnalyzer/CMakeLists.txt b/clang/unittests/StaticAnalyzer/CMakeLists.txt index db56e77331b8..775f0f8486b8 100644 --- a/clang/unittests/StaticAnalyzer/CMakeLists.txt +++ b/clang/unittests/StaticAnalyzer/CMakeLists.txt @@ -11,7 +11,6 @@ add_clang_unittest(StaticAnalysisTests CallEventTest.cpp ConflictingEvalCallsTest.cpp FalsePositiveRefutationBRVisitorTest.cpp - IsCLibraryFunctionTest.cpp NoStateChangeFuncVisitorTest.cpp ParamRegionTest.cpp RangeSetTest.cpp diff --git a/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp b/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp deleted file mode 100644 index 31ff13f428da..000000000000 --- a/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/ASTMatchers/ASTMatchers.h" -#include "clang/Analysis/AnalysisDeclContext.h" -#include "clang/Frontend/ASTUnit.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" -#include "clang/Tooling/Tooling.h" -#include "gtest/gtest.h" - -#include - -using namespace clang; -using namespace ento; -using namespace ast_matchers; - -class IsCLibraryFunctionTest : public testing::Test { -public: - const FunctionDecl *getFunctionDecl() const { return Result; } - - testing::AssertionResult buildAST(StringRef Code) { - ASTUnit = tooling::buildASTFromCode(Code); - if (!ASTUnit) - return testing::AssertionFailure() << "AST construction failed"; - - ASTContext &Context = ASTUnit->getASTContext(); - if (Context.getDiagnostics().hasErrorOccurred()) - return testing::AssertionFailure() << "Compilation error"; - - auto Matches = ast_matchers::match(functionDecl().bind("fn"), Context); - if (Matches.empty()) - return testing::AssertionFailure() << "No function declaration found"; - - if (Matches.size() > 1) - return testing::AssertionFailure() - << "Multiple function declarations found"; - - Result = Matches[0].getNodeAs("fn"); - return testing::AssertionSuccess(); - } - -private: - std::unique_ptr ASTUnit; - const FunctionDecl *Result = nullptr; -}; - -TEST_F(IsCLibraryFunctionTest, AcceptsGlobal) { - ASSERT_TRUE(buildAST(R"cpp(void fun();)cpp")); - EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); -} - -TEST_F(IsCLibraryFunctionTest, AcceptsExternCGlobal) { - ASSERT_TRUE(buildAST(R"cpp(extern "C" { void fun(); })cpp")); - EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); -} - -TEST_F(IsCLibraryFunctionTest, RejectsNoInlineNoExternalLinkage) { - // Functions that are neither inlined nor externally visible cannot be C library functions. - ASSERT_TRUE(buildAST(R"cpp(static void fun();)cpp")); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); -} - -TEST_F(IsCLibraryFunctionTest, RejectsAnonymousNamespace) { - ASSERT_TRUE(buildAST(R"cpp(namespace { void fun(); })cpp")); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); -} - -TEST_F(IsCLibraryFunctionTest, AcceptsStdNamespace) { - ASSERT_TRUE(buildAST(R"cpp(namespace std { void fun(); })cpp")); - EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); -} - -TEST_F(IsCLibraryFunctionTest, RejectsOtherNamespaces) { - ASSERT_TRUE(buildAST(R"cpp(namespace stdx { void fun(); })cpp")); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); -} - -TEST_F(IsCLibraryFunctionTest, RejectsClassStatic) { - ASSERT_TRUE(buildAST(R"cpp(class A { static void fun(); };)cpp")); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); -} - -TEST_F(IsCLibraryFunctionTest, RejectsClassMember) { - ASSERT_TRUE(buildAST(R"cpp(class A { void fun(); };)cpp")); - EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); -} diff --git a/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn index 9c240cff1816..01c2b6ced336 100644 --- a/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn @@ -19,7 +19,6 @@ unittest("StaticAnalysisTests") { "CallEventTest.cpp", "ConflictingEvalCallsTest.cpp", "FalsePositiveRefutationBRVisitorTest.cpp", - "IsCLibraryFunctionTest.cpp", "NoStateChangeFuncVisitorTest.cpp", "ParamRegionTest.cpp", "RangeSetTest.cpp", -- GitLab From cd20600767409b183a6d213d56f85f8041a21487 Mon Sep 17 00:00:00 2001 From: Aleksandr Popov <42888396+aleks-tmb@users.noreply.github.com> Date: Wed, 13 Mar 2024 18:30:03 +0100 Subject: [PATCH 411/953] [LoopConstrainer] Apply loop gurads to check that loop bounds are safe (#71531) Loop guards that apply to loop SCEV bounds allow IRCE for cases with compound loop bounds such as: if (K > 0 && M > 0) for (i = 0; i < min(K, M); i++) {...} if (K > 0 && M > 0) for (i = min(K, M); i >= 0; i--) {...} Otherwise SCEV couldn't prove that loops have safe bounds in these cases. Co-authored-by: Aleksander Popov --- llvm/lib/Transforms/Utils/LoopConstrainer.cpp | 22 +++-- .../Transforms/IRCE/compound-loop-bound.ll | 85 +++++++++++++++++-- 2 files changed, 90 insertions(+), 17 deletions(-) diff --git a/llvm/lib/Transforms/Utils/LoopConstrainer.cpp b/llvm/lib/Transforms/Utils/LoopConstrainer.cpp index 81545ef37521..d9832eeb0697 100644 --- a/llvm/lib/Transforms/Utils/LoopConstrainer.cpp +++ b/llvm/lib/Transforms/Utils/LoopConstrainer.cpp @@ -42,8 +42,11 @@ static bool isSafeDecreasingBound(const SCEV *Start, const SCEV *BoundSCEV, ICmpInst::Predicate BoundPred = IsSigned ? CmpInst::ICMP_SGT : CmpInst::ICMP_UGT; + auto StartLG = SE.applyLoopGuards(Start, L); + auto BoundLG = SE.applyLoopGuards(BoundSCEV, L); + if (LatchBrExitIdx == 1) - return SE.isLoopEntryGuardedByCond(L, BoundPred, Start, BoundSCEV); + return SE.isLoopEntryGuardedByCond(L, BoundPred, StartLG, BoundLG); assert(LatchBrExitIdx == 0 && "LatchBrExitIdx should be either 0 or 1"); @@ -54,10 +57,10 @@ static bool isSafeDecreasingBound(const SCEV *Start, const SCEV *BoundSCEV, const SCEV *Limit = SE.getMinusSCEV(SE.getConstant(Min), StepPlusOne); const SCEV *MinusOne = - SE.getMinusSCEV(BoundSCEV, SE.getOne(BoundSCEV->getType())); + SE.getMinusSCEV(BoundLG, SE.getOne(BoundLG->getType())); - return SE.isLoopEntryGuardedByCond(L, BoundPred, Start, MinusOne) && - SE.isLoopEntryGuardedByCond(L, BoundPred, BoundSCEV, Limit); + return SE.isLoopEntryGuardedByCond(L, BoundPred, StartLG, MinusOne) && + SE.isLoopEntryGuardedByCond(L, BoundPred, BoundLG, Limit); } /// Given a loop with an increasing induction variable, is it possible to @@ -86,8 +89,11 @@ static bool isSafeIncreasingBound(const SCEV *Start, const SCEV *BoundSCEV, ICmpInst::Predicate BoundPred = IsSigned ? CmpInst::ICMP_SLT : CmpInst::ICMP_ULT; + auto StartLG = SE.applyLoopGuards(Start, L); + auto BoundLG = SE.applyLoopGuards(BoundSCEV, L); + if (LatchBrExitIdx == 1) - return SE.isLoopEntryGuardedByCond(L, BoundPred, Start, BoundSCEV); + return SE.isLoopEntryGuardedByCond(L, BoundPred, StartLG, BoundLG); assert(LatchBrExitIdx == 0 && "LatchBrExitIdx should be 0 or 1"); @@ -97,9 +103,9 @@ static bool isSafeIncreasingBound(const SCEV *Start, const SCEV *BoundSCEV, : APInt::getMaxValue(BitWidth); const SCEV *Limit = SE.getMinusSCEV(SE.getConstant(Max), StepMinusOne); - return (SE.isLoopEntryGuardedByCond(L, BoundPred, Start, - SE.getAddExpr(BoundSCEV, Step)) && - SE.isLoopEntryGuardedByCond(L, BoundPred, BoundSCEV, Limit)); + return (SE.isLoopEntryGuardedByCond(L, BoundPred, StartLG, + SE.getAddExpr(BoundLG, Step)) && + SE.isLoopEntryGuardedByCond(L, BoundPred, BoundLG, Limit)); } /// Returns estimate for max latch taken count of the loop of the narrowest diff --git a/llvm/test/Transforms/IRCE/compound-loop-bound.ll b/llvm/test/Transforms/IRCE/compound-loop-bound.ll index 0930d19e2215..e50d8c6127f4 100644 --- a/llvm/test/Transforms/IRCE/compound-loop-bound.ll +++ b/llvm/test/Transforms/IRCE/compound-loop-bound.ll @@ -16,23 +16,56 @@ define void @incrementing_loop(ptr %arr, ptr %len_ptr, i32 %K, i32 %M) { ; CHECK-NEXT: br i1 [[AND]], label [[PREHEADER:%.*]], label [[EXIT:%.*]] ; CHECK: preheader: ; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[K]], i32 [[M]]) +; CHECK-NEXT: [[SMIN1:%.*]] = call i32 @llvm.smin.i32(i32 [[LEN]], i32 [[M]]) +; CHECK-NEXT: [[SMIN2:%.*]] = call i32 @llvm.smin.i32(i32 [[SMIN1]], i32 [[K]]) +; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN2]], i32 0) +; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] +; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] +; CHECK: loop.preheader: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ] -; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1 +; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], 1 ; CHECK-NEXT: [[GUARD:%.*]] = icmp slt i32 [[IDX]], [[LEN]] -; CHECK-NEXT: br i1 [[GUARD]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]] +; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT3:%.*]] ; CHECK: in.bounds: ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]] ; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4 ; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[SMIN]] -; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] +; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] +; CHECK: main.exit.selector: +; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], [[SMIN]] +; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] +; CHECK: main.pseudo.exit: +; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] +; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] +; CHECK-NEXT: br label [[POSTLOOP:%.*]] +; CHECK: out.of.bounds.loopexit: +; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] +; CHECK: out.of.bounds.loopexit3: +; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] ; CHECK: out.of.bounds: ; CHECK-NEXT: ret void +; CHECK: exit.loopexit.loopexit: +; CHECK-NEXT: br label [[EXIT_LOOPEXIT]] ; CHECK: exit.loopexit: ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret void +; CHECK: postloop: +; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]] +; CHECK: loop.postloop: +; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ] +; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1 +; CHECK-NEXT: [[GUARD_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[LEN]] +; CHECK-NEXT: br i1 [[GUARD_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] +; CHECK: in.bounds.postloop: +; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]] +; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4 +; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], [[SMIN]] +; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP1:![0-9]+]], !loop_constrainer.loop.clone !6 ; entry: %len = load i32, ptr %len_ptr, !range !0 @@ -78,24 +111,58 @@ define void @decrementing_loop(ptr %arr, ptr %len_ptr, i32 %K, i32 %M) { ; CHECK-NEXT: [[AND:%.*]] = and i1 [[CHECK0]], [[CHECK1]] ; CHECK-NEXT: br i1 [[AND]], label [[PREHEADER:%.*]], label [[EXIT:%.*]] ; CHECK: preheader: -; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[K]], i32 [[M]]) +; CHECK-NEXT: [[INDVAR_START:%.*]] = call i32 @llvm.smin.i32(i32 [[K]], i32 [[M]]) +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDVAR_START]], 1 +; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[LEN]], i32 [[TMP0]]) +; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 0) +; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[SMAX]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[INDVAR_START]], [[EXIT_PRELOOP_AT]] +; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]] +; CHECK: loop.preloop.preheader: +; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]] +; CHECK: mainloop: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[SMIN]], [[PREHEADER]] ], [ [[IDX_DEC:%.*]], [[IN_BOUNDS:%.*]] ] -; CHECK-NEXT: [[IDX_DEC]] = sub i32 [[IDX]], 1 +; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_DEC:%.*]], [[IN_BOUNDS:%.*]] ] +; CHECK-NEXT: [[IDX_DEC]] = sub nsw i32 [[IDX]], 1 ; CHECK-NEXT: [[GUARD:%.*]] = icmp slt i32 [[IDX]], [[LEN]] -; CHECK-NEXT: br i1 [[GUARD]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]] +; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]] ; CHECK: in.bounds: ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]] ; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4 ; CHECK-NEXT: [[NEXT:%.*]] = icmp sgt i32 [[IDX_DEC]], -1 -; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] +; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] +; CHECK: out.of.bounds.loopexit: +; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] +; CHECK: out.of.bounds.loopexit1: +; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] ; CHECK: out.of.bounds: ; CHECK-NEXT: ret void +; CHECK: exit.loopexit.loopexit: +; CHECK-NEXT: br label [[EXIT_LOOPEXIT:%.*]] ; CHECK: exit.loopexit: ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret void +; CHECK: loop.preloop: +; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_DEC_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ [[INDVAR_START]], [[LOOP_PRELOOP_PREHEADER]] ] +; CHECK-NEXT: [[IDX_DEC_PRELOOP]] = sub i32 [[IDX_PRELOOP]], 1 +; CHECK-NEXT: [[GUARD_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]] +; CHECK-NEXT: br i1 [[GUARD_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] +; CHECK: in.bounds.preloop: +; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]] +; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4 +; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp sgt i32 [[IDX_DEC_PRELOOP]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[IDX_DEC_PRELOOP]], [[EXIT_PRELOOP_AT]] +; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP7:![0-9]+]], !loop_constrainer.loop.clone !6 +; CHECK: preloop.exit.selector: +; CHECK-NEXT: [[IDX_DEC_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_DEC_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ] +; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[IDX_DEC_PRELOOP_LCSSA]], -1 +; CHECK-NEXT: br i1 [[TMP3]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT]] +; CHECK: preloop.pseudo.exit: +; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ [[INDVAR_START]], [[PREHEADER]] ], [ [[IDX_DEC_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ] +; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ [[INDVAR_START]], [[PREHEADER]] ], [ [[IDX_DEC_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ] +; CHECK-NEXT: br label [[MAINLOOP]] ; entry: %len = load i32, ptr %len_ptr, !range !0 -- GitLab From 175b533720956017bb18d1280362f6890ee15b05 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Wed, 13 Mar 2024 10:44:12 -0700 Subject: [PATCH 412/953] workflows: Add workaround for lld failures on MacOS (#85021) See #81967 --- .github/workflows/llvm-project-tests.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/llvm-project-tests.yml b/.github/workflows/llvm-project-tests.yml index 43b90193406f..a52dd2db8035 100644 --- a/.github/workflows/llvm-project-tests.yml +++ b/.github/workflows/llvm-project-tests.yml @@ -118,6 +118,11 @@ jobs: else builddir="$(pwd)"/build fi + if [ "${{ runner.os }}" == "macOS" ]; then + # Workaround test failure on some lld tests on MacOS + # https://github.com/llvm/llvm-project/issues/81967 + extra_cmake_args="-DLLVM_DISABLE_ASSEMBLY_FILES=ON" + fi echo "llvm-builddir=$builddir" >> "$GITHUB_OUTPUT" cmake -G Ninja \ -B "$builddir" \ -- GitLab From bd77a26e9a15981114e9802d83047f42631125a2 Mon Sep 17 00:00:00 2001 From: Sirraide Date: Wed, 13 Mar 2024 18:49:44 +0100 Subject: [PATCH 413/953] [Clang][Sema] Properly get captured 'this' pointer in lambdas with an explicit object parameter in constant evaluator (#81102) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There were some bugs wrt explicit object parameters in lambdas in the constant evaluator: - The code evaluating a `CXXThisExpr` wasn’t checking for explicit object parameters at all and thus assumed that there was no `this` in the current context because the lambda didn’t have one, even though we were in a member function and had captured its `this`. - The code retrieving captures as lvalues *did* account for explicit object parameters, but it did not handle the case of the explicit object parameter being passed by value rather than by reference. This fixes #80997. --------- Co-authored-by: cor3ntin Co-authored-by: Aaron Ballman --- clang/docs/ReleaseNotes.rst | 3 + clang/lib/AST/ExprConstant.cpp | 129 ++++++++++-------- .../constexpr-explicit-object-lambda.cpp | 34 +++++ 3 files changed, 111 insertions(+), 55 deletions(-) create mode 100644 clang/test/SemaCXX/constexpr-explicit-object-lambda.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c5488e8742f6..5fe3fd066df2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -373,6 +373,9 @@ Bug Fixes to C++ Support and (`#74494 `_) - Allow access to a public template alias declaration that refers to friend's private nested type. (#GH25708). +- Fixed a crash in constant evaluation when trying to access a + captured ``this`` pointer in a lambda with an explicit object parameter. + Fixes (#GH80997) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 726415cfbde0..b154a196e11c 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8517,6 +8517,53 @@ public: }; } // end anonymous namespace +/// Get an lvalue to a field of a lambda's closure type. +static bool HandleLambdaCapture(EvalInfo &Info, const Expr *E, LValue &Result, + const CXXMethodDecl *MD, const FieldDecl *FD, + bool LValueToRValueConversion) { + // Static lambda function call operators can't have captures. We already + // diagnosed this, so bail out here. + if (MD->isStatic()) { + assert(Info.CurrentCall->This == nullptr && + "This should not be set for a static call operator"); + return false; + } + + // Start with 'Result' referring to the complete closure object... + if (MD->isExplicitObjectMemberFunction()) { + // Self may be passed by reference or by value. + const ParmVarDecl *Self = MD->getParamDecl(0); + if (Self->getType()->isReferenceType()) { + APValue *RefValue = Info.getParamSlot(Info.CurrentCall->Arguments, Self); + Result.setFrom(Info.Ctx, *RefValue); + } else { + const ParmVarDecl *VD = Info.CurrentCall->Arguments.getOrigParam(Self); + CallStackFrame *Frame = + Info.getCallFrameAndDepth(Info.CurrentCall->Arguments.CallIndex) + .first; + unsigned Version = Info.CurrentCall->Arguments.Version; + Result.set({VD, Frame->Index, Version}); + } + } else + Result = *Info.CurrentCall->This; + + // ... then update it to refer to the field of the closure object + // that represents the capture. + if (!HandleLValueMember(Info, E, Result, FD)) + return false; + + // And if the field is of reference type (or if we captured '*this' by + // reference), update 'Result' to refer to what + // the field refers to. + if (LValueToRValueConversion) { + APValue RVal; + if (!handleLValueToRValueConversion(Info, E, FD->getType(), Result, RVal)) + return false; + Result.setFrom(Info.Ctx, RVal); + } + return true; +} + /// Evaluate an expression as an lvalue. This can be legitimately called on /// expressions which are not glvalues, in three cases: /// * function designators in C, and @@ -8561,37 +8608,8 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) { const auto *MD = cast(Info.CurrentCall->Callee); - - // Static lambda function call operators can't have captures. We already - // diagnosed this, so bail out here. - if (MD->isStatic()) { - assert(Info.CurrentCall->This == nullptr && - "This should not be set for a static call operator"); - return false; - } - - // Start with 'Result' referring to the complete closure object... - if (MD->isExplicitObjectMemberFunction()) { - APValue *RefValue = - Info.getParamSlot(Info.CurrentCall->Arguments, MD->getParamDecl(0)); - Result.setFrom(Info.Ctx, *RefValue); - } else - Result = *Info.CurrentCall->This; - - // ... then update it to refer to the field of the closure object - // that represents the capture. - if (!HandleLValueMember(Info, E, Result, FD)) - return false; - // And if the field is of reference type, update 'Result' to refer to what - // the field refers to. - if (FD->getType()->isReferenceType()) { - APValue RVal; - if (!handleLValueToRValueConversion(Info, E, FD->getType(), Result, - RVal)) - return false; - Result.setFrom(Info.Ctx, RVal); - } - return true; + return HandleLambdaCapture(Info, E, Result, MD, FD, + FD->getType()->isReferenceType()); } } @@ -9069,45 +9087,46 @@ public: return Error(E); } bool VisitCXXThisExpr(const CXXThisExpr *E) { - // Can't look at 'this' when checking a potential constant expression. - if (Info.checkingPotentialConstantExpression()) - return false; - if (!Info.CurrentCall->This) { + auto DiagnoseInvalidUseOfThis = [&] { if (Info.getLangOpts().CPlusPlus11) Info.FFDiag(E, diag::note_constexpr_this) << E->isImplicit(); else Info.FFDiag(E); + }; + + // Can't look at 'this' when checking a potential constant expression. + if (Info.checkingPotentialConstantExpression()) return false; + + bool IsExplicitLambda = + isLambdaCallWithExplicitObjectParameter(Info.CurrentCall->Callee); + if (!IsExplicitLambda) { + if (!Info.CurrentCall->This) { + DiagnoseInvalidUseOfThis(); + return false; + } + + Result = *Info.CurrentCall->This; } - Result = *Info.CurrentCall->This; if (isLambdaCallOperator(Info.CurrentCall->Callee)) { // Ensure we actually have captured 'this'. If something was wrong with // 'this' capture, the error would have been previously reported. // Otherwise we can be inside of a default initialization of an object // declared by lambda's body, so no need to return false. - if (!Info.CurrentCall->LambdaThisCaptureField) - return true; - - // If we have captured 'this', the 'this' expression refers - // to the enclosing '*this' object (either by value or reference) which is - // either copied into the closure object's field that represents the - // '*this' or refers to '*this'. - // Update 'Result' to refer to the data member/field of the closure object - // that represents the '*this' capture. - if (!HandleLValueMember(Info, E, Result, - Info.CurrentCall->LambdaThisCaptureField)) - return false; - // If we captured '*this' by reference, replace the field with its referent. - if (Info.CurrentCall->LambdaThisCaptureField->getType() - ->isPointerType()) { - APValue RVal; - if (!handleLValueToRValueConversion(Info, E, E->getType(), Result, - RVal)) + if (!Info.CurrentCall->LambdaThisCaptureField) { + if (IsExplicitLambda && !Info.CurrentCall->This) { + DiagnoseInvalidUseOfThis(); return false; + } - Result.setFrom(Info.Ctx, RVal); + return true; } + + const auto *MD = cast(Info.CurrentCall->Callee); + return HandleLambdaCapture( + Info, E, Result, MD, Info.CurrentCall->LambdaThisCaptureField, + Info.CurrentCall->LambdaThisCaptureField->getType()->isPointerType()); } return true; } diff --git a/clang/test/SemaCXX/constexpr-explicit-object-lambda.cpp b/clang/test/SemaCXX/constexpr-explicit-object-lambda.cpp new file mode 100644 index 000000000000..4e8e94d428d0 --- /dev/null +++ b/clang/test/SemaCXX/constexpr-explicit-object-lambda.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++23 -verify %s +// expected-no-diagnostics + +struct S { + int i = 42; + constexpr auto f1() { + return [this](this auto) { + return this->i; + }(); + }; + + constexpr auto f2() { + return [this](this auto&&) { + return this->i; + }(); + }; + + constexpr auto f3() { + return [i = this->i](this auto) { + return i; + }(); + }; + + constexpr auto f4() { + return [i = this->i](this auto&&) { + return i; + }(); + }; +}; + +static_assert(S().f1() == 42); +static_assert(S().f2() == 42); +static_assert(S().f3() == 42); +static_assert(S().f4() == 42); -- GitLab From ab9564c315c5111f73788aec9715b488db68d895 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 13 Mar 2024 10:51:48 -0700 Subject: [PATCH 414/953] [RISCV] Add SMLoc to expanded vector pseudoinstructions in AsmParser. (#84875) This is needed for llvm-mca to correctly apply vsetvli instruments to these instructions. Fixes #84799. --- llvm/include/llvm/MC/MCInstBuilder.h | 6 ++ .../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 39 +++++++---- .../RISCV/SiFive7/vector-integer-arithmetic.s | 70 +++++++++++++++++-- 3 files changed, 97 insertions(+), 18 deletions(-) diff --git a/llvm/include/llvm/MC/MCInstBuilder.h b/llvm/include/llvm/MC/MCInstBuilder.h index 6e5e9dd69018..d06ed4c6c840 100644 --- a/llvm/include/llvm/MC/MCInstBuilder.h +++ b/llvm/include/llvm/MC/MCInstBuilder.h @@ -27,6 +27,12 @@ public: Inst.setOpcode(Opcode); } + /// Set the location. + MCInstBuilder &setLoc(SMLoc SM) { + Inst.setLoc(SM); + return *this; + } + /// Add a new register operand. MCInstBuilder &addReg(unsigned Reg) { Inst.addOperand(MCOperand::createReg(Reg)); diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index d83979a873f2..caff0e8fcefe 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -3271,11 +3271,13 @@ void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(1)) .addOperand(Inst.getOperand(2)) - .addReg(RISCV::NoRegister)); + .addReg(RISCV::NoRegister) + .setLoc(IDLoc)); emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM) .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(0)) - .addOperand(Inst.getOperand(0))); + .addOperand(Inst.getOperand(0)) + .setLoc(IDLoc)); } else if (Inst.getNumOperands() == 4) { // masked va >= x, vd != v0 // @@ -3287,11 +3289,13 @@ void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(1)) .addOperand(Inst.getOperand(2)) - .addOperand(Inst.getOperand(3))); + .addOperand(Inst.getOperand(3)) + .setLoc(IDLoc)); emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM) .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(0)) - .addReg(RISCV::V0)); + .addReg(RISCV::V0) + .setLoc(IDLoc)); } else if (Inst.getNumOperands() == 5 && Inst.getOperand(0).getReg() == RISCV::V0) { // masked va >= x, vd == v0 @@ -3306,11 +3310,13 @@ void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, .addOperand(Inst.getOperand(1)) .addOperand(Inst.getOperand(2)) .addOperand(Inst.getOperand(3)) - .addReg(RISCV::NoRegister)); + .addReg(RISCV::NoRegister) + .setLoc(IDLoc)); emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM) .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(0)) - .addOperand(Inst.getOperand(1))); + .addOperand(Inst.getOperand(1)) + .setLoc(IDLoc)); } else if (Inst.getNumOperands() == 5) { // masked va >= x, any vd // @@ -3323,19 +3329,23 @@ void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, .addOperand(Inst.getOperand(1)) .addOperand(Inst.getOperand(2)) .addOperand(Inst.getOperand(3)) - .addReg(RISCV::NoRegister)); + .addReg(RISCV::NoRegister) + .setLoc(IDLoc)); emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM) .addOperand(Inst.getOperand(1)) .addReg(RISCV::V0) - .addOperand(Inst.getOperand(1))); + .addOperand(Inst.getOperand(1)) + .setLoc(IDLoc)); emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM) .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(0)) - .addReg(RISCV::V0)); + .addReg(RISCV::V0) + .setLoc(IDLoc)); emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM) .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(1)) - .addOperand(Inst.getOperand(0))); + .addOperand(Inst.getOperand(0)) + .setLoc(IDLoc)); } } @@ -3637,7 +3647,8 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(1)) .addImm(Imm - 1) - .addOperand(Inst.getOperand(3))); + .addOperand(Inst.getOperand(3)) + .setLoc(IDLoc)); return false; } case RISCV::PseudoVMSGEU_VI: @@ -3655,7 +3666,8 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(1)) .addOperand(Inst.getOperand(1)) - .addOperand(Inst.getOperand(3))); + .addOperand(Inst.getOperand(3)) + .setLoc(IDLoc)); } else { // Other immediate values can subtract one like signed. unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI @@ -3665,7 +3677,8 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(1)) .addImm(Imm - 1) - .addOperand(Inst.getOperand(3))); + .addOperand(Inst.getOperand(3)) + .setLoc(IDLoc)); } return false; diff --git a/llvm/test/tools/llvm-mca/RISCV/SiFive7/vector-integer-arithmetic.s b/llvm/test/tools/llvm-mca/RISCV/SiFive7/vector-integer-arithmetic.s index 21459bc45d45..3b6fd7e15013 100644 --- a/llvm/test/tools/llvm-mca/RISCV/SiFive7/vector-integer-arithmetic.s +++ b/llvm/test/tools/llvm-mca/RISCV/SiFive7/vector-integer-arithmetic.s @@ -399,6 +399,26 @@ vmseq.vv v4, v8, v12 vsetvli zero, zero, e64, m8, tu, mu vmseq.vx v4, v8, x10 +# Pseudo instructions +vsetvli zero, zero, e8, mf8, tu, mu +vmslt.vi v4, v8, 1 +vsetvli zero, zero, e8, mf4, tu, mu +vmsltu.vi v4, v8, 1 +vsetvli zero, zero, e8, mf2, tu, mu +vmsltu.vi v4, v8, 0 +vsetvli zero, zero, e8, m1, tu, mu +vmsgeu.vi v4, v8, 1 +vsetvli zero, zero, e8, m2, tu, mu +vmsge.vi v4, v8, 1 +vsetvli zero, zero, e8, m4, tu, mu +vmsgeu.vi v4, v8, 0 +vsetvli zero, zero, e16, mf4, tu, mu +vmsge.vi v4, v8, 0 +vsetvli zero, zero, e16, mf2, tu, mu +vmsge.vx v4, v8, x10 +vsetvli zero, zero, e16, m1, tu, mu +vmsgeu.vx v4, v8, x11 + # Vector Integer Min/Max Instructions vsetvli zero, zero, e8, mf8, tu, mu vminu.vv v4, v8, v12 @@ -754,14 +774,14 @@ vsetvli zero, zero, e64, m8, tu, mu vmv.v.v v4, v12 # CHECK: Iterations: 1 -# CHECK-NEXT: Instructions: 707 -# CHECK-NEXT: Total Cycles: 11962 -# CHECK-NEXT: Total uOps: 707 +# CHECK-NEXT: Instructions: 727 +# CHECK-NEXT: Total Cycles: 12018 +# CHECK-NEXT: Total uOps: 727 # CHECK: Dispatch Width: 2 # CHECK-NEXT: uOps Per Cycle: 0.06 # CHECK-NEXT: IPC: 0.06 -# CHECK-NEXT: Block RThroughput: 11549.0 +# CHECK-NEXT: Block RThroughput: 11583.0 # CHECK: Instruction Info: # CHECK-NEXT: [1]: #uOps @@ -1144,6 +1164,26 @@ vmv.v.v v4, v12 # CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e64, m8, tu, mu # CHECK-NEXT: 1 19 17.00 vmseq.vx v4, v8, a0 # CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, mf8, tu, mu +# CHECK-NEXT: 1 4 2.00 vmsle.vi v4, v8, 0 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, mf4, tu, mu +# CHECK-NEXT: 1 4 2.00 vmsleu.vi v4, v8, 0 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, mf2, tu, mu +# CHECK-NEXT: 1 4 2.00 vmsne.vv v4, v8, v8 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, m1, tu, mu +# CHECK-NEXT: 1 5 3.00 vmsgtu.vi v4, v8, 0 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, m2, tu, mu +# CHECK-NEXT: 1 7 5.00 vmsgt.vi v4, v8, 0 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, m4, tu, mu +# CHECK-NEXT: 1 11 9.00 vmseq.vv v4, v8, v8 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e16, mf4, tu, mu +# CHECK-NEXT: 1 4 2.00 vmsgt.vi v4, v8, -1 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e16, mf2, tu, mu +# CHECK-NEXT: 1 4 2.00 vmslt.vx v4, v8, a0 +# CHECK-NEXT: 1 4 2.00 vmnot.m v4, v4 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e16, m1, tu, mu +# CHECK-NEXT: 1 5 3.00 vmsltu.vx v4, v8, a1 +# CHECK-NEXT: 1 4 2.00 vmnot.m v4, v4 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, mf8, tu, mu # CHECK-NEXT: 1 4 2.00 vminu.vv v4, v8, v12 # CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, mf4, tu, mu # CHECK-NEXT: 1 4 2.00 vminu.vx v4, v8, a0 @@ -1492,7 +1532,7 @@ vmv.v.v v4, v12 # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] -# CHECK-NEXT: - - 333.00 - 11549.00 374.00 - - +# CHECK-NEXT: - - 342.00 - 11583.00 385.00 - - # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] Instructions: @@ -1868,6 +1908,26 @@ vmv.v.v v4, v12 # CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e64, m8, tu, mu # CHECK-NEXT: - - - - 17.00 1.00 - - vmseq.vx v4, v8, a0 # CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, mf8, tu, mu +# CHECK-NEXT: - - - - 2.00 1.00 - - vmsle.vi v4, v8, 0 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, mf4, tu, mu +# CHECK-NEXT: - - - - 2.00 1.00 - - vmsleu.vi v4, v8, 0 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, mf2, tu, mu +# CHECK-NEXT: - - - - 2.00 1.00 - - vmsne.vv v4, v8, v8 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, m1, tu, mu +# CHECK-NEXT: - - - - 3.00 1.00 - - vmsgtu.vi v4, v8, 0 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, m2, tu, mu +# CHECK-NEXT: - - - - 5.00 1.00 - - vmsgt.vi v4, v8, 0 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, m4, tu, mu +# CHECK-NEXT: - - - - 9.00 1.00 - - vmseq.vv v4, v8, v8 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e16, mf4, tu, mu +# CHECK-NEXT: - - - - 2.00 1.00 - - vmsgt.vi v4, v8, -1 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e16, mf2, tu, mu +# CHECK-NEXT: - - - - 2.00 1.00 - - vmslt.vx v4, v8, a0 +# CHECK-NEXT: - - - - 2.00 1.00 - - vmnot.m v4, v4 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e16, m1, tu, mu +# CHECK-NEXT: - - - - 3.00 1.00 - - vmsltu.vx v4, v8, a1 +# CHECK-NEXT: - - - - 2.00 1.00 - - vmnot.m v4, v4 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, mf8, tu, mu # CHECK-NEXT: - - - - 2.00 1.00 - - vminu.vv v4, v8, v12 # CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, mf4, tu, mu # CHECK-NEXT: - - - - 2.00 1.00 - - vminu.vx v4, v8, a0 -- GitLab From 0bb30f9896d9cdd92514e0a2bfdc03811831f21c Mon Sep 17 00:00:00 2001 From: Florian Mayer Date: Wed, 13 Mar 2024 10:56:26 -0700 Subject: [PATCH 415/953] [NFC] [hwasan] factor out some opt handling (#84414) --- .../Instrumentation/HWAddressSanitizer.cpp | 47 +++++++------------ 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index 11a5c29c35f7..87584dace32d 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -260,6 +260,10 @@ static cl::opt ClUsePageAliases("hwasan-experimental-use-page-aliases", namespace { +template T optOr(cl::opt &Opt, T Other) { + return Opt.getNumOccurrences() ? Opt : Other; +} + bool shouldUsePageAliases(const Triple &TargetTriple) { return ClUsePageAliases && TargetTriple.getArch() == Triple::x86_64; } @@ -269,14 +273,11 @@ bool shouldInstrumentStack(const Triple &TargetTriple) { } bool shouldInstrumentWithCalls(const Triple &TargetTriple) { - return ClInstrumentWithCalls.getNumOccurrences() - ? ClInstrumentWithCalls - : TargetTriple.getArch() == Triple::x86_64; + return optOr(ClInstrumentWithCalls, TargetTriple.getArch() == Triple::x86_64); } bool mightUseStackSafetyAnalysis(bool DisableOptimization) { - return ClUseStackSafety.getNumOccurrences() ? ClUseStackSafety - : !DisableOptimization; + return optOr(ClUseStackSafety, !DisableOptimization); } bool shouldUseStackSafetyAnalysis(const Triple &TargetTriple, @@ -296,10 +297,8 @@ public: HWAddressSanitizer(Module &M, bool CompileKernel, bool Recover, const StackSafetyGlobalInfo *SSI) : M(M), SSI(SSI) { - this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover; - this->CompileKernel = ClEnableKhwasan.getNumOccurrences() > 0 - ? ClEnableKhwasan - : CompileKernel; + this->Recover = optOr(ClRecover, Recover); + this->CompileKernel = optOr(ClEnableKhwasan, CompileKernel); this->Rng = ClRandomSkipRate.getNumOccurrences() ? M.createRNG("hwasan") : nullptr; @@ -625,19 +624,14 @@ void HWAddressSanitizer::initializeModule() { bool NewRuntime = !TargetTriple.isAndroid() || !TargetTriple.isAndroidVersionLT(30); - UseShortGranules = - ClUseShortGranules.getNumOccurrences() ? ClUseShortGranules : NewRuntime; - OutlinedChecks = - (TargetTriple.isAArch64() || TargetTriple.isRISCV64()) && - TargetTriple.isOSBinFormatELF() && - (ClInlineAllChecks.getNumOccurrences() ? !ClInlineAllChecks : !Recover); + UseShortGranules = optOr(ClUseShortGranules, NewRuntime); + OutlinedChecks = (TargetTriple.isAArch64() || TargetTriple.isRISCV64()) && + TargetTriple.isOSBinFormatELF() && + !optOr(ClInlineAllChecks, Recover); - InlineFastPath = - (ClInlineFastPathChecks.getNumOccurrences() - ? ClInlineFastPathChecks - : !(TargetTriple.isAndroid() || - TargetTriple.isOSFuchsia())); // These platforms may prefer less - // inlining to reduce binary size. + // These platforms may prefer less inlining to reduce binary size. + InlineFastPath = optOr(ClInlineFastPathChecks, !(TargetTriple.isAndroid() || + TargetTriple.isOSFuchsia())); if (ClMatchAllTag.getNumOccurrences()) { if (ClMatchAllTag != -1) { @@ -649,22 +643,17 @@ void HWAddressSanitizer::initializeModule() { UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value(); // If we don't have personality function support, fall back to landing pads. - InstrumentLandingPads = ClInstrumentLandingPads.getNumOccurrences() - ? ClInstrumentLandingPads - : !NewRuntime; + InstrumentLandingPads = optOr(ClInstrumentLandingPads, !NewRuntime); if (!CompileKernel) { createHwasanCtorComdat(); - bool InstrumentGlobals = - ClGlobals.getNumOccurrences() ? ClGlobals : NewRuntime; + bool InstrumentGlobals = optOr(ClGlobals, NewRuntime); if (InstrumentGlobals && !UsePageAliases) instrumentGlobals(); bool InstrumentPersonalityFunctions = - ClInstrumentPersonalityFunctions.getNumOccurrences() - ? ClInstrumentPersonalityFunctions - : NewRuntime; + optOr(ClInstrumentPersonalityFunctions, NewRuntime); if (InstrumentPersonalityFunctions) instrumentPersonalityFunctions(); } -- GitLab From c41966161fffea6ef280fbd341ef1751f70379dd Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 13 Mar 2024 18:56:46 +0100 Subject: [PATCH 416/953] [llvm-ar] Be explicit about archive format in coff-symtab.test tests. (#85112) Fixes test failures on AIX after #82898. --- llvm/test/tools/llvm-ar/coff-symtab.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/tools/llvm-ar/coff-symtab.test b/llvm/test/tools/llvm-ar/coff-symtab.test index 4f7270d9e2c6..4a574723a9be 100644 --- a/llvm/test/tools/llvm-ar/coff-symtab.test +++ b/llvm/test/tools/llvm-ar/coff-symtab.test @@ -16,7 +16,7 @@ RUN: llvm-nm --print-armap out3.a | FileCheck %s Create an empty archive with no symbol map, add a COFF file to it and check that the output archive is a COFF archive. -RUN: llvm-ar rcS out4.a +RUN: llvm-ar --format coff rcS out4.a RUN: llvm-ar rs out4.a coff-symtab.obj RUN: llvm-nm --print-armap out4.a | FileCheck %s -- GitLab From 3e6d56617f43f86d65dba04c94277dc4a40c2a86 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 13 Mar 2024 11:01:37 -0700 Subject: [PATCH 417/953] [SLP][NFC]Add a test with reused buildvector node, being resized after minbitwidth analysis. --- .../AArch64/gather-with-minbith-user.ll | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 llvm/test/Transforms/SLPVectorizer/AArch64/gather-with-minbith-user.ll diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/gather-with-minbith-user.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/gather-with-minbith-user.ll new file mode 100644 index 000000000000..9566c00dd630 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/gather-with-minbith-user.ll @@ -0,0 +1,89 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s + +define void @h() { +; CHECK-LABEL: define void @h() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr null, i64 16 +; CHECK-NEXT: [[TMP0:%.*]] = sub <8 x i32> zeroinitializer, zeroinitializer +; CHECK-NEXT: [[TMP1:%.*]] = add <8 x i32> zeroinitializer, zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i32> [[TMP0]], <8 x i32> [[TMP1]], <8 x i32> +; CHECK-NEXT: [[TMP3:%.*]] = or <8 x i32> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = trunc <8 x i32> [[TMP3]] to <8 x i16> +; CHECK-NEXT: store <8 x i16> [[TMP4]], ptr [[ARRAYIDX2]], align 2 +; CHECK-NEXT: ret void +; +entry: + %conv9 = zext i16 0 to i32 + %arrayidx2 = getelementptr i8, ptr null, i64 16 + %conv310 = zext i16 0 to i32 + %add4 = add i32 %conv310, %conv9 + %sub = sub i32 0, %conv310 + %conv15 = sext i16 0 to i32 + %shr = ashr i32 0, 0 + %arrayidx18 = getelementptr i8, ptr null, i64 24 + %conv19 = sext i16 0 to i32 + %sub20 = sub i32 %shr, %conv19 + %shr29 = ashr i32 0, 0 + %add30 = add i32 %shr29, %conv15 + %sub39 = or i32 %sub, %sub20 + %conv40 = trunc i32 %sub39 to i16 + store i16 %conv40, ptr %arrayidx2, align 2 + %sub44 = or i32 %add4, %add30 + %conv45 = trunc i32 %sub44 to i16 + store i16 %conv45, ptr %arrayidx18, align 2 + %arrayidx2.1 = getelementptr i8, ptr null, i64 18 + %conv3.112 = zext i16 0 to i32 + %add4.1 = add i32 %conv3.112, 0 + %sub.1 = sub i32 0, %conv3.112 + %conv15.1 = sext i16 0 to i32 + %shr.1 = ashr i32 0, 0 + %arrayidx18.1 = getelementptr i8, ptr null, i64 26 + %conv19.1 = sext i16 0 to i32 + %sub20.1 = sub i32 %shr.1, %conv19.1 + %shr29.1 = ashr i32 0, 0 + %add30.1 = add i32 %shr29.1, %conv15.1 + %sub39.1 = or i32 %sub.1, %sub20.1 + %conv40.1 = trunc i32 %sub39.1 to i16 + store i16 %conv40.1, ptr %arrayidx2.1, align 2 + %sub44.1 = or i32 %add4.1, %add30.1 + %conv45.1 = trunc i32 %sub44.1 to i16 + store i16 %conv45.1, ptr %arrayidx18.1, align 2 + %conv.213 = zext i16 0 to i32 + %arrayidx2.2 = getelementptr i8, ptr null, i64 20 + %conv3.214 = zext i16 0 to i32 + %add4.2 = add i32 0, %conv.213 + %sub.2 = sub i32 0, %conv3.214 + %conv15.2 = sext i16 0 to i32 + %shr.2 = ashr i32 0, 0 + %arrayidx18.2 = getelementptr i8, ptr null, i64 28 + %conv19.2 = sext i16 0 to i32 + %sub20.2 = sub i32 %shr.2, %conv19.2 + %shr29.2 = ashr i32 0, 0 + %add30.2 = add i32 %shr29.2, %conv15.2 + %sub39.2 = or i32 %sub.2, %sub20.2 + %conv40.2 = trunc i32 %sub39.2 to i16 + store i16 %conv40.2, ptr %arrayidx2.2, align 2 + %sub44.2 = or i32 %add4.2, %add30.2 + %conv45.2 = trunc i32 %sub44.2 to i16 + store i16 %conv45.2, ptr %arrayidx18.2, align 2 + %conv.315 = zext i16 0 to i32 + %arrayidx2.3 = getelementptr i8, ptr null, i64 22 + %conv3.316 = zext i16 0 to i32 + %add4.3 = add i32 0, %conv.315 + %sub.3 = sub i32 0, %conv3.316 + %conv15.3 = sext i16 0 to i32 + %shr.3 = ashr i32 0, 0 + %arrayidx18.3 = getelementptr i8, ptr null, i64 30 + %conv19.3 = sext i16 0 to i32 + %sub20.3 = sub i32 %shr.3, %conv19.3 + %shr29.3 = ashr i32 0, 0 + %add30.3 = add i32 %shr29.3, %conv15.3 + %sub39.3 = or i32 %sub.3, %sub20.3 + %conv40.3 = trunc i32 %sub39.3 to i16 + store i16 %conv40.3, ptr %arrayidx2.3, align 2 + %sub44.3 = or i32 %add4.3, %add30.3 + %conv45.3 = trunc i32 %sub44.3 to i16 + store i16 %conv45.3, ptr %arrayidx18.3, align 2 + ret void +} -- GitLab From f50d3582b4844b86ad86372028e44b52c560ec7d Mon Sep 17 00:00:00 2001 From: Ian Anderson Date: Wed, 13 Mar 2024 11:15:41 -0700 Subject: [PATCH 418/953] [clang][modules] giving the __stddef_ headers their own modules can cause redeclaration errors with -fbuiltin-headers-in-system-modules (#84127) On Apple platforms, some of the stddef.h types are also declared in system headers. In particular NULL has a conflicting declaration in . When that's in a different module from <__stddef_null.h>, redeclaration errors can occur. Make the \_\_stddef_ headers be non-modular in -fbuiltin-headers-in-system-modules and restore them back to not respecting their header guards. Still define the header guards though. __stddef_max_align_t.h was in _Builtin_stddef_max_align_t prior to the addition of _Builtin_stddef, and it needs to stay in a module because struct's can't be type merged. __stddef_wint_t.h didn't used to have a module, but leave it in it current module since it doesn't really belong to stddef.h. --- clang/lib/Basic/Module.cpp | 7 ++-- clang/lib/Headers/__stddef_null.h | 2 +- clang/lib/Headers/__stddef_nullptr_t.h | 7 +++- clang/lib/Headers/__stddef_offsetof.h | 7 +++- clang/lib/Headers/__stddef_ptrdiff_t.h | 7 +++- clang/lib/Headers/__stddef_rsize_t.h | 7 +++- clang/lib/Headers/__stddef_size_t.h | 7 +++- clang/lib/Headers/__stddef_unreachable.h | 7 +++- clang/lib/Headers/__stddef_wchar_t.h | 7 +++- clang/lib/Headers/module.modulemap | 20 ++++++------ clang/lib/Lex/ModuleMap.cpp | 9 ++++-- .../no-undeclared-includes-builtins.cpp | 2 +- clang/test/Modules/stddef.c | 32 +++++++++++-------- 13 files changed, 80 insertions(+), 41 deletions(-) diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index 9f597dcf8b0f..256365d66bb9 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -301,10 +301,9 @@ bool Module::directlyUses(const Module *Requested) { if (Requested->isSubModuleOf(Use)) return true; - // Anyone is allowed to use our builtin stdarg.h and stddef.h and their - // accompanying modules. - if (Requested->getTopLevelModuleName() == "_Builtin_stdarg" || - Requested->getTopLevelModuleName() == "_Builtin_stddef") + // Anyone is allowed to use our builtin stddef.h and its accompanying modules. + if (Requested->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}) || + Requested->fullModuleNameIs({"_Builtin_stddef_wint_t"})) return true; if (NoUndeclaredIncludes) diff --git a/clang/lib/Headers/__stddef_null.h b/clang/lib/Headers/__stddef_null.h index 7336fdab3897..c10bd2d7d988 100644 --- a/clang/lib/Headers/__stddef_null.h +++ b/clang/lib/Headers/__stddef_null.h @@ -7,7 +7,7 @@ *===-----------------------------------------------------------------------=== */ -#if !defined(NULL) || !__has_feature(modules) +#if !defined(NULL) || !__building_module(_Builtin_stddef) /* linux/stddef.h will define NULL to 0. glibc (and other) headers then define * __need_NULL and rely on stddef.h to redefine NULL to the correct value again. diff --git a/clang/lib/Headers/__stddef_nullptr_t.h b/clang/lib/Headers/__stddef_nullptr_t.h index 183d394d56c1..7f3fbe6fe0d3 100644 --- a/clang/lib/Headers/__stddef_nullptr_t.h +++ b/clang/lib/Headers/__stddef_nullptr_t.h @@ -7,7 +7,12 @@ *===-----------------------------------------------------------------------=== */ -#ifndef _NULLPTR_T +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(_NULLPTR_T) || \ + (__has_feature(modules) && !__building_module(_Builtin_stddef)) #define _NULLPTR_T #ifdef __cplusplus diff --git a/clang/lib/Headers/__stddef_offsetof.h b/clang/lib/Headers/__stddef_offsetof.h index 3b347b3b92f6..84172c6cd273 100644 --- a/clang/lib/Headers/__stddef_offsetof.h +++ b/clang/lib/Headers/__stddef_offsetof.h @@ -7,6 +7,11 @@ *===-----------------------------------------------------------------------=== */ -#ifndef offsetof +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(offsetof) || \ + (__has_feature(modules) && !__building_module(_Builtin_stddef)) #define offsetof(t, d) __builtin_offsetof(t, d) #endif diff --git a/clang/lib/Headers/__stddef_ptrdiff_t.h b/clang/lib/Headers/__stddef_ptrdiff_t.h index 3ea6d7d2852e..fd3c893c66c9 100644 --- a/clang/lib/Headers/__stddef_ptrdiff_t.h +++ b/clang/lib/Headers/__stddef_ptrdiff_t.h @@ -7,7 +7,12 @@ *===-----------------------------------------------------------------------=== */ -#ifndef _PTRDIFF_T +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(_PTRDIFF_T) || \ + (__has_feature(modules) && !__building_module(_Builtin_stddef)) #define _PTRDIFF_T typedef __PTRDIFF_TYPE__ ptrdiff_t; diff --git a/clang/lib/Headers/__stddef_rsize_t.h b/clang/lib/Headers/__stddef_rsize_t.h index b6428d0c12b6..dd433d40d973 100644 --- a/clang/lib/Headers/__stddef_rsize_t.h +++ b/clang/lib/Headers/__stddef_rsize_t.h @@ -7,7 +7,12 @@ *===-----------------------------------------------------------------------=== */ -#ifndef _RSIZE_T +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(_RSIZE_T) || \ + (__has_feature(modules) && !__building_module(_Builtin_stddef)) #define _RSIZE_T typedef __SIZE_TYPE__ rsize_t; diff --git a/clang/lib/Headers/__stddef_size_t.h b/clang/lib/Headers/__stddef_size_t.h index e4a389510bcd..3dd7b1f37929 100644 --- a/clang/lib/Headers/__stddef_size_t.h +++ b/clang/lib/Headers/__stddef_size_t.h @@ -7,7 +7,12 @@ *===-----------------------------------------------------------------------=== */ -#ifndef _SIZE_T +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(_SIZE_T) || \ + (__has_feature(modules) && !__building_module(_Builtin_stddef)) #define _SIZE_T typedef __SIZE_TYPE__ size_t; diff --git a/clang/lib/Headers/__stddef_unreachable.h b/clang/lib/Headers/__stddef_unreachable.h index 3e7fe0197966..518580c92d3f 100644 --- a/clang/lib/Headers/__stddef_unreachable.h +++ b/clang/lib/Headers/__stddef_unreachable.h @@ -7,6 +7,11 @@ *===-----------------------------------------------------------------------=== */ -#ifndef unreachable +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(unreachable) || \ + (__has_feature(modules) && !__building_module(_Builtin_stddef)) #define unreachable() __builtin_unreachable() #endif diff --git a/clang/lib/Headers/__stddef_wchar_t.h b/clang/lib/Headers/__stddef_wchar_t.h index 16a6186512c0..bd69f6322541 100644 --- a/clang/lib/Headers/__stddef_wchar_t.h +++ b/clang/lib/Headers/__stddef_wchar_t.h @@ -9,7 +9,12 @@ #if !defined(__cplusplus) || (defined(_MSC_VER) && !_NATIVE_WCHAR_T_DEFINED) -#ifndef _WCHAR_T +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(_WCHAR_T) || \ + (__has_feature(modules) && !__building_module(_Builtin_stddef)) #define _WCHAR_T #ifdef _MSC_EXTENSIONS diff --git a/clang/lib/Headers/module.modulemap b/clang/lib/Headers/module.modulemap index a786689d3917..56a13f69bc05 100644 --- a/clang/lib/Headers/module.modulemap +++ b/clang/lib/Headers/module.modulemap @@ -155,9 +155,9 @@ module _Builtin_intrinsics [system] [extern_c] { // Start -fbuiltin-headers-in-system-modules affected modules -// The following modules all ignore their top level headers -// when -fbuiltin-headers-in-system-modules is passed, and -// most of those headers join system modules when present. +// The following modules all ignore their headers when +// -fbuiltin-headers-in-system-modules is passed, and many of +// those headers join system modules when present. // e.g. if -fbuiltin-headers-in-system-modules is passed, then // float.h will not be in the _Builtin_float module (that module @@ -190,11 +190,6 @@ module _Builtin_stdalign [system] { export * } -// When -fbuiltin-headers-in-system-modules is passed, only -// the top level headers are removed, the implementation headers -// will always be in their submodules. That means when stdarg.h -// is included, it will still import this module and make the -// appropriate submodules visible. module _Builtin_stdarg [system] { textual header "stdarg.h" @@ -237,6 +232,8 @@ module _Builtin_stdbool [system] { module _Builtin_stddef [system] { textual header "stddef.h" + // __stddef_max_align_t.h is always in this module, even if + // -fbuiltin-headers-in-system-modules is passed. explicit module max_align_t { header "__stddef_max_align_t.h" export * @@ -283,9 +280,10 @@ module _Builtin_stddef [system] { } } -/* wint_t is provided by and not . It's here - * for compatibility, but must be explicitly requested. Therefore - * __stddef_wint_t.h is not part of _Builtin_stddef. */ +// wint_t is provided by and not . It's here +// for compatibility, but must be explicitly requested. Therefore +// __stddef_wint_t.h is not part of _Builtin_stddef. It is always in +// this module even if -fbuiltin-headers-in-system-modules is passed. module _Builtin_stddef_wint_t [system] { header "__stddef_wint_t.h" export * diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index afb2948f05ae..10c475f617d4 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -2498,9 +2498,12 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, } bool NeedsFramework = false; - // Don't add the top level headers to the builtin modules if the builtin headers - // belong to the system modules. - if (!Map.LangOpts.BuiltinHeadersInSystemModules || ActiveModule->isSubModule() || !isBuiltInModuleName(ActiveModule->Name)) + // Don't add headers to the builtin modules if the builtin headers belong to + // the system modules, with the exception of __stddef_max_align_t.h which + // always had its own module. + if (!Map.LangOpts.BuiltinHeadersInSystemModules || + !isBuiltInModuleName(ActiveModule->getTopLevelModuleName()) || + ActiveModule->fullModuleNameIs({"_Builtin_stddef", "max_align_t"})) Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework); if (NeedsFramework) diff --git a/clang/test/Modules/no-undeclared-includes-builtins.cpp b/clang/test/Modules/no-undeclared-includes-builtins.cpp index c9bffc556199..f9eefd24a33c 100644 --- a/clang/test/Modules/no-undeclared-includes-builtins.cpp +++ b/clang/test/Modules/no-undeclared-includes-builtins.cpp @@ -8,7 +8,7 @@ // headers. // RUN: rm -rf %t -// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/no-undeclared-includes-builtins/libcxx -I %S/Inputs/no-undeclared-includes-builtins/glibc %s +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fbuiltin-headers-in-system-modules -fimplicit-module-maps -I %S/Inputs/no-undeclared-includes-builtins/libcxx -I %S/Inputs/no-undeclared-includes-builtins/glibc %s // expected-no-diagnostics #include diff --git a/clang/test/Modules/stddef.c b/clang/test/Modules/stddef.c index 5bc0d1e44c85..762398261468 100644 --- a/clang/test/Modules/stddef.c +++ b/clang/test/Modules/stddef.c @@ -1,29 +1,33 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fbuiltin-headers-in-system-modules -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify -fno-modules-error-recovery +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fbuiltin-headers-in-system-modules -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify=builtin-headers-in-system-modules -fno-modules-error-recovery // RUN: rm -rf %t -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify -fno-modules-error-recovery +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify=no-builtin-headers-in-system-modules -fno-modules-error-recovery #include "ptrdiff_t.h" ptrdiff_t pdt; -// size_t is declared in both size_t.h and __stddef_size_t.h, both of which are -// modular headers. Regardless of whether stddef.h joins the StdDef test module -// or is in its _Builtin_stddef module, __stddef_size_t.h will be in -// _Builtin_stddef.size_t. It's not defined which module will win as the expected -// provider of size_t. For the purposes of this test it doesn't matter which header -// gets reported, just as long as it isn't other.h or include_again.h. -size_t st; // expected-error-re {{missing '#include "{{size_t|__stddef_size_t}}.h"'; 'size_t' must be declared before it is used}} -// expected-note@size_t.h:* 0+ {{here}} -// expected-note@__stddef_size_t.h:* 0+ {{here}} +// size_t is declared in both size_t.h and __stddef_size_t.h. If +// -fbuiltin-headers-in-system-modules is set, then __stddef_size_t.h is a +// non-modular header that will be transitively pulled in the StdDef test module +// by include_again.h. Otherwise it will be in the _Builtin_stddef module. In +// any case it's not defined which module will win as the expected provider of +// size_t. For the purposes of this test it doesn't matter which of the two +// providing headers get reported. +size_t st; // builtin-headers-in-system-modules-error-re {{missing '#include "{{size_t|include_again}}.h"'; 'size_t' must be declared before it is used}} \ + no-builtin-headers-in-system-modules-error-re {{missing '#include "{{size_t|__stddef_size_t}}.h"'; 'size_t' must be declared before it is used}} +// builtin-headers-in-system-modules-note@size_t.h:* 0+ {{here}} \ + no-builtin-headers-in-system-modules-note@size_t.h:* 0+ {{here}} +// builtin-headers-in-system-modules-note@__stddef_size_t.h:* 0+ {{here}} \ + no-builtin-headers-in-system-modules-note@__stddef_size_t.h:* 0+ {{here}} #include "include_again.h" -// Includes which includes <__stddef_size_t.h> which imports the -// _Builtin_stddef.size_t module. +// Includes which includes <__stddef_size_t.h>. size_t st2; #include "size_t.h" -// Redeclares size_t, but the type merger should figure it out. +// Redeclares size_t when -fbuiltin-headers-in-system-modules is not passed, but +// the type merger should figure it out. size_t st3; -- GitLab From 55b90b5140a2fe5f625a1dfe9dbb4ed4df968ce0 Mon Sep 17 00:00:00 2001 From: Alexander Richardson Date: Wed, 13 Mar 2024 11:28:44 -0700 Subject: [PATCH 419/953] [compiler-rt] Remove llvm_gtest dependency from unit tests All these unit tests already include ${COMPILER_RT_GTEST_SOURCE} as an input source file and the target llvm_gtest does not exist for standalone builds. Currently the DEPS argument is ignored for standalone builds so the missing target is not a problem, but as part of fixing a build race for standalone builds I am planning to include those dependencies in COMPILER_RT_TEST_STANDALONE_BUILD_LIBS configurations. Reviewed By: vitalybuka Pull Request: https://github.com/llvm/llvm-project/pull/83649 --- compiler-rt/lib/asan/tests/CMakeLists.txt | 2 +- compiler-rt/lib/fuzzer/tests/CMakeLists.txt | 4 ++-- compiler-rt/lib/gwp_asan/tests/CMakeLists.txt | 2 +- compiler-rt/lib/interception/tests/CMakeLists.txt | 1 - compiler-rt/lib/msan/tests/CMakeLists.txt | 2 +- compiler-rt/lib/orc/tests/CMakeLists.txt | 2 +- compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt | 1 - compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt | 2 +- compiler-rt/lib/tsan/tests/CMakeLists.txt | 2 +- compiler-rt/lib/xray/tests/CMakeLists.txt | 2 +- 10 files changed, 9 insertions(+), 11 deletions(-) diff --git a/compiler-rt/lib/asan/tests/CMakeLists.txt b/compiler-rt/lib/asan/tests/CMakeLists.txt index 6ee2fb01c0df..bda47bd7fd6a 100644 --- a/compiler-rt/lib/asan/tests/CMakeLists.txt +++ b/compiler-rt/lib/asan/tests/CMakeLists.txt @@ -172,7 +172,7 @@ function(add_asan_tests arch test_runtime) function(generate_asan_tests test_objects test_suite testname) generate_compiler_rt_tests(${test_objects} ${test_suite} ${testname} ${arch} COMPILE_DEPS ${ASAN_UNITTEST_HEADERS} ${ASAN_IGNORELIST_FILE} - DEPS llvm_gtest asan + DEPS asan KIND ${TEST_KIND} ${ARGN} ) diff --git a/compiler-rt/lib/fuzzer/tests/CMakeLists.txt b/compiler-rt/lib/fuzzer/tests/CMakeLists.txt index dd82c492e83a..8f5707c687ac 100644 --- a/compiler-rt/lib/fuzzer/tests/CMakeLists.txt +++ b/compiler-rt/lib/fuzzer/tests/CMakeLists.txt @@ -74,7 +74,7 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST FUZZER_SUPPORTED_ARCH) FuzzerUnitTests "Fuzzer-${arch}-Test" ${arch} SOURCES FuzzerUnittest.cpp ${COMPILER_RT_GTEST_SOURCE} RUNTIME ${LIBFUZZER_TEST_RUNTIME} - DEPS llvm_gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} + DEPS ${LIBFUZZER_TEST_RUNTIME_DEPS} CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS} LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS}) set_target_properties(FuzzerUnitTests PROPERTIES @@ -84,7 +84,7 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST FUZZER_SUPPORTED_ARCH) generate_compiler_rt_tests(FuzzedDataProviderTestObjects FuzzedDataProviderUnitTests "FuzzerUtils-${arch}-Test" ${arch} SOURCES FuzzedDataProviderUnittest.cpp ${COMPILER_RT_GTEST_SOURCE} - DEPS llvm_gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} ${COMPILER_RT_SOURCE_DIR}/include/fuzzer/FuzzedDataProvider.h + DEPS ${LIBFUZZER_TEST_RUNTIME_DEPS} ${COMPILER_RT_SOURCE_DIR}/include/fuzzer/FuzzedDataProvider.h CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS} LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS}) set_target_properties(FuzzedDataProviderUnitTests PROPERTIES diff --git a/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt b/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt index 4915c83d49ca..2ec332ea74c1 100644 --- a/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt +++ b/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt @@ -74,7 +74,7 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST GWP_ASAN_SUPPORTED_ARCH) GwpAsanUnitTests "GwpAsan-${arch}-Test" ${arch} SOURCES ${GWP_ASAN_UNITTESTS} ${COMPILER_RT_GTEST_SOURCE} RUNTIME ${GWP_ASAN_TEST_RUNTIME} - DEPS llvm_gtest ${GWP_ASAN_UNIT_TEST_HEADERS} + DEPS ${GWP_ASAN_UNIT_TEST_HEADERS} CFLAGS ${GWP_ASAN_UNITTEST_CFLAGS} LINK_FLAGS ${GWP_ASAN_UNITTEST_LINK_FLAGS}) set_target_properties(GwpAsanUnitTests PROPERTIES diff --git a/compiler-rt/lib/interception/tests/CMakeLists.txt b/compiler-rt/lib/interception/tests/CMakeLists.txt index 644a57664cc4..0a235c662af3 100644 --- a/compiler-rt/lib/interception/tests/CMakeLists.txt +++ b/compiler-rt/lib/interception/tests/CMakeLists.txt @@ -107,7 +107,6 @@ macro(add_interception_tests_for_arch arch) RUNTIME ${INTERCEPTION_COMMON_LIB} SOURCES ${INTERCEPTION_UNITTESTS} ${COMPILER_RT_GTEST_SOURCE} COMPILE_DEPS ${INTERCEPTION_TEST_HEADERS} - DEPS llvm_gtest CFLAGS ${INTERCEPTION_TEST_CFLAGS_COMMON} LINK_FLAGS ${INTERCEPTION_TEST_LINK_FLAGS_COMMON}) endmacro() diff --git a/compiler-rt/lib/msan/tests/CMakeLists.txt b/compiler-rt/lib/msan/tests/CMakeLists.txt index 412a0f6b3de7..bc58c0b9fabf 100644 --- a/compiler-rt/lib/msan/tests/CMakeLists.txt +++ b/compiler-rt/lib/msan/tests/CMakeLists.txt @@ -70,7 +70,7 @@ macro(msan_compile obj_list source arch kind cflags) ${obj_list} ${source} ${arch} KIND ${kind} COMPILE_DEPS ${MSAN_UNITTEST_HEADERS} - DEPS llvm_gtest msan + DEPS msan CFLAGS -isystem ${CMAKE_CURRENT_BINARY_DIR}/../libcxx_msan_${arch}/include/c++/v1 ${MSAN_UNITTEST_INSTRUMENTED_CFLAGS} ${cflags} ) diff --git a/compiler-rt/lib/orc/tests/CMakeLists.txt b/compiler-rt/lib/orc/tests/CMakeLists.txt index 2f1cb7657c28..e8f4c95b8a65 100644 --- a/compiler-rt/lib/orc/tests/CMakeLists.txt +++ b/compiler-rt/lib/orc/tests/CMakeLists.txt @@ -73,7 +73,7 @@ macro(add_orc_unittest testname) SOURCES ${TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE} RUNTIME "${ORC_RUNTIME_LIBS}" COMPILE_DEPS ${TEST_HEADERS} ${ORC_HEADERS} - DEPS llvm_gtest ${ORC_DEPS} + DEPS ${ORC_DEPS} CFLAGS ${ORC_UNITTEST_CFLAGS} ${COMPILER_RT_GTEST_CFLAGS} LINK_FLAGS ${ORC_UNITTEST_LINK_FLAGS}) endif() diff --git a/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt index 3c709e411e48..a3efe6871508 100644 --- a/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt +++ b/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt @@ -176,7 +176,6 @@ macro(add_sanitizer_tests_for_arch arch) RUNTIME "${SANITIZER_COMMON_LIB}" SOURCES ${SANITIZER_UNITTESTS} ${COMPILER_RT_GTEST_SOURCE} ${COMPILER_RT_GMOCK_SOURCE} COMPILE_DEPS ${SANITIZER_TEST_HEADERS} - DEPS llvm_gtest CFLAGS ${SANITIZER_TEST_CFLAGS_COMMON} ${extra_flags} LINK_FLAGS ${SANITIZER_TEST_LINK_FLAGS_COMMON} ${TARGET_LINK_FLAGS} ${extra_flags}) diff --git a/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt index c6b6a1cb57ce..ac92805872f9 100644 --- a/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt +++ b/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt @@ -81,7 +81,7 @@ macro(add_scudo_unittest testname) "${testname}-${arch}-Test" ${arch} SOURCES ${TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE} COMPILE_DEPS ${SCUDO_TEST_HEADERS} - DEPS llvm_gtest scudo_standalone + DEPS scudo_standalone RUNTIME ${RUNTIME} CFLAGS ${SCUDO_UNITTEST_CFLAGS} LINK_FLAGS ${SCUDO_UNITTEST_LINK_FLAGS}) diff --git a/compiler-rt/lib/tsan/tests/CMakeLists.txt b/compiler-rt/lib/tsan/tests/CMakeLists.txt index c02c2279583b..ad8cc9b0eb05 100644 --- a/compiler-rt/lib/tsan/tests/CMakeLists.txt +++ b/compiler-rt/lib/tsan/tests/CMakeLists.txt @@ -64,7 +64,7 @@ foreach (header ${TSAN_HEADERS}) list(APPEND TSAN_RTL_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../${header}) endforeach() -set(TSAN_DEPS llvm_gtest tsan) +set(TSAN_DEPS tsan) # TSan uses C++ standard library headers. if (TARGET cxx-headers OR HAVE_LIBCXX) set(TSAN_DEPS cxx-headers) diff --git a/compiler-rt/lib/xray/tests/CMakeLists.txt b/compiler-rt/lib/xray/tests/CMakeLists.txt index 732f982c932f..0a428b9a30b1 100644 --- a/compiler-rt/lib/xray/tests/CMakeLists.txt +++ b/compiler-rt/lib/xray/tests/CMakeLists.txt @@ -109,7 +109,7 @@ macro(add_xray_unittest testname) ${XRAY_HEADERS} ${XRAY_ALL_SOURCE_FILES_ABS_PATHS} "test_helpers.h" RUNTIME "${XRAY_RUNTIME_LIBS}" - DEPS llvm_gtest xray llvm-xray LLVMXRay LLVMTestingSupport + DEPS xray llvm-xray LLVMXRay LLVMTestingSupport CFLAGS ${XRAY_UNITTEST_CFLAGS} LINK_FLAGS ${TARGET_LINK_FLAGS} ${XRAY_UNITTEST_LINK_FLAGS} ) -- GitLab From 27e5312a8bc8935f9c5620ff061c647d9fbcec85 Mon Sep 17 00:00:00 2001 From: Alexander Richardson Date: Wed, 13 Mar 2024 11:32:36 -0700 Subject: [PATCH 420/953] [compiler-rt] Avoid generating coredumps when piped to a tool I was trying to debug why `ninja check-compiler-rt` was taking so long to run on my system and after some debugging it turned out that most of the time was being spent generating core dumps. On many current Linux systems, coredumps are no longer dumped in the CWD but instead piped to a utility such as systemd-coredumpd that stores them in a deterministic location. This can be done by setting the kernel.core_pattern sysctl to start with a '|'. However, when using such a setup the kernel ignores a coredump limit of 0 (since there is no file being written) and we can end up piping many gigabytes of data to systemd-coredumpd which causes the test suite to freeze for a long time. While most piped coredump handlers do respect the crashing processes' RLIMIT_CORE, this is notable not the case for Debian's systemd-coredump due to a local patch that changes sysctl.d/50-coredump.conf to ignore the specified limit and instead use RLIM_INFINITY (https://salsa.debian.org/systemd-team/systemd/-/commit/64599ffe44f0d). Fortunately there is a workaround: the kernel recognizes the magic value of 1 for RLIMIT_CORE to disable coredumps when piping. One byte is also too small to generate any coredump, so it effectively behaves as if we had set the value to zero. The alternative to using RLIMIT_CORE=1 would be to use prctl() with the PR_SET_DUMPABLE flag, however that also prevents ptrace(), so makes it impossible to attach a debugger. Fixes: https://github.com/llvm/llvm-project/issues/45797 Reviewed By: vitalybuka Pull Request: https://github.com/llvm/llvm-project/pull/83701 --- .../sanitizer_posix_libcdep.cpp | 19 ++++++++++++++++++- .../sanitizer_common/TestCases/corelimit.cpp | 7 ++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp index ef1fc3549743..3605d0d666e3 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp @@ -104,7 +104,24 @@ static void setlim(int res, rlim_t lim) { void DisableCoreDumperIfNecessary() { if (common_flags()->disable_coredump) { - setlim(RLIMIT_CORE, 0); + rlimit rlim; + CHECK_EQ(0, getrlimit(RLIMIT_CORE, &rlim)); + // On Linux, if the kernel.core_pattern sysctl starts with a '|' (i.e. it + // is being piped to a coredump handler such as systemd-coredumpd), the + // kernel ignores RLIMIT_CORE (since we aren't creating a file in the file + // system) except for the magic value of 1, which disables coredumps when + // piping. 1 byte is too small for any kind of valid core dump, so it + // also disables coredumps if kernel.core_pattern creates files directly. + // While most piped coredump handlers do respect the crashing processes' + // RLIMIT_CORE, this is notable not the case for Debian's systemd-coredump + // due to a local patch that changes sysctl.d/50-coredump.conf to ignore + // the specified limit and instead use RLIM_INFINITY. + // + // The alternative to using RLIMIT_CORE=1 would be to use prctl() with the + // PR_SET_DUMPABLE flag, however that also prevents ptrace(), so makes it + // impossible to attach a debugger. + rlim.rlim_cur = Min(SANITIZER_LINUX ? 1 : 0, rlim.rlim_max); + CHECK_EQ(0, setrlimit(RLIMIT_CORE, &rlim)); } } diff --git a/compiler-rt/test/sanitizer_common/TestCases/corelimit.cpp b/compiler-rt/test/sanitizer_common/TestCases/corelimit.cpp index 2378a4cfdced..fed2e1d89cbf 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/corelimit.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/corelimit.cpp @@ -10,7 +10,12 @@ int main() { getrlimit(RLIMIT_CORE, &lim_core); void *p; if (sizeof(p) == 8) { - assert(0 == lim_core.rlim_cur); +#ifdef __linux__ + // See comments in DisableCoreDumperIfNecessary(). + assert(lim_core.rlim_cur == 1); +#else + assert(lim_core.rlim_cur == 0); +#endif } return 0; } -- GitLab From 06e310fee12c3e5ea5c7ef066eab946eb84f317d Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Wed, 13 Mar 2024 11:32:53 -0700 Subject: [PATCH 421/953] Revert "[AArch64] Improve lowering of truncating uzp1" (#85115) Reverts llvm/llvm-project#82457 The bot is broken, likely because of mid-air collision. --- .../Target/AArch64/AArch64ISelLowering.cpp | 39 ++- llvm/lib/Target/AArch64/AArch64InstrInfo.td | 53 ++-- .../CodeGen/AArch64/arm64-convert-v4f64.ll | 21 +- llvm/test/CodeGen/AArch64/extbinopload.ll | 31 +-- .../CodeGen/AArch64/fp-conversion-to-tbl.ll | 5 +- llvm/test/CodeGen/AArch64/fptoi.ll | 256 ++++++++++++------ llvm/test/CodeGen/AArch64/neon-truncstore.ll | 5 +- llvm/test/CodeGen/AArch64/sadd_sat_vec.ll | 2 +- llvm/test/CodeGen/AArch64/shuffle-tbl34.ll | 14 +- llvm/test/CodeGen/AArch64/ssub_sat_vec.ll | 2 +- llvm/test/CodeGen/AArch64/tbl-loops.ll | 4 +- llvm/test/CodeGen/AArch64/trunc-to-tbl.ll | 28 +- llvm/test/CodeGen/AArch64/uadd_sat_vec.ll | 2 +- llvm/test/CodeGen/AArch64/usub_sat_vec.ll | 2 +- llvm/test/CodeGen/AArch64/vcvt-oversize.ll | 5 +- .../vec-combine-compare-truncate-store.ll | 2 +- .../AArch64/vec3-loads-ext-trunc-stores.ll | 22 +- 17 files changed, 284 insertions(+), 209 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 9665ae5ceb90..5b7a36d2eba7 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -21423,8 +21423,12 @@ static SDValue performUzpCombine(SDNode *N, SelectionDAG &DAG, } } - // These optimizations only work on little endian. - if (!DAG.getDataLayout().isLittleEndian()) + // uzp1(xtn x, xtn y) -> xtn(uzp1 (x, y)) + // Only implemented on little-endian subtargets. + bool IsLittleEndian = DAG.getDataLayout().isLittleEndian(); + + // This optimization only works on little endian. + if (!IsLittleEndian) return SDValue(); // uzp1(bitcast(x), bitcast(y)) -> uzp1(x, y) @@ -21443,28 +21447,21 @@ static SDValue performUzpCombine(SDNode *N, SelectionDAG &DAG, if (ResVT != MVT::v2i32 && ResVT != MVT::v4i16 && ResVT != MVT::v8i8) return SDValue(); - SDValue SourceOp0 = peekThroughBitcasts(Op0); - SDValue SourceOp1 = peekThroughBitcasts(Op1); + auto getSourceOp = [](SDValue Operand) -> SDValue { + const unsigned Opcode = Operand.getOpcode(); + if (Opcode == ISD::TRUNCATE) + return Operand->getOperand(0); + if (Opcode == ISD::BITCAST && + Operand->getOperand(0).getOpcode() == ISD::TRUNCATE) + return Operand->getOperand(0)->getOperand(0); + return SDValue(); + }; - // truncating uzp1(x, y) -> xtn(concat (x, y)) - if (SourceOp0.getValueType() == SourceOp1.getValueType()) { - EVT Op0Ty = SourceOp0.getValueType(); - if ((ResVT == MVT::v4i16 && Op0Ty == MVT::v2i32) || - (ResVT == MVT::v8i8 && Op0Ty == MVT::v4i16)) { - SDValue Concat = - DAG.getNode(ISD::CONCAT_VECTORS, DL, - Op0Ty.getDoubleNumVectorElementsVT(*DAG.getContext()), - SourceOp0, SourceOp1); - return DAG.getNode(ISD::TRUNCATE, DL, ResVT, Concat); - } - } + SDValue SourceOp0 = getSourceOp(Op0); + SDValue SourceOp1 = getSourceOp(Op1); - // uzp1(xtn x, xtn y) -> xtn(uzp1 (x, y)) - if (SourceOp0.getOpcode() != ISD::TRUNCATE || - SourceOp1.getOpcode() != ISD::TRUNCATE) + if (!SourceOp0 || !SourceOp1) return SDValue(); - SourceOp0 = SourceOp0.getOperand(0); - SourceOp1 = SourceOp1.getOperand(0); if (SourceOp0.getValueType() != SourceOp1.getValueType() || !SourceOp0.getValueType().isSimple()) diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index b4b975cce007..6254e68326f7 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -6153,39 +6153,26 @@ defm UZP2 : SIMDZipVector<0b101, "uzp2", AArch64uzp2>; defm ZIP1 : SIMDZipVector<0b011, "zip1", AArch64zip1>; defm ZIP2 : SIMDZipVector<0b111, "zip2", AArch64zip2>; -def trunc_optional_assert_ext : PatFrags<(ops node:$op0), - [(trunc node:$op0), - (assertzext (trunc node:$op0)), - (assertsext (trunc node:$op0))]>; - -// concat_vectors(trunc(x), trunc(y)) -> uzp1(x, y) -// concat_vectors(assertzext(trunc(x)), assertzext(trunc(y))) -> uzp1(x, y) -// concat_vectors(assertsext(trunc(x)), assertsext(trunc(y))) -> uzp1(x, y) -class concat_trunc_to_uzp1_pat - : Pat<(ConcatTy (concat_vectors (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vn))), - (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vm))))), - (!cast("UZP1"#ConcatTy) V128:$Vn, V128:$Vm)>; -def : concat_trunc_to_uzp1_pat; -def : concat_trunc_to_uzp1_pat; -def : concat_trunc_to_uzp1_pat; - -// trunc(concat_vectors(trunc(x), trunc(y))) -> xtn(uzp1(x, y)) -// trunc(concat_vectors(assertzext(trunc(x)), assertzext(trunc(y)))) -> xtn(uzp1(x, y)) -// trunc(concat_vectors(assertsext(trunc(x)), assertsext(trunc(y)))) -> xtn(uzp1(x, y)) -class trunc_concat_trunc_to_xtn_uzp1_pat - : Pat<(Ty (trunc_optional_assert_ext - (ConcatTy (concat_vectors - (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vn))), - (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vm))))))), - (!cast("XTN"#Ty) (!cast("UZP1"#ConcatTy) V128:$Vn, V128:$Vm))>; -def : trunc_concat_trunc_to_xtn_uzp1_pat; -def : trunc_concat_trunc_to_xtn_uzp1_pat; - -def : Pat<(v8i8 (trunc (concat_vectors (v4i16 V64:$Vn), (v4i16 V64:$Vm)))), - (UZP1v8i8 V64:$Vn, V64:$Vm)>; -def : Pat<(v4i16 (trunc (concat_vectors (v2i32 V64:$Vn), (v2i32 V64:$Vm)))), - (UZP1v4i16 V64:$Vn, V64:$Vm)>; +def : Pat<(v16i8 (concat_vectors (v8i8 (trunc (v8i16 V128:$Vn))), + (v8i8 (trunc (v8i16 V128:$Vm))))), + (UZP1v16i8 V128:$Vn, V128:$Vm)>; +def : Pat<(v8i16 (concat_vectors (v4i16 (trunc (v4i32 V128:$Vn))), + (v4i16 (trunc (v4i32 V128:$Vm))))), + (UZP1v8i16 V128:$Vn, V128:$Vm)>; +def : Pat<(v4i32 (concat_vectors (v2i32 (trunc (v2i64 V128:$Vn))), + (v2i32 (trunc (v2i64 V128:$Vm))))), + (UZP1v4i32 V128:$Vn, V128:$Vm)>; +// These are the same as above, with an optional assertzext node that can be +// generated from fptoi lowering. +def : Pat<(v16i8 (concat_vectors (v8i8 (assertzext (trunc (v8i16 V128:$Vn)))), + (v8i8 (assertzext (trunc (v8i16 V128:$Vm)))))), + (UZP1v16i8 V128:$Vn, V128:$Vm)>; +def : Pat<(v8i16 (concat_vectors (v4i16 (assertzext (trunc (v4i32 V128:$Vn)))), + (v4i16 (assertzext (trunc (v4i32 V128:$Vm)))))), + (UZP1v8i16 V128:$Vn, V128:$Vm)>; +def : Pat<(v4i32 (concat_vectors (v2i32 (assertzext (trunc (v2i64 V128:$Vn)))), + (v2i32 (assertzext (trunc (v2i64 V128:$Vm)))))), + (UZP1v4i32 V128:$Vn, V128:$Vm)>; def : Pat<(v16i8 (concat_vectors (v8i8 (trunc (AArch64vlshr (v8i16 V128:$Vn), (i32 8)))), diff --git a/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll b/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll index 3007e7ce771e..49325299f74a 100644 --- a/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll +++ b/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll @@ -8,8 +8,9 @@ define <4 x i16> @fptosi_v4f64_to_v4i16(ptr %ptr) { ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: xtn v1.2s, v1.2d +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: uzp1 v0.4h, v0.4h, v1.4h ; CHECK-NEXT: ret %tmp1 = load <4 x double>, ptr %ptr %tmp2 = fptosi <4 x double> %tmp1 to <4 x i16> @@ -25,10 +26,13 @@ define <8 x i8> @fptosi_v4f64_to_v4i8(ptr %ptr) { ; CHECK-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-NEXT: fcvtzs v3.2d, v3.2d ; CHECK-NEXT: fcvtzs v2.2d, v2.2d -; CHECK-NEXT: uzp1 v0.4s, v1.4s, v0.4s -; CHECK-NEXT: uzp1 v1.4s, v2.4s, v3.4s -; CHECK-NEXT: uzp1 v0.8h, v1.8h, v0.8h -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: xtn v1.2s, v1.2d +; CHECK-NEXT: xtn v3.2s, v3.2d +; CHECK-NEXT: xtn v2.2s, v2.2d +; CHECK-NEXT: uzp1 v0.4h, v1.4h, v0.4h +; CHECK-NEXT: uzp1 v1.4h, v2.4h, v3.4h +; CHECK-NEXT: uzp1 v0.8b, v1.8b, v0.8b ; CHECK-NEXT: ret %tmp1 = load <8 x double>, ptr %ptr %tmp2 = fptosi <8 x double> %tmp1 to <8 x i8> @@ -92,8 +96,9 @@ define <4 x i16> @fptoui_v4f64_to_v4i16(ptr %ptr) { ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: xtn v1.2s, v1.2d +; CHECK-NEXT: xtn v0.2s, v0.2d +; CHECK-NEXT: uzp1 v0.4h, v0.4h, v1.4h ; CHECK-NEXT: ret %tmp1 = load <4 x double>, ptr %ptr %tmp2 = fptoui <4 x double> %tmp1 to <4 x i16> diff --git a/llvm/test/CodeGen/AArch64/extbinopload.ll b/llvm/test/CodeGen/AArch64/extbinopload.ll index dff4831330de..1f68c77611e1 100644 --- a/llvm/test/CodeGen/AArch64/extbinopload.ll +++ b/llvm/test/CodeGen/AArch64/extbinopload.ll @@ -650,7 +650,7 @@ define <16 x i32> @extrause_load(ptr %p, ptr %q, ptr %r, ptr %s, ptr %z) { ; CHECK-NEXT: add x11, x3, #12 ; CHECK-NEXT: str s1, [x4] ; CHECK-NEXT: ushll v1.8h, v1.8b, #0 -; CHECK-NEXT: ldp s0, s4, [x2] +; CHECK-NEXT: ldp s0, s5, [x2] ; CHECK-NEXT: ushll v2.8h, v0.8b, #0 ; CHECK-NEXT: umov w9, v2.h[0] ; CHECK-NEXT: umov w10, v2.h[1] @@ -662,25 +662,24 @@ define <16 x i32> @extrause_load(ptr %p, ptr %q, ptr %r, ptr %s, ptr %z) { ; CHECK-NEXT: ushll v2.8h, v2.8b, #0 ; CHECK-NEXT: mov v0.b[10], w9 ; CHECK-NEXT: add x9, x1, #4 -; CHECK-NEXT: mov v1.d[1], v2.d[0] +; CHECK-NEXT: uzp1 v1.8b, v1.8b, v2.8b ; CHECK-NEXT: mov v0.b[11], w10 ; CHECK-NEXT: add x10, x1, #12 -; CHECK-NEXT: bic v1.8h, #255, lsl #8 ; CHECK-NEXT: ld1 { v0.s }[3], [x3], #4 -; CHECK-NEXT: ldr s3, [x0, #12] -; CHECK-NEXT: ldp s2, s7, [x0, #4] -; CHECK-NEXT: ld1 { v4.s }[1], [x3] -; CHECK-NEXT: ldp s5, s6, [x2, #8] -; CHECK-NEXT: ld1 { v3.s }[1], [x10] -; CHECK-NEXT: ld1 { v2.s }[1], [x9] -; CHECK-NEXT: ld1 { v5.s }[1], [x8] -; CHECK-NEXT: ld1 { v6.s }[1], [x11] +; CHECK-NEXT: ldr s4, [x0, #12] +; CHECK-NEXT: ldp s3, s16, [x0, #4] +; CHECK-NEXT: ld1 { v5.s }[1], [x3] +; CHECK-NEXT: ldp s6, s7, [x2, #8] +; CHECK-NEXT: ld1 { v4.s }[1], [x10] +; CHECK-NEXT: ld1 { v3.s }[1], [x9] +; CHECK-NEXT: ld1 { v6.s }[1], [x8] +; CHECK-NEXT: ld1 { v7.s }[1], [x11] ; CHECK-NEXT: add x8, x1, #8 -; CHECK-NEXT: ld1 { v7.s }[1], [x8] -; CHECK-NEXT: uaddl v2.8h, v2.8b, v3.8b -; CHECK-NEXT: ushll v3.8h, v5.8b, #0 -; CHECK-NEXT: uaddl v4.8h, v4.8b, v6.8b -; CHECK-NEXT: uaddw v1.8h, v1.8h, v7.8b +; CHECK-NEXT: ld1 { v16.s }[1], [x8] +; CHECK-NEXT: uaddl v2.8h, v3.8b, v4.8b +; CHECK-NEXT: ushll v3.8h, v6.8b, #0 +; CHECK-NEXT: uaddl v4.8h, v5.8b, v7.8b +; CHECK-NEXT: uaddl v1.8h, v1.8b, v16.8b ; CHECK-NEXT: uaddw2 v5.8h, v3.8h, v0.16b ; CHECK-NEXT: ushll v0.4s, v2.4h, #3 ; CHECK-NEXT: ushll2 v2.4s, v2.8h, #3 diff --git a/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll b/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll index 0a3b9a070c2b..1ea87bb6b04b 100644 --- a/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll +++ b/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll @@ -73,8 +73,9 @@ define void @fptoui_v8f32_to_v8i8_no_loop(ptr %A, ptr %dst) { ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: fcvtzs.4s v1, v1 ; CHECK-NEXT: fcvtzs.4s v0, v0 -; CHECK-NEXT: uzp1.8h v0, v0, v1 -; CHECK-NEXT: xtn.8b v0, v0 +; CHECK-NEXT: xtn.4h v1, v1 +; CHECK-NEXT: xtn.4h v0, v0 +; CHECK-NEXT: uzp1.8b v0, v0, v1 ; CHECK-NEXT: str d0, [x1] ; CHECK-NEXT: ret entry: diff --git a/llvm/test/CodeGen/AArch64/fptoi.ll b/llvm/test/CodeGen/AArch64/fptoi.ll index 7af01b53dae7..67190e8596c4 100644 --- a/llvm/test/CodeGen/AArch64/fptoi.ll +++ b/llvm/test/CodeGen/AArch64/fptoi.ll @@ -1096,17 +1096,30 @@ entry: } define <3 x i16> @fptos_v3f64_v3i16(<3 x double> %a) { -; CHECK-LABEL: fptos_v3f64_v3i16: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 -; CHECK-NEXT: // kill: def $d2 killed $d2 def $q2 -; CHECK-NEXT: mov v0.d[1], v1.d[0] -; CHECK-NEXT: fcvtzs v1.2d, v2.2d -; CHECK-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-NEXT: xtn v0.4h, v0.4s -; CHECK-NEXT: ret +; CHECK-SD-LABEL: fptos_v3f64_v3i16: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-SD-NEXT: // kill: def $d2 killed $d2 def $q2 +; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] +; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d +; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-SD-NEXT: xtn v1.2s, v1.2d +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: fptos_v3f64_v3i16: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: // kill: def $d2 killed $d2 def $q2 +; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] +; CHECK-GI-NEXT: fcvtzs v1.2d, v2.2d +; CHECK-GI-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: ret entry: %c = fptosi <3 x double> %a to <3 x i16> ret <3 x i16> %c @@ -1121,8 +1134,9 @@ define <3 x i16> @fptou_v3f64_v3i16(<3 x double> %a) { ; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] ; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: xtn v1.2s, v1.2d +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v3f64_v3i16: @@ -1146,8 +1160,9 @@ define <4 x i16> @fptos_v4f64_v4i16(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: xtn v1.2s, v1.2d +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v4f64_v4i16: @@ -1167,8 +1182,9 @@ define <4 x i16> @fptou_v4f64_v4i16(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: xtn v1.2s, v1.2d +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v4f64_v4i16: @@ -1584,8 +1600,9 @@ define <3 x i8> @fptos_v3f64_v3i8(<3 x double> %a) { ; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] ; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: xtn v1.2s, v1.2d +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h ; CHECK-SD-NEXT: umov w0, v0.h[0] ; CHECK-SD-NEXT: umov w1, v0.h[1] ; CHECK-SD-NEXT: umov w2, v0.h[2] @@ -1621,8 +1638,9 @@ define <3 x i8> @fptou_v3f64_v3i8(<3 x double> %a) { ; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] ; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: xtn v1.2s, v1.2d +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h ; CHECK-SD-NEXT: umov w0, v0.h[0] ; CHECK-SD-NEXT: umov w1, v0.h[1] ; CHECK-SD-NEXT: umov w2, v0.h[2] @@ -1654,8 +1672,9 @@ define <4 x i8> @fptos_v4f64_v4i8(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: xtn v1.2s, v1.2d +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v4f64_v4i8: @@ -1675,8 +1694,9 @@ define <4 x i8> @fptou_v4f64_v4i8(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: xtn v1.2s, v1.2d +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v4f64_v4i8: @@ -1698,10 +1718,13 @@ define <8 x i8> @fptos_v8f64_v8i8(<8 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s -; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h -; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: xtn v3.2s, v3.2d +; CHECK-SD-NEXT: xtn v2.2s, v2.2d +; CHECK-SD-NEXT: xtn v1.2s, v1.2d +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h +; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v2.8b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v8f64_v8i8: @@ -1727,10 +1750,13 @@ define <8 x i8> @fptou_v8f64_v8i8(<8 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s -; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h -; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: xtn v3.2s, v3.2d +; CHECK-SD-NEXT: xtn v2.2s, v2.2d +; CHECK-SD-NEXT: xtn v1.2s, v1.2d +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h +; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v2.8b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v8f64_v8i8: @@ -1760,13 +1786,21 @@ define <16 x i8> @fptos_v16f64_v16i8(<16 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s -; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s -; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s -; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-SD-NEXT: uzp1 v1.8h, v4.8h, v6.8h -; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h -; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v1.16b +; CHECK-SD-NEXT: xtn v7.2s, v7.2d +; CHECK-SD-NEXT: xtn v6.2s, v6.2d +; CHECK-SD-NEXT: xtn v5.2s, v5.2d +; CHECK-SD-NEXT: xtn v4.2s, v4.2d +; CHECK-SD-NEXT: xtn v3.2s, v3.2d +; CHECK-SD-NEXT: xtn v2.2s, v2.2d +; CHECK-SD-NEXT: xtn v1.2s, v1.2d +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h +; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h +; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h +; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] +; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] +; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v16f64_v16i8: @@ -1803,13 +1837,21 @@ define <16 x i8> @fptou_v16f64_v16i8(<16 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s -; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s -; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s -; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-SD-NEXT: uzp1 v1.8h, v4.8h, v6.8h -; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h -; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v1.16b +; CHECK-SD-NEXT: xtn v7.2s, v7.2d +; CHECK-SD-NEXT: xtn v6.2s, v6.2d +; CHECK-SD-NEXT: xtn v5.2s, v5.2d +; CHECK-SD-NEXT: xtn v4.2s, v4.2d +; CHECK-SD-NEXT: xtn v3.2s, v3.2d +; CHECK-SD-NEXT: xtn v2.2s, v2.2d +; CHECK-SD-NEXT: xtn v1.2s, v1.2d +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h +; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h +; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h +; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] +; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] +; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v16f64_v16i8: @@ -1858,20 +1900,36 @@ define <32 x i8> @fptos_v32f64_v32i8(<32 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v18.2d, v18.2d ; CHECK-SD-NEXT: fcvtzs v17.2d, v17.2d ; CHECK-SD-NEXT: fcvtzs v16.2d, v16.2d -; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s -; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s -; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s -; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-SD-NEXT: uzp1 v3.4s, v20.4s, v21.4s -; CHECK-SD-NEXT: uzp1 v1.4s, v22.4s, v23.4s -; CHECK-SD-NEXT: uzp1 v5.4s, v18.4s, v19.4s -; CHECK-SD-NEXT: uzp1 v7.4s, v16.4s, v17.4s -; CHECK-SD-NEXT: uzp1 v4.8h, v4.8h, v6.8h -; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h -; CHECK-SD-NEXT: uzp1 v1.8h, v3.8h, v1.8h -; CHECK-SD-NEXT: uzp1 v2.8h, v7.8h, v5.8h +; CHECK-SD-NEXT: xtn v7.2s, v7.2d +; CHECK-SD-NEXT: xtn v6.2s, v6.2d +; CHECK-SD-NEXT: xtn v5.2s, v5.2d +; CHECK-SD-NEXT: xtn v4.2s, v4.2d +; CHECK-SD-NEXT: xtn v3.2s, v3.2d +; CHECK-SD-NEXT: xtn v2.2s, v2.2d +; CHECK-SD-NEXT: xtn v1.2s, v1.2d +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: xtn v23.2s, v23.2d +; CHECK-SD-NEXT: xtn v22.2s, v22.2d +; CHECK-SD-NEXT: xtn v21.2s, v21.2d +; CHECK-SD-NEXT: xtn v20.2s, v20.2d +; CHECK-SD-NEXT: xtn v19.2s, v19.2d +; CHECK-SD-NEXT: xtn v18.2s, v18.2d +; CHECK-SD-NEXT: xtn v17.2s, v17.2d +; CHECK-SD-NEXT: xtn v16.2s, v16.2d +; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h +; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h +; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h +; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v1.4h, v22.4h, v23.4h +; CHECK-SD-NEXT: uzp1 v3.4h, v20.4h, v21.4h +; CHECK-SD-NEXT: uzp1 v5.4h, v18.4h, v19.4h +; CHECK-SD-NEXT: uzp1 v7.4h, v16.4h, v17.4h +; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] +; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] +; CHECK-SD-NEXT: mov v3.d[1], v1.d[0] +; CHECK-SD-NEXT: mov v7.d[1], v5.d[0] ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b -; CHECK-SD-NEXT: uzp1 v1.16b, v2.16b, v1.16b +; CHECK-SD-NEXT: uzp1 v1.16b, v7.16b, v3.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v32f64_v32i8: @@ -1939,20 +1997,36 @@ define <32 x i8> @fptou_v32f64_v32i8(<32 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v18.2d, v18.2d ; CHECK-SD-NEXT: fcvtzs v17.2d, v17.2d ; CHECK-SD-NEXT: fcvtzs v16.2d, v16.2d -; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s -; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s -; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s -; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-SD-NEXT: uzp1 v3.4s, v20.4s, v21.4s -; CHECK-SD-NEXT: uzp1 v1.4s, v22.4s, v23.4s -; CHECK-SD-NEXT: uzp1 v5.4s, v18.4s, v19.4s -; CHECK-SD-NEXT: uzp1 v7.4s, v16.4s, v17.4s -; CHECK-SD-NEXT: uzp1 v4.8h, v4.8h, v6.8h -; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h -; CHECK-SD-NEXT: uzp1 v1.8h, v3.8h, v1.8h -; CHECK-SD-NEXT: uzp1 v2.8h, v7.8h, v5.8h +; CHECK-SD-NEXT: xtn v7.2s, v7.2d +; CHECK-SD-NEXT: xtn v6.2s, v6.2d +; CHECK-SD-NEXT: xtn v5.2s, v5.2d +; CHECK-SD-NEXT: xtn v4.2s, v4.2d +; CHECK-SD-NEXT: xtn v3.2s, v3.2d +; CHECK-SD-NEXT: xtn v2.2s, v2.2d +; CHECK-SD-NEXT: xtn v1.2s, v1.2d +; CHECK-SD-NEXT: xtn v0.2s, v0.2d +; CHECK-SD-NEXT: xtn v23.2s, v23.2d +; CHECK-SD-NEXT: xtn v22.2s, v22.2d +; CHECK-SD-NEXT: xtn v21.2s, v21.2d +; CHECK-SD-NEXT: xtn v20.2s, v20.2d +; CHECK-SD-NEXT: xtn v19.2s, v19.2d +; CHECK-SD-NEXT: xtn v18.2s, v18.2d +; CHECK-SD-NEXT: xtn v17.2s, v17.2d +; CHECK-SD-NEXT: xtn v16.2s, v16.2d +; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h +; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h +; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h +; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v1.4h, v22.4h, v23.4h +; CHECK-SD-NEXT: uzp1 v3.4h, v20.4h, v21.4h +; CHECK-SD-NEXT: uzp1 v5.4h, v18.4h, v19.4h +; CHECK-SD-NEXT: uzp1 v7.4h, v16.4h, v17.4h +; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] +; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] +; CHECK-SD-NEXT: mov v3.d[1], v1.d[0] +; CHECK-SD-NEXT: mov v7.d[1], v5.d[0] ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b -; CHECK-SD-NEXT: uzp1 v1.16b, v2.16b, v1.16b +; CHECK-SD-NEXT: uzp1 v1.16b, v7.16b, v3.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v32f64_v32i8: @@ -2952,8 +3026,9 @@ define <8 x i8> @fptos_v8f32_v8i8(<8 x float> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.4s, v1.4s ; CHECK-SD-NEXT: fcvtzs v0.4s, v0.4s -; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h -; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: xtn v1.4h, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v1.8b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v8f32_v8i8: @@ -2973,8 +3048,9 @@ define <8 x i8> @fptou_v8f32_v8i8(<8 x float> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.4s, v1.4s ; CHECK-SD-NEXT: fcvtzs v0.4s, v0.4s -; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h -; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: xtn v1.4h, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v1.8b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v8f32_v8i8: @@ -2996,8 +3072,12 @@ define <16 x i8> @fptos_v16f32_v16i8(<16 x float> %a) { ; CHECK-SD-NEXT: fcvtzs v2.4s, v2.4s ; CHECK-SD-NEXT: fcvtzs v1.4s, v1.4s ; CHECK-SD-NEXT: fcvtzs v0.4s, v0.4s -; CHECK-SD-NEXT: uzp1 v2.8h, v2.8h, v3.8h -; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h +; CHECK-SD-NEXT: xtn v3.4h, v3.4s +; CHECK-SD-NEXT: xtn v2.4h, v2.4s +; CHECK-SD-NEXT: xtn v1.4h, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: mov v2.d[1], v3.d[0] +; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v2.16b ; CHECK-SD-NEXT: ret ; @@ -3054,12 +3134,20 @@ define <32 x i8> @fptos_v32f32_v32i8(<32 x float> %a) { ; CHECK-SD-NEXT: fcvtzs v6.4s, v6.4s ; CHECK-SD-NEXT: fcvtzs v5.4s, v5.4s ; CHECK-SD-NEXT: fcvtzs v4.4s, v4.4s -; CHECK-SD-NEXT: uzp1 v2.8h, v2.8h, v3.8h -; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h -; CHECK-SD-NEXT: uzp1 v1.8h, v6.8h, v7.8h -; CHECK-SD-NEXT: uzp1 v3.8h, v4.8h, v5.8h +; CHECK-SD-NEXT: xtn v3.4h, v3.4s +; CHECK-SD-NEXT: xtn v2.4h, v2.4s +; CHECK-SD-NEXT: xtn v1.4h, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s +; CHECK-SD-NEXT: xtn v7.4h, v7.4s +; CHECK-SD-NEXT: xtn v6.4h, v6.4s +; CHECK-SD-NEXT: xtn v5.4h, v5.4s +; CHECK-SD-NEXT: xtn v4.4h, v4.4s +; CHECK-SD-NEXT: mov v2.d[1], v3.d[0] +; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] +; CHECK-SD-NEXT: mov v6.d[1], v7.d[0] +; CHECK-SD-NEXT: mov v4.d[1], v5.d[0] ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v2.16b -; CHECK-SD-NEXT: uzp1 v1.16b, v3.16b, v1.16b +; CHECK-SD-NEXT: uzp1 v1.16b, v4.16b, v6.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v32f32_v32i8: diff --git a/llvm/test/CodeGen/AArch64/neon-truncstore.ll b/llvm/test/CodeGen/AArch64/neon-truncstore.ll index 5d78ad24eb33..b677d077b98c 100644 --- a/llvm/test/CodeGen/AArch64/neon-truncstore.ll +++ b/llvm/test/CodeGen/AArch64/neon-truncstore.ll @@ -104,7 +104,7 @@ define void @v4i32_v4i8(<4 x i32> %a, ptr %result) { ; CHECK-LABEL: v4i32_v4i8: ; CHECK: // %bb.0: ; CHECK-NEXT: xtn v0.4h, v0.4s -; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b +; CHECK-NEXT: xtn v0.8b, v0.8h ; CHECK-NEXT: str s0, [x0] ; CHECK-NEXT: ret %b = trunc <4 x i32> %a to <4 x i8> @@ -170,7 +170,8 @@ define void @v2i16_v2i8(<2 x i16> %a, ptr %result) { define void @v4i16_v4i8(<4 x i16> %a, ptr %result) { ; CHECK-LABEL: v4i16_v4i8: ; CHECK: // %bb.0: -; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: xtn v0.8b, v0.8h ; CHECK-NEXT: str s0, [x0] ; CHECK-NEXT: ret %b = trunc <4 x i16> %a to <4 x i8> diff --git a/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll b/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll index 6f1ae023bf25..5f905d94e357 100644 --- a/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll @@ -145,7 +145,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-NEXT: sqadd v0.4h, v0.4h, v1.4h ; CHECK-NEXT: sshr v0.4h, v0.4h, #8 -; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b +; CHECK-NEXT: xtn v0.8b, v0.8h ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll b/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll index fb571eff39fe..0ef64789ad97 100644 --- a/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll +++ b/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll @@ -353,17 +353,13 @@ define <8 x i8> @shuffle4_v8i8_v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c, <8 x define <8 x i16> @shuffle4_v4i8_zext(<4 x i8> %a, <4 x i8> %b, <4 x i8> %c, <4 x i8> %d) { ; CHECK-LABEL: shuffle4_v4i8_zext: ; CHECK: // %bb.0: -; CHECK-NEXT: fmov d5, d2 -; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 -; CHECK-NEXT: // kill: def $d3 killed $d3 def $q3 +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v1.8b +; CHECK-NEXT: uzp1 v1.8b, v2.8b, v3.8b ; CHECK-NEXT: adrp x8, .LCPI8_0 -; CHECK-NEXT: fmov d4, d0 +; CHECK-NEXT: ushll v2.8h, v0.8b, #0 ; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI8_0] -; CHECK-NEXT: mov v4.d[1], v1.d[0] -; CHECK-NEXT: mov v5.d[1], v3.d[0] -; CHECK-NEXT: bic v4.8h, #255, lsl #8 -; CHECK-NEXT: bic v5.8h, #255, lsl #8 -; CHECK-NEXT: tbl v0.16b, { v4.16b, v5.16b }, v0.16b +; CHECK-NEXT: ushll v3.8h, v1.8b, #0 +; CHECK-NEXT: tbl v0.16b, { v2.16b, v3.16b }, v0.16b ; CHECK-NEXT: ret %x = shufflevector <4 x i8> %a, <4 x i8> %b, <8 x i32> %y = shufflevector <4 x i8> %c, <4 x i8> %d, <8 x i32> diff --git a/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll b/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll index d1f843a09f74..acec3e74d3e9 100644 --- a/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll @@ -146,7 +146,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-NEXT: sqsub v0.4h, v0.4h, v1.4h ; CHECK-NEXT: sshr v0.4h, v0.4h, #8 -; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b +; CHECK-NEXT: xtn v0.8b, v0.8h ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/tbl-loops.ll b/llvm/test/CodeGen/AArch64/tbl-loops.ll index 0ad990086551..4f8a4f7aede3 100644 --- a/llvm/test/CodeGen/AArch64/tbl-loops.ll +++ b/llvm/test/CodeGen/AArch64/tbl-loops.ll @@ -41,8 +41,8 @@ define void @loop1(ptr noalias nocapture noundef writeonly %dst, ptr nocapture n ; CHECK-NEXT: fcvtzs v2.4s, v2.4s ; CHECK-NEXT: xtn v1.4h, v1.4s ; CHECK-NEXT: xtn v2.4h, v2.4s -; CHECK-NEXT: uzp1 v1.8b, v1.8b, v0.8b -; CHECK-NEXT: uzp1 v2.8b, v2.8b, v0.8b +; CHECK-NEXT: xtn v1.8b, v1.8h +; CHECK-NEXT: xtn v2.8b, v2.8h ; CHECK-NEXT: mov v1.s[1], v2.s[0] ; CHECK-NEXT: stur d1, [x12, #-4] ; CHECK-NEXT: add x12, x12, #8 diff --git a/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll b/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll index 18cd4cc2111a..ba367b0dbfde 100644 --- a/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll +++ b/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll @@ -710,23 +710,23 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) { ; CHECK-NEXT: LBB6_1: ; %loop ; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: ldp q4, q1, [x0, #48] -; CHECK-NEXT: add x9, x1, #10 -; CHECK-NEXT: ldr d0, [x0, #80] +; CHECK-NEXT: add x9, x1, #8 ; CHECK-NEXT: ldp q3, q2, [x0] -; CHECK-NEXT: ldr q5, [x0, #32] ; CHECK-NEXT: subs x8, x8, #1 +; CHECK-NEXT: ldr d0, [x0, #80] +; CHECK-NEXT: ldr q5, [x0, #32] ; CHECK-NEXT: add x0, x0, #128 -; CHECK-NEXT: uzp1.4s v0, v1, v0 -; CHECK-NEXT: uzp1.4s v1, v5, v4 +; CHECK-NEXT: uzp1.4s v4, v5, v4 ; CHECK-NEXT: uzp1.4s v2, v3, v2 +; CHECK-NEXT: uzp1.4s v0, v1, v0 +; CHECK-NEXT: uzp1.8h v1, v2, v4 ; CHECK-NEXT: xtn.4h v0, v0 -; CHECK-NEXT: uzp1.8h v1, v2, v1 -; CHECK-NEXT: uzp1.8b v2, v0, v0 -; CHECK-NEXT: uzp1.16b v0, v1, v0 -; CHECK-NEXT: st1.b { v2 }[2], [x9] -; CHECK-NEXT: add x9, x1, #8 -; CHECK-NEXT: st1.h { v0 }[4], [x9] -; CHECK-NEXT: str d0, [x1], #16 +; CHECK-NEXT: uzp1.16b v1, v1, v0 +; CHECK-NEXT: xtn.8b v0, v0 +; CHECK-NEXT: st1.h { v1 }[4], [x9] +; CHECK-NEXT: add x9, x1, #10 +; CHECK-NEXT: st1.b { v0 }[2], [x9] +; CHECK-NEXT: str d1, [x1], #16 ; CHECK-NEXT: b.eq LBB6_1 ; CHECK-NEXT: ; %bb.2: ; %exit ; CHECK-NEXT: ret @@ -755,7 +755,7 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) { ; CHECK-BE-NEXT: xtn v0.4h, v0.4s ; CHECK-BE-NEXT: uzp1 v1.8h, v1.8h, v2.8h ; CHECK-BE-NEXT: uzp1 v1.16b, v1.16b, v0.16b -; CHECK-BE-NEXT: uzp1 v0.8b, v0.8b, v0.8b +; CHECK-BE-NEXT: xtn v0.8b, v0.8h ; CHECK-BE-NEXT: rev16 v2.16b, v1.16b ; CHECK-BE-NEXT: rev64 v1.16b, v1.16b ; CHECK-BE-NEXT: st1 { v0.b }[2], [x9] @@ -790,7 +790,7 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) { ; CHECK-DISABLE-NEXT: xtn v0.4h, v0.4s ; CHECK-DISABLE-NEXT: uzp1 v1.8h, v1.8h, v2.8h ; CHECK-DISABLE-NEXT: uzp1 v1.16b, v1.16b, v0.16b -; CHECK-DISABLE-NEXT: uzp1 v0.8b, v0.8b, v0.8b +; CHECK-DISABLE-NEXT: xtn v0.8b, v0.8h ; CHECK-DISABLE-NEXT: rev16 v2.16b, v1.16b ; CHECK-DISABLE-NEXT: rev64 v1.16b, v1.16b ; CHECK-DISABLE-NEXT: st1 { v0.b }[2], [x9] diff --git a/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll b/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll index f0bbed59405e..e05c65daf50a 100644 --- a/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll @@ -142,7 +142,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: movi d0, #0xff00ff00ff00ff ; CHECK-NEXT: uaddl v1.8h, v1.8b, v2.8b ; CHECK-NEXT: umin v0.4h, v1.4h, v0.4h -; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b +; CHECK-NEXT: xtn v0.8b, v0.8h ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/usub_sat_vec.ll b/llvm/test/CodeGen/AArch64/usub_sat_vec.ll index 82c0327219f5..05f43e7d8427 100644 --- a/llvm/test/CodeGen/AArch64/usub_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/usub_sat_vec.ll @@ -143,7 +143,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: ushll v0.8h, v0.8b, #0 ; CHECK-NEXT: ushll v1.8h, v1.8b, #0 ; CHECK-NEXT: uqsub v0.4h, v0.4h, v1.4h -; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b +; CHECK-NEXT: xtn v0.8b, v0.8h ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/vcvt-oversize.ll b/llvm/test/CodeGen/AArch64/vcvt-oversize.ll index 611940546bc1..380bdbcc7f74 100644 --- a/llvm/test/CodeGen/AArch64/vcvt-oversize.ll +++ b/llvm/test/CodeGen/AArch64/vcvt-oversize.ll @@ -9,8 +9,9 @@ define <8 x i8> @float_to_i8(ptr %in) { ; CHECK-NEXT: fadd v0.4s, v0.4s, v0.4s ; CHECK-NEXT: fcvtzs v0.4s, v0.4s ; CHECK-NEXT: fcvtzs v1.4s, v1.4s -; CHECK-NEXT: uzp1 v0.8h, v1.8h, v0.8h -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: xtn v1.4h, v1.4s +; CHECK-NEXT: uzp1 v0.8b, v1.8b, v0.8b ; CHECK-NEXT: ret %l = load <8 x float>, ptr %in %scale = fmul <8 x float> %l, diff --git a/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll b/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll index dd7a9c6d7768..9c6ab8da0fa7 100644 --- a/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll +++ b/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll @@ -210,7 +210,7 @@ define void @no_combine_for_non_bool_truncate(<4 x i32> %vec, ptr %out) { ; CHECK-LABEL: no_combine_for_non_bool_truncate: ; CHECK: ; %bb.0: ; CHECK-NEXT: xtn.4h v0, v0 -; CHECK-NEXT: uzp1.8b v0, v0, v0 +; CHECK-NEXT: xtn.8b v0, v0 ; CHECK-NEXT: str s0, [x0] ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll b/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll index 71d55df66517..90328f73f86b 100644 --- a/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll +++ b/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll @@ -410,7 +410,7 @@ define void @store_trunc_from_64bits(ptr %src, ptr %dst) { ; BE-NEXT: ldrh w8, [x0, #4] ; BE-NEXT: rev32 v0.4h, v0.4h ; BE-NEXT: mov v0.h[2], w8 -; BE-NEXT: uzp1 v0.8b, v0.8b, v0.8b +; BE-NEXT: xtn v0.8b, v0.8h ; BE-NEXT: rev32 v0.16b, v0.16b ; BE-NEXT: str s0, [sp, #12] ; BE-NEXT: ldrh w9, [sp, #12] @@ -456,7 +456,7 @@ define void @store_trunc_add_from_64bits(ptr %src, ptr %dst) { ; BE-NEXT: add x8, x8, :lo12:.LCPI11_0 ; BE-NEXT: ld1 { v1.4h }, [x8] ; BE-NEXT: add v0.4h, v0.4h, v1.4h -; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b +; BE-NEXT: xtn v1.8b, v0.8h ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -638,7 +638,7 @@ define void @shift_trunc_store(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b +; BE-NEXT: xtn v1.8b, v0.8h ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -672,7 +672,7 @@ define void @shift_trunc_store_default_align(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b +; BE-NEXT: xtn v1.8b, v0.8h ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -706,7 +706,7 @@ define void @shift_trunc_store_align_4(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b +; BE-NEXT: xtn v1.8b, v0.8h ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -741,7 +741,7 @@ define void @shift_trunc_store_const_offset_1(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b +; BE-NEXT: xtn v1.8b, v0.8h ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -777,7 +777,7 @@ define void @shift_trunc_store_const_offset_3(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b +; BE-NEXT: xtn v1.8b, v0.8h ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -801,7 +801,7 @@ define void @shift_trunc_volatile_store(ptr %src, ptr %dst) { ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: ldr q0, [x0] ; CHECK-NEXT: shrn.4h v0, v0, #16 -; CHECK-NEXT: uzp1.8b v1, v0, v0 +; CHECK-NEXT: xtn.8b v1, v0 ; CHECK-NEXT: umov.h w8, v0[2] ; CHECK-NEXT: str s1, [sp, #12] ; CHECK-NEXT: ldrh w9, [sp, #12] @@ -816,7 +816,7 @@ define void @shift_trunc_volatile_store(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b +; BE-NEXT: xtn v1.8b, v0.8h ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -868,7 +868,7 @@ define void @load_v3i8_zext_to_3xi32_add_trunc_store(ptr %src) { ; BE-NEXT: ushll v0.8h, v0.8b, #0 ; BE-NEXT: ld1 { v0.b }[4], [x9] ; BE-NEXT: add v0.4h, v0.4h, v1.4h -; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b +; BE-NEXT: xtn v1.8b, v0.8h ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #8] @@ -921,7 +921,7 @@ define void @load_v3i8_sext_to_3xi32_add_trunc_store(ptr %src) { ; BE-NEXT: ushll v0.8h, v0.8b, #0 ; BE-NEXT: ld1 { v0.b }[4], [x9] ; BE-NEXT: add v0.4h, v0.4h, v1.4h -; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b +; BE-NEXT: xtn v1.8b, v0.8h ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #8] -- GitLab From 417324a6c1e7ecb6c145b20905f918378cc824e3 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 13 Mar 2024 10:59:09 -0700 Subject: [PATCH 422/953] [RISCV] Remove unnecessary ArrayRef. NFC --- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index caff0e8fcefe..0607240efff8 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -2823,9 +2823,8 @@ bool RISCVAsmParser::parseDirectiveOption() { break; } - ArrayRef KVArray(RISCVFeatureKV); - auto Ext = llvm::lower_bound(KVArray, Arch); - if (Ext == KVArray.end() || StringRef(Ext->Key) != Arch || + auto Ext = llvm::lower_bound(RISCVFeatureKV, Arch); + if (Ext == std::end(RISCVFeatureKV) || StringRef(Ext->Key) != Arch || !RISCVISAInfo::isSupportedExtension(Arch)) { if (isDigit(Arch.back())) return Error( @@ -2858,7 +2857,7 @@ bool RISCVAsmParser::parseDirectiveOption() { // It is invalid to disable an extension that there are other enabled // extensions depend on it. // TODO: Make use of RISCVISAInfo to handle this - for (auto Feature : KVArray) { + for (auto Feature : RISCVFeatureKV) { if (getSTI().hasFeature(Feature.Value) && Feature.Implies.test(Ext->Value)) return Error(Loc, -- GitLab From 66dd38e8dfd51209aa1fd9bae0a43a355215768f Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 13 Mar 2024 11:37:31 -0700 Subject: [PATCH 423/953] [RISCV] Use references to avoid unnecessary struct copies. NFC --- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 0607240efff8..2da75bda8d12 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -2716,7 +2716,7 @@ ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) { bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result, bool FromOptionDirective) { - for (auto Feature : RISCVFeatureKV) + for (auto &Feature : RISCVFeatureKV) if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key)) clearFeatureBits(Feature.Value, Feature.Key); @@ -2735,7 +2735,7 @@ bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result, } auto &ISAInfo = *ParseResult; - for (auto Feature : RISCVFeatureKV) + for (auto &Feature : RISCVFeatureKV) if (ISAInfo->hasExtension(Feature.Key)) setFeatureBits(Feature.Value, Feature.Key); @@ -2857,7 +2857,7 @@ bool RISCVAsmParser::parseDirectiveOption() { // It is invalid to disable an extension that there are other enabled // extensions depend on it. // TODO: Make use of RISCVISAInfo to handle this - for (auto Feature : RISCVFeatureKV) { + for (auto &Feature : RISCVFeatureKV) { if (getSTI().hasFeature(Feature.Value) && Feature.Implies.test(Ext->Value)) return Error(Loc, -- GitLab From b61fb18456ecd798b2fc340367018ab3109ebfae Mon Sep 17 00:00:00 2001 From: Alastair Houghton Date: Wed, 13 Mar 2024 18:48:13 +0000 Subject: [PATCH 424/953] [libc++] Fix tests on musl (#85085) One or two of the tests need slight tweaks to make them pass when building with musl. rdar://118885724 --- .../generic_category.pass.cpp | 19 ++++--- .../system_category.pass.cpp | 19 ++++--- .../put_long_double.pass.cpp | 51 ++++++++++--------- 3 files changed, 52 insertions(+), 37 deletions(-) diff --git a/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp b/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp index 068202c6e415..d4bbde75ae88 100644 --- a/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp +++ b/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/generic_category.pass.cpp @@ -44,14 +44,19 @@ int main(int, char**) errno = E2BIG; // something that message will never generate const std::error_category& e_cat1 = std::generic_category(); const std::string msg = e_cat1.message(-1); - // Exact message format varies by platform. -#if defined(_AIX) - LIBCPP_ASSERT(msg.rfind("Error -1 occurred", 0) == 0); -#elif defined(_NEWLIB_VERSION) - LIBCPP_ASSERT(msg.empty()); -#else - LIBCPP_ASSERT(msg.rfind("Unknown error", 0) == 0); + // Exact message format varies by platform. We can't detect + // some of these (Musl in particular) using the preprocessor, + // so accept a few sensible messages. Newlib unfortunately + // responds with an empty message, which we probably want to + // treat as a failure code otherwise, but we can detect that + // with the preprocessor. + LIBCPP_ASSERT(msg.rfind("Error -1 occurred", 0) == 0 // AIX + || msg.rfind("No error information", 0) == 0 // Musl + || msg.rfind("Unknown error", 0) == 0 // Glibc +#if defined(_NEWLIB_VERSION) + || msg.empty() #endif + ); assert(errno == E2BIG); } diff --git a/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp b/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp index 42fdd1cb3b91..eefbddd27a7f 100644 --- a/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp +++ b/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp @@ -50,14 +50,19 @@ int main(int, char**) { errno = E2BIG; // something that message will never generate const std::error_category& e_cat1 = std::system_category(); const std::string msg = e_cat1.message(-1); - // Exact message format varies by platform. -#if defined(_AIX) - LIBCPP_ASSERT(msg.rfind("Error -1 occurred", 0) == 0); -#elif defined(_NEWLIB_VERSION) - LIBCPP_ASSERT(msg.empty()); -#else - LIBCPP_ASSERT(msg.rfind("Unknown error", 0) == 0); + // Exact message format varies by platform. We can't detect + // some of these (Musl in particular) using the preprocessor, + // so accept a few sensible messages. Newlib unfortunately + // responds with an empty message, which we probably want to + // treat as a failure code otherwise, but we can detect that + // with the preprocessor. + LIBCPP_ASSERT(msg.rfind("Error -1 occurred", 0) == 0 // AIX + || msg.rfind("No error information", 0) == 0 // Musl + || msg.rfind("Unknown error", 0) == 0 // Glibc +#if defined(_NEWLIB_VERSION) + || msg.empty() #endif + ); assert(errno == E2BIG); } diff --git a/libcxx/test/std/localization/locale.categories/category.numeric/locale.nm.put/facet.num.put.members/put_long_double.pass.cpp b/libcxx/test/std/localization/locale.categories/category.numeric/locale.nm.put/facet.num.put.members/put_long_double.pass.cpp index 8637a933008f..0258ebf87243 100644 --- a/libcxx/test/std/localization/locale.categories/category.numeric/locale.nm.put/facet.num.put.members/put_long_double.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.numeric/locale.nm.put/facet.num.put.members/put_long_double.pass.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include "test_macros.h" @@ -8934,11 +8935,12 @@ void test4() char str[200]; std::locale lc = std::locale::classic(); std::locale lg(lc, new my_numpunct); -#ifdef _AIX - std::string inf = "INF"; -#else - std::string inf = "inf"; -#endif + + std::string inf; + + // This should match the underlying C library + std::sprintf(str, "%f", INFINITY); + inf = str; const my_facet f(1); { @@ -10727,24 +10729,27 @@ void test5() std::locale lc = std::locale::classic(); std::locale lg(lc, new my_numpunct); const my_facet f(1); -#if defined(_AIX) - std::string nan= "NaNQ"; - std::string NaN = "NaNQ"; - std::string nan_padding25 = "*********************"; - std::string pnan_sign = "+"; - std::string pnan_padding25 = "********************"; -#else - std::string nan= "nan"; - std::string NaN = "NAN"; - std::string nan_padding25 = "**********************"; -#if defined(TEST_HAS_GLIBC) || defined(_WIN32) - std::string pnan_sign = "+"; - std::string pnan_padding25 = "*********************"; -#else - std::string pnan_sign = ""; - std::string pnan_padding25 = "**********************"; -#endif -#endif + + std::string nan; + std::string NaN; + std::string pnan_sign; + + // The output here depends on the underlying C library, so work out what + // that does. + std::sprintf(str, "%f", std::nan("")); + nan = str; + + std::sprintf(str, "%F", std::nan("")); + NaN = str; + + std::sprintf(str, "%+f", std::nan("")); + if (str[0] == '+') { + pnan_sign = "+"; + } + + std::string nan_padding25 = std::string(25 - nan.length(), '*'); + std::string pnan_padding25 = std::string(25 - nan.length() - pnan_sign.length(), '*'); + { long double v = std::nan(""); std::ios ios(0); -- GitLab From a8967b060df01e46c021f718b4e2d7ed858b8726 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 13 Mar 2024 11:51:51 -0700 Subject: [PATCH 425/953] [SLP][NFC]Add a test with buildvector with minbitwidth Root, NFC. --- ...ather-buildvector-with-minbitwidth-user.ll | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 llvm/test/Transforms/SLPVectorizer/AArch64/gather-buildvector-with-minbitwidth-user.ll diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/gather-buildvector-with-minbitwidth-user.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/gather-buildvector-with-minbitwidth-user.ll new file mode 100644 index 000000000000..705e425d3e44 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/gather-buildvector-with-minbitwidth-user.ll @@ -0,0 +1,88 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s + +define void @h() { +; CHECK-LABEL: define void @h() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr null, i64 16 +; CHECK-NEXT: [[TMP0:%.*]] = insertelement <8 x i32> , i32 0, i32 0 +; CHECK-NEXT: [[TMP1:%.*]] = or <8 x i32> zeroinitializer, [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = or <8 x i32> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = trunc <8 x i32> [[TMP2]] to <8 x i16> +; CHECK-NEXT: store <8 x i16> [[TMP3]], ptr [[ARRAYIDX2]], align 2 +; CHECK-NEXT: ret void +; +entry: + %conv9 = zext i16 0 to i32 + %arrayidx2 = getelementptr i8, ptr null, i64 16 + %conv310 = zext i16 0 to i32 + %add4 = or i32 %conv310, %conv9 + %sub = or i32 %conv9, %conv310 + %conv15 = sext i16 0 to i32 + %shr = ashr i32 0, 0 + %arrayidx18 = getelementptr i8, ptr null, i64 24 + %conv19 = sext i16 0 to i32 + %sub20 = or i32 %shr, %conv19 + %shr29 = ashr i32 0, 0 + %add30 = or i32 %shr29, %conv15 + %sub39 = or i32 %sub, %sub20 + %conv40 = trunc i32 %sub39 to i16 + store i16 %conv40, ptr %arrayidx2, align 2 + %sub44 = or i32 %add4, %add30 + %conv45 = trunc i32 %sub44 to i16 + store i16 %conv45, ptr %arrayidx18, align 2 + %arrayidx2.1 = getelementptr i8, ptr null, i64 18 + %conv3.112 = zext i16 0 to i32 + %add4.1 = or i32 %conv3.112, 0 + %sub.1 = or i32 0, %conv3.112 + %conv15.1 = sext i16 0 to i32 + %shr.1 = ashr i32 0, 0 + %arrayidx18.1 = getelementptr i8, ptr null, i64 26 + %conv19.1 = sext i16 0 to i32 + %sub20.1 = or i32 %shr.1, %conv19.1 + %shr29.1 = ashr i32 0, 0 + %add30.1 = or i32 %shr29.1, %conv15.1 + %sub39.1 = or i32 %sub.1, %sub20.1 + %conv40.1 = trunc i32 %sub39.1 to i16 + store i16 %conv40.1, ptr %arrayidx2.1, align 2 + %sub44.1 = or i32 %add4.1, %add30.1 + %conv45.1 = trunc i32 %sub44.1 to i16 + store i16 %conv45.1, ptr %arrayidx18.1, align 2 + %conv.213 = zext i16 0 to i32 + %arrayidx2.2 = getelementptr i8, ptr null, i64 20 + %conv3.214 = zext i16 0 to i32 + %add4.2 = or i32 0, %conv.213 + %sub.2 = or i32 0, %conv3.214 + %conv15.2 = sext i16 0 to i32 + %shr.2 = ashr i32 0, 0 + %arrayidx18.2 = getelementptr i8, ptr null, i64 28 + %conv19.2 = sext i16 0 to i32 + %sub20.2 = or i32 %shr.2, %conv19.2 + %shr29.2 = ashr i32 0, 0 + %add30.2 = or i32 %shr29.2, %conv15.2 + %sub39.2 = or i32 %sub.2, %sub20.2 + %conv40.2 = trunc i32 %sub39.2 to i16 + store i16 %conv40.2, ptr %arrayidx2.2, align 2 + %sub44.2 = or i32 %add4.2, %add30.2 + %conv45.2 = trunc i32 %sub44.2 to i16 + store i16 %conv45.2, ptr %arrayidx18.2, align 2 + %conv.315 = zext i16 0 to i32 + %arrayidx2.3 = getelementptr i8, ptr null, i64 22 + %conv3.316 = zext i16 0 to i32 + %add4.3 = or i32 0, %conv.315 + %sub.3 = or i32 0, %conv3.316 + %conv15.3 = sext i16 0 to i32 + %shr.3 = ashr i32 0, 0 + %arrayidx18.3 = getelementptr i8, ptr null, i64 30 + %conv19.3 = sext i16 0 to i32 + %sub20.3 = or i32 %shr.3, %conv19.3 + %shr29.3 = ashr i32 0, 0 + %add30.3 = or i32 %shr29.3, %conv15.3 + %sub39.3 = or i32 %sub.3, %sub20.3 + %conv40.3 = trunc i32 %sub39.3 to i16 + store i16 %conv40.3, ptr %arrayidx2.3, align 2 + %sub44.3 = or i32 %add4.3, %add30.3 + %conv45.3 = trunc i32 %sub44.3 to i16 + store i16 %conv45.3, ptr %arrayidx18.3, align 2 + ret void +} -- GitLab From 0b4688403672264ab451992a3461a0df113c3bd7 Mon Sep 17 00:00:00 2001 From: Usman Nadeem Date: Wed, 13 Mar 2024 11:58:10 -0700 Subject: [PATCH 426/953] Revert "Revert "[AArch64] Improve lowering of truncating uzp1"" (#85119) Reverts llvm/llvm-project#85115 The fix was already merged in https://github.com/llvm/llvm-project/commit/79cd2c0bb9acb4685094d6b3bf21c758aa51d3df --- .../Target/AArch64/AArch64ISelLowering.cpp | 39 +-- llvm/lib/Target/AArch64/AArch64InstrInfo.td | 53 ++-- .../CodeGen/AArch64/arm64-convert-v4f64.ll | 21 +- llvm/test/CodeGen/AArch64/extbinopload.ll | 31 ++- .../CodeGen/AArch64/fp-conversion-to-tbl.ll | 5 +- llvm/test/CodeGen/AArch64/fptoi.ll | 256 ++++++------------ llvm/test/CodeGen/AArch64/neon-truncstore.ll | 5 +- llvm/test/CodeGen/AArch64/sadd_sat_vec.ll | 2 +- llvm/test/CodeGen/AArch64/shuffle-tbl34.ll | 14 +- llvm/test/CodeGen/AArch64/ssub_sat_vec.ll | 2 +- llvm/test/CodeGen/AArch64/tbl-loops.ll | 4 +- llvm/test/CodeGen/AArch64/trunc-to-tbl.ll | 28 +- llvm/test/CodeGen/AArch64/uadd_sat_vec.ll | 2 +- llvm/test/CodeGen/AArch64/usub_sat_vec.ll | 2 +- llvm/test/CodeGen/AArch64/vcvt-oversize.ll | 5 +- .../vec-combine-compare-truncate-store.ll | 2 +- .../AArch64/vec3-loads-ext-trunc-stores.ll | 22 +- 17 files changed, 209 insertions(+), 284 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 5b7a36d2eba7..9665ae5ceb90 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -21423,12 +21423,8 @@ static SDValue performUzpCombine(SDNode *N, SelectionDAG &DAG, } } - // uzp1(xtn x, xtn y) -> xtn(uzp1 (x, y)) - // Only implemented on little-endian subtargets. - bool IsLittleEndian = DAG.getDataLayout().isLittleEndian(); - - // This optimization only works on little endian. - if (!IsLittleEndian) + // These optimizations only work on little endian. + if (!DAG.getDataLayout().isLittleEndian()) return SDValue(); // uzp1(bitcast(x), bitcast(y)) -> uzp1(x, y) @@ -21447,21 +21443,28 @@ static SDValue performUzpCombine(SDNode *N, SelectionDAG &DAG, if (ResVT != MVT::v2i32 && ResVT != MVT::v4i16 && ResVT != MVT::v8i8) return SDValue(); - auto getSourceOp = [](SDValue Operand) -> SDValue { - const unsigned Opcode = Operand.getOpcode(); - if (Opcode == ISD::TRUNCATE) - return Operand->getOperand(0); - if (Opcode == ISD::BITCAST && - Operand->getOperand(0).getOpcode() == ISD::TRUNCATE) - return Operand->getOperand(0)->getOperand(0); - return SDValue(); - }; + SDValue SourceOp0 = peekThroughBitcasts(Op0); + SDValue SourceOp1 = peekThroughBitcasts(Op1); - SDValue SourceOp0 = getSourceOp(Op0); - SDValue SourceOp1 = getSourceOp(Op1); + // truncating uzp1(x, y) -> xtn(concat (x, y)) + if (SourceOp0.getValueType() == SourceOp1.getValueType()) { + EVT Op0Ty = SourceOp0.getValueType(); + if ((ResVT == MVT::v4i16 && Op0Ty == MVT::v2i32) || + (ResVT == MVT::v8i8 && Op0Ty == MVT::v4i16)) { + SDValue Concat = + DAG.getNode(ISD::CONCAT_VECTORS, DL, + Op0Ty.getDoubleNumVectorElementsVT(*DAG.getContext()), + SourceOp0, SourceOp1); + return DAG.getNode(ISD::TRUNCATE, DL, ResVT, Concat); + } + } - if (!SourceOp0 || !SourceOp1) + // uzp1(xtn x, xtn y) -> xtn(uzp1 (x, y)) + if (SourceOp0.getOpcode() != ISD::TRUNCATE || + SourceOp1.getOpcode() != ISD::TRUNCATE) return SDValue(); + SourceOp0 = SourceOp0.getOperand(0); + SourceOp1 = SourceOp1.getOperand(0); if (SourceOp0.getValueType() != SourceOp1.getValueType() || !SourceOp0.getValueType().isSimple()) diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 6254e68326f7..b4b975cce007 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -6153,26 +6153,39 @@ defm UZP2 : SIMDZipVector<0b101, "uzp2", AArch64uzp2>; defm ZIP1 : SIMDZipVector<0b011, "zip1", AArch64zip1>; defm ZIP2 : SIMDZipVector<0b111, "zip2", AArch64zip2>; -def : Pat<(v16i8 (concat_vectors (v8i8 (trunc (v8i16 V128:$Vn))), - (v8i8 (trunc (v8i16 V128:$Vm))))), - (UZP1v16i8 V128:$Vn, V128:$Vm)>; -def : Pat<(v8i16 (concat_vectors (v4i16 (trunc (v4i32 V128:$Vn))), - (v4i16 (trunc (v4i32 V128:$Vm))))), - (UZP1v8i16 V128:$Vn, V128:$Vm)>; -def : Pat<(v4i32 (concat_vectors (v2i32 (trunc (v2i64 V128:$Vn))), - (v2i32 (trunc (v2i64 V128:$Vm))))), - (UZP1v4i32 V128:$Vn, V128:$Vm)>; -// These are the same as above, with an optional assertzext node that can be -// generated from fptoi lowering. -def : Pat<(v16i8 (concat_vectors (v8i8 (assertzext (trunc (v8i16 V128:$Vn)))), - (v8i8 (assertzext (trunc (v8i16 V128:$Vm)))))), - (UZP1v16i8 V128:$Vn, V128:$Vm)>; -def : Pat<(v8i16 (concat_vectors (v4i16 (assertzext (trunc (v4i32 V128:$Vn)))), - (v4i16 (assertzext (trunc (v4i32 V128:$Vm)))))), - (UZP1v8i16 V128:$Vn, V128:$Vm)>; -def : Pat<(v4i32 (concat_vectors (v2i32 (assertzext (trunc (v2i64 V128:$Vn)))), - (v2i32 (assertzext (trunc (v2i64 V128:$Vm)))))), - (UZP1v4i32 V128:$Vn, V128:$Vm)>; +def trunc_optional_assert_ext : PatFrags<(ops node:$op0), + [(trunc node:$op0), + (assertzext (trunc node:$op0)), + (assertsext (trunc node:$op0))]>; + +// concat_vectors(trunc(x), trunc(y)) -> uzp1(x, y) +// concat_vectors(assertzext(trunc(x)), assertzext(trunc(y))) -> uzp1(x, y) +// concat_vectors(assertsext(trunc(x)), assertsext(trunc(y))) -> uzp1(x, y) +class concat_trunc_to_uzp1_pat + : Pat<(ConcatTy (concat_vectors (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vn))), + (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vm))))), + (!cast("UZP1"#ConcatTy) V128:$Vn, V128:$Vm)>; +def : concat_trunc_to_uzp1_pat; +def : concat_trunc_to_uzp1_pat; +def : concat_trunc_to_uzp1_pat; + +// trunc(concat_vectors(trunc(x), trunc(y))) -> xtn(uzp1(x, y)) +// trunc(concat_vectors(assertzext(trunc(x)), assertzext(trunc(y)))) -> xtn(uzp1(x, y)) +// trunc(concat_vectors(assertsext(trunc(x)), assertsext(trunc(y)))) -> xtn(uzp1(x, y)) +class trunc_concat_trunc_to_xtn_uzp1_pat + : Pat<(Ty (trunc_optional_assert_ext + (ConcatTy (concat_vectors + (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vn))), + (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vm))))))), + (!cast("XTN"#Ty) (!cast("UZP1"#ConcatTy) V128:$Vn, V128:$Vm))>; +def : trunc_concat_trunc_to_xtn_uzp1_pat; +def : trunc_concat_trunc_to_xtn_uzp1_pat; + +def : Pat<(v8i8 (trunc (concat_vectors (v4i16 V64:$Vn), (v4i16 V64:$Vm)))), + (UZP1v8i8 V64:$Vn, V64:$Vm)>; +def : Pat<(v4i16 (trunc (concat_vectors (v2i32 V64:$Vn), (v2i32 V64:$Vm)))), + (UZP1v4i16 V64:$Vn, V64:$Vm)>; def : Pat<(v16i8 (concat_vectors (v8i8 (trunc (AArch64vlshr (v8i16 V128:$Vn), (i32 8)))), diff --git a/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll b/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll index 49325299f74a..3007e7ce771e 100644 --- a/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll +++ b/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll @@ -8,9 +8,8 @@ define <4 x i16> @fptosi_v4f64_to_v4i16(ptr %ptr) { ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-NEXT: xtn v1.2s, v1.2d -; CHECK-NEXT: xtn v0.2s, v0.2d -; CHECK-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-NEXT: xtn v0.4h, v0.4s ; CHECK-NEXT: ret %tmp1 = load <4 x double>, ptr %ptr %tmp2 = fptosi <4 x double> %tmp1 to <4 x i16> @@ -26,13 +25,10 @@ define <8 x i8> @fptosi_v4f64_to_v4i8(ptr %ptr) { ; CHECK-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-NEXT: fcvtzs v3.2d, v3.2d ; CHECK-NEXT: fcvtzs v2.2d, v2.2d -; CHECK-NEXT: xtn v0.2s, v0.2d -; CHECK-NEXT: xtn v1.2s, v1.2d -; CHECK-NEXT: xtn v3.2s, v3.2d -; CHECK-NEXT: xtn v2.2s, v2.2d -; CHECK-NEXT: uzp1 v0.4h, v1.4h, v0.4h -; CHECK-NEXT: uzp1 v1.4h, v2.4h, v3.4h -; CHECK-NEXT: uzp1 v0.8b, v1.8b, v0.8b +; CHECK-NEXT: uzp1 v0.4s, v1.4s, v0.4s +; CHECK-NEXT: uzp1 v1.4s, v2.4s, v3.4s +; CHECK-NEXT: uzp1 v0.8h, v1.8h, v0.8h +; CHECK-NEXT: xtn v0.8b, v0.8h ; CHECK-NEXT: ret %tmp1 = load <8 x double>, ptr %ptr %tmp2 = fptosi <8 x double> %tmp1 to <8 x i8> @@ -96,9 +92,8 @@ define <4 x i16> @fptoui_v4f64_to_v4i16(ptr %ptr) { ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-NEXT: xtn v1.2s, v1.2d -; CHECK-NEXT: xtn v0.2s, v0.2d -; CHECK-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-NEXT: xtn v0.4h, v0.4s ; CHECK-NEXT: ret %tmp1 = load <4 x double>, ptr %ptr %tmp2 = fptoui <4 x double> %tmp1 to <4 x i16> diff --git a/llvm/test/CodeGen/AArch64/extbinopload.ll b/llvm/test/CodeGen/AArch64/extbinopload.ll index 1f68c77611e1..dff4831330de 100644 --- a/llvm/test/CodeGen/AArch64/extbinopload.ll +++ b/llvm/test/CodeGen/AArch64/extbinopload.ll @@ -650,7 +650,7 @@ define <16 x i32> @extrause_load(ptr %p, ptr %q, ptr %r, ptr %s, ptr %z) { ; CHECK-NEXT: add x11, x3, #12 ; CHECK-NEXT: str s1, [x4] ; CHECK-NEXT: ushll v1.8h, v1.8b, #0 -; CHECK-NEXT: ldp s0, s5, [x2] +; CHECK-NEXT: ldp s0, s4, [x2] ; CHECK-NEXT: ushll v2.8h, v0.8b, #0 ; CHECK-NEXT: umov w9, v2.h[0] ; CHECK-NEXT: umov w10, v2.h[1] @@ -662,24 +662,25 @@ define <16 x i32> @extrause_load(ptr %p, ptr %q, ptr %r, ptr %s, ptr %z) { ; CHECK-NEXT: ushll v2.8h, v2.8b, #0 ; CHECK-NEXT: mov v0.b[10], w9 ; CHECK-NEXT: add x9, x1, #4 -; CHECK-NEXT: uzp1 v1.8b, v1.8b, v2.8b +; CHECK-NEXT: mov v1.d[1], v2.d[0] ; CHECK-NEXT: mov v0.b[11], w10 ; CHECK-NEXT: add x10, x1, #12 +; CHECK-NEXT: bic v1.8h, #255, lsl #8 ; CHECK-NEXT: ld1 { v0.s }[3], [x3], #4 -; CHECK-NEXT: ldr s4, [x0, #12] -; CHECK-NEXT: ldp s3, s16, [x0, #4] -; CHECK-NEXT: ld1 { v5.s }[1], [x3] -; CHECK-NEXT: ldp s6, s7, [x2, #8] -; CHECK-NEXT: ld1 { v4.s }[1], [x10] -; CHECK-NEXT: ld1 { v3.s }[1], [x9] -; CHECK-NEXT: ld1 { v6.s }[1], [x8] -; CHECK-NEXT: ld1 { v7.s }[1], [x11] +; CHECK-NEXT: ldr s3, [x0, #12] +; CHECK-NEXT: ldp s2, s7, [x0, #4] +; CHECK-NEXT: ld1 { v4.s }[1], [x3] +; CHECK-NEXT: ldp s5, s6, [x2, #8] +; CHECK-NEXT: ld1 { v3.s }[1], [x10] +; CHECK-NEXT: ld1 { v2.s }[1], [x9] +; CHECK-NEXT: ld1 { v5.s }[1], [x8] +; CHECK-NEXT: ld1 { v6.s }[1], [x11] ; CHECK-NEXT: add x8, x1, #8 -; CHECK-NEXT: ld1 { v16.s }[1], [x8] -; CHECK-NEXT: uaddl v2.8h, v3.8b, v4.8b -; CHECK-NEXT: ushll v3.8h, v6.8b, #0 -; CHECK-NEXT: uaddl v4.8h, v5.8b, v7.8b -; CHECK-NEXT: uaddl v1.8h, v1.8b, v16.8b +; CHECK-NEXT: ld1 { v7.s }[1], [x8] +; CHECK-NEXT: uaddl v2.8h, v2.8b, v3.8b +; CHECK-NEXT: ushll v3.8h, v5.8b, #0 +; CHECK-NEXT: uaddl v4.8h, v4.8b, v6.8b +; CHECK-NEXT: uaddw v1.8h, v1.8h, v7.8b ; CHECK-NEXT: uaddw2 v5.8h, v3.8h, v0.16b ; CHECK-NEXT: ushll v0.4s, v2.4h, #3 ; CHECK-NEXT: ushll2 v2.4s, v2.8h, #3 diff --git a/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll b/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll index 1ea87bb6b04b..0a3b9a070c2b 100644 --- a/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll +++ b/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll @@ -73,9 +73,8 @@ define void @fptoui_v8f32_to_v8i8_no_loop(ptr %A, ptr %dst) { ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: fcvtzs.4s v1, v1 ; CHECK-NEXT: fcvtzs.4s v0, v0 -; CHECK-NEXT: xtn.4h v1, v1 -; CHECK-NEXT: xtn.4h v0, v0 -; CHECK-NEXT: uzp1.8b v0, v0, v1 +; CHECK-NEXT: uzp1.8h v0, v0, v1 +; CHECK-NEXT: xtn.8b v0, v0 ; CHECK-NEXT: str d0, [x1] ; CHECK-NEXT: ret entry: diff --git a/llvm/test/CodeGen/AArch64/fptoi.ll b/llvm/test/CodeGen/AArch64/fptoi.ll index 67190e8596c4..7af01b53dae7 100644 --- a/llvm/test/CodeGen/AArch64/fptoi.ll +++ b/llvm/test/CodeGen/AArch64/fptoi.ll @@ -1096,30 +1096,17 @@ entry: } define <3 x i16> @fptos_v3f64_v3i16(<3 x double> %a) { -; CHECK-SD-LABEL: fptos_v3f64_v3i16: -; CHECK-SD: // %bb.0: // %entry -; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1 -; CHECK-SD-NEXT: // kill: def $d2 killed $d2 def $q2 -; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] -; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d -; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: fptos_v3f64_v3i16: -; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 -; CHECK-GI-NEXT: // kill: def $d2 killed $d2 def $q2 -; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] -; CHECK-GI-NEXT: fcvtzs v1.2d, v2.2d -; CHECK-GI-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: fptos_v3f64_v3i16: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: // kill: def $d2 killed $d2 def $q2 +; CHECK-NEXT: mov v0.d[1], v1.d[0] +; CHECK-NEXT: fcvtzs v1.2d, v2.2d +; CHECK-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret entry: %c = fptosi <3 x double> %a to <3 x i16> ret <3 x i16> %c @@ -1134,9 +1121,8 @@ define <3 x i16> @fptou_v3f64_v3i16(<3 x double> %a) { ; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] ; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v3f64_v3i16: @@ -1160,9 +1146,8 @@ define <4 x i16> @fptos_v4f64_v4i16(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v4f64_v4i16: @@ -1182,9 +1167,8 @@ define <4 x i16> @fptou_v4f64_v4i16(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v4f64_v4i16: @@ -1600,9 +1584,8 @@ define <3 x i8> @fptos_v3f64_v3i8(<3 x double> %a) { ; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] ; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: umov w0, v0.h[0] ; CHECK-SD-NEXT: umov w1, v0.h[1] ; CHECK-SD-NEXT: umov w2, v0.h[2] @@ -1638,9 +1621,8 @@ define <3 x i8> @fptou_v3f64_v3i8(<3 x double> %a) { ; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] ; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: umov w0, v0.h[0] ; CHECK-SD-NEXT: umov w1, v0.h[1] ; CHECK-SD-NEXT: umov w2, v0.h[2] @@ -1672,9 +1654,8 @@ define <4 x i8> @fptos_v4f64_v4i8(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v4f64_v4i8: @@ -1694,9 +1675,8 @@ define <4 x i8> @fptou_v4f64_v4i8(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v4f64_v4i8: @@ -1718,13 +1698,10 @@ define <8 x i8> @fptos_v8f64_v8i8(<8 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v2.8b +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: xtn v0.8b, v0.8h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v8f64_v8i8: @@ -1750,13 +1727,10 @@ define <8 x i8> @fptou_v8f64_v8i8(<8 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v2.8b +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: xtn v0.8b, v0.8h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v8f64_v8i8: @@ -1786,21 +1760,13 @@ define <16 x i8> @fptos_v16f64_v16i8(<16 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v7.2s, v7.2d -; CHECK-SD-NEXT: xtn v6.2s, v6.2d -; CHECK-SD-NEXT: xtn v5.2s, v5.2d -; CHECK-SD-NEXT: xtn v4.2s, v4.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h -; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] -; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b +; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s +; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v1.8h, v4.8h, v6.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v16f64_v16i8: @@ -1837,21 +1803,13 @@ define <16 x i8> @fptou_v16f64_v16i8(<16 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v7.2s, v7.2d -; CHECK-SD-NEXT: xtn v6.2s, v6.2d -; CHECK-SD-NEXT: xtn v5.2s, v5.2d -; CHECK-SD-NEXT: xtn v4.2s, v4.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h -; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] -; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b +; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s +; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v1.8h, v4.8h, v6.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v16f64_v16i8: @@ -1900,36 +1858,20 @@ define <32 x i8> @fptos_v32f64_v32i8(<32 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v18.2d, v18.2d ; CHECK-SD-NEXT: fcvtzs v17.2d, v17.2d ; CHECK-SD-NEXT: fcvtzs v16.2d, v16.2d -; CHECK-SD-NEXT: xtn v7.2s, v7.2d -; CHECK-SD-NEXT: xtn v6.2s, v6.2d -; CHECK-SD-NEXT: xtn v5.2s, v5.2d -; CHECK-SD-NEXT: xtn v4.2s, v4.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: xtn v23.2s, v23.2d -; CHECK-SD-NEXT: xtn v22.2s, v22.2d -; CHECK-SD-NEXT: xtn v21.2s, v21.2d -; CHECK-SD-NEXT: xtn v20.2s, v20.2d -; CHECK-SD-NEXT: xtn v19.2s, v19.2d -; CHECK-SD-NEXT: xtn v18.2s, v18.2d -; CHECK-SD-NEXT: xtn v17.2s, v17.2d -; CHECK-SD-NEXT: xtn v16.2s, v16.2d -; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h -; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: uzp1 v1.4h, v22.4h, v23.4h -; CHECK-SD-NEXT: uzp1 v3.4h, v20.4h, v21.4h -; CHECK-SD-NEXT: uzp1 v5.4h, v18.4h, v19.4h -; CHECK-SD-NEXT: uzp1 v7.4h, v16.4h, v17.4h -; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] -; CHECK-SD-NEXT: mov v3.d[1], v1.d[0] -; CHECK-SD-NEXT: mov v7.d[1], v5.d[0] +; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s +; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v3.4s, v20.4s, v21.4s +; CHECK-SD-NEXT: uzp1 v1.4s, v22.4s, v23.4s +; CHECK-SD-NEXT: uzp1 v5.4s, v18.4s, v19.4s +; CHECK-SD-NEXT: uzp1 v7.4s, v16.4s, v17.4s +; CHECK-SD-NEXT: uzp1 v4.8h, v4.8h, v6.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: uzp1 v1.8h, v3.8h, v1.8h +; CHECK-SD-NEXT: uzp1 v2.8h, v7.8h, v5.8h ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b -; CHECK-SD-NEXT: uzp1 v1.16b, v7.16b, v3.16b +; CHECK-SD-NEXT: uzp1 v1.16b, v2.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v32f64_v32i8: @@ -1997,36 +1939,20 @@ define <32 x i8> @fptou_v32f64_v32i8(<32 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v18.2d, v18.2d ; CHECK-SD-NEXT: fcvtzs v17.2d, v17.2d ; CHECK-SD-NEXT: fcvtzs v16.2d, v16.2d -; CHECK-SD-NEXT: xtn v7.2s, v7.2d -; CHECK-SD-NEXT: xtn v6.2s, v6.2d -; CHECK-SD-NEXT: xtn v5.2s, v5.2d -; CHECK-SD-NEXT: xtn v4.2s, v4.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: xtn v23.2s, v23.2d -; CHECK-SD-NEXT: xtn v22.2s, v22.2d -; CHECK-SD-NEXT: xtn v21.2s, v21.2d -; CHECK-SD-NEXT: xtn v20.2s, v20.2d -; CHECK-SD-NEXT: xtn v19.2s, v19.2d -; CHECK-SD-NEXT: xtn v18.2s, v18.2d -; CHECK-SD-NEXT: xtn v17.2s, v17.2d -; CHECK-SD-NEXT: xtn v16.2s, v16.2d -; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h -; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: uzp1 v1.4h, v22.4h, v23.4h -; CHECK-SD-NEXT: uzp1 v3.4h, v20.4h, v21.4h -; CHECK-SD-NEXT: uzp1 v5.4h, v18.4h, v19.4h -; CHECK-SD-NEXT: uzp1 v7.4h, v16.4h, v17.4h -; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] -; CHECK-SD-NEXT: mov v3.d[1], v1.d[0] -; CHECK-SD-NEXT: mov v7.d[1], v5.d[0] +; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s +; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v3.4s, v20.4s, v21.4s +; CHECK-SD-NEXT: uzp1 v1.4s, v22.4s, v23.4s +; CHECK-SD-NEXT: uzp1 v5.4s, v18.4s, v19.4s +; CHECK-SD-NEXT: uzp1 v7.4s, v16.4s, v17.4s +; CHECK-SD-NEXT: uzp1 v4.8h, v4.8h, v6.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: uzp1 v1.8h, v3.8h, v1.8h +; CHECK-SD-NEXT: uzp1 v2.8h, v7.8h, v5.8h ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b -; CHECK-SD-NEXT: uzp1 v1.16b, v7.16b, v3.16b +; CHECK-SD-NEXT: uzp1 v1.16b, v2.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v32f64_v32i8: @@ -3026,9 +2952,8 @@ define <8 x i8> @fptos_v8f32_v8i8(<8 x float> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.4s, v1.4s ; CHECK-SD-NEXT: fcvtzs v0.4s, v0.4s -; CHECK-SD-NEXT: xtn v1.4h, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v1.8b +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h +; CHECK-SD-NEXT: xtn v0.8b, v0.8h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v8f32_v8i8: @@ -3048,9 +2973,8 @@ define <8 x i8> @fptou_v8f32_v8i8(<8 x float> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.4s, v1.4s ; CHECK-SD-NEXT: fcvtzs v0.4s, v0.4s -; CHECK-SD-NEXT: xtn v1.4h, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v1.8b +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h +; CHECK-SD-NEXT: xtn v0.8b, v0.8h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v8f32_v8i8: @@ -3072,12 +2996,8 @@ define <16 x i8> @fptos_v16f32_v16i8(<16 x float> %a) { ; CHECK-SD-NEXT: fcvtzs v2.4s, v2.4s ; CHECK-SD-NEXT: fcvtzs v1.4s, v1.4s ; CHECK-SD-NEXT: fcvtzs v0.4s, v0.4s -; CHECK-SD-NEXT: xtn v3.4h, v3.4s -; CHECK-SD-NEXT: xtn v2.4h, v2.4s -; CHECK-SD-NEXT: xtn v1.4h, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: mov v2.d[1], v3.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] +; CHECK-SD-NEXT: uzp1 v2.8h, v2.8h, v3.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v2.16b ; CHECK-SD-NEXT: ret ; @@ -3134,20 +3054,12 @@ define <32 x i8> @fptos_v32f32_v32i8(<32 x float> %a) { ; CHECK-SD-NEXT: fcvtzs v6.4s, v6.4s ; CHECK-SD-NEXT: fcvtzs v5.4s, v5.4s ; CHECK-SD-NEXT: fcvtzs v4.4s, v4.4s -; CHECK-SD-NEXT: xtn v3.4h, v3.4s -; CHECK-SD-NEXT: xtn v2.4h, v2.4s -; CHECK-SD-NEXT: xtn v1.4h, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: xtn v7.4h, v7.4s -; CHECK-SD-NEXT: xtn v6.4h, v6.4s -; CHECK-SD-NEXT: xtn v5.4h, v5.4s -; CHECK-SD-NEXT: xtn v4.4h, v4.4s -; CHECK-SD-NEXT: mov v2.d[1], v3.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] -; CHECK-SD-NEXT: mov v6.d[1], v7.d[0] -; CHECK-SD-NEXT: mov v4.d[1], v5.d[0] +; CHECK-SD-NEXT: uzp1 v2.8h, v2.8h, v3.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h +; CHECK-SD-NEXT: uzp1 v1.8h, v6.8h, v7.8h +; CHECK-SD-NEXT: uzp1 v3.8h, v4.8h, v5.8h ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v2.16b -; CHECK-SD-NEXT: uzp1 v1.16b, v4.16b, v6.16b +; CHECK-SD-NEXT: uzp1 v1.16b, v3.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v32f32_v32i8: diff --git a/llvm/test/CodeGen/AArch64/neon-truncstore.ll b/llvm/test/CodeGen/AArch64/neon-truncstore.ll index b677d077b98c..5d78ad24eb33 100644 --- a/llvm/test/CodeGen/AArch64/neon-truncstore.ll +++ b/llvm/test/CodeGen/AArch64/neon-truncstore.ll @@ -104,7 +104,7 @@ define void @v4i32_v4i8(<4 x i32> %a, ptr %result) { ; CHECK-LABEL: v4i32_v4i8: ; CHECK: // %bb.0: ; CHECK-NEXT: xtn v0.4h, v0.4s -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x0] ; CHECK-NEXT: ret %b = trunc <4 x i32> %a to <4 x i8> @@ -170,8 +170,7 @@ define void @v2i16_v2i8(<2 x i16> %a, ptr %result) { define void @v4i16_v4i8(<4 x i16> %a, ptr %result) { ; CHECK-LABEL: v4i16_v4i8: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x0] ; CHECK-NEXT: ret %b = trunc <4 x i16> %a to <4 x i8> diff --git a/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll b/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll index 5f905d94e357..6f1ae023bf25 100644 --- a/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll @@ -145,7 +145,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-NEXT: sqadd v0.4h, v0.4h, v1.4h ; CHECK-NEXT: sshr v0.4h, v0.4h, #8 -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll b/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll index 0ef64789ad97..fb571eff39fe 100644 --- a/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll +++ b/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll @@ -353,13 +353,17 @@ define <8 x i8> @shuffle4_v8i8_v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c, <8 x define <8 x i16> @shuffle4_v4i8_zext(<4 x i8> %a, <4 x i8> %b, <4 x i8> %c, <4 x i8> %d) { ; CHECK-LABEL: shuffle4_v4i8_zext: ; CHECK: // %bb.0: -; CHECK-NEXT: uzp1 v0.8b, v0.8b, v1.8b -; CHECK-NEXT: uzp1 v1.8b, v2.8b, v3.8b +; CHECK-NEXT: fmov d5, d2 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: // kill: def $d3 killed $d3 def $q3 ; CHECK-NEXT: adrp x8, .LCPI8_0 -; CHECK-NEXT: ushll v2.8h, v0.8b, #0 +; CHECK-NEXT: fmov d4, d0 ; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI8_0] -; CHECK-NEXT: ushll v3.8h, v1.8b, #0 -; CHECK-NEXT: tbl v0.16b, { v2.16b, v3.16b }, v0.16b +; CHECK-NEXT: mov v4.d[1], v1.d[0] +; CHECK-NEXT: mov v5.d[1], v3.d[0] +; CHECK-NEXT: bic v4.8h, #255, lsl #8 +; CHECK-NEXT: bic v5.8h, #255, lsl #8 +; CHECK-NEXT: tbl v0.16b, { v4.16b, v5.16b }, v0.16b ; CHECK-NEXT: ret %x = shufflevector <4 x i8> %a, <4 x i8> %b, <8 x i32> %y = shufflevector <4 x i8> %c, <4 x i8> %d, <8 x i32> diff --git a/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll b/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll index acec3e74d3e9..d1f843a09f74 100644 --- a/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll @@ -146,7 +146,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-NEXT: sqsub v0.4h, v0.4h, v1.4h ; CHECK-NEXT: sshr v0.4h, v0.4h, #8 -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/tbl-loops.ll b/llvm/test/CodeGen/AArch64/tbl-loops.ll index 4f8a4f7aede3..0ad990086551 100644 --- a/llvm/test/CodeGen/AArch64/tbl-loops.ll +++ b/llvm/test/CodeGen/AArch64/tbl-loops.ll @@ -41,8 +41,8 @@ define void @loop1(ptr noalias nocapture noundef writeonly %dst, ptr nocapture n ; CHECK-NEXT: fcvtzs v2.4s, v2.4s ; CHECK-NEXT: xtn v1.4h, v1.4s ; CHECK-NEXT: xtn v2.4h, v2.4s -; CHECK-NEXT: xtn v1.8b, v1.8h -; CHECK-NEXT: xtn v2.8b, v2.8h +; CHECK-NEXT: uzp1 v1.8b, v1.8b, v0.8b +; CHECK-NEXT: uzp1 v2.8b, v2.8b, v0.8b ; CHECK-NEXT: mov v1.s[1], v2.s[0] ; CHECK-NEXT: stur d1, [x12, #-4] ; CHECK-NEXT: add x12, x12, #8 diff --git a/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll b/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll index ba367b0dbfde..18cd4cc2111a 100644 --- a/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll +++ b/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll @@ -710,23 +710,23 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) { ; CHECK-NEXT: LBB6_1: ; %loop ; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: ldp q4, q1, [x0, #48] -; CHECK-NEXT: add x9, x1, #8 -; CHECK-NEXT: ldp q3, q2, [x0] -; CHECK-NEXT: subs x8, x8, #1 +; CHECK-NEXT: add x9, x1, #10 ; CHECK-NEXT: ldr d0, [x0, #80] +; CHECK-NEXT: ldp q3, q2, [x0] ; CHECK-NEXT: ldr q5, [x0, #32] +; CHECK-NEXT: subs x8, x8, #1 ; CHECK-NEXT: add x0, x0, #128 -; CHECK-NEXT: uzp1.4s v4, v5, v4 -; CHECK-NEXT: uzp1.4s v2, v3, v2 ; CHECK-NEXT: uzp1.4s v0, v1, v0 -; CHECK-NEXT: uzp1.8h v1, v2, v4 +; CHECK-NEXT: uzp1.4s v1, v5, v4 +; CHECK-NEXT: uzp1.4s v2, v3, v2 ; CHECK-NEXT: xtn.4h v0, v0 -; CHECK-NEXT: uzp1.16b v1, v1, v0 -; CHECK-NEXT: xtn.8b v0, v0 -; CHECK-NEXT: st1.h { v1 }[4], [x9] -; CHECK-NEXT: add x9, x1, #10 -; CHECK-NEXT: st1.b { v0 }[2], [x9] -; CHECK-NEXT: str d1, [x1], #16 +; CHECK-NEXT: uzp1.8h v1, v2, v1 +; CHECK-NEXT: uzp1.8b v2, v0, v0 +; CHECK-NEXT: uzp1.16b v0, v1, v0 +; CHECK-NEXT: st1.b { v2 }[2], [x9] +; CHECK-NEXT: add x9, x1, #8 +; CHECK-NEXT: st1.h { v0 }[4], [x9] +; CHECK-NEXT: str d0, [x1], #16 ; CHECK-NEXT: b.eq LBB6_1 ; CHECK-NEXT: ; %bb.2: ; %exit ; CHECK-NEXT: ret @@ -755,7 +755,7 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) { ; CHECK-BE-NEXT: xtn v0.4h, v0.4s ; CHECK-BE-NEXT: uzp1 v1.8h, v1.8h, v2.8h ; CHECK-BE-NEXT: uzp1 v1.16b, v1.16b, v0.16b -; CHECK-BE-NEXT: xtn v0.8b, v0.8h +; CHECK-BE-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-BE-NEXT: rev16 v2.16b, v1.16b ; CHECK-BE-NEXT: rev64 v1.16b, v1.16b ; CHECK-BE-NEXT: st1 { v0.b }[2], [x9] @@ -790,7 +790,7 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) { ; CHECK-DISABLE-NEXT: xtn v0.4h, v0.4s ; CHECK-DISABLE-NEXT: uzp1 v1.8h, v1.8h, v2.8h ; CHECK-DISABLE-NEXT: uzp1 v1.16b, v1.16b, v0.16b -; CHECK-DISABLE-NEXT: xtn v0.8b, v0.8h +; CHECK-DISABLE-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-DISABLE-NEXT: rev16 v2.16b, v1.16b ; CHECK-DISABLE-NEXT: rev64 v1.16b, v1.16b ; CHECK-DISABLE-NEXT: st1 { v0.b }[2], [x9] diff --git a/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll b/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll index e05c65daf50a..f0bbed59405e 100644 --- a/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll @@ -142,7 +142,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: movi d0, #0xff00ff00ff00ff ; CHECK-NEXT: uaddl v1.8h, v1.8b, v2.8b ; CHECK-NEXT: umin v0.4h, v1.4h, v0.4h -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/usub_sat_vec.ll b/llvm/test/CodeGen/AArch64/usub_sat_vec.ll index 05f43e7d8427..82c0327219f5 100644 --- a/llvm/test/CodeGen/AArch64/usub_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/usub_sat_vec.ll @@ -143,7 +143,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: ushll v0.8h, v0.8b, #0 ; CHECK-NEXT: ushll v1.8h, v1.8b, #0 ; CHECK-NEXT: uqsub v0.4h, v0.4h, v1.4h -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/vcvt-oversize.ll b/llvm/test/CodeGen/AArch64/vcvt-oversize.ll index 380bdbcc7f74..611940546bc1 100644 --- a/llvm/test/CodeGen/AArch64/vcvt-oversize.ll +++ b/llvm/test/CodeGen/AArch64/vcvt-oversize.ll @@ -9,9 +9,8 @@ define <8 x i8> @float_to_i8(ptr %in) { ; CHECK-NEXT: fadd v0.4s, v0.4s, v0.4s ; CHECK-NEXT: fcvtzs v0.4s, v0.4s ; CHECK-NEXT: fcvtzs v1.4s, v1.4s -; CHECK-NEXT: xtn v0.4h, v0.4s -; CHECK-NEXT: xtn v1.4h, v1.4s -; CHECK-NEXT: uzp1 v0.8b, v1.8b, v0.8b +; CHECK-NEXT: uzp1 v0.8h, v1.8h, v0.8h +; CHECK-NEXT: xtn v0.8b, v0.8h ; CHECK-NEXT: ret %l = load <8 x float>, ptr %in %scale = fmul <8 x float> %l, diff --git a/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll b/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll index 9c6ab8da0fa7..dd7a9c6d7768 100644 --- a/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll +++ b/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll @@ -210,7 +210,7 @@ define void @no_combine_for_non_bool_truncate(<4 x i32> %vec, ptr %out) { ; CHECK-LABEL: no_combine_for_non_bool_truncate: ; CHECK: ; %bb.0: ; CHECK-NEXT: xtn.4h v0, v0 -; CHECK-NEXT: xtn.8b v0, v0 +; CHECK-NEXT: uzp1.8b v0, v0, v0 ; CHECK-NEXT: str s0, [x0] ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll b/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll index 90328f73f86b..71d55df66517 100644 --- a/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll +++ b/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll @@ -410,7 +410,7 @@ define void @store_trunc_from_64bits(ptr %src, ptr %dst) { ; BE-NEXT: ldrh w8, [x0, #4] ; BE-NEXT: rev32 v0.4h, v0.4h ; BE-NEXT: mov v0.h[2], w8 -; BE-NEXT: xtn v0.8b, v0.8h +; BE-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; BE-NEXT: rev32 v0.16b, v0.16b ; BE-NEXT: str s0, [sp, #12] ; BE-NEXT: ldrh w9, [sp, #12] @@ -456,7 +456,7 @@ define void @store_trunc_add_from_64bits(ptr %src, ptr %dst) { ; BE-NEXT: add x8, x8, :lo12:.LCPI11_0 ; BE-NEXT: ld1 { v1.4h }, [x8] ; BE-NEXT: add v0.4h, v0.4h, v1.4h -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -638,7 +638,7 @@ define void @shift_trunc_store(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -672,7 +672,7 @@ define void @shift_trunc_store_default_align(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -706,7 +706,7 @@ define void @shift_trunc_store_align_4(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -741,7 +741,7 @@ define void @shift_trunc_store_const_offset_1(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -777,7 +777,7 @@ define void @shift_trunc_store_const_offset_3(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -801,7 +801,7 @@ define void @shift_trunc_volatile_store(ptr %src, ptr %dst) { ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: ldr q0, [x0] ; CHECK-NEXT: shrn.4h v0, v0, #16 -; CHECK-NEXT: xtn.8b v1, v0 +; CHECK-NEXT: uzp1.8b v1, v0, v0 ; CHECK-NEXT: umov.h w8, v0[2] ; CHECK-NEXT: str s1, [sp, #12] ; CHECK-NEXT: ldrh w9, [sp, #12] @@ -816,7 +816,7 @@ define void @shift_trunc_volatile_store(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -868,7 +868,7 @@ define void @load_v3i8_zext_to_3xi32_add_trunc_store(ptr %src) { ; BE-NEXT: ushll v0.8h, v0.8b, #0 ; BE-NEXT: ld1 { v0.b }[4], [x9] ; BE-NEXT: add v0.4h, v0.4h, v1.4h -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #8] @@ -921,7 +921,7 @@ define void @load_v3i8_sext_to_3xi32_add_trunc_store(ptr %src) { ; BE-NEXT: ushll v0.8h, v0.8b, #0 ; BE-NEXT: ld1 { v0.b }[4], [x9] ; BE-NEXT: add v0.4h, v0.4h, v1.4h -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #8] -- GitLab From 3d45d8bc70d437283f8afe422011420d0fe6533e Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 13 Mar 2024 12:03:45 -0700 Subject: [PATCH 427/953] [SLP][NFC]Add a test with the operand node, not being in MinBWs, though user is in. --- .../AArch64/user-node-not-in-bitwidths.ll | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 llvm/test/Transforms/SLPVectorizer/AArch64/user-node-not-in-bitwidths.ll diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/user-node-not-in-bitwidths.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/user-node-not-in-bitwidths.ll new file mode 100644 index 000000000000..6404cf4a2cd1 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/user-node-not-in-bitwidths.ll @@ -0,0 +1,83 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s + +define void @h() { +; CHECK-LABEL: define void @h() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr null, i64 16 +; CHECK-NEXT: store <8 x i16> zeroinitializer, ptr [[ARRAYIDX2]], align 2 +; CHECK-NEXT: ret void +; +entry: + %arrayidx2 = getelementptr i8, ptr null, i64 16 + %conv310 = zext i16 0 to i32 + %add4 = or i32 %conv310, 0 + %sub = or i32 0, %conv310 + %conv15 = sext i16 0 to i32 + %shr = ashr i32 %conv15, 0 + %arrayidx18 = getelementptr i8, ptr null, i64 24 + %conv19 = sext i16 0 to i32 + %sub20 = or i32 %shr, 0 + %shr29 = ashr i32 %conv19, 0 + %add30 = or i32 %shr29, %conv15 + %sub39 = or i32 %sub, %sub20 + %conv40 = trunc i32 %sub39 to i16 + store i16 %conv40, ptr %arrayidx2, align 2 + %sub44 = or i32 %add4, %add30 + %conv45 = trunc i32 %sub44 to i16 + store i16 %conv45, ptr %arrayidx18, align 2 + %arrayidx2.1 = getelementptr i8, ptr null, i64 18 + %conv3.112 = zext i16 0 to i32 + %add4.1 = or i32 %conv3.112, 0 + %sub.1 = or i32 0, %conv3.112 + %conv15.1 = sext i16 0 to i32 + %shr.1 = ashr i32 %conv15.1, 0 + %arrayidx18.1 = getelementptr i8, ptr null, i64 26 + %conv19.1 = sext i16 0 to i32 + %sub20.1 = or i32 %shr.1, 0 + %shr29.1 = ashr i32 %conv19.1, 0 + %add30.1 = or i32 %shr29.1, 0 + %sub39.1 = or i32 %sub.1, %sub20.1 + %conv40.1 = trunc i32 %sub39.1 to i16 + store i16 %conv40.1, ptr %arrayidx2.1, align 2 + %sub44.1 = or i32 %add4.1, %add30.1 + %conv45.1 = trunc i32 %sub44.1 to i16 + store i16 %conv45.1, ptr %arrayidx18.1, align 2 + %conv.213 = zext i16 0 to i32 + %arrayidx2.2 = getelementptr i8, ptr null, i64 20 + %conv3.214 = zext i16 0 to i32 + %add4.2 = or i32 0, %conv.213 + %sub.2 = or i32 0, %conv3.214 + %conv15.2 = sext i16 0 to i32 + %shr.2 = ashr i32 %conv15.2, 0 + %arrayidx18.2 = getelementptr i8, ptr null, i64 28 + %conv19.2 = sext i16 0 to i32 + %sub20.2 = or i32 %shr.2, 0 + %shr29.2 = ashr i32 %conv19.2, 0 + %add30.2 = or i32 %shr29.2, 0 + %sub39.2 = or i32 %sub.2, %sub20.2 + %conv40.2 = trunc i32 %sub39.2 to i16 + store i16 %conv40.2, ptr %arrayidx2.2, align 2 + %sub44.2 = or i32 %add4.2, %add30.2 + %conv45.2 = trunc i32 %sub44.2 to i16 + store i16 %conv45.2, ptr %arrayidx18.2, align 2 + %conv.315 = zext i16 0 to i32 + %arrayidx2.3 = getelementptr i8, ptr null, i64 22 + %conv3.316 = zext i16 0 to i32 + %add4.3 = or i32 0, %conv.315 + %sub.3 = or i32 0, %conv3.316 + %conv15.3 = sext i16 0 to i32 + %shr.3 = ashr i32 %conv15.3, 0 + %arrayidx18.3 = getelementptr i8, ptr null, i64 30 + %conv19.3 = sext i16 0 to i32 + %sub20.3 = or i32 %shr.3, 0 + %shr29.3 = ashr i32 %conv19.3, 0 + %add30.3 = or i32 %shr29.3, 0 + %sub39.3 = or i32 %sub.3, %sub20.3 + %conv40.3 = trunc i32 %sub39.3 to i16 + store i16 %conv40.3, ptr %arrayidx2.3, align 2 + %sub44.3 = or i32 %add4.3, %add30.3 + %conv45.3 = trunc i32 %sub44.3 to i16 + store i16 %conv45.3, ptr %arrayidx18.3, align 2 + ret void +} -- GitLab From b77c079987182748fe1746466a74633cfe057cc1 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 13 Mar 2024 12:10:40 -0700 Subject: [PATCH 428/953] Revert "[SLP]Fix PR85082: PHI node has multiple entries." This reverts commit 59ff907fc14aa2d02e57b4af4140949d4f8caca1 to fix crash revealed in https://lab.llvm.org/buildbot/#/builders/198/builds/8881 --- .../Transforms/Vectorize/SLPVectorizer.cpp | 10 +-- .../X86/same-scalar-in-same-phi-extract.ll | 75 ------------------- 2 files changed, 5 insertions(+), 80 deletions(-) delete mode 100644 llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 5e0f5b7efadc..b8b67609d755 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -12592,11 +12592,6 @@ Value *BoUpSLP::vectorizeTree( } else { Ex = Builder.CreateExtractElement(Vec, Lane); } - // If necessary, sign-extend or zero-extend ScalarRoot - // to the larger type. - if (Scalar->getType() != Ex->getType()) - Ex = Builder.CreateIntCast(Ex, Scalar->getType(), - MinBWs.find(E)->second.second); if (auto *I = dyn_cast(Ex)) ScalarToEEs[Scalar].try_emplace(Builder.GetInsertBlock(), I); } @@ -12606,6 +12601,11 @@ Value *BoUpSLP::vectorizeTree( GatherShuffleExtractSeq.insert(ExI); CSEBlocks.insert(ExI->getParent()); } + // If necessary, sign-extend or zero-extend ScalarRoot + // to the larger type. + if (Scalar->getType() != Ex->getType()) + return Builder.CreateIntCast(Ex, Scalar->getType(), + MinBWs.find(E)->second.second); return Ex; } assert(isa(Scalar->getType()) && diff --git a/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll b/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll deleted file mode 100644 index 35f2f9e052e7..000000000000 --- a/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll +++ /dev/null @@ -1,75 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 -; RUN: opt -S --passes=slp-vectorizer -slp-threshold=-99999 -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s - -define void @test(i32 %arg) { -; CHECK-LABEL: define void @test( -; CHECK-SAME: i32 [[ARG:%.*]]) { -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i32> , i32 [[ARG]], i32 0 -; CHECK-NEXT: br label [[BB2:%.*]] -; CHECK: bb2: -; CHECK-NEXT: switch i32 0, label [[BB10:%.*]] [ -; CHECK-NEXT: i32 0, label [[BB9:%.*]] -; CHECK-NEXT: i32 11, label [[BB9]] -; CHECK-NEXT: i32 1, label [[BB4:%.*]] -; CHECK-NEXT: ] -; CHECK: bb3: -; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x i32> [[TMP0]], i32 0 -; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[TMP1]] to i64 -; CHECK-NEXT: switch i32 0, label [[BB10]] [ -; CHECK-NEXT: i32 18, label [[BB7:%.*]] -; CHECK-NEXT: i32 1, label [[BB7]] -; CHECK-NEXT: i32 0, label [[BB10]] -; CHECK-NEXT: ] -; CHECK: bb4: -; CHECK-NEXT: [[TMP3:%.*]] = phi <2 x i32> [ [[TMP0]], [[BB2]] ] -; CHECK-NEXT: [[TMP4:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64> -; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i64> [[TMP4]], i32 0 -; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr i32, ptr null, i64 [[TMP5]] -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i64> [[TMP4]], i32 1 -; CHECK-NEXT: [[GETELEMENTPTR6:%.*]] = getelementptr i32, ptr null, i64 [[TMP6]] -; CHECK-NEXT: ret void -; CHECK: bb7: -; CHECK-NEXT: [[PHI8:%.*]] = phi i64 [ [[TMP2]], [[BB3:%.*]] ], [ [[TMP2]], [[BB3]] ] -; CHECK-NEXT: br label [[BB9]] -; CHECK: bb9: -; CHECK-NEXT: ret void -; CHECK: bb10: -; CHECK-NEXT: ret void -; -bb: - %zext = zext i32 %arg to i64 - %zext1 = zext i32 0 to i64 - br label %bb2 - -bb2: - switch i32 0, label %bb10 [ - i32 0, label %bb9 - i32 11, label %bb9 - i32 1, label %bb4 - ] - -bb3: - switch i32 0, label %bb10 [ - i32 18, label %bb7 - i32 1, label %bb7 - i32 0, label %bb10 - ] - -bb4: - %phi = phi i64 [ %zext, %bb2 ] - %phi5 = phi i64 [ %zext1, %bb2 ] - %getelementptr = getelementptr i32, ptr null, i64 %phi - %getelementptr6 = getelementptr i32, ptr null, i64 %phi5 - ret void - -bb7: - %phi8 = phi i64 [ %zext, %bb3 ], [ %zext, %bb3 ] - br label %bb9 - -bb9: - ret void - -bb10: - ret void -} -- GitLab From aa68e2814d9a4bad21e4def900152b2e78e25e98 Mon Sep 17 00:00:00 2001 From: Kolya Panchenko <87679760+nikolaypanchenko@users.noreply.github.com> Date: Wed, 13 Mar 2024 12:18:51 -0700 Subject: [PATCH 429/953] [RISCV] Support `llvm.masked.compressstore` intrinsic (#83457) The changeset enables lowering of `llvm.masked.compressstore(%data, %ptr, %mask)` for RVV for fixed vector type into: ``` %0 = vcompress %data, %mask, %vl %new_vl = vcpop %mask, %vl vse %0, %ptr, %1, %new_vl ``` Such lowering is only possible when `%data` fits into available LMULs and otherwise `llvm.masked.compressstore` is scalarized by `ScalarizeMaskedMemIntrin` pass. Even though RVV spec in the section `15.8` provide alternative sequence for compressstore, use of `vcompress + vcpop` should be a proper canonical form to lower `llvm.masked.compressstore`. If RISC-V target find the sequence from `15.8` better, peephole optimization can transform `vcompress + vcpop` into that sequence. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 16 +- .../Target/RISCV/RISCVTargetTransformInfo.cpp | 10 + .../Target/RISCV/RISCVTargetTransformInfo.h | 2 + llvm/test/CodeGen/RISCV/rvv/compressstore.ll | 871 ++++++++++++++ .../rvv/fixed-vectors-compressstore-fp.ll | 1004 ++--------------- .../rvv/fixed-vectors-compressstore-int.ll | 928 ++------------- 6 files changed, 1085 insertions(+), 1746 deletions(-) create mode 100644 llvm/test/CodeGen/RISCV/rvv/compressstore.ll diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 08678a859ae2..803774fd16db 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -10466,6 +10466,7 @@ SDValue RISCVTargetLowering::lowerMaskedStore(SDValue Op, SDValue BasePtr = MemSD->getBasePtr(); SDValue Val, Mask, VL; + bool IsCompressingStore = false; if (const auto *VPStore = dyn_cast(Op)) { Val = VPStore->getValue(); Mask = VPStore->getMask(); @@ -10474,9 +10475,11 @@ SDValue RISCVTargetLowering::lowerMaskedStore(SDValue Op, const auto *MStore = cast(Op); Val = MStore->getValue(); Mask = MStore->getMask(); + IsCompressingStore = MStore->isCompressingStore(); } - bool IsUnmasked = ISD::isConstantSplatVectorAllOnes(Mask.getNode()); + bool IsUnmasked = + ISD::isConstantSplatVectorAllOnes(Mask.getNode()) || IsCompressingStore; MVT VT = Val.getSimpleValueType(); MVT XLenVT = Subtarget.getXLenVT(); @@ -10486,7 +10489,7 @@ SDValue RISCVTargetLowering::lowerMaskedStore(SDValue Op, ContainerVT = getContainerForFixedLengthVector(VT); Val = convertToScalableVector(ContainerVT, Val, DAG, Subtarget); - if (!IsUnmasked) { + if (!IsUnmasked || IsCompressingStore) { MVT MaskVT = getMaskTypeFor(ContainerVT); Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget); } @@ -10495,6 +10498,15 @@ SDValue RISCVTargetLowering::lowerMaskedStore(SDValue Op, if (!VL) VL = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).second; + if (IsCompressingStore) { + Val = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, ContainerVT, + DAG.getConstant(Intrinsic::riscv_vcompress, DL, XLenVT), + DAG.getUNDEF(ContainerVT), Val, Mask, VL); + VL = + DAG.getNode(RISCVISD::VCPOP_VL, DL, XLenVT, Mask, + getAllOnesMask(Mask.getSimpleValueType(), VL, DL, DAG), VL); + } + unsigned IntID = IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask; SmallVector Ops{Chain, DAG.getTargetConstant(IntID, DL, XLenVT)}; diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index ecd373649e2c..8f46fdc2f7ca 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -1620,3 +1620,13 @@ bool RISCVTTIImpl::isLSRCostLess(const TargetTransformInfo::LSRCost &C1, C2.NumIVMuls, C2.NumBaseAdds, C2.ScaleCost, C2.ImmCost, C2.SetupCost); } + +bool RISCVTTIImpl::isLegalMaskedCompressStore(Type *DataTy, Align Alignment) { + auto *VTy = dyn_cast(DataTy); + if (!VTy || VTy->isScalableTy()) + return false; + + if (!isLegalMaskedLoadStore(DataTy, Alignment)) + return false; + return true; +} diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h index af36e9d5d5e8..8daf6845dc8b 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h @@ -261,6 +261,8 @@ public: return TLI->isLegalStridedLoadStore(DataTypeVT, Alignment); } + bool isLegalMaskedCompressStore(Type *DataTy, Align Alignment); + bool isVScaleKnownToBeAPowerOfTwo() const { return TLI->isVScaleKnownToBeAPowerOfTwo(); } diff --git a/llvm/test/CodeGen/RISCV/rvv/compressstore.ll b/llvm/test/CodeGen/RISCV/rvv/compressstore.ll new file mode 100644 index 000000000000..673008d9c0b3 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/compressstore.ll @@ -0,0 +1,871 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -verify-machineinstrs -mtriple=riscv64 -mattr=+v,+d,+m,+zbb %s -o - | FileCheck %s --check-prefix=RV64 +; RUN: llc -verify-machineinstrs -mtriple=riscv32 -mattr=+v,+d,+m,+zbb %s -o - | FileCheck %s --check-prefix=RV32 + +; Compress + store for i8 type + +define void @test_compresstore_v1i8(ptr %p, <1 x i1> %mask, <1 x i8> %data) { +; RV64-LABEL: test_compresstore_v1i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 1, e8, mf8, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, mf8, ta, ma +; RV64-NEXT: vse8.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v1i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 1, e8, mf8, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, mf8, ta, ma +; RV32-NEXT: vse8.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v1i8(<1 x i8> %data, ptr align 1 %p, <1 x i1> %mask) + ret void +} + +define void @test_compresstore_v2i8(ptr %p, <2 x i1> %mask, <2 x i8> %data) { +; RV64-LABEL: test_compresstore_v2i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 2, e8, mf8, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, mf8, ta, ma +; RV64-NEXT: vse8.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v2i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 2, e8, mf8, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, mf8, ta, ma +; RV32-NEXT: vse8.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v2i8(<2 x i8> %data, ptr align 1 %p, <2 x i1> %mask) + ret void +} + +define void @test_compresstore_v4i8(ptr %p, <4 x i1> %mask, <4 x i8> %data) { +; RV64-LABEL: test_compresstore_v4i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, mf4, ta, ma +; RV64-NEXT: vse8.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v4i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, mf4, ta, ma +; RV32-NEXT: vse8.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v4i8(<4 x i8> %data, ptr align 1 %p, <4 x i1> %mask) + ret void +} + +define void @test_compresstore_v8i8(ptr %p, <8 x i1> %mask, <8 x i8> %data) { +; RV64-LABEL: test_compresstore_v8i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, mf2, ta, ma +; RV64-NEXT: vse8.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v8i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, mf2, ta, ma +; RV32-NEXT: vse8.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v8i8(<8 x i8> %data, ptr align 1 %p, <8 x i1> %mask) + ret void +} + +define void @test_compresstore_v16i8(ptr %p, <16 x i1> %mask, <16 x i8> %data) { +; RV64-LABEL: test_compresstore_v16i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, m1, ta, ma +; RV64-NEXT: vse8.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v16i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, m1, ta, ma +; RV32-NEXT: vse8.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v16i8(<16 x i8> %data, ptr align 1 %p, <16 x i1> %mask) + ret void +} + +define void @test_compresstore_v32i8(ptr %p, <32 x i1> %mask, <32 x i8> %data) { +; RV64-LABEL: test_compresstore_v32i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 32 +; RV64-NEXT: vsetvli zero, a1, e8, m2, ta, ma +; RV64-NEXT: vcompress.vm v10, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, m2, ta, ma +; RV64-NEXT: vse8.v v10, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v32i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 32 +; RV32-NEXT: vsetvli zero, a1, e8, m2, ta, ma +; RV32-NEXT: vcompress.vm v10, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, m2, ta, ma +; RV32-NEXT: vse8.v v10, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v32i8(<32 x i8> %data, ptr align 1 %p, <32 x i1> %mask) + ret void +} + +define void @test_compresstore_v64i8(ptr %p, <64 x i1> %mask, <64 x i8> %data) { +; RV64-LABEL: test_compresstore_v64i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 64 +; RV64-NEXT: vsetvli zero, a1, e8, m4, ta, ma +; RV64-NEXT: vcompress.vm v12, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, m4, ta, ma +; RV64-NEXT: vse8.v v12, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v64i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 64 +; RV32-NEXT: vsetvli zero, a1, e8, m4, ta, ma +; RV32-NEXT: vcompress.vm v12, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, m4, ta, ma +; RV32-NEXT: vse8.v v12, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v64i8(<64 x i8> %data, ptr align 1 %p, <64 x i1> %mask) + ret void +} + +define void @test_compresstore_v128i8(ptr %p, <128 x i1> %mask, <128 x i8> %data) { +; RV64-LABEL: test_compresstore_v128i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 128 +; RV64-NEXT: vsetvli zero, a1, e8, m8, ta, ma +; RV64-NEXT: vcompress.vm v16, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, m8, ta, ma +; RV64-NEXT: vse8.v v16, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v128i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 128 +; RV32-NEXT: vsetvli zero, a1, e8, m8, ta, ma +; RV32-NEXT: vcompress.vm v16, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, m8, ta, ma +; RV32-NEXT: vse8.v v16, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v128i8(<128 x i8> %data, ptr align 1 %p, <128 x i1> %mask) + ret void +} + +define void @test_compresstore_v256i8(ptr %p, <256 x i1> %mask, <256 x i8> %data) { +; RV64-LABEL: test_compresstore_v256i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vmv1r.v v7, v8 +; RV64-NEXT: li a2, 128 +; RV64-NEXT: vsetvli zero, a2, e8, m8, ta, ma +; RV64-NEXT: vle8.v v24, (a1) +; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; RV64-NEXT: vslidedown.vi v9, v0, 1 +; RV64-NEXT: vmv.x.s a1, v9 +; RV64-NEXT: vmv.x.s a3, v0 +; RV64-NEXT: vsetvli zero, a2, e8, m8, ta, ma +; RV64-NEXT: vcompress.vm v8, v16, v0 +; RV64-NEXT: vcpop.m a4, v0 +; RV64-NEXT: vsetvli zero, a4, e8, m8, ta, ma +; RV64-NEXT: vse8.v v8, (a0) +; RV64-NEXT: vsetvli zero, a2, e8, m8, ta, ma +; RV64-NEXT: vcompress.vm v8, v24, v7 +; RV64-NEXT: vcpop.m a2, v7 +; RV64-NEXT: cpop a3, a3 +; RV64-NEXT: cpop a1, a1 +; RV64-NEXT: add a0, a0, a3 +; RV64-NEXT: add a0, a0, a1 +; RV64-NEXT: vsetvli zero, a2, e8, m8, ta, ma +; RV64-NEXT: vse8.v v8, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v256i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vmv1r.v v7, v8 +; RV32-NEXT: li a2, 128 +; RV32-NEXT: vsetvli zero, a2, e8, m8, ta, ma +; RV32-NEXT: vle8.v v24, (a1) +; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; RV32-NEXT: vslidedown.vi v9, v0, 1 +; RV32-NEXT: li a1, 32 +; RV32-NEXT: vsrl.vx v10, v9, a1 +; RV32-NEXT: vmv.x.s a3, v10 +; RV32-NEXT: vsrl.vx v10, v0, a1 +; RV32-NEXT: vmv.x.s a1, v10 +; RV32-NEXT: vmv.x.s a4, v9 +; RV32-NEXT: vmv.x.s a5, v0 +; RV32-NEXT: vsetvli zero, a2, e8, m8, ta, ma +; RV32-NEXT: vcompress.vm v8, v16, v0 +; RV32-NEXT: vcpop.m a6, v0 +; RV32-NEXT: vsetvli zero, a6, e8, m8, ta, ma +; RV32-NEXT: vse8.v v8, (a0) +; RV32-NEXT: cpop a1, a1 +; RV32-NEXT: cpop a5, a5 +; RV32-NEXT: add a1, a5, a1 +; RV32-NEXT: cpop a3, a3 +; RV32-NEXT: cpop a4, a4 +; RV32-NEXT: add a3, a4, a3 +; RV32-NEXT: add a1, a1, a3 +; RV32-NEXT: add a0, a0, a1 +; RV32-NEXT: vsetvli zero, a2, e8, m8, ta, ma +; RV32-NEXT: vcompress.vm v8, v24, v7 +; RV32-NEXT: vcpop.m a1, v7 +; RV32-NEXT: vsetvli zero, a1, e8, m8, ta, ma +; RV32-NEXT: vse8.v v8, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v256i8(<256 x i8> %data, ptr align 1 %p, <256 x i1> %mask) + ret void +} + +; Compress + store for i16 type + +define void @test_compresstore_v1i16(ptr %p, <1 x i1> %mask, <1 x i16> %data) { +; RV64-LABEL: test_compresstore_v1i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 1, e16, mf4, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV64-NEXT: vse16.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v1i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 1, e16, mf4, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV32-NEXT: vse16.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v1i16(<1 x i16> %data, ptr align 2 %p, <1 x i1> %mask) + ret void +} + +define void @test_compresstore_v2i16(ptr %p, <2 x i1> %mask, <2 x i16> %data) { +; RV64-LABEL: test_compresstore_v2i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV64-NEXT: vse16.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v2i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV32-NEXT: vse16.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v2i16(<2 x i16> %data, ptr align 2 %p, <2 x i1> %mask) + ret void +} + +define void @test_compresstore_v4i16(ptr %p, <4 x i1> %mask, <4 x i16> %data) { +; RV64-LABEL: test_compresstore_v4i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, mf2, ta, ma +; RV64-NEXT: vse16.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v4i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, mf2, ta, ma +; RV32-NEXT: vse16.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v4i16(<4 x i16> %data, ptr align 2 %p, <4 x i1> %mask) + ret void +} + +define void @test_compresstore_v8i16(ptr %p, <8 x i1> %mask, <8 x i16> %data) { +; RV64-LABEL: test_compresstore_v8i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, m1, ta, ma +; RV64-NEXT: vse16.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v8i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, m1, ta, ma +; RV32-NEXT: vse16.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v8i16(<8 x i16> %data, ptr align 2 %p, <8 x i1> %mask) + ret void +} + +define void @test_compresstore_v16i16(ptr %p, <16 x i1> %mask, <16 x i16> %data) { +; RV64-LABEL: test_compresstore_v16i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; RV64-NEXT: vcompress.vm v10, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, m2, ta, ma +; RV64-NEXT: vse16.v v10, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v16i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; RV32-NEXT: vcompress.vm v10, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, m2, ta, ma +; RV32-NEXT: vse16.v v10, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v16i16(<16 x i16> %data, ptr align 2 %p, <16 x i1> %mask) + ret void +} + +define void @test_compresstore_v32i16(ptr %p, <32 x i1> %mask, <32 x i16> %data) { +; RV64-LABEL: test_compresstore_v32i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 32 +; RV64-NEXT: vsetvli zero, a1, e16, m4, ta, ma +; RV64-NEXT: vcompress.vm v12, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, m4, ta, ma +; RV64-NEXT: vse16.v v12, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v32i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 32 +; RV32-NEXT: vsetvli zero, a1, e16, m4, ta, ma +; RV32-NEXT: vcompress.vm v12, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, m4, ta, ma +; RV32-NEXT: vse16.v v12, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v32i16(<32 x i16> %data, ptr align 2 %p, <32 x i1> %mask) + ret void +} + +define void @test_compresstore_v64i16(ptr %p, <64 x i1> %mask, <64 x i16> %data) { +; RV64-LABEL: test_compresstore_v64i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 64 +; RV64-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV64-NEXT: vcompress.vm v16, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV64-NEXT: vse16.v v16, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v64i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 64 +; RV32-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV32-NEXT: vcompress.vm v16, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV32-NEXT: vse16.v v16, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v64i16(<64 x i16> %data, ptr align 2 %p, <64 x i1> %mask) + ret void +} + +define void @test_compresstore_v128i16(ptr %p, <128 x i1> %mask, <128 x i16> %data) { +; RV64-LABEL: test_compresstore_v128i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 64 +; RV64-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV64-NEXT: vcompress.vm v24, v8, v0 +; RV64-NEXT: vcpop.m a2, v0 +; RV64-NEXT: vsetvli zero, a2, e16, m8, ta, ma +; RV64-NEXT: vse16.v v24, (a0) +; RV64-NEXT: vsetivli zero, 8, e8, m1, ta, ma +; RV64-NEXT: vslidedown.vi v8, v0, 8 +; RV64-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV64-NEXT: vcompress.vm v24, v16, v8 +; RV64-NEXT: vcpop.m a2, v8 +; RV64-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV64-NEXT: vmv.x.s a1, v0 +; RV64-NEXT: cpop a1, a1 +; RV64-NEXT: slli a1, a1, 1 +; RV64-NEXT: add a0, a0, a1 +; RV64-NEXT: vsetvli zero, a2, e16, m8, ta, ma +; RV64-NEXT: vse16.v v24, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v128i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 64 +; RV32-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV32-NEXT: vcompress.vm v24, v8, v0 +; RV32-NEXT: vcpop.m a2, v0 +; RV32-NEXT: vsetvli zero, a2, e16, m8, ta, ma +; RV32-NEXT: vse16.v v24, (a0) +; RV32-NEXT: vsetivli zero, 8, e8, m1, ta, ma +; RV32-NEXT: vslidedown.vi v24, v0, 8 +; RV32-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV32-NEXT: vcompress.vm v8, v16, v24 +; RV32-NEXT: vcpop.m a1, v24 +; RV32-NEXT: li a2, 32 +; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; RV32-NEXT: vsrl.vx v16, v0, a2 +; RV32-NEXT: vmv.x.s a2, v16 +; RV32-NEXT: cpop a2, a2 +; RV32-NEXT: vmv.x.s a3, v0 +; RV32-NEXT: cpop a3, a3 +; RV32-NEXT: add a2, a3, a2 +; RV32-NEXT: slli a2, a2, 1 +; RV32-NEXT: add a0, a0, a2 +; RV32-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV32-NEXT: vse16.v v8, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v128i16(<128 x i16> %data, ptr align 2 %p, <128 x i1> %mask) + ret void +} + +; Compress + store for i32 type + +define void @test_compresstore_v1i32(ptr %p, <1 x i1> %mask, <1 x i32> %data) { +; RV64-LABEL: test_compresstore_v1i32: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 1, e32, mf2, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV64-NEXT: vse32.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v1i32: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 1, e32, mf2, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV32-NEXT: vse32.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v1i32(<1 x i32> %data, ptr align 4 %p, <1 x i1> %mask) + ret void +} + +define void @test_compresstore_v2i32(ptr %p, <2 x i1> %mask, <2 x i32> %data) { +; RV64-LABEL: test_compresstore_v2i32: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV64-NEXT: vse32.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v2i32: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV32-NEXT: vse32.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v2i32(<2 x i32> %data, ptr align 4 %p, <2 x i1> %mask) + ret void +} + +define void @test_compresstore_v4i32(ptr %p, <4 x i1> %mask, <4 x i32> %data) { +; RV64-LABEL: test_compresstore_v4i32: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, m1, ta, ma +; RV64-NEXT: vse32.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v4i32: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, m1, ta, ma +; RV32-NEXT: vse32.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v4i32(<4 x i32> %data, ptr align 4 %p, <4 x i1> %mask) + ret void +} + +define void @test_compresstore_v8i32(ptr %p, <8 x i1> %mask, <8 x i32> %data) { +; RV64-LABEL: test_compresstore_v8i32: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; RV64-NEXT: vcompress.vm v10, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, m2, ta, ma +; RV64-NEXT: vse32.v v10, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v8i32: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; RV32-NEXT: vcompress.vm v10, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, m2, ta, ma +; RV32-NEXT: vse32.v v10, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v8i32(<8 x i32> %data, ptr align 4 %p, <8 x i1> %mask) + ret void +} + +define void @test_compresstore_v16i32(ptr %p, <16 x i1> %mask, <16 x i32> %data) { +; RV64-LABEL: test_compresstore_v16i32: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 16, e32, m4, ta, ma +; RV64-NEXT: vcompress.vm v12, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, m4, ta, ma +; RV64-NEXT: vse32.v v12, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v16i32: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 16, e32, m4, ta, ma +; RV32-NEXT: vcompress.vm v12, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, m4, ta, ma +; RV32-NEXT: vse32.v v12, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v16i32(<16 x i32> %data, ptr align 4 %p, <16 x i1> %mask) + ret void +} + +define void @test_compresstore_v32i32(ptr %p, <32 x i1> %mask, <32 x i32> %data) { +; RV64-LABEL: test_compresstore_v32i32: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 32 +; RV64-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV64-NEXT: vcompress.vm v16, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV64-NEXT: vse32.v v16, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v32i32: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 32 +; RV32-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV32-NEXT: vcompress.vm v16, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV32-NEXT: vse32.v v16, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v32i32(<32 x i32> %data, ptr align 4 %p, <32 x i1> %mask) + ret void +} + +define void @test_compresstore_v64i32(ptr %p, <64 x i1> %mask, <64 x i32> %data) { +; RV64-LABEL: test_compresstore_v64i32: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 32 +; RV64-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV64-NEXT: vcompress.vm v24, v8, v0 +; RV64-NEXT: vcpop.m a2, v0 +; RV64-NEXT: vsetvli zero, a2, e32, m8, ta, ma +; RV64-NEXT: vse32.v v24, (a0) +; RV64-NEXT: vsetivli zero, 4, e8, mf2, ta, ma +; RV64-NEXT: vslidedown.vi v8, v0, 4 +; RV64-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV64-NEXT: vcompress.vm v24, v16, v8 +; RV64-NEXT: vcpop.m a1, v8 +; RV64-NEXT: vmv.x.s a2, v0 +; RV64-NEXT: cpopw a2, a2 +; RV64-NEXT: slli a2, a2, 2 +; RV64-NEXT: add a0, a0, a2 +; RV64-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV64-NEXT: vse32.v v24, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v64i32: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 32 +; RV32-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV32-NEXT: vcompress.vm v24, v8, v0 +; RV32-NEXT: vcpop.m a2, v0 +; RV32-NEXT: vsetvli zero, a2, e32, m8, ta, ma +; RV32-NEXT: vse32.v v24, (a0) +; RV32-NEXT: vsetivli zero, 4, e8, mf2, ta, ma +; RV32-NEXT: vslidedown.vi v8, v0, 4 +; RV32-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV32-NEXT: vcompress.vm v24, v16, v8 +; RV32-NEXT: vcpop.m a1, v8 +; RV32-NEXT: vmv.x.s a2, v0 +; RV32-NEXT: cpop a2, a2 +; RV32-NEXT: slli a2, a2, 2 +; RV32-NEXT: add a0, a0, a2 +; RV32-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV32-NEXT: vse32.v v24, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v64i32(<64 x i32> %data, ptr align 4 %p, <64 x i1> %mask) + ret void +} + +; Compress + store for i64 type + +define void @test_compresstore_v1i64(ptr %p, <1 x i1> %mask, <1 x i64> %data) { +; RV64-LABEL: test_compresstore_v1i64: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV64-NEXT: vse64.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v1i64: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV32-NEXT: vse64.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v1i64(<1 x i64> %data, ptr align 8 %p, <1 x i1> %mask) + ret void +} + +define void @test_compresstore_v2i64(ptr %p, <2 x i1> %mask, <2 x i64> %data) { +; RV64-LABEL: test_compresstore_v2i64: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV64-NEXT: vse64.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v2i64: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV32-NEXT: vse64.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v2i64(<2 x i64> %data, ptr align 8 %p, <2 x i1> %mask) + ret void +} + +define void @test_compresstore_v4i64(ptr %p, <4 x i1> %mask, <4 x i64> %data) { +; RV64-LABEL: test_compresstore_v4i64: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; RV64-NEXT: vcompress.vm v10, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m2, ta, ma +; RV64-NEXT: vse64.v v10, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v4i64: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; RV32-NEXT: vcompress.vm v10, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m2, ta, ma +; RV32-NEXT: vse64.v v10, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v4i64(<4 x i64> %data, ptr align 8 %p, <4 x i1> %mask) + ret void +} + +define void @test_compresstore_v8i64(ptr %p, <8 x i1> %mask, <8 x i64> %data) { +; RV64-LABEL: test_compresstore_v8i64: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma +; RV64-NEXT: vcompress.vm v12, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m4, ta, ma +; RV64-NEXT: vse64.v v12, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v8i64: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 8, e64, m4, ta, ma +; RV32-NEXT: vcompress.vm v12, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m4, ta, ma +; RV32-NEXT: vse64.v v12, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v8i64(<8 x i64> %data, ptr align 8 %p, <8 x i1> %mask) + ret void +} + +define void @test_compresstore_v16i64(ptr %p, <16 x i1> %mask, <16 x i64> %data) { +; RV64-LABEL: test_compresstore_v16i64: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 16, e64, m8, ta, ma +; RV64-NEXT: vcompress.vm v16, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m8, ta, ma +; RV64-NEXT: vse64.v v16, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v16i64: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 16, e64, m8, ta, ma +; RV32-NEXT: vcompress.vm v16, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m8, ta, ma +; RV32-NEXT: vse64.v v16, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v16i64(<16 x i64> %data, ptr align 8 %p, <16 x i1> %mask) + ret void +} + +define void @test_compresstore_v32i64(ptr %p, <32 x i1> %mask, <32 x i64> %data) { +; RV64-LABEL: test_compresstore_v32i64: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 16, e64, m8, ta, ma +; RV64-NEXT: vcompress.vm v24, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m8, ta, ma +; RV64-NEXT: vse64.v v24, (a0) +; RV64-NEXT: vsetivli zero, 2, e8, mf4, ta, ma +; RV64-NEXT: vslidedown.vi v24, v0, 2 +; RV64-NEXT: vsetivli zero, 16, e64, m8, ta, ma +; RV64-NEXT: vcompress.vm v8, v16, v24 +; RV64-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; RV64-NEXT: vmv.x.s a1, v0 +; RV64-NEXT: zext.h a1, a1 +; RV64-NEXT: cpopw a1, a1 +; RV64-NEXT: slli a1, a1, 3 +; RV64-NEXT: add a0, a0, a1 +; RV64-NEXT: vcpop.m a1, v24 +; RV64-NEXT: vsetvli zero, a1, e64, m8, ta, ma +; RV64-NEXT: vse64.v v8, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v32i64: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 16, e64, m8, ta, ma +; RV32-NEXT: vcompress.vm v24, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m8, ta, ma +; RV32-NEXT: vse64.v v24, (a0) +; RV32-NEXT: vsetivli zero, 2, e8, mf4, ta, ma +; RV32-NEXT: vslidedown.vi v24, v0, 2 +; RV32-NEXT: vsetivli zero, 16, e64, m8, ta, ma +; RV32-NEXT: vcompress.vm v8, v16, v24 +; RV32-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; RV32-NEXT: vmv.x.s a1, v0 +; RV32-NEXT: zext.h a1, a1 +; RV32-NEXT: cpop a1, a1 +; RV32-NEXT: slli a1, a1, 3 +; RV32-NEXT: add a0, a0, a1 +; RV32-NEXT: vcpop.m a1, v24 +; RV32-NEXT: vsetvli zero, a1, e64, m8, ta, ma +; RV32-NEXT: vse64.v v8, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v32i64(<32 x i64> %data, ptr align 8 %p, <32 x i1> %mask) + ret void +} + +declare void @llvm.masked.compressstore.v1i8(<1 x i8>, ptr, <1 x i1>) +declare void @llvm.masked.compressstore.v2i8(<2 x i8>, ptr, <2 x i1>) +declare void @llvm.masked.compressstore.v4i8(<4 x i8>, ptr, <4 x i1>) +declare void @llvm.masked.compressstore.v8i8(<8 x i8>, ptr, <8 x i1>) +declare void @llvm.masked.compressstore.v16i8(<16 x i8>, ptr, <16 x i1>) +declare void @llvm.masked.compressstore.v32i8(<32 x i8>, ptr, <32 x i1>) +declare void @llvm.masked.compressstore.v64i8(<64 x i8>, ptr, <64 x i1>) +declare void @llvm.masked.compressstore.v128i8(<128 x i8>, ptr, <128 x i1>) +declare void @llvm.masked.compressstore.v256i8(<256 x i8>, ptr, <256 x i1>) + +declare void @llvm.masked.compressstore.v1i16(<1 x i16>, ptr, <1 x i1>) +declare void @llvm.masked.compressstore.v2i16(<2 x i16>, ptr, <2 x i1>) +declare void @llvm.masked.compressstore.v4i16(<4 x i16>, ptr, <4 x i1>) +declare void @llvm.masked.compressstore.v8i16(<8 x i16>, ptr, <8 x i1>) +declare void @llvm.masked.compressstore.v16i16(<16 x i16>, ptr, <16 x i1>) +declare void @llvm.masked.compressstore.v32i16(<32 x i16>, ptr, <32 x i1>) +declare void @llvm.masked.compressstore.v64i16(<64 x i16>, ptr, <64 x i1>) +declare void @llvm.masked.compressstore.v128i16(<128 x i16>, ptr, <128 x i1>) + +declare void @llvm.masked.compressstore.v1i32(<1 x i32>, ptr, <1 x i1>) +declare void @llvm.masked.compressstore.v2i32(<2 x i32>, ptr, <2 x i1>) +declare void @llvm.masked.compressstore.v4i32(<4 x i32>, ptr, <4 x i1>) +declare void @llvm.masked.compressstore.v8i32(<8 x i32>, ptr, <8 x i1>) +declare void @llvm.masked.compressstore.v16i32(<16 x i32>, ptr, <16 x i1>) +declare void @llvm.masked.compressstore.v32i32(<32 x i32>, ptr, <32 x i1>) +declare void @llvm.masked.compressstore.v64i32(<64 x i32>, ptr, <64 x i1>) + +declare void @llvm.masked.compressstore.v1i64(<1 x i64>, ptr, <1 x i1>) +declare void @llvm.masked.compressstore.v2i64(<2 x i64>, ptr, <2 x i1>) +declare void @llvm.masked.compressstore.v4i64(<4 x i64>, ptr, <4 x i1>) +declare void @llvm.masked.compressstore.v8i64(<8 x i64>, ptr, <8 x i1>) +declare void @llvm.masked.compressstore.v16i64(<16 x i64>, ptr, <16 x i1>) +declare void @llvm.masked.compressstore.v32i64(<32 x i64>, ptr, <32 x i1>) diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-fp.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-fp.ll index 52c52921e7e1..36fbdd8e0664 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-fp.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-fp.ll @@ -6,24 +6,20 @@ declare void @llvm.masked.compressstore.v1f16(<1 x half>, ptr, <1 x i1>) define void @compressstore_v1f16(ptr %base, <1 x half> %v, <1 x i1> %mask) { ; RV32-LABEL: compressstore_v1f16: ; RV32: # %bb.0: -; RV32-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV32-NEXT: vfirst.m a1, v0 -; RV32-NEXT: bnez a1, .LBB0_2 -; RV32-NEXT: # %bb.1: # %cond.store ; RV32-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; RV32-NEXT: vse16.v v8, (a0) -; RV32-NEXT: .LBB0_2: # %else +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV32-NEXT: vse16.v v9, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v1f16: ; RV64: # %bb.0: -; RV64-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV64-NEXT: vfirst.m a1, v0 -; RV64-NEXT: bnez a1, .LBB0_2 -; RV64-NEXT: # %bb.1: # %cond.store ; RV64-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; RV64-NEXT: vse16.v v8, (a0) -; RV64-NEXT: .LBB0_2: # %else +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV64-NEXT: vse16.v v9, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v1f16(<1 x half> %v, ptr align 2 %base, <1 x i1> %mask) ret void @@ -33,48 +29,20 @@ declare void @llvm.masked.compressstore.v2f16(<2 x half>, ptr, <2 x i1>) define void @compressstore_v2f16(ptr %base, <2 x half> %v, <2 x i1> %mask) { ; RV32-LABEL: compressstore_v2f16: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB1_3 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: bnez a1, .LBB1_4 -; RV32-NEXT: .LBB1_2: # %else2 -; RV32-NEXT: ret -; RV32-NEXT: .LBB1_3: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; RV32-NEXT: vse16.v v8, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: beqz a1, .LBB1_2 -; RV32-NEXT: .LBB1_4: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 1 -; RV32-NEXT: vse16.v v8, (a0) +; RV32-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV32-NEXT: vse16.v v9, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v2f16: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB1_3 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: bnez a1, .LBB1_4 -; RV64-NEXT: .LBB1_2: # %else2 -; RV64-NEXT: ret -; RV64-NEXT: .LBB1_3: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; RV64-NEXT: vse16.v v8, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: beqz a1, .LBB1_2 -; RV64-NEXT: .LBB1_4: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 1 -; RV64-NEXT: vse16.v v8, (a0) +; RV64-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV64-NEXT: vse16.v v9, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v2f16(<2 x half> %v, ptr align 2 %base, <2 x i1> %mask) ret void @@ -84,88 +52,20 @@ declare void @llvm.masked.compressstore.v4f16(<4 x half>, ptr, <4 x i1>) define void @compressstore_v4f16(ptr %base, <4 x half> %v, <4 x i1> %mask) { ; RV32-LABEL: compressstore_v4f16: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB2_5 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB2_6 -; RV32-NEXT: .LBB2_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB2_7 -; RV32-NEXT: .LBB2_3: # %else5 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: bnez a1, .LBB2_8 -; RV32-NEXT: .LBB2_4: # %else8 -; RV32-NEXT: ret -; RV32-NEXT: .LBB2_5: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV32-NEXT: vse16.v v8, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB2_2 -; RV32-NEXT: .LBB2_6: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 1 -; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB2_3 -; RV32-NEXT: .LBB2_7: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 2 +; RV32-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, mf2, ta, ma ; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: beqz a1, .LBB2_4 -; RV32-NEXT: .LBB2_8: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 3 -; RV32-NEXT: vse16.v v8, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v4f16: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB2_5 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB2_6 -; RV64-NEXT: .LBB2_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB2_7 -; RV64-NEXT: .LBB2_3: # %else5 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: bnez a1, .LBB2_8 -; RV64-NEXT: .LBB2_4: # %else8 -; RV64-NEXT: ret -; RV64-NEXT: .LBB2_5: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV64-NEXT: vse16.v v8, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB2_2 -; RV64-NEXT: .LBB2_6: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 1 -; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB2_3 -; RV64-NEXT: .LBB2_7: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 2 +; RV64-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, mf2, ta, ma ; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: beqz a1, .LBB2_4 -; RV64-NEXT: .LBB2_8: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 3 -; RV64-NEXT: vse16.v v8, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v4f16(<4 x half> %v, ptr align 2 %base, <4 x i1> %mask) ret void @@ -175,168 +75,20 @@ declare void @llvm.masked.compressstore.v8f16(<8 x half>, ptr, <8 x i1>) define void @compressstore_v8f16(ptr %base, <8 x half> %v, <8 x i1> %mask) { ; RV32-LABEL: compressstore_v8f16: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB3_9 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB3_10 -; RV32-NEXT: .LBB3_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB3_11 -; RV32-NEXT: .LBB3_3: # %else5 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: bnez a2, .LBB3_12 -; RV32-NEXT: .LBB3_4: # %else8 -; RV32-NEXT: andi a2, a1, 16 -; RV32-NEXT: bnez a2, .LBB3_13 -; RV32-NEXT: .LBB3_5: # %else11 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: bnez a2, .LBB3_14 -; RV32-NEXT: .LBB3_6: # %else14 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: bnez a2, .LBB3_15 -; RV32-NEXT: .LBB3_7: # %else17 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: bnez a1, .LBB3_16 -; RV32-NEXT: .LBB3_8: # %else20 -; RV32-NEXT: ret -; RV32-NEXT: .LBB3_9: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vse16.v v8, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB3_2 -; RV32-NEXT: .LBB3_10: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 1 -; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB3_3 -; RV32-NEXT: .LBB3_11: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 2 -; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: beqz a2, .LBB3_4 -; RV32-NEXT: .LBB3_12: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 3 -; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 16 -; RV32-NEXT: beqz a2, .LBB3_5 -; RV32-NEXT: .LBB3_13: # %cond.store10 -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 4 +; RV32-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, m1, ta, ma ; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: beqz a2, .LBB3_6 -; RV32-NEXT: .LBB3_14: # %cond.store13 -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 5 -; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: beqz a2, .LBB3_7 -; RV32-NEXT: .LBB3_15: # %cond.store16 -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 6 -; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: beqz a1, .LBB3_8 -; RV32-NEXT: .LBB3_16: # %cond.store19 -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 7 -; RV32-NEXT: vse16.v v8, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v8f16: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB3_9 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB3_10 -; RV64-NEXT: .LBB3_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB3_11 -; RV64-NEXT: .LBB3_3: # %else5 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: bnez a2, .LBB3_12 -; RV64-NEXT: .LBB3_4: # %else8 -; RV64-NEXT: andi a2, a1, 16 -; RV64-NEXT: bnez a2, .LBB3_13 -; RV64-NEXT: .LBB3_5: # %else11 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: bnez a2, .LBB3_14 -; RV64-NEXT: .LBB3_6: # %else14 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: bnez a2, .LBB3_15 -; RV64-NEXT: .LBB3_7: # %else17 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: bnez a1, .LBB3_16 -; RV64-NEXT: .LBB3_8: # %else20 -; RV64-NEXT: ret -; RV64-NEXT: .LBB3_9: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vse16.v v8, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB3_2 -; RV64-NEXT: .LBB3_10: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 1 -; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB3_3 -; RV64-NEXT: .LBB3_11: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 2 -; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: beqz a2, .LBB3_4 -; RV64-NEXT: .LBB3_12: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 3 +; RV64-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, m1, ta, ma ; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 16 -; RV64-NEXT: beqz a2, .LBB3_5 -; RV64-NEXT: .LBB3_13: # %cond.store10 -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 4 -; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: beqz a2, .LBB3_6 -; RV64-NEXT: .LBB3_14: # %cond.store13 -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 5 -; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: beqz a2, .LBB3_7 -; RV64-NEXT: .LBB3_15: # %cond.store16 -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 6 -; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: beqz a1, .LBB3_8 -; RV64-NEXT: .LBB3_16: # %cond.store19 -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 7 -; RV64-NEXT: vse16.v v8, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v8f16(<8 x half> %v, ptr align 2 %base, <8 x i1> %mask) ret void @@ -346,24 +98,20 @@ declare void @llvm.masked.compressstore.v1f32(<1 x float>, ptr, <1 x i1>) define void @compressstore_v1f32(ptr %base, <1 x float> %v, <1 x i1> %mask) { ; RV32-LABEL: compressstore_v1f32: ; RV32: # %bb.0: -; RV32-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV32-NEXT: vfirst.m a1, v0 -; RV32-NEXT: bnez a1, .LBB4_2 -; RV32-NEXT: # %bb.1: # %cond.store ; RV32-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; RV32-NEXT: vse32.v v8, (a0) -; RV32-NEXT: .LBB4_2: # %else +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV32-NEXT: vse32.v v9, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v1f32: ; RV64: # %bb.0: -; RV64-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV64-NEXT: vfirst.m a1, v0 -; RV64-NEXT: bnez a1, .LBB4_2 -; RV64-NEXT: # %bb.1: # %cond.store ; RV64-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; RV64-NEXT: vse32.v v8, (a0) -; RV64-NEXT: .LBB4_2: # %else +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV64-NEXT: vse32.v v9, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v1f32(<1 x float> %v, ptr align 4 %base, <1 x i1> %mask) ret void @@ -373,48 +121,20 @@ declare void @llvm.masked.compressstore.v2f32(<2 x float>, ptr, <2 x i1>) define void @compressstore_v2f32(ptr %base, <2 x float> %v, <2 x i1> %mask) { ; RV32-LABEL: compressstore_v2f32: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB5_3 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: bnez a1, .LBB5_4 -; RV32-NEXT: .LBB5_2: # %else2 -; RV32-NEXT: ret -; RV32-NEXT: .LBB5_3: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; RV32-NEXT: vse32.v v8, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: beqz a1, .LBB5_2 -; RV32-NEXT: .LBB5_4: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 1 -; RV32-NEXT: vse32.v v8, (a0) +; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV32-NEXT: vse32.v v9, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v2f32: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB5_3 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: bnez a1, .LBB5_4 -; RV64-NEXT: .LBB5_2: # %else2 -; RV64-NEXT: ret -; RV64-NEXT: .LBB5_3: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; RV64-NEXT: vse32.v v8, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: beqz a1, .LBB5_2 -; RV64-NEXT: .LBB5_4: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 1 -; RV64-NEXT: vse32.v v8, (a0) +; RV64-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV64-NEXT: vse32.v v9, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v2f32(<2 x float> %v, ptr align 4 %base, <2 x i1> %mask) ret void @@ -424,88 +144,20 @@ declare void @llvm.masked.compressstore.v4f32(<4 x float>, ptr, <4 x i1>) define void @compressstore_v4f32(ptr %base, <4 x float> %v, <4 x i1> %mask) { ; RV32-LABEL: compressstore_v4f32: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB6_5 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB6_6 -; RV32-NEXT: .LBB6_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB6_7 -; RV32-NEXT: .LBB6_3: # %else5 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: bnez a1, .LBB6_8 -; RV32-NEXT: .LBB6_4: # %else8 -; RV32-NEXT: ret -; RV32-NEXT: .LBB6_5: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vse32.v v8, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB6_2 -; RV32-NEXT: .LBB6_6: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 1 -; RV32-NEXT: vse32.v v9, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB6_3 -; RV32-NEXT: .LBB6_7: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 2 +; RV32-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, m1, ta, ma ; RV32-NEXT: vse32.v v9, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: beqz a1, .LBB6_4 -; RV32-NEXT: .LBB6_8: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 3 -; RV32-NEXT: vse32.v v8, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v4f32: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB6_5 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB6_6 -; RV64-NEXT: .LBB6_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB6_7 -; RV64-NEXT: .LBB6_3: # %else5 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: bnez a1, .LBB6_8 -; RV64-NEXT: .LBB6_4: # %else8 -; RV64-NEXT: ret -; RV64-NEXT: .LBB6_5: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vse32.v v8, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB6_2 -; RV64-NEXT: .LBB6_6: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 1 -; RV64-NEXT: vse32.v v9, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB6_3 -; RV64-NEXT: .LBB6_7: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 2 +; RV64-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, m1, ta, ma ; RV64-NEXT: vse32.v v9, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: beqz a1, .LBB6_4 -; RV64-NEXT: .LBB6_8: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 3 -; RV64-NEXT: vse32.v v8, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v4f32(<4 x float> %v, ptr align 4 %base, <4 x i1> %mask) ret void @@ -515,176 +167,20 @@ declare void @llvm.masked.compressstore.v8f32(<8 x float>, ptr, <8 x i1>) define void @compressstore_v8f32(ptr %base, <8 x float> %v, <8 x i1> %mask) { ; RV32-LABEL: compressstore_v8f32: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB7_9 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB7_10 -; RV32-NEXT: .LBB7_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB7_11 -; RV32-NEXT: .LBB7_3: # %else5 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: bnez a2, .LBB7_12 -; RV32-NEXT: .LBB7_4: # %else8 -; RV32-NEXT: andi a2, a1, 16 -; RV32-NEXT: bnez a2, .LBB7_13 -; RV32-NEXT: .LBB7_5: # %else11 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: bnez a2, .LBB7_14 -; RV32-NEXT: .LBB7_6: # %else14 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: bnez a2, .LBB7_15 -; RV32-NEXT: .LBB7_7: # %else17 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: bnez a1, .LBB7_16 -; RV32-NEXT: .LBB7_8: # %else20 -; RV32-NEXT: ret -; RV32-NEXT: .LBB7_9: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vse32.v v8, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB7_2 -; RV32-NEXT: .LBB7_10: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 1 -; RV32-NEXT: vse32.v v10, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB7_3 -; RV32-NEXT: .LBB7_11: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 2 -; RV32-NEXT: vse32.v v10, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: beqz a2, .LBB7_4 -; RV32-NEXT: .LBB7_12: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 3 -; RV32-NEXT: vse32.v v10, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 16 -; RV32-NEXT: beqz a2, .LBB7_5 -; RV32-NEXT: .LBB7_13: # %cond.store10 -; RV32-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 4 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vse32.v v10, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: beqz a2, .LBB7_6 -; RV32-NEXT: .LBB7_14: # %cond.store13 -; RV32-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 5 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vse32.v v10, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: beqz a2, .LBB7_7 -; RV32-NEXT: .LBB7_15: # %cond.store16 -; RV32-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 6 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma +; RV32-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; RV32-NEXT: vcompress.vm v10, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, m2, ta, ma ; RV32-NEXT: vse32.v v10, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: beqz a1, .LBB7_8 -; RV32-NEXT: .LBB7_16: # %cond.store19 -; RV32-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 7 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vse32.v v8, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v8f32: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB7_9 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB7_10 -; RV64-NEXT: .LBB7_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB7_11 -; RV64-NEXT: .LBB7_3: # %else5 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: bnez a2, .LBB7_12 -; RV64-NEXT: .LBB7_4: # %else8 -; RV64-NEXT: andi a2, a1, 16 -; RV64-NEXT: bnez a2, .LBB7_13 -; RV64-NEXT: .LBB7_5: # %else11 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: bnez a2, .LBB7_14 -; RV64-NEXT: .LBB7_6: # %else14 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: bnez a2, .LBB7_15 -; RV64-NEXT: .LBB7_7: # %else17 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: bnez a1, .LBB7_16 -; RV64-NEXT: .LBB7_8: # %else20 -; RV64-NEXT: ret -; RV64-NEXT: .LBB7_9: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vse32.v v8, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB7_2 -; RV64-NEXT: .LBB7_10: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 1 -; RV64-NEXT: vse32.v v10, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB7_3 -; RV64-NEXT: .LBB7_11: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 2 -; RV64-NEXT: vse32.v v10, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: beqz a2, .LBB7_4 -; RV64-NEXT: .LBB7_12: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 3 -; RV64-NEXT: vse32.v v10, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 16 -; RV64-NEXT: beqz a2, .LBB7_5 -; RV64-NEXT: .LBB7_13: # %cond.store10 -; RV64-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 4 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vse32.v v10, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: beqz a2, .LBB7_6 -; RV64-NEXT: .LBB7_14: # %cond.store13 -; RV64-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 5 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vse32.v v10, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: beqz a2, .LBB7_7 -; RV64-NEXT: .LBB7_15: # %cond.store16 -; RV64-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 6 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma +; RV64-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; RV64-NEXT: vcompress.vm v10, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, m2, ta, ma ; RV64-NEXT: vse32.v v10, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: beqz a1, .LBB7_8 -; RV64-NEXT: .LBB7_16: # %cond.store19 -; RV64-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 7 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vse32.v v8, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v8f32(<8 x float> %v, ptr align 4 %base, <8 x i1> %mask) ret void @@ -694,24 +190,20 @@ declare void @llvm.masked.compressstore.v1f64(<1 x double>, ptr, <1 x i1>) define void @compressstore_v1f64(ptr %base, <1 x double> %v, <1 x i1> %mask) { ; RV32-LABEL: compressstore_v1f64: ; RV32: # %bb.0: -; RV32-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV32-NEXT: vfirst.m a1, v0 -; RV32-NEXT: bnez a1, .LBB8_2 -; RV32-NEXT: # %bb.1: # %cond.store ; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v8, (a0) -; RV32-NEXT: .LBB8_2: # %else +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV32-NEXT: vse64.v v9, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v1f64: ; RV64: # %bb.0: -; RV64-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV64-NEXT: vfirst.m a1, v0 -; RV64-NEXT: bnez a1, .LBB8_2 -; RV64-NEXT: # %bb.1: # %cond.store ; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: .LBB8_2: # %else +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV64-NEXT: vse64.v v9, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v1f64(<1 x double> %v, ptr align 8 %base, <1 x i1> %mask) ret void @@ -721,48 +213,20 @@ declare void @llvm.masked.compressstore.v2f64(<2 x double>, ptr, <2 x i1>) define void @compressstore_v2f64(ptr %base, <2 x double> %v, <2 x i1> %mask) { ; RV32-LABEL: compressstore_v2f64: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB9_3 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: bnez a1, .LBB9_4 -; RV32-NEXT: .LBB9_2: # %else2 -; RV32-NEXT: ret -; RV32-NEXT: .LBB9_3: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v8, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: beqz a1, .LBB9_2 -; RV32-NEXT: .LBB9_4: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 1 -; RV32-NEXT: vse64.v v8, (a0) +; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV32-NEXT: vse64.v v9, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v2f64: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB9_3 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: bnez a1, .LBB9_4 -; RV64-NEXT: .LBB9_2: # %else2 -; RV64-NEXT: ret -; RV64-NEXT: .LBB9_3: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: beqz a1, .LBB9_2 -; RV64-NEXT: .LBB9_4: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 1 -; RV64-NEXT: vse64.v v8, (a0) +; RV64-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV64-NEXT: vse64.v v9, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v2f64(<2 x double> %v, ptr align 8 %base, <2 x i1> %mask) ret void @@ -772,92 +236,20 @@ declare void @llvm.masked.compressstore.v4f64(<4 x double>, ptr, <4 x i1>) define void @compressstore_v4f64(ptr %base, <4 x double> %v, <4 x i1> %mask) { ; RV32-LABEL: compressstore_v4f64: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB10_5 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB10_6 -; RV32-NEXT: .LBB10_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB10_7 -; RV32-NEXT: .LBB10_3: # %else5 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: bnez a1, .LBB10_8 -; RV32-NEXT: .LBB10_4: # %else8 -; RV32-NEXT: ret -; RV32-NEXT: .LBB10_5: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v8, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB10_2 -; RV32-NEXT: .LBB10_6: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 1 +; RV32-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; RV32-NEXT: vcompress.vm v10, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m2, ta, ma ; RV32-NEXT: vse64.v v10, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB10_3 -; RV32-NEXT: .LBB10_7: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 2 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v10, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: beqz a1, .LBB10_4 -; RV32-NEXT: .LBB10_8: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 3 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v8, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v4f64: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB10_5 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB10_6 -; RV64-NEXT: .LBB10_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB10_7 -; RV64-NEXT: .LBB10_3: # %else5 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: bnez a1, .LBB10_8 -; RV64-NEXT: .LBB10_4: # %else8 -; RV64-NEXT: ret -; RV64-NEXT: .LBB10_5: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB10_2 -; RV64-NEXT: .LBB10_6: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 1 -; RV64-NEXT: vse64.v v10, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB10_3 -; RV64-NEXT: .LBB10_7: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 2 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; RV64-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; RV64-NEXT: vcompress.vm v10, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m2, ta, ma ; RV64-NEXT: vse64.v v10, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: beqz a1, .LBB10_4 -; RV64-NEXT: .LBB10_8: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 3 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v4f64(<4 x double> %v, ptr align 8 %base, <4 x i1> %mask) ret void @@ -867,213 +259,21 @@ declare void @llvm.masked.compressstore.v8f64(<8 x double>, ptr, <8 x i1>) define void @compressstore_v8f64(ptr %base, <8 x double> %v, <8 x i1> %mask) { ; RV32-LABEL: compressstore_v8f64: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB11_11 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB11_12 -; RV32-NEXT: .LBB11_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB11_13 -; RV32-NEXT: .LBB11_3: # %else5 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: beqz a2, .LBB11_5 -; RV32-NEXT: .LBB11_4: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 3 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v12, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: .LBB11_5: # %else8 -; RV32-NEXT: addi sp, sp, -320 -; RV32-NEXT: .cfi_def_cfa_offset 320 -; RV32-NEXT: sw ra, 316(sp) # 4-byte Folded Spill -; RV32-NEXT: sw s0, 312(sp) # 4-byte Folded Spill -; RV32-NEXT: .cfi_offset ra, -4 -; RV32-NEXT: .cfi_offset s0, -8 -; RV32-NEXT: addi s0, sp, 320 -; RV32-NEXT: .cfi_def_cfa s0, 0 -; RV32-NEXT: andi sp, sp, -64 -; RV32-NEXT: andi a2, a1, 16 -; RV32-NEXT: bnez a2, .LBB11_14 -; RV32-NEXT: # %bb.6: # %else11 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: bnez a2, .LBB11_15 -; RV32-NEXT: .LBB11_7: # %else14 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: bnez a2, .LBB11_16 -; RV32-NEXT: .LBB11_8: # %else17 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: beqz a1, .LBB11_10 -; RV32-NEXT: .LBB11_9: # %cond.store19 -; RV32-NEXT: mv a1, sp ; RV32-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV32-NEXT: vse64.v v8, (a1) -; RV32-NEXT: fld fa5, 56(sp) -; RV32-NEXT: fsd fa5, 0(a0) -; RV32-NEXT: .LBB11_10: # %else20 -; RV32-NEXT: addi sp, s0, -320 -; RV32-NEXT: lw ra, 316(sp) # 4-byte Folded Reload -; RV32-NEXT: lw s0, 312(sp) # 4-byte Folded Reload -; RV32-NEXT: addi sp, sp, 320 -; RV32-NEXT: ret -; RV32-NEXT: .LBB11_11: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v8, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB11_2 -; RV32-NEXT: .LBB11_12: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 1 +; RV32-NEXT: vcompress.vm v12, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m4, ta, ma ; RV32-NEXT: vse64.v v12, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB11_3 -; RV32-NEXT: .LBB11_13: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 2 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v12, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: bnez a2, .LBB11_4 -; RV32-NEXT: j .LBB11_5 -; RV32-NEXT: .LBB11_14: # %cond.store10 -; RV32-NEXT: addi a2, sp, 192 -; RV32-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV32-NEXT: vse64.v v8, (a2) -; RV32-NEXT: fld fa5, 224(sp) -; RV32-NEXT: fsd fa5, 0(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: beqz a2, .LBB11_7 -; RV32-NEXT: .LBB11_15: # %cond.store13 -; RV32-NEXT: addi a2, sp, 128 -; RV32-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV32-NEXT: vse64.v v8, (a2) -; RV32-NEXT: fld fa5, 168(sp) -; RV32-NEXT: fsd fa5, 0(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: beqz a2, .LBB11_8 -; RV32-NEXT: .LBB11_16: # %cond.store16 -; RV32-NEXT: addi a2, sp, 64 -; RV32-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV32-NEXT: vse64.v v8, (a2) -; RV32-NEXT: fld fa5, 112(sp) -; RV32-NEXT: fsd fa5, 0(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: bnez a1, .LBB11_9 -; RV32-NEXT: j .LBB11_10 +; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v8f64: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB11_11 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB11_12 -; RV64-NEXT: .LBB11_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB11_13 -; RV64-NEXT: .LBB11_3: # %else5 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: beqz a2, .LBB11_5 -; RV64-NEXT: .LBB11_4: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v12, v8, 3 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v12, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: .LBB11_5: # %else8 -; RV64-NEXT: addi sp, sp, -320 -; RV64-NEXT: .cfi_def_cfa_offset 320 -; RV64-NEXT: sd ra, 312(sp) # 8-byte Folded Spill -; RV64-NEXT: sd s0, 304(sp) # 8-byte Folded Spill -; RV64-NEXT: .cfi_offset ra, -8 -; RV64-NEXT: .cfi_offset s0, -16 -; RV64-NEXT: addi s0, sp, 320 -; RV64-NEXT: .cfi_def_cfa s0, 0 -; RV64-NEXT: andi sp, sp, -64 -; RV64-NEXT: andi a2, a1, 16 -; RV64-NEXT: bnez a2, .LBB11_14 -; RV64-NEXT: # %bb.6: # %else11 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: bnez a2, .LBB11_15 -; RV64-NEXT: .LBB11_7: # %else14 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: bnez a2, .LBB11_16 -; RV64-NEXT: .LBB11_8: # %else17 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: beqz a1, .LBB11_10 -; RV64-NEXT: .LBB11_9: # %cond.store19 -; RV64-NEXT: mv a1, sp ; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a1) -; RV64-NEXT: fld fa5, 56(sp) -; RV64-NEXT: fsd fa5, 0(a0) -; RV64-NEXT: .LBB11_10: # %else20 -; RV64-NEXT: addi sp, s0, -320 -; RV64-NEXT: ld ra, 312(sp) # 8-byte Folded Reload -; RV64-NEXT: ld s0, 304(sp) # 8-byte Folded Reload -; RV64-NEXT: addi sp, sp, 320 -; RV64-NEXT: ret -; RV64-NEXT: .LBB11_11: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB11_2 -; RV64-NEXT: .LBB11_12: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vslidedown.vi v12, v8, 1 +; RV64-NEXT: vcompress.vm v12, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m4, ta, ma ; RV64-NEXT: vse64.v v12, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB11_3 -; RV64-NEXT: .LBB11_13: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v12, v8, 2 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v12, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: bnez a2, .LBB11_4 -; RV64-NEXT: j .LBB11_5 -; RV64-NEXT: .LBB11_14: # %cond.store10 -; RV64-NEXT: addi a2, sp, 192 -; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a2) -; RV64-NEXT: fld fa5, 224(sp) -; RV64-NEXT: fsd fa5, 0(a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: beqz a2, .LBB11_7 -; RV64-NEXT: .LBB11_15: # %cond.store13 -; RV64-NEXT: addi a2, sp, 128 -; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a2) -; RV64-NEXT: fld fa5, 168(sp) -; RV64-NEXT: fsd fa5, 0(a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: beqz a2, .LBB11_8 -; RV64-NEXT: .LBB11_16: # %cond.store16 -; RV64-NEXT: addi a2, sp, 64 -; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a2) -; RV64-NEXT: fld fa5, 112(sp) -; RV64-NEXT: fsd fa5, 0(a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: bnez a1, .LBB11_9 -; RV64-NEXT: j .LBB11_10 +; RV64-NEXT: ret call void @llvm.masked.compressstore.v8f64(<8 x double> %v, ptr align 8 %base, <8 x i1> %mask) ret void } diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-int.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-int.ll index eb0096dbfba6..a388ba92f302 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-int.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-int.ll @@ -6,13 +6,11 @@ declare void @llvm.masked.compressstore.v1i8(<1 x i8>, ptr, <1 x i1>) define void @compressstore_v1i8(ptr %base, <1 x i8> %v, <1 x i1> %mask) { ; CHECK-LABEL: compressstore_v1i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; CHECK-NEXT: vfirst.m a1, v0 -; CHECK-NEXT: bnez a1, .LBB0_2 -; CHECK-NEXT: # %bb.1: # %cond.store ; CHECK-NEXT: vsetivli zero, 1, e8, mf8, ta, ma -; CHECK-NEXT: vse8.v v8, (a0) -; CHECK-NEXT: .LBB0_2: # %else +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e8, mf8, ta, ma +; CHECK-NEXT: vse8.v v9, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v1i8(<1 x i8> %v, ptr %base, <1 x i1> %mask) ret void @@ -22,25 +20,11 @@ declare void @llvm.masked.compressstore.v2i8(<2 x i8>, ptr, <2 x i1>) define void @compressstore_v2i8(ptr %base, <2 x i8> %v, <2 x i1> %mask) { ; CHECK-LABEL: compressstore_v2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB1_3 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a1, a1, 2 -; CHECK-NEXT: bnez a1, .LBB1_4 -; CHECK-NEXT: .LBB1_2: # %else2 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB1_3: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e8, mf8, ta, ma -; CHECK-NEXT: vse8.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a1, a1, 2 -; CHECK-NEXT: beqz a1, .LBB1_2 -; CHECK-NEXT: .LBB1_4: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e8, mf8, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 1 -; CHECK-NEXT: vse8.v v8, (a0) +; CHECK-NEXT: vsetivli zero, 2, e8, mf8, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e8, mf8, ta, ma +; CHECK-NEXT: vse8.v v9, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v2i8(<2 x i8> %v, ptr %base, <2 x i1> %mask) ret void @@ -50,45 +34,11 @@ declare void @llvm.masked.compressstore.v4i8(<4 x i8>, ptr, <4 x i1>) define void @compressstore_v4i8(ptr %base, <4 x i8> %v, <4 x i1> %mask) { ; CHECK-LABEL: compressstore_v4i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB2_5 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: bnez a2, .LBB2_6 -; CHECK-NEXT: .LBB2_2: # %else2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: bnez a2, .LBB2_7 -; CHECK-NEXT: .LBB2_3: # %else5 -; CHECK-NEXT: andi a1, a1, 8 -; CHECK-NEXT: bnez a1, .LBB2_8 -; CHECK-NEXT: .LBB2_4: # %else8 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB2_5: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e8, mf4, ta, ma -; CHECK-NEXT: vse8.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: beqz a2, .LBB2_2 -; CHECK-NEXT: .LBB2_6: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e8, mf4, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 1 +; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e8, mf4, ta, ma ; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: beqz a2, .LBB2_3 -; CHECK-NEXT: .LBB2_7: # %cond.store4 -; CHECK-NEXT: vsetivli zero, 1, e8, mf4, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 2 -; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a1, a1, 8 -; CHECK-NEXT: beqz a1, .LBB2_4 -; CHECK-NEXT: .LBB2_8: # %cond.store7 -; CHECK-NEXT: vsetivli zero, 1, e8, mf4, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 3 -; CHECK-NEXT: vse8.v v8, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v4i8(<4 x i8> %v, ptr %base, <4 x i1> %mask) ret void @@ -98,85 +48,11 @@ declare void @llvm.masked.compressstore.v8i8(<8 x i8>, ptr, <8 x i1>) define void @compressstore_v8i8(ptr %base, <8 x i8> %v, <8 x i1> %mask) { ; CHECK-LABEL: compressstore_v8i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB3_9 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: bnez a2, .LBB3_10 -; CHECK-NEXT: .LBB3_2: # %else2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: bnez a2, .LBB3_11 -; CHECK-NEXT: .LBB3_3: # %else5 -; CHECK-NEXT: andi a2, a1, 8 -; CHECK-NEXT: bnez a2, .LBB3_12 -; CHECK-NEXT: .LBB3_4: # %else8 -; CHECK-NEXT: andi a2, a1, 16 -; CHECK-NEXT: bnez a2, .LBB3_13 -; CHECK-NEXT: .LBB3_5: # %else11 -; CHECK-NEXT: andi a2, a1, 32 -; CHECK-NEXT: bnez a2, .LBB3_14 -; CHECK-NEXT: .LBB3_6: # %else14 -; CHECK-NEXT: andi a2, a1, 64 -; CHECK-NEXT: bnez a2, .LBB3_15 -; CHECK-NEXT: .LBB3_7: # %else17 -; CHECK-NEXT: andi a1, a1, -128 -; CHECK-NEXT: bnez a1, .LBB3_16 -; CHECK-NEXT: .LBB3_8: # %else20 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB3_9: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vse8.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: beqz a2, .LBB3_2 -; CHECK-NEXT: .LBB3_10: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 1 -; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: beqz a2, .LBB3_3 -; CHECK-NEXT: .LBB3_11: # %cond.store4 -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 2 -; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 8 -; CHECK-NEXT: beqz a2, .LBB3_4 -; CHECK-NEXT: .LBB3_12: # %cond.store7 -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 3 -; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 16 -; CHECK-NEXT: beqz a2, .LBB3_5 -; CHECK-NEXT: .LBB3_13: # %cond.store10 -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 4 -; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 32 -; CHECK-NEXT: beqz a2, .LBB3_6 -; CHECK-NEXT: .LBB3_14: # %cond.store13 -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 5 +; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e8, mf2, ta, ma ; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 64 -; CHECK-NEXT: beqz a2, .LBB3_7 -; CHECK-NEXT: .LBB3_15: # %cond.store16 -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 6 -; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a1, a1, -128 -; CHECK-NEXT: beqz a1, .LBB3_8 -; CHECK-NEXT: .LBB3_16: # %cond.store19 -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 7 -; CHECK-NEXT: vse8.v v8, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v8i8(<8 x i8> %v, ptr %base, <8 x i1> %mask) ret void @@ -186,13 +62,11 @@ declare void @llvm.masked.compressstore.v1i16(<1 x i16>, ptr, <1 x i1>) define void @compressstore_v1i16(ptr %base, <1 x i16> %v, <1 x i1> %mask) { ; CHECK-LABEL: compressstore_v1i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; CHECK-NEXT: vfirst.m a1, v0 -; CHECK-NEXT: bnez a1, .LBB4_2 -; CHECK-NEXT: # %bb.1: # %cond.store ; CHECK-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; CHECK-NEXT: vse16.v v8, (a0) -; CHECK-NEXT: .LBB4_2: # %else +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; CHECK-NEXT: vse16.v v9, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v1i16(<1 x i16> %v, ptr align 2 %base, <1 x i1> %mask) ret void @@ -202,25 +76,11 @@ declare void @llvm.masked.compressstore.v2i16(<2 x i16>, ptr, <2 x i1>) define void @compressstore_v2i16(ptr %base, <2 x i16> %v, <2 x i1> %mask) { ; CHECK-LABEL: compressstore_v2i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB5_3 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a1, a1, 2 -; CHECK-NEXT: bnez a1, .LBB5_4 -; CHECK-NEXT: .LBB5_2: # %else2 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB5_3: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; CHECK-NEXT: vse16.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a1, a1, 2 -; CHECK-NEXT: beqz a1, .LBB5_2 -; CHECK-NEXT: .LBB5_4: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 1 -; CHECK-NEXT: vse16.v v8, (a0) +; CHECK-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; CHECK-NEXT: vse16.v v9, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v2i16(<2 x i16> %v, ptr align 2 %base, <2 x i1> %mask) ret void @@ -230,45 +90,11 @@ declare void @llvm.masked.compressstore.v4i16(<4 x i16>, ptr, <4 x i1>) define void @compressstore_v4i16(ptr %base, <4 x i16> %v, <4 x i1> %mask) { ; CHECK-LABEL: compressstore_v4i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB6_5 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: bnez a2, .LBB6_6 -; CHECK-NEXT: .LBB6_2: # %else2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: bnez a2, .LBB6_7 -; CHECK-NEXT: .LBB6_3: # %else5 -; CHECK-NEXT: andi a1, a1, 8 -; CHECK-NEXT: bnez a1, .LBB6_8 -; CHECK-NEXT: .LBB6_4: # %else8 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB6_5: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; CHECK-NEXT: vse16.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: beqz a2, .LBB6_2 -; CHECK-NEXT: .LBB6_6: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 1 -; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: beqz a2, .LBB6_3 -; CHECK-NEXT: .LBB6_7: # %cond.store4 -; CHECK-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 2 +; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e16, mf2, ta, ma ; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a1, a1, 8 -; CHECK-NEXT: beqz a1, .LBB6_4 -; CHECK-NEXT: .LBB6_8: # %cond.store7 -; CHECK-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 3 -; CHECK-NEXT: vse16.v v8, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v4i16(<4 x i16> %v, ptr align 2 %base, <4 x i1> %mask) ret void @@ -278,85 +104,11 @@ declare void @llvm.masked.compressstore.v8i16(<8 x i16>, ptr, <8 x i1>) define void @compressstore_v8i16(ptr %base, <8 x i16> %v, <8 x i1> %mask) { ; CHECK-LABEL: compressstore_v8i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB7_9 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: bnez a2, .LBB7_10 -; CHECK-NEXT: .LBB7_2: # %else2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: bnez a2, .LBB7_11 -; CHECK-NEXT: .LBB7_3: # %else5 -; CHECK-NEXT: andi a2, a1, 8 -; CHECK-NEXT: bnez a2, .LBB7_12 -; CHECK-NEXT: .LBB7_4: # %else8 -; CHECK-NEXT: andi a2, a1, 16 -; CHECK-NEXT: bnez a2, .LBB7_13 -; CHECK-NEXT: .LBB7_5: # %else11 -; CHECK-NEXT: andi a2, a1, 32 -; CHECK-NEXT: bnez a2, .LBB7_14 -; CHECK-NEXT: .LBB7_6: # %else14 -; CHECK-NEXT: andi a2, a1, 64 -; CHECK-NEXT: bnez a2, .LBB7_15 -; CHECK-NEXT: .LBB7_7: # %else17 -; CHECK-NEXT: andi a1, a1, -128 -; CHECK-NEXT: bnez a1, .LBB7_16 -; CHECK-NEXT: .LBB7_8: # %else20 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB7_9: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vse16.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: beqz a2, .LBB7_2 -; CHECK-NEXT: .LBB7_10: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 1 -; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: beqz a2, .LBB7_3 -; CHECK-NEXT: .LBB7_11: # %cond.store4 -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 2 -; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 8 -; CHECK-NEXT: beqz a2, .LBB7_4 -; CHECK-NEXT: .LBB7_12: # %cond.store7 -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 3 -; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 16 -; CHECK-NEXT: beqz a2, .LBB7_5 -; CHECK-NEXT: .LBB7_13: # %cond.store10 -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 4 +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e16, m1, ta, ma ; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 32 -; CHECK-NEXT: beqz a2, .LBB7_6 -; CHECK-NEXT: .LBB7_14: # %cond.store13 -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 5 -; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 64 -; CHECK-NEXT: beqz a2, .LBB7_7 -; CHECK-NEXT: .LBB7_15: # %cond.store16 -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 6 -; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a1, a1, -128 -; CHECK-NEXT: beqz a1, .LBB7_8 -; CHECK-NEXT: .LBB7_16: # %cond.store19 -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 7 -; CHECK-NEXT: vse16.v v8, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v8i16(<8 x i16> %v, ptr align 2 %base, <8 x i1> %mask) ret void @@ -366,13 +118,11 @@ declare void @llvm.masked.compressstore.v1i32(<1 x i32>, ptr, <1 x i1>) define void @compressstore_v1i32(ptr %base, <1 x i32> %v, <1 x i1> %mask) { ; CHECK-LABEL: compressstore_v1i32: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; CHECK-NEXT: vfirst.m a1, v0 -; CHECK-NEXT: bnez a1, .LBB8_2 -; CHECK-NEXT: # %bb.1: # %cond.store ; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vse32.v v8, (a0) -; CHECK-NEXT: .LBB8_2: # %else +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; CHECK-NEXT: vse32.v v9, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v1i32(<1 x i32> %v, ptr align 4 %base, <1 x i1> %mask) ret void @@ -382,25 +132,11 @@ declare void @llvm.masked.compressstore.v2i32(<2 x i32>, ptr, <2 x i1>) define void @compressstore_v2i32(ptr %base, <2 x i32> %v, <2 x i1> %mask) { ; CHECK-LABEL: compressstore_v2i32: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB9_3 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a1, a1, 2 -; CHECK-NEXT: bnez a1, .LBB9_4 -; CHECK-NEXT: .LBB9_2: # %else2 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB9_3: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vse32.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a1, a1, 2 -; CHECK-NEXT: beqz a1, .LBB9_2 -; CHECK-NEXT: .LBB9_4: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 1 -; CHECK-NEXT: vse32.v v8, (a0) +; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; CHECK-NEXT: vse32.v v9, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v2i32(<2 x i32> %v, ptr align 4 %base, <2 x i1> %mask) ret void @@ -410,45 +146,11 @@ declare void @llvm.masked.compressstore.v4i32(<4 x i32>, ptr, <4 x i1>) define void @compressstore_v4i32(ptr %base, <4 x i32> %v, <4 x i1> %mask) { ; CHECK-LABEL: compressstore_v4i32: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB10_5 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: bnez a2, .LBB10_6 -; CHECK-NEXT: .LBB10_2: # %else2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: bnez a2, .LBB10_7 -; CHECK-NEXT: .LBB10_3: # %else5 -; CHECK-NEXT: andi a1, a1, 8 -; CHECK-NEXT: bnez a1, .LBB10_8 -; CHECK-NEXT: .LBB10_4: # %else8 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB10_5: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vse32.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: beqz a2, .LBB10_2 -; CHECK-NEXT: .LBB10_6: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 1 -; CHECK-NEXT: vse32.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: beqz a2, .LBB10_3 -; CHECK-NEXT: .LBB10_7: # %cond.store4 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 2 +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e32, m1, ta, ma ; CHECK-NEXT: vse32.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a1, a1, 8 -; CHECK-NEXT: beqz a1, .LBB10_4 -; CHECK-NEXT: .LBB10_8: # %cond.store7 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 3 -; CHECK-NEXT: vse32.v v8, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v4i32(<4 x i32> %v, ptr align 4 %base, <4 x i1> %mask) ret void @@ -458,89 +160,11 @@ declare void @llvm.masked.compressstore.v8i32(<8 x i32>, ptr, <8 x i1>) define void @compressstore_v8i32(ptr %base, <8 x i32> %v, <8 x i1> %mask) { ; CHECK-LABEL: compressstore_v8i32: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB11_9 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: bnez a2, .LBB11_10 -; CHECK-NEXT: .LBB11_2: # %else2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: bnez a2, .LBB11_11 -; CHECK-NEXT: .LBB11_3: # %else5 -; CHECK-NEXT: andi a2, a1, 8 -; CHECK-NEXT: bnez a2, .LBB11_12 -; CHECK-NEXT: .LBB11_4: # %else8 -; CHECK-NEXT: andi a2, a1, 16 -; CHECK-NEXT: bnez a2, .LBB11_13 -; CHECK-NEXT: .LBB11_5: # %else11 -; CHECK-NEXT: andi a2, a1, 32 -; CHECK-NEXT: bnez a2, .LBB11_14 -; CHECK-NEXT: .LBB11_6: # %else14 -; CHECK-NEXT: andi a2, a1, 64 -; CHECK-NEXT: bnez a2, .LBB11_15 -; CHECK-NEXT: .LBB11_7: # %else17 -; CHECK-NEXT: andi a1, a1, -128 -; CHECK-NEXT: bnez a1, .LBB11_16 -; CHECK-NEXT: .LBB11_8: # %else20 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB11_9: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vse32.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: beqz a2, .LBB11_2 -; CHECK-NEXT: .LBB11_10: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v8, 1 -; CHECK-NEXT: vse32.v v10, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: beqz a2, .LBB11_3 -; CHECK-NEXT: .LBB11_11: # %cond.store4 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v8, 2 -; CHECK-NEXT: vse32.v v10, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 8 -; CHECK-NEXT: beqz a2, .LBB11_4 -; CHECK-NEXT: .LBB11_12: # %cond.store7 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v8, 3 +; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-NEXT: vcompress.vm v10, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e32, m2, ta, ma ; CHECK-NEXT: vse32.v v10, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 16 -; CHECK-NEXT: beqz a2, .LBB11_5 -; CHECK-NEXT: .LBB11_13: # %cond.store10 -; CHECK-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v8, 4 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vse32.v v10, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 32 -; CHECK-NEXT: beqz a2, .LBB11_6 -; CHECK-NEXT: .LBB11_14: # %cond.store13 -; CHECK-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v8, 5 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vse32.v v10, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 64 -; CHECK-NEXT: beqz a2, .LBB11_7 -; CHECK-NEXT: .LBB11_15: # %cond.store16 -; CHECK-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v8, 6 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vse32.v v10, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a1, a1, -128 -; CHECK-NEXT: beqz a1, .LBB11_8 -; CHECK-NEXT: .LBB11_16: # %cond.store19 -; CHECK-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 7 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vse32.v v8, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v8i32(<8 x i32> %v, ptr align 4 %base, <8 x i1> %mask) ret void @@ -548,439 +172,59 @@ define void @compressstore_v8i32(ptr %base, <8 x i32> %v, <8 x i1> %mask) { declare void @llvm.masked.compressstore.v1i64(<1 x i64>, ptr, <1 x i1>) define void @compressstore_v1i64(ptr %base, <1 x i64> %v, <1 x i1> %mask) { -; RV32-LABEL: compressstore_v1i64: -; RV32: # %bb.0: -; RV32-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV32-NEXT: vfirst.m a1, v0 -; RV32-NEXT: bnez a1, .LBB12_2 -; RV32-NEXT: # %bb.1: # %cond.store -; RV32-NEXT: li a1, 32 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vsrl.vx v9, v8, a1 -; RV32-NEXT: vmv.x.s a1, v9 -; RV32-NEXT: vmv.x.s a2, v8 -; RV32-NEXT: sw a2, 0(a0) -; RV32-NEXT: sw a1, 4(a0) -; RV32-NEXT: .LBB12_2: # %else -; RV32-NEXT: ret -; -; RV64-LABEL: compressstore_v1i64: -; RV64: # %bb.0: -; RV64-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV64-NEXT: vfirst.m a1, v0 -; RV64-NEXT: bnez a1, .LBB12_2 -; RV64-NEXT: # %bb.1: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: .LBB12_2: # %else -; RV64-NEXT: ret +; CHECK-LABEL: compressstore_v1i64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; CHECK-NEXT: vse64.v v9, (a0) +; CHECK-NEXT: ret call void @llvm.masked.compressstore.v1i64(<1 x i64> %v, ptr align 8 %base, <1 x i1> %mask) ret void } declare void @llvm.masked.compressstore.v2i64(<2 x i64>, ptr, <2 x i1>) define void @compressstore_v2i64(ptr %base, <2 x i64> %v, <2 x i1> %mask) { -; RV32-LABEL: compressstore_v2i64: -; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB13_3 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: bnez a1, .LBB13_4 -; RV32-NEXT: .LBB13_2: # %else2 -; RV32-NEXT: ret -; RV32-NEXT: .LBB13_3: # %cond.store -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vsrl.vx v9, v8, a2 -; RV32-NEXT: vmv.x.s a2, v9 -; RV32-NEXT: vmv.x.s a3, v8 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: beqz a1, .LBB13_2 -; RV32-NEXT: .LBB13_4: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 1 -; RV32-NEXT: li a1, 32 -; RV32-NEXT: vsrl.vx v9, v8, a1 -; RV32-NEXT: vmv.x.s a1, v9 -; RV32-NEXT: vmv.x.s a2, v8 -; RV32-NEXT: sw a2, 0(a0) -; RV32-NEXT: sw a1, 4(a0) -; RV32-NEXT: ret -; -; RV64-LABEL: compressstore_v2i64: -; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB13_3 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: bnez a1, .LBB13_4 -; RV64-NEXT: .LBB13_2: # %else2 -; RV64-NEXT: ret -; RV64-NEXT: .LBB13_3: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: beqz a1, .LBB13_2 -; RV64-NEXT: .LBB13_4: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 1 -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: ret +; CHECK-LABEL: compressstore_v2i64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; CHECK-NEXT: vse64.v v9, (a0) +; CHECK-NEXT: ret call void @llvm.masked.compressstore.v2i64(<2 x i64> %v, ptr align 8 %base, <2 x i1> %mask) ret void } declare void @llvm.masked.compressstore.v4i64(<4 x i64>, ptr, <4 x i1>) define void @compressstore_v4i64(ptr %base, <4 x i64> %v, <4 x i1> %mask) { -; RV32-LABEL: compressstore_v4i64: -; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB14_5 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB14_6 -; RV32-NEXT: .LBB14_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB14_7 -; RV32-NEXT: .LBB14_3: # %else5 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: bnez a1, .LBB14_8 -; RV32-NEXT: .LBB14_4: # %else8 -; RV32-NEXT: ret -; RV32-NEXT: .LBB14_5: # %cond.store -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vsrl.vx v10, v8, a2 -; RV32-NEXT: vmv.x.s a2, v10 -; RV32-NEXT: vmv.x.s a3, v8 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB14_2 -; RV32-NEXT: .LBB14_6: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 1 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v12, v10, a2 -; RV32-NEXT: vmv.x.s a2, v12 -; RV32-NEXT: vmv.x.s a3, v10 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB14_3 -; RV32-NEXT: .LBB14_7: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 2 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v12, v10, a2 -; RV32-NEXT: vmv.x.s a2, v12 -; RV32-NEXT: vmv.x.s a3, v10 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: beqz a1, .LBB14_4 -; RV32-NEXT: .LBB14_8: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 3 -; RV32-NEXT: li a1, 32 -; RV32-NEXT: vsrl.vx v10, v8, a1 -; RV32-NEXT: vmv.x.s a1, v10 -; RV32-NEXT: vmv.x.s a2, v8 -; RV32-NEXT: sw a2, 0(a0) -; RV32-NEXT: sw a1, 4(a0) -; RV32-NEXT: ret -; -; RV64-LABEL: compressstore_v4i64: -; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB14_5 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB14_6 -; RV64-NEXT: .LBB14_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB14_7 -; RV64-NEXT: .LBB14_3: # %else5 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: bnez a1, .LBB14_8 -; RV64-NEXT: .LBB14_4: # %else8 -; RV64-NEXT: ret -; RV64-NEXT: .LBB14_5: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB14_2 -; RV64-NEXT: .LBB14_6: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 1 -; RV64-NEXT: vse64.v v10, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB14_3 -; RV64-NEXT: .LBB14_7: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 2 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v10, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: beqz a1, .LBB14_4 -; RV64-NEXT: .LBB14_8: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 3 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: ret +; CHECK-LABEL: compressstore_v4i64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-NEXT: vcompress.vm v10, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e64, m2, ta, ma +; CHECK-NEXT: vse64.v v10, (a0) +; CHECK-NEXT: ret call void @llvm.masked.compressstore.v4i64(<4 x i64> %v, ptr align 8 %base, <4 x i1> %mask) ret void } declare void @llvm.masked.compressstore.v8i64(<8 x i64>, ptr, <8 x i1>) define void @compressstore_v8i64(ptr %base, <8 x i64> %v, <8 x i1> %mask) { -; RV32-LABEL: compressstore_v8i64: -; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB15_9 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB15_10 -; RV32-NEXT: .LBB15_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB15_11 -; RV32-NEXT: .LBB15_3: # %else5 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: bnez a2, .LBB15_12 -; RV32-NEXT: .LBB15_4: # %else8 -; RV32-NEXT: andi a2, a1, 16 -; RV32-NEXT: bnez a2, .LBB15_13 -; RV32-NEXT: .LBB15_5: # %else11 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: bnez a2, .LBB15_14 -; RV32-NEXT: .LBB15_6: # %else14 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: bnez a2, .LBB15_15 -; RV32-NEXT: .LBB15_7: # %else17 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: bnez a1, .LBB15_16 -; RV32-NEXT: .LBB15_8: # %else20 -; RV32-NEXT: ret -; RV32-NEXT: .LBB15_9: # %cond.store -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vsrl.vx v12, v8, a2 -; RV32-NEXT: vmv.x.s a2, v12 -; RV32-NEXT: vmv.x.s a3, v8 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB15_2 -; RV32-NEXT: .LBB15_10: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 1 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v16, v12, a2 -; RV32-NEXT: vmv.x.s a2, v16 -; RV32-NEXT: vmv.x.s a3, v12 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB15_3 -; RV32-NEXT: .LBB15_11: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 2 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v16, v12, a2 -; RV32-NEXT: vmv.x.s a2, v16 -; RV32-NEXT: vmv.x.s a3, v12 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: beqz a2, .LBB15_4 -; RV32-NEXT: .LBB15_12: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 3 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v16, v12, a2 -; RV32-NEXT: vmv.x.s a2, v16 -; RV32-NEXT: vmv.x.s a3, v12 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 16 -; RV32-NEXT: beqz a2, .LBB15_5 -; RV32-NEXT: .LBB15_13: # %cond.store10 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 4 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v16, v12, a2 -; RV32-NEXT: vmv.x.s a2, v16 -; RV32-NEXT: vmv.x.s a3, v12 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: beqz a2, .LBB15_6 -; RV32-NEXT: .LBB15_14: # %cond.store13 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 5 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v16, v12, a2 -; RV32-NEXT: vmv.x.s a2, v16 -; RV32-NEXT: vmv.x.s a3, v12 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: beqz a2, .LBB15_7 -; RV32-NEXT: .LBB15_15: # %cond.store16 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 6 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v16, v12, a2 -; RV32-NEXT: vmv.x.s a2, v16 -; RV32-NEXT: vmv.x.s a3, v12 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: beqz a1, .LBB15_8 -; RV32-NEXT: .LBB15_16: # %cond.store19 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 7 -; RV32-NEXT: li a1, 32 -; RV32-NEXT: vsrl.vx v12, v8, a1 -; RV32-NEXT: vmv.x.s a1, v12 -; RV32-NEXT: vmv.x.s a2, v8 -; RV32-NEXT: sw a2, 0(a0) -; RV32-NEXT: sw a1, 4(a0) -; RV32-NEXT: ret -; -; RV64-LABEL: compressstore_v8i64: -; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB15_11 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB15_12 -; RV64-NEXT: .LBB15_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB15_13 -; RV64-NEXT: .LBB15_3: # %else5 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: beqz a2, .LBB15_5 -; RV64-NEXT: .LBB15_4: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v12, v8, 3 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v12, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: .LBB15_5: # %else8 -; RV64-NEXT: addi sp, sp, -320 -; RV64-NEXT: .cfi_def_cfa_offset 320 -; RV64-NEXT: sd ra, 312(sp) # 8-byte Folded Spill -; RV64-NEXT: sd s0, 304(sp) # 8-byte Folded Spill -; RV64-NEXT: .cfi_offset ra, -8 -; RV64-NEXT: .cfi_offset s0, -16 -; RV64-NEXT: addi s0, sp, 320 -; RV64-NEXT: .cfi_def_cfa s0, 0 -; RV64-NEXT: andi sp, sp, -64 -; RV64-NEXT: andi a2, a1, 16 -; RV64-NEXT: bnez a2, .LBB15_14 -; RV64-NEXT: # %bb.6: # %else11 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: bnez a2, .LBB15_15 -; RV64-NEXT: .LBB15_7: # %else14 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: bnez a2, .LBB15_16 -; RV64-NEXT: .LBB15_8: # %else17 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: beqz a1, .LBB15_10 -; RV64-NEXT: .LBB15_9: # %cond.store19 -; RV64-NEXT: mv a1, sp -; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a1) -; RV64-NEXT: ld a1, 56(sp) -; RV64-NEXT: sd a1, 0(a0) -; RV64-NEXT: .LBB15_10: # %else20 -; RV64-NEXT: addi sp, s0, -320 -; RV64-NEXT: ld ra, 312(sp) # 8-byte Folded Reload -; RV64-NEXT: ld s0, 304(sp) # 8-byte Folded Reload -; RV64-NEXT: addi sp, sp, 320 -; RV64-NEXT: ret -; RV64-NEXT: .LBB15_11: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB15_2 -; RV64-NEXT: .LBB15_12: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vslidedown.vi v12, v8, 1 -; RV64-NEXT: vse64.v v12, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB15_3 -; RV64-NEXT: .LBB15_13: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v12, v8, 2 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v12, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: bnez a2, .LBB15_4 -; RV64-NEXT: j .LBB15_5 -; RV64-NEXT: .LBB15_14: # %cond.store10 -; RV64-NEXT: addi a2, sp, 192 -; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a2) -; RV64-NEXT: ld a2, 224(sp) -; RV64-NEXT: sd a2, 0(a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: beqz a2, .LBB15_7 -; RV64-NEXT: .LBB15_15: # %cond.store13 -; RV64-NEXT: addi a2, sp, 128 -; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a2) -; RV64-NEXT: ld a2, 168(sp) -; RV64-NEXT: sd a2, 0(a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: beqz a2, .LBB15_8 -; RV64-NEXT: .LBB15_16: # %cond.store16 -; RV64-NEXT: addi a2, sp, 64 -; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a2) -; RV64-NEXT: ld a2, 112(sp) -; RV64-NEXT: sd a2, 0(a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: bnez a1, .LBB15_9 -; RV64-NEXT: j .LBB15_10 +; CHECK-LABEL: compressstore_v8i64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma +; CHECK-NEXT: vcompress.vm v12, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e64, m4, ta, ma +; CHECK-NEXT: vse64.v v12, (a0) +; CHECK-NEXT: ret call void @llvm.masked.compressstore.v8i64(<8 x i64> %v, ptr align 8 %base, <8 x i1> %mask) ret void } +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; RV32: {{.*}} +; RV64: {{.*}} -- GitLab From fbd7c50065705c44e1b3d39f456963810124051b Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 13 Mar 2024 14:25:22 -0500 Subject: [PATCH 430/953] [libc] Repurpose `LIBC_GPU_BUILD` option to enable the new format (#82848) Summary: We previously used the `LIBC_GPU_BUILD` option to control whether or not the GPU build was enabled. This was recently replaced with a new format that allows treating the GPU targets more directly. However, the new format is somewhat difficult to use for people unfamiliar with the runtimes builds, and the removal of this option somewhat broke backward compatibility. This patch seeks to simplify enabling the GPU build by repurposing the old enabling option and convert it to the new interface. Unsure what the rules are here, since this is technically a `LIBC` option living in the LLVM location. --- libc/CMakeLists.txt | 1 - llvm/CMakeLists.txt | 12 ++++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 6edf5c656193..7afb3c5f0faa 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -134,7 +134,6 @@ option(LLVM_LIBC_FULL_BUILD "Build and test LLVM libc as if it is the full libc" option(LLVM_LIBC_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR "Build LLVM libc tests assuming our implementation-defined behavior" ON) option(LLVM_LIBC_ENABLE_LINTING "Enables linting of libc source files" OFF) -option(LIBC_GPU_BUILD "Build libc for the GPU. All CPU build options will be ignored." OFF) set(LIBC_TARGET_TRIPLE "" CACHE STRING "The target triple for the libc build.") option(LIBC_CONFIG_PATH "The path to user provided folder that configures the build for the target system." OFF) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index bd141619d03f..6f5647d70d8b 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -159,6 +159,18 @@ foreach(proj IN LISTS LLVM_ENABLE_RUNTIMES) endif() endforeach() +# Set a shorthand option to enable the GPU build of the 'libc' project. +option(LIBC_GPU_BUILD "Enable the 'libc' project targeting the GPU" OFF) +if(LIBC_GPU_BUILD) + if(LLVM_RUNTIME_TARGETS) + list(APPEND LLVM_RUNTIME_TARGETS "nvptx64-nvidia-cuda" "amdgcn-amd-amdhsa") + else() + set(LLVM_RUNTIME_TARGETS "default;nvptx64-nvidia-cuda;amdgcn-amd-amdhsa") + endif() + list(APPEND RUNTIMES_nvptx64-nvidia-cuda_LLVM_ENABLE_RUNTIMES "libc") + list(APPEND RUNTIMES_amdgcn-amd-amdhsa_LLVM_ENABLE_RUNTIMES "libc") +endif() + set(NEED_LIBC_HDRGEN FALSE) if("libc" IN_LIST LLVM_ENABLE_RUNTIMES) set(NEED_LIBC_HDRGEN TRUE) -- GitLab From 882992a951a3d92d5e19d4fe6c6eb9ba1e87d39c Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Sun, 10 Mar 2024 17:24:09 -0500 Subject: [PATCH 431/953] [ValueTracking] Add tests for inferring select arm bits from condition; NFC --- .../knownbits-select-from-cond.ll | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 llvm/test/Analysis/ValueTracking/knownbits-select-from-cond.ll diff --git a/llvm/test/Analysis/ValueTracking/knownbits-select-from-cond.ll b/llvm/test/Analysis/ValueTracking/knownbits-select-from-cond.ll new file mode 100644 index 000000000000..0a1cccaca2bb --- /dev/null +++ b/llvm/test/Analysis/ValueTracking/knownbits-select-from-cond.ll @@ -0,0 +1,81 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes=instcombine -S < %s | FileCheck %s + +define i8 @select_condition_implies_highbits_op1(i8 %xx, i8 noundef %y) { +; CHECK-LABEL: @select_condition_implies_highbits_op1( +; CHECK-NEXT: [[X:%.*]] = and i8 [[XX:%.*]], 15 +; CHECK-NEXT: [[COND:%.*]] = icmp ult i8 [[Y:%.*]], 3 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i8 [[Y]], i8 [[X]] +; CHECK-NEXT: [[R:%.*]] = add i8 [[SEL]], 32 +; CHECK-NEXT: ret i8 [[R]] +; + %x = and i8 %xx, 15 + %cond = icmp ult i8 %y, 3 + %sel = select i1 %cond, i8 %y, i8 %x + %r = add i8 %sel, 32 + ret i8 %r +} + +define i8 @select_condition_implies_highbits_op1_maybe_undef_fail(i8 %xx, i8 %y) { +; CHECK-LABEL: @select_condition_implies_highbits_op1_maybe_undef_fail( +; CHECK-NEXT: [[X:%.*]] = and i8 [[XX:%.*]], 15 +; CHECK-NEXT: [[COND:%.*]] = icmp ult i8 [[Y:%.*]], 3 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i8 [[Y]], i8 [[X]] +; CHECK-NEXT: [[R:%.*]] = add i8 [[SEL]], 32 +; CHECK-NEXT: ret i8 [[R]] +; + %x = and i8 %xx, 15 + %cond = icmp ult i8 %y, 3 + %sel = select i1 %cond, i8 %y, i8 %x + %r = add i8 %sel, 32 + ret i8 %r +} + +define i8 @select_condition_implies_highbits_op2(i8 %xx, i8 noundef %y) { +; CHECK-LABEL: @select_condition_implies_highbits_op2( +; CHECK-NEXT: [[X:%.*]] = and i8 [[XX:%.*]], 15 +; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[Y:%.*]], 3 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i8 [[X]], i8 [[Y]] +; CHECK-NEXT: [[R:%.*]] = add i8 [[SEL]], 32 +; CHECK-NEXT: ret i8 [[R]] +; + %x = and i8 %xx, 15 + %cond = icmp ugt i8 %y, 3 + %sel = select i1 %cond, i8 %x, i8 %y + %r = add i8 %sel, 32 + ret i8 %r +} + +define i8 @select_condition_implies_highbits_op1_and(i8 %xx, i8 noundef %y, i1 %other_cond) { +; CHECK-LABEL: @select_condition_implies_highbits_op1_and( +; CHECK-NEXT: [[X:%.*]] = and i8 [[XX:%.*]], 15 +; CHECK-NEXT: [[COND0:%.*]] = icmp ult i8 [[Y:%.*]], 3 +; CHECK-NEXT: [[COND:%.*]] = and i1 [[COND0]], [[OTHER_COND:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i8 [[Y]], i8 [[X]] +; CHECK-NEXT: [[R:%.*]] = add i8 [[SEL]], 32 +; CHECK-NEXT: ret i8 [[R]] +; + %x = and i8 %xx, 15 + %cond0 = icmp ult i8 %y, 3 + %cond = and i1 %cond0, %other_cond + %sel = select i1 %cond, i8 %y, i8 %x + %r = add i8 %sel, 32 + ret i8 %r +} + +define i8 @select_condition_implies_highbits_op2_or(i8 %xx, i8 noundef %y, i1 %other_cond) { +; CHECK-LABEL: @select_condition_implies_highbits_op2_or( +; CHECK-NEXT: [[X:%.*]] = and i8 [[XX:%.*]], 15 +; CHECK-NEXT: [[COND0:%.*]] = icmp ugt i8 [[Y:%.*]], 3 +; CHECK-NEXT: [[COND:%.*]] = or i1 [[COND0]], [[OTHER_COND:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i8 [[X]], i8 [[Y]] +; CHECK-NEXT: [[R:%.*]] = add i8 [[SEL]], 32 +; CHECK-NEXT: ret i8 [[R]] +; + %x = and i8 %xx, 15 + %cond0 = icmp ugt i8 %y, 3 + %cond = or i1 %cond0, %other_cond + %sel = select i1 %cond, i8 %x, i8 %y + %r = add i8 %sel, 32 + ret i8 %r +} -- GitLab From 744a23f24b08e8b988b176173c433d64761e66b3 Mon Sep 17 00:00:00 2001 From: Noah Goldstein Date: Sun, 10 Mar 2024 17:24:12 -0500 Subject: [PATCH 432/953] [ValueTracking] Use select condition to help infer bits of arms If we have something like `(select (icmp ult x, 8), x, y)`, we can use the `(icmp ult x, 8)` to help compute the knownbits of `x`. Closes #84699 --- llvm/lib/Analysis/ValueTracking.cpp | 41 +++++++++++++++++-- .../knownbits-select-from-cond.ll | 8 ++-- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 8a4a2c4f92a0..edbeede910d7 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1023,11 +1023,44 @@ static void computeKnownBitsFromOperator(const Operator *I, break; } case Instruction::Select: { - computeKnownBits(I->getOperand(2), Known, Depth + 1, Q); - computeKnownBits(I->getOperand(1), Known2, Depth + 1, Q); - + auto ComputeForArm = [&](Value *Arm, bool Invert) { + KnownBits Res(Known.getBitWidth()); + computeKnownBits(Arm, Res, Depth + 1, Q); + // If we have a constant arm, we are done. + if (Res.isConstant()) + return Res; + + // See what condition implies about the bits of the two select arms. + KnownBits CondRes(Res.getBitWidth()); + computeKnownBitsFromCond(Arm, I->getOperand(0), CondRes, Depth + 1, Q, + Invert); + // If we don't get any information from the condition, no reason to + // proceed. + if (CondRes.isUnknown()) + return Res; + + // We can have conflict if the condition is dead. I.e if we have + // (x | 64) < 32 ? (x | 64) : y + // we will have conflict at bit 6 from the condition/the `or`. + // In that case just return. Its not particularly important + // what we do, as this select is going to be simplified soon. + CondRes = CondRes.unionWith(Res); + if (CondRes.hasConflict()) + return Res; + + // Finally make sure the information we found is valid. This is relatively + // expensive so it's left for the very end. + if (!isGuaranteedNotToBeUndef(Arm, Q.AC, Q.CxtI, Q.DT, Depth + 1)) + return Res; + + // Finally, we know we get information from the condition and its valid, + // so return it. + return CondRes; + }; // Only known if known in both the LHS and RHS. - Known = Known.intersectWith(Known2); + Known = + ComputeForArm(I->getOperand(1), /*Invert=*/false) + .intersectWith(ComputeForArm(I->getOperand(2), /*Invert=*/true)); break; } case Instruction::FPTrunc: diff --git a/llvm/test/Analysis/ValueTracking/knownbits-select-from-cond.ll b/llvm/test/Analysis/ValueTracking/knownbits-select-from-cond.ll index 0a1cccaca2bb..c3343edfb4c9 100644 --- a/llvm/test/Analysis/ValueTracking/knownbits-select-from-cond.ll +++ b/llvm/test/Analysis/ValueTracking/knownbits-select-from-cond.ll @@ -6,7 +6,7 @@ define i8 @select_condition_implies_highbits_op1(i8 %xx, i8 noundef %y) { ; CHECK-NEXT: [[X:%.*]] = and i8 [[XX:%.*]], 15 ; CHECK-NEXT: [[COND:%.*]] = icmp ult i8 [[Y:%.*]], 3 ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i8 [[Y]], i8 [[X]] -; CHECK-NEXT: [[R:%.*]] = add i8 [[SEL]], 32 +; CHECK-NEXT: [[R:%.*]] = or disjoint i8 [[SEL]], 32 ; CHECK-NEXT: ret i8 [[R]] ; %x = and i8 %xx, 15 @@ -36,7 +36,7 @@ define i8 @select_condition_implies_highbits_op2(i8 %xx, i8 noundef %y) { ; CHECK-NEXT: [[X:%.*]] = and i8 [[XX:%.*]], 15 ; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[Y:%.*]], 3 ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i8 [[X]], i8 [[Y]] -; CHECK-NEXT: [[R:%.*]] = add i8 [[SEL]], 32 +; CHECK-NEXT: [[R:%.*]] = or disjoint i8 [[SEL]], 32 ; CHECK-NEXT: ret i8 [[R]] ; %x = and i8 %xx, 15 @@ -52,7 +52,7 @@ define i8 @select_condition_implies_highbits_op1_and(i8 %xx, i8 noundef %y, i1 % ; CHECK-NEXT: [[COND0:%.*]] = icmp ult i8 [[Y:%.*]], 3 ; CHECK-NEXT: [[COND:%.*]] = and i1 [[COND0]], [[OTHER_COND:%.*]] ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i8 [[Y]], i8 [[X]] -; CHECK-NEXT: [[R:%.*]] = add i8 [[SEL]], 32 +; CHECK-NEXT: [[R:%.*]] = or disjoint i8 [[SEL]], 32 ; CHECK-NEXT: ret i8 [[R]] ; %x = and i8 %xx, 15 @@ -69,7 +69,7 @@ define i8 @select_condition_implies_highbits_op2_or(i8 %xx, i8 noundef %y, i1 %o ; CHECK-NEXT: [[COND0:%.*]] = icmp ugt i8 [[Y:%.*]], 3 ; CHECK-NEXT: [[COND:%.*]] = or i1 [[COND0]], [[OTHER_COND:%.*]] ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i8 [[X]], i8 [[Y]] -; CHECK-NEXT: [[R:%.*]] = add i8 [[SEL]], 32 +; CHECK-NEXT: [[R:%.*]] = or disjoint i8 [[SEL]], 32 ; CHECK-NEXT: ret i8 [[R]] ; %x = and i8 %xx, 15 -- GitLab From 8237520eb42b37d7ed353d64a865d3ba5ac24ec6 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 13 Mar 2024 07:45:14 -0700 Subject: [PATCH 433/953] [SLP]Fix PR85082: PHI node has multiple entries. Need to record casted extractelement for the externally used scalar, not original extract instruction. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 16 ++-- .../X86/same-scalar-in-same-phi-extract.ll | 75 +++++++++++++++++++ 2 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index b8b67609d755..1da509ce4794 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -12582,6 +12582,7 @@ Value *BoUpSLP::vectorizeTree( Ex = I; } } + Value *ExV = Ex; if (!Ex) { // "Reuse" the existing extract to improve final codegen. if (auto *ES = dyn_cast(Scalar)) { @@ -12592,7 +12593,13 @@ Value *BoUpSLP::vectorizeTree( } else { Ex = Builder.CreateExtractElement(Vec, Lane); } - if (auto *I = dyn_cast(Ex)) + // If necessary, sign-extend or zero-extend ScalarRoot + // to the larger type. + ExV = Ex; + if (Scalar->getType() != Ex->getType()) + ExV = Builder.CreateIntCast(Ex, Scalar->getType(), + MinBWs.find(E)->second.second); + if (auto *I = dyn_cast(ExV)) ScalarToEEs[Scalar].try_emplace(Builder.GetInsertBlock(), I); } // The then branch of the previous if may produce constants, since 0 @@ -12601,12 +12608,7 @@ Value *BoUpSLP::vectorizeTree( GatherShuffleExtractSeq.insert(ExI); CSEBlocks.insert(ExI->getParent()); } - // If necessary, sign-extend or zero-extend ScalarRoot - // to the larger type. - if (Scalar->getType() != Ex->getType()) - return Builder.CreateIntCast(Ex, Scalar->getType(), - MinBWs.find(E)->second.second); - return Ex; + return ExV; } assert(isa(Scalar->getType()) && isa(Scalar) && diff --git a/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll b/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll new file mode 100644 index 000000000000..35f2f9e052e7 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll @@ -0,0 +1,75 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -slp-threshold=-99999 -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s + +define void @test(i32 %arg) { +; CHECK-LABEL: define void @test( +; CHECK-SAME: i32 [[ARG:%.*]]) { +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i32> , i32 [[ARG]], i32 0 +; CHECK-NEXT: br label [[BB2:%.*]] +; CHECK: bb2: +; CHECK-NEXT: switch i32 0, label [[BB10:%.*]] [ +; CHECK-NEXT: i32 0, label [[BB9:%.*]] +; CHECK-NEXT: i32 11, label [[BB9]] +; CHECK-NEXT: i32 1, label [[BB4:%.*]] +; CHECK-NEXT: ] +; CHECK: bb3: +; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x i32> [[TMP0]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[TMP1]] to i64 +; CHECK-NEXT: switch i32 0, label [[BB10]] [ +; CHECK-NEXT: i32 18, label [[BB7:%.*]] +; CHECK-NEXT: i32 1, label [[BB7]] +; CHECK-NEXT: i32 0, label [[BB10]] +; CHECK-NEXT: ] +; CHECK: bb4: +; CHECK-NEXT: [[TMP3:%.*]] = phi <2 x i32> [ [[TMP0]], [[BB2]] ] +; CHECK-NEXT: [[TMP4:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64> +; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i64> [[TMP4]], i32 0 +; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr i32, ptr null, i64 [[TMP5]] +; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i64> [[TMP4]], i32 1 +; CHECK-NEXT: [[GETELEMENTPTR6:%.*]] = getelementptr i32, ptr null, i64 [[TMP6]] +; CHECK-NEXT: ret void +; CHECK: bb7: +; CHECK-NEXT: [[PHI8:%.*]] = phi i64 [ [[TMP2]], [[BB3:%.*]] ], [ [[TMP2]], [[BB3]] ] +; CHECK-NEXT: br label [[BB9]] +; CHECK: bb9: +; CHECK-NEXT: ret void +; CHECK: bb10: +; CHECK-NEXT: ret void +; +bb: + %zext = zext i32 %arg to i64 + %zext1 = zext i32 0 to i64 + br label %bb2 + +bb2: + switch i32 0, label %bb10 [ + i32 0, label %bb9 + i32 11, label %bb9 + i32 1, label %bb4 + ] + +bb3: + switch i32 0, label %bb10 [ + i32 18, label %bb7 + i32 1, label %bb7 + i32 0, label %bb10 + ] + +bb4: + %phi = phi i64 [ %zext, %bb2 ] + %phi5 = phi i64 [ %zext1, %bb2 ] + %getelementptr = getelementptr i32, ptr null, i64 %phi + %getelementptr6 = getelementptr i32, ptr null, i64 %phi5 + ret void + +bb7: + %phi8 = phi i64 [ %zext, %bb3 ], [ %zext, %bb3 ] + br label %bb9 + +bb9: + ret void + +bb10: + ret void +} -- GitLab From 1f973efd335f34c75fcba1ccbe288fd5ece15a64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 13 Mar 2024 22:01:01 +0200 Subject: [PATCH 434/953] [runtimes] Prefer -fvisibility-global-new-delete=force-hidden (#84917) 27ce26b06655cfece3d54b30e442ef93d3e78ac7 added the new option -fvisibility-global-new-delete=, where -fvisibility-global-new-delete=force-hidden is equivalent to the old option -fvisibility-global-new-delete-hidden. At the same time, the old option was deprecated. Test for and use the new option form first; if unsupported, try using the old form. This avoids warnings in the MinGW builds, if built with Clang 18 or newer. --- libcxx/src/CMakeLists.txt | 5 ++++- libcxxabi/src/CMakeLists.txt | 5 ++++- libunwind/src/CMakeLists.txt | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index 07ffc8bfdaae..1110a79ddcac 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -301,7 +301,10 @@ if (LIBCXX_ENABLE_STATIC) # then its code shouldn't declare them with hidden visibility. They might # actually be provided by a shared library at link time. if (LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS) - append_flags_if_supported(CXX_STATIC_LIBRARY_FLAGS -fvisibility-global-new-delete-hidden) + append_flags_if_supported(CXX_STATIC_LIBRARY_FLAGS -fvisibility-global-new-delete=force-hidden) + if (NOT CXX_SUPPORTS_FVISIBILITY_GLOBAL_NEW_DELETE_EQ_FORCE_HIDDEN_FLAG) + append_flags_if_supported(CXX_STATIC_LIBRARY_FLAGS -fvisibility-global-new-delete-hidden) + endif() endif() target_compile_options(cxx_static PRIVATE ${CXX_STATIC_LIBRARY_FLAGS}) # _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS can be defined in __config_site diff --git a/libcxxabi/src/CMakeLists.txt b/libcxxabi/src/CMakeLists.txt index 0af4dc1448e9..c8cc93de5077 100644 --- a/libcxxabi/src/CMakeLists.txt +++ b/libcxxabi/src/CMakeLists.txt @@ -268,7 +268,10 @@ if(LIBCXXABI_HERMETIC_STATIC_LIBRARY) # then its code shouldn't declare them with hidden visibility. They might # actually be provided by a shared library at link time. if (LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS) - target_add_compile_flags_if_supported(cxxabi_static_objects PRIVATE -fvisibility-global-new-delete-hidden) + target_add_compile_flags_if_supported(cxxabi_static_objects PRIVATE -fvisibility-global-new-delete=force-hidden) + if (NOT CXX_SUPPORTS_FVISIBILITY_GLOBAL_NEW_DELETE_EQ_FORCE_HIDDEN_FLAG) + target_add_compile_flags_if_supported(cxxabi_static_objects PRIVATE -fvisibility-global-new-delete-hidden) + endif() endif() # _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS can be defined in libcxx's # __config_site too. Define it in the same way here, to avoid redefinition diff --git a/libunwind/src/CMakeLists.txt b/libunwind/src/CMakeLists.txt index 9c6f5d908b09..780430ba70ba 100644 --- a/libunwind/src/CMakeLists.txt +++ b/libunwind/src/CMakeLists.txt @@ -201,7 +201,10 @@ set_target_properties(unwind_static_objects if(LIBUNWIND_HIDE_SYMBOLS) target_add_compile_flags_if_supported(unwind_static_objects PRIVATE -fvisibility=hidden) - target_add_compile_flags_if_supported(unwind_static_objects PRIVATE -fvisibility-global-new-delete-hidden) + target_add_compile_flags_if_supported(unwind_static_objects PRIVATE -fvisibility-global-new-delete=force-hidden) + if (NOT CXX_SUPPORTS_FVISIBILITY_GLOBAL_NEW_DELETE_EQ_FORCE_HIDDEN_FLAG) + target_add_compile_flags_if_supported(unwind_static_objects PRIVATE -fvisibility-global-new-delete-hidden) + endif() target_compile_definitions(unwind_static_objects PRIVATE _LIBUNWIND_HIDE_SYMBOLS) endif() -- GitLab From cd8843f87af2f04a85dda12b37738596cbf4cd5e Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Wed, 13 Mar 2024 15:05:22 -0500 Subject: [PATCH 435/953] [OpenMP] Disable flaky barrier fence test (#85093) Summary: This test is flaky on all targets I know of. We should disable it for now so running the test suite doesn't randomly fail 50% of the time. --- openmp/libomptarget/test/offloading/barrier_fence.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openmp/libomptarget/test/offloading/barrier_fence.c b/openmp/libomptarget/test/offloading/barrier_fence.c index 5d1096478ed9..3eeaac52a2d6 100644 --- a/openmp/libomptarget/test/offloading/barrier_fence.c +++ b/openmp/libomptarget/test/offloading/barrier_fence.c @@ -3,6 +3,10 @@ // RUN: %libomptarget-compileopt-generic -fopenmp-offload-mandatory -O3 // RUN: %libomptarget-run-generic +// FIXME: This test is flaky on all targets +// UNSUPPORTED: amdgcn-amd-amdhsa +// UNSUPPORTED: nvptx64-nvidia-cuda +// UNSUPPORTED: nvptx64-nvidia-cuda-LTO // UNSUPPORTED: aarch64-unknown-linux-gnu // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu -- GitLab From 8bed754c2f965c8cbbb050be6f650b78f7fd78a6 Mon Sep 17 00:00:00 2001 From: Jordan Rupprecht Date: Wed, 13 Mar 2024 15:16:15 -0500 Subject: [PATCH 436/953] [lldb][test] Add `pexpect` category for tests that `import pexpect` (#84860) Instead of directly annotating pexpect-based tests with `@skipIfWindows`, we can tag them with a new `pexpect` category. We still automatically skip windows behavior by adding `pexpect` to the skip category list if the platform is windows, but also allow non-Windows users to skip them by configuring cmake with `-DLLDB_TEST_USER_ARGS=--skip-category=pexpect` As a prerequisite, remove the restriction that `@add_test_categories` can only apply to test cases, and we make the test runner look for categories on both the class and the test method. --- lldb/packages/Python/lldbsuite/test/decorators.py | 4 ---- lldb/packages/Python/lldbsuite/test/dotest.py | 13 +++++++++++++ lldb/packages/Python/lldbsuite/test/lldbpexpect.py | 2 +- .../Python/lldbsuite/test/test_categories.py | 1 + lldb/packages/Python/lldbsuite/test/test_result.py | 6 ++++-- .../API/benchmarks/expression/TestExpressionCmd.py | 5 +---- .../API/benchmarks/expression/TestRepeatedExprs.py | 5 +---- .../frame_variable/TestFrameVariableResponse.py | 5 +---- .../API/benchmarks/startup/TestStartupDelays.py | 5 +---- .../API/benchmarks/stepping/TestSteppingSpeed.py | 5 +---- .../TestCompileRunToBreakpointTurnaround.py | 5 +---- lldb/test/API/terminal/TestSTTYBeforeAndAfter.py | 2 +- 12 files changed, 26 insertions(+), 32 deletions(-) diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py index b691f82b9065..8e13aa6a1388 100644 --- a/lldb/packages/Python/lldbsuite/test/decorators.py +++ b/lldb/packages/Python/lldbsuite/test/decorators.py @@ -409,10 +409,6 @@ def add_test_categories(cat): cat = test_categories.validate(cat, True) def impl(func): - if isinstance(func, type) and issubclass(func, unittest.TestCase): - raise Exception( - "@add_test_categories can only be used to decorate a test method" - ) try: if hasattr(func, "categories"): cat.extend(func.categories) diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py index 291d7bad5c08..8c29145ecc52 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -914,6 +914,18 @@ def checkForkVForkSupport(): configuration.skip_categories.append("fork") +def checkPexpectSupport(): + from lldbsuite.test import lldbplatformutil + + platform = lldbplatformutil.getPlatform() + + # llvm.org/pr22274: need a pexpect replacement for windows + if platform in ["windows"]: + if configuration.verbose: + print("pexpect tests will be skipped because of unsupported platform") + configuration.skip_categories.append("pexpect") + + def run_suite(): # On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults # does not exist before proceeding to running the test suite. @@ -1013,6 +1025,7 @@ def run_suite(): checkDebugServerSupport() checkObjcSupport() checkForkVForkSupport() + checkPexpectSupport() skipped_categories_list = ", ".join(configuration.skip_categories) print( diff --git a/lldb/packages/Python/lldbsuite/test/lldbpexpect.py b/lldb/packages/Python/lldbsuite/test/lldbpexpect.py index 9d216d903074..998a080565b6 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbpexpect.py +++ b/lldb/packages/Python/lldbsuite/test/lldbpexpect.py @@ -10,7 +10,7 @@ from lldbsuite.test.decorators import * @skipIfRemote -@skipIfWindows # llvm.org/pr22274: need a pexpect replacement for windows +@add_test_categories(["pexpect"]) class PExpectTest(TestBase): NO_DEBUG_INFO_TESTCASE = True PROMPT = "(lldb) " diff --git a/lldb/packages/Python/lldbsuite/test/test_categories.py b/lldb/packages/Python/lldbsuite/test/test_categories.py index 3f8de175e29d..036bda9c957d 100644 --- a/lldb/packages/Python/lldbsuite/test/test_categories.py +++ b/lldb/packages/Python/lldbsuite/test/test_categories.py @@ -33,6 +33,7 @@ all_categories = { "lldb-server": "Tests related to lldb-server", "lldb-dap": "Tests for the Debug Adaptor Protocol with lldb-dap", "llgs": "Tests for the gdb-server functionality of lldb-server", + "pexpect": "Tests requiring the pexpect library to be available", "objc": "Tests related to the Objective-C programming language support", "pyapi": "Tests related to the Python API", "std-module": "Tests related to importing the std module", diff --git a/lldb/packages/Python/lldbsuite/test/test_result.py b/lldb/packages/Python/lldbsuite/test/test_result.py index 20365f53a675..2d574b343b41 100644 --- a/lldb/packages/Python/lldbsuite/test/test_result.py +++ b/lldb/packages/Python/lldbsuite/test/test_result.py @@ -148,9 +148,11 @@ class LLDBTestResult(unittest.TextTestResult): Gets all the categories for the currently running test method in test case """ test_categories = [] + test_categories.extend(getattr(test, "categories", [])) + test_method = getattr(test, test._testMethodName) - if test_method is not None and hasattr(test_method, "categories"): - test_categories.extend(test_method.categories) + if test_method is not None: + test_categories.extend(getattr(test_method, "categories", [])) test_categories.extend(self._getFileBasedCategories(test)) diff --git a/lldb/test/API/benchmarks/expression/TestExpressionCmd.py b/lldb/test/API/benchmarks/expression/TestExpressionCmd.py index 9b512305d626..8261b1b25da9 100644 --- a/lldb/test/API/benchmarks/expression/TestExpressionCmd.py +++ b/lldb/test/API/benchmarks/expression/TestExpressionCmd.py @@ -17,10 +17,7 @@ class ExpressionEvaluationCase(BenchBase): self.count = 25 @benchmarks_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows", - ) + @add_test_categories(["pexpect"]) def test_expr_cmd(self): """Test lldb's expression commands and collect statistics.""" self.build() diff --git a/lldb/test/API/benchmarks/expression/TestRepeatedExprs.py b/lldb/test/API/benchmarks/expression/TestRepeatedExprs.py index 104e69b38423..acc6b74c17b7 100644 --- a/lldb/test/API/benchmarks/expression/TestRepeatedExprs.py +++ b/lldb/test/API/benchmarks/expression/TestRepeatedExprs.py @@ -19,10 +19,7 @@ class RepeatedExprsCase(BenchBase): self.count = 100 @benchmarks_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows", - ) + @add_test_categories(["pexpect"]) def test_compare_lldb_to_gdb(self): """Test repeated expressions with lldb vs. gdb.""" self.build() diff --git a/lldb/test/API/benchmarks/frame_variable/TestFrameVariableResponse.py b/lldb/test/API/benchmarks/frame_variable/TestFrameVariableResponse.py index f3989fc0ff48..e364fb8ce778 100644 --- a/lldb/test/API/benchmarks/frame_variable/TestFrameVariableResponse.py +++ b/lldb/test/API/benchmarks/frame_variable/TestFrameVariableResponse.py @@ -17,10 +17,7 @@ class FrameVariableResponseBench(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows", - ) + @add_test_categories(["pexpect"]) def test_startup_delay(self): """Test response time for the 'frame variable' command.""" print() diff --git a/lldb/test/API/benchmarks/startup/TestStartupDelays.py b/lldb/test/API/benchmarks/startup/TestStartupDelays.py index f31a10507ed7..faec21e95e5d 100644 --- a/lldb/test/API/benchmarks/startup/TestStartupDelays.py +++ b/lldb/test/API/benchmarks/startup/TestStartupDelays.py @@ -22,10 +22,7 @@ class StartupDelaysBench(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows", - ) + @add_test_categories(["pexpect"]) def test_startup_delay(self): """Test start up delays creating a target, setting a breakpoint, and run to breakpoint stop.""" print() diff --git a/lldb/test/API/benchmarks/stepping/TestSteppingSpeed.py b/lldb/test/API/benchmarks/stepping/TestSteppingSpeed.py index a3264e3f3253..d0f9b0d61d17 100644 --- a/lldb/test/API/benchmarks/stepping/TestSteppingSpeed.py +++ b/lldb/test/API/benchmarks/stepping/TestSteppingSpeed.py @@ -22,10 +22,7 @@ class SteppingSpeedBench(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows", - ) + @add_test_categories(["pexpect"]) def test_run_lldb_steppings(self): """Test lldb steppings on a large executable.""" print() diff --git a/lldb/test/API/benchmarks/turnaround/TestCompileRunToBreakpointTurnaround.py b/lldb/test/API/benchmarks/turnaround/TestCompileRunToBreakpointTurnaround.py index 98a2ec9ebf23..91527cd11453 100644 --- a/lldb/test/API/benchmarks/turnaround/TestCompileRunToBreakpointTurnaround.py +++ b/lldb/test/API/benchmarks/turnaround/TestCompileRunToBreakpointTurnaround.py @@ -21,10 +21,7 @@ class CompileRunToBreakpointBench(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows", - ) + @add_test_categories(["pexpect"]) def test_run_lldb_then_gdb(self): """Benchmark turnaround time with lldb vs. gdb.""" print() diff --git a/lldb/test/API/terminal/TestSTTYBeforeAndAfter.py b/lldb/test/API/terminal/TestSTTYBeforeAndAfter.py index e5663c50c736..21aca5fc85d5 100644 --- a/lldb/test/API/terminal/TestSTTYBeforeAndAfter.py +++ b/lldb/test/API/terminal/TestSTTYBeforeAndAfter.py @@ -19,7 +19,7 @@ class TestSTTYBeforeAndAfter(TestBase): cls.RemoveTempFile("child_send2.txt") cls.RemoveTempFile("child_read2.txt") - @skipIfWindows # llvm.org/pr22274: need a pexpect replacement for windows + @add_test_categories(["pexpect"]) @no_debug_info_test def test_stty_dash_a_before_and_afetr_invoking_lldb_command(self): """Test that 'stty -a' displays the same output before and after running the lldb command.""" -- GitLab From c0f2177dac02903bb1ae85af5d91760d0a1b6a02 Mon Sep 17 00:00:00 2001 From: erichkeane Date: Wed, 13 Mar 2024 13:30:27 -0700 Subject: [PATCH 437/953] Revert "[NFC] Remove unnecessary 'Builtins.def' file." This reverts commit 5a95378659506b0ce94ceb79a43477e73c9756f4. It was pointed out that this serves as documentation for the targets where the builtin files have yet to be converted, so this should be left in place. Reverting! --- clang/include/clang/Basic/Builtins.def | 102 +++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 clang/include/clang/Basic/Builtins.def diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def new file mode 100644 index 000000000000..f356f881d5ef --- /dev/null +++ b/clang/include/clang/Basic/Builtins.def @@ -0,0 +1,102 @@ +//===--- Builtins.def - Builtin function info database ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This is only documentation for the database layout. This will be removed once +// all builtin databases are converted to tablegen files + +// The second value provided to the macro specifies the type of the function +// (result value, then each argument) as follows: +// v -> void +// b -> boolean +// c -> char +// s -> short +// i -> int +// h -> half (__fp16, OpenCL) +// x -> half (_Float16) +// y -> half (__bf16) +// f -> float +// d -> double +// z -> size_t +// w -> wchar_t +// F -> constant CFString +// G -> id +// H -> SEL +// M -> struct objc_super +// a -> __builtin_va_list +// A -> "reference" to __builtin_va_list +// V -> Vector, followed by the number of elements and the base type. +// q -> Scalable vector, followed by the number of elements and the base type. +// Q -> target builtin type, followed by a character to distinguish the builtin type +// Qa -> AArch64 svcount_t builtin type. +// E -> ext_vector, followed by the number of elements and the base type. +// X -> _Complex, followed by the base type. +// Y -> ptrdiff_t +// P -> FILE +// J -> jmp_buf +// SJ -> sigjmp_buf +// K -> ucontext_t +// p -> pid_t +// . -> "...". This may only occur at the end of the function list. +// +// Types may be prefixed with the following modifiers: +// L -> long (e.g. Li for 'long int', Ld for 'long double') +// LL -> long long (e.g. LLi for 'long long int', LLd for __float128) +// LLL -> __int128_t (e.g. LLLi) +// Z -> int32_t (require a native 32-bit integer type on the target) +// W -> int64_t (require a native 64-bit integer type on the target) +// N -> 'int' size if target is LP64, 'L' otherwise. +// O -> long for OpenCL targets, long long otherwise. +// S -> signed +// U -> unsigned +// I -> Required to constant fold to an integer constant expression. +// +// Types may be postfixed with the following modifiers: +// * -> pointer (optionally followed by an address space number, if no address +// space is specified than any address space will be accepted) +// & -> reference (optionally followed by an address space number) +// C -> const +// D -> volatile +// R -> restrict + +// The third value provided to the macro specifies information about attributes +// of the function. These must be kept in sync with the predicates in the +// Builtin::Context class. Currently we have: +// n -> nothrow +// r -> noreturn +// U -> pure +// c -> const +// t -> signature is meaningless, use custom typechecking +// T -> type is not important to semantic analysis and codegen; recognize as +// builtin even if type doesn't match signature, and don't warn if we +// can't be sure the type is right +// F -> this is a libc/libm function with a '__builtin_' prefix added. +// f -> this is a libc/libm function without a '__builtin_' prefix, or with +// 'z', a C++ standard library function in namespace std::. This builtin +// is disableable by '-fno-builtin-foo' / '-fno-builtin-std-foo'. +// h -> this function requires a specific header or an explicit declaration. +// i -> this is a runtime library implemented function without the +// '__builtin_' prefix. It will be implemented in compiler-rt or libgcc. +// p:N: -> this is a printf-like function whose Nth argument is the format +// string. +// P:N: -> similar to the p:N: attribute, but the function is like vprintf +// in that it accepts its arguments as a va_list rather than +// through an ellipsis +// s:N: -> this is a scanf-like function whose Nth argument is the format +// string. +// S:N: -> similar to the s:N: attribute, but the function is like vscanf +// in that it accepts its arguments as a va_list rather than +// through an ellipsis +// e -> const, but only when -fno-math-errno and FP exceptions are ignored +// g -> const when FP exceptions are ignored +// j -> returns_twice (like setjmp) +// u -> arguments are not evaluated for their side-effects +// V:N: -> requires vectors of at least N bits to be legal +// C -> callback behavior: argument N is called with argument +// M_0, ..., M_k as payload +// z -> this is a function in (possibly-versioned) namespace std +// E -> this function can be constant evaluated by Clang frontend -- GitLab From e2b8cc11b307aaf2717c344cbaa1d3eb5a4e0401 Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Wed, 13 Mar 2024 13:34:01 -0700 Subject: [PATCH 438/953] [lldb] XFAIL TestIndirectSymbols on darwin (#85127) ``` AssertionError: 'main' != 'call_through_indirect_hidden' ``` --- lldb/test/API/macosx/indirect_symbol/TestIndirectSymbols.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lldb/test/API/macosx/indirect_symbol/TestIndirectSymbols.py b/lldb/test/API/macosx/indirect_symbol/TestIndirectSymbols.py index fbe6db9f892d..ad4cb4b12c79 100644 --- a/lldb/test/API/macosx/indirect_symbol/TestIndirectSymbols.py +++ b/lldb/test/API/macosx/indirect_symbol/TestIndirectSymbols.py @@ -16,6 +16,7 @@ class TestIndirectFunctions(TestBase): @skipUnlessDarwin @add_test_categories(["pyapi"]) + @expectedFailureDarwin("rdar://120796553") def test_with_python_api(self): """Test stepping and setting breakpoints in indirect and re-exported symbols.""" self.build() -- GitLab From 26bd3d0f9a5a518de02f4dc1921648cda54a0d4e Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Wed, 13 Mar 2024 13:34:33 -0700 Subject: [PATCH 439/953] [Fuchsia] Add LLDB_TEST_USER_ARGS to stage2 passthrough --- clang/cmake/caches/Fuchsia.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/cmake/caches/Fuchsia.cmake b/clang/cmake/caches/Fuchsia.cmake index 1209fd935986..df69d7d0dd41 100644 --- a/clang/cmake/caches/Fuchsia.cmake +++ b/clang/cmake/caches/Fuchsia.cmake @@ -66,6 +66,7 @@ set(_FUCHSIA_BOOTSTRAP_PASSTHROUGH LLDB_PYTHON_HOME LLDB_PYTHON_RELATIVE_PATH LLDB_TEST_USE_VENDOR_PACKAGES + LLDB_TEST_USER_ARGS Python3_EXECUTABLE Python3_LIBRARIES Python3_INCLUDE_DIRS -- GitLab From b966b224b32aada3d83fb6d58abe413b5c59f3c1 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 13 Mar 2024 13:38:07 -0700 Subject: [PATCH 440/953] Revert "[SLP]Fix PR85082: PHI node has multiple entries." This reverts commit 8237520eb42b37d7ed353d64a865d3ba5ac24ec6 to fix a crash in https://lab.llvm.org/buildbot/#/builders/198/builds/8891. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 16 ++-- .../X86/same-scalar-in-same-phi-extract.ll | 75 ------------------- 2 files changed, 7 insertions(+), 84 deletions(-) delete mode 100644 llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 1da509ce4794..b8b67609d755 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -12582,7 +12582,6 @@ Value *BoUpSLP::vectorizeTree( Ex = I; } } - Value *ExV = Ex; if (!Ex) { // "Reuse" the existing extract to improve final codegen. if (auto *ES = dyn_cast(Scalar)) { @@ -12593,13 +12592,7 @@ Value *BoUpSLP::vectorizeTree( } else { Ex = Builder.CreateExtractElement(Vec, Lane); } - // If necessary, sign-extend or zero-extend ScalarRoot - // to the larger type. - ExV = Ex; - if (Scalar->getType() != Ex->getType()) - ExV = Builder.CreateIntCast(Ex, Scalar->getType(), - MinBWs.find(E)->second.second); - if (auto *I = dyn_cast(ExV)) + if (auto *I = dyn_cast(Ex)) ScalarToEEs[Scalar].try_emplace(Builder.GetInsertBlock(), I); } // The then branch of the previous if may produce constants, since 0 @@ -12608,7 +12601,12 @@ Value *BoUpSLP::vectorizeTree( GatherShuffleExtractSeq.insert(ExI); CSEBlocks.insert(ExI->getParent()); } - return ExV; + // If necessary, sign-extend or zero-extend ScalarRoot + // to the larger type. + if (Scalar->getType() != Ex->getType()) + return Builder.CreateIntCast(Ex, Scalar->getType(), + MinBWs.find(E)->second.second); + return Ex; } assert(isa(Scalar->getType()) && isa(Scalar) && diff --git a/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll b/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll deleted file mode 100644 index 35f2f9e052e7..000000000000 --- a/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll +++ /dev/null @@ -1,75 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 -; RUN: opt -S --passes=slp-vectorizer -slp-threshold=-99999 -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s - -define void @test(i32 %arg) { -; CHECK-LABEL: define void @test( -; CHECK-SAME: i32 [[ARG:%.*]]) { -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i32> , i32 [[ARG]], i32 0 -; CHECK-NEXT: br label [[BB2:%.*]] -; CHECK: bb2: -; CHECK-NEXT: switch i32 0, label [[BB10:%.*]] [ -; CHECK-NEXT: i32 0, label [[BB9:%.*]] -; CHECK-NEXT: i32 11, label [[BB9]] -; CHECK-NEXT: i32 1, label [[BB4:%.*]] -; CHECK-NEXT: ] -; CHECK: bb3: -; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x i32> [[TMP0]], i32 0 -; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[TMP1]] to i64 -; CHECK-NEXT: switch i32 0, label [[BB10]] [ -; CHECK-NEXT: i32 18, label [[BB7:%.*]] -; CHECK-NEXT: i32 1, label [[BB7]] -; CHECK-NEXT: i32 0, label [[BB10]] -; CHECK-NEXT: ] -; CHECK: bb4: -; CHECK-NEXT: [[TMP3:%.*]] = phi <2 x i32> [ [[TMP0]], [[BB2]] ] -; CHECK-NEXT: [[TMP4:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64> -; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i64> [[TMP4]], i32 0 -; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr i32, ptr null, i64 [[TMP5]] -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i64> [[TMP4]], i32 1 -; CHECK-NEXT: [[GETELEMENTPTR6:%.*]] = getelementptr i32, ptr null, i64 [[TMP6]] -; CHECK-NEXT: ret void -; CHECK: bb7: -; CHECK-NEXT: [[PHI8:%.*]] = phi i64 [ [[TMP2]], [[BB3:%.*]] ], [ [[TMP2]], [[BB3]] ] -; CHECK-NEXT: br label [[BB9]] -; CHECK: bb9: -; CHECK-NEXT: ret void -; CHECK: bb10: -; CHECK-NEXT: ret void -; -bb: - %zext = zext i32 %arg to i64 - %zext1 = zext i32 0 to i64 - br label %bb2 - -bb2: - switch i32 0, label %bb10 [ - i32 0, label %bb9 - i32 11, label %bb9 - i32 1, label %bb4 - ] - -bb3: - switch i32 0, label %bb10 [ - i32 18, label %bb7 - i32 1, label %bb7 - i32 0, label %bb10 - ] - -bb4: - %phi = phi i64 [ %zext, %bb2 ] - %phi5 = phi i64 [ %zext1, %bb2 ] - %getelementptr = getelementptr i32, ptr null, i64 %phi - %getelementptr6 = getelementptr i32, ptr null, i64 %phi5 - ret void - -bb7: - %phi8 = phi i64 [ %zext, %bb3 ], [ %zext, %bb3 ] - br label %bb9 - -bb9: - ret void - -bb10: - ret void -} -- GitLab From 4dd186afd502e1e56b8f3d6d923b7f8cfa124572 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Wed, 13 Mar 2024 07:45:14 -0700 Subject: [PATCH 441/953] [SLP]Fix PR85082: PHI node has multiple entries. Need to record casted extractelement for the externally used scalar, not original extract instruction. --- .../Transforms/Vectorize/SLPVectorizer.cpp | 30 +++++--- .../X86/same-scalar-in-same-phi-extract.ll | 75 +++++++++++++++++++ 2 files changed, 95 insertions(+), 10 deletions(-) create mode 100644 llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index b8b67609d755..739dae3bdd0c 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -12539,7 +12539,9 @@ Value *BoUpSLP::vectorizeTree( DenseMap VectorToInsertElement; // Maps extract Scalar to the corresponding extractelement instruction in the // basic block. Only one extractelement per block should be emitted. - DenseMap> ScalarToEEs; + DenseMap>> + ScalarToEEs; SmallDenseSet UsedInserts; DenseMap, Value *> VectorCasts; SmallDenseSet ScalarsWithNullptrUser; @@ -12568,18 +12570,23 @@ Value *BoUpSLP::vectorizeTree( auto ExtractAndExtendIfNeeded = [&](Value *Vec) { if (Scalar->getType() != Vec->getType()) { Value *Ex = nullptr; + Value *ExV = nullptr; auto It = ScalarToEEs.find(Scalar); if (It != ScalarToEEs.end()) { // No need to emit many extracts, just move the only one in the // current block. auto EEIt = It->second.find(Builder.GetInsertBlock()); if (EEIt != It->second.end()) { - Instruction *I = EEIt->second; + Instruction *I = EEIt->second.first; if (Builder.GetInsertPoint() != Builder.GetInsertBlock()->end() && - Builder.GetInsertPoint()->comesBefore(I)) + Builder.GetInsertPoint()->comesBefore(I)) { I->moveBefore(*Builder.GetInsertPoint()->getParent(), Builder.GetInsertPoint()); + if (auto *CI = EEIt->second.second) + CI->moveAfter(I); + } Ex = I; + ExV = EEIt->second.second ? EEIt->second.second : Ex; } } if (!Ex) { @@ -12592,8 +12599,16 @@ Value *BoUpSLP::vectorizeTree( } else { Ex = Builder.CreateExtractElement(Vec, Lane); } + // If necessary, sign-extend or zero-extend ScalarRoot + // to the larger type. + ExV = Ex; + if (Scalar->getType() != Ex->getType()) + ExV = Builder.CreateIntCast(Ex, Scalar->getType(), + MinBWs.find(E)->second.second); if (auto *I = dyn_cast(Ex)) - ScalarToEEs[Scalar].try_emplace(Builder.GetInsertBlock(), I); + ScalarToEEs[Scalar].try_emplace( + Builder.GetInsertBlock(), + std::make_pair(I, cast(ExV))); } // The then branch of the previous if may produce constants, since 0 // operand might be a constant. @@ -12601,12 +12616,7 @@ Value *BoUpSLP::vectorizeTree( GatherShuffleExtractSeq.insert(ExI); CSEBlocks.insert(ExI->getParent()); } - // If necessary, sign-extend or zero-extend ScalarRoot - // to the larger type. - if (Scalar->getType() != Ex->getType()) - return Builder.CreateIntCast(Ex, Scalar->getType(), - MinBWs.find(E)->second.second); - return Ex; + return ExV; } assert(isa(Scalar->getType()) && isa(Scalar) && diff --git a/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll b/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll new file mode 100644 index 000000000000..35f2f9e052e7 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll @@ -0,0 +1,75 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -slp-threshold=-99999 -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s + +define void @test(i32 %arg) { +; CHECK-LABEL: define void @test( +; CHECK-SAME: i32 [[ARG:%.*]]) { +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i32> , i32 [[ARG]], i32 0 +; CHECK-NEXT: br label [[BB2:%.*]] +; CHECK: bb2: +; CHECK-NEXT: switch i32 0, label [[BB10:%.*]] [ +; CHECK-NEXT: i32 0, label [[BB9:%.*]] +; CHECK-NEXT: i32 11, label [[BB9]] +; CHECK-NEXT: i32 1, label [[BB4:%.*]] +; CHECK-NEXT: ] +; CHECK: bb3: +; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x i32> [[TMP0]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[TMP1]] to i64 +; CHECK-NEXT: switch i32 0, label [[BB10]] [ +; CHECK-NEXT: i32 18, label [[BB7:%.*]] +; CHECK-NEXT: i32 1, label [[BB7]] +; CHECK-NEXT: i32 0, label [[BB10]] +; CHECK-NEXT: ] +; CHECK: bb4: +; CHECK-NEXT: [[TMP3:%.*]] = phi <2 x i32> [ [[TMP0]], [[BB2]] ] +; CHECK-NEXT: [[TMP4:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64> +; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i64> [[TMP4]], i32 0 +; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr i32, ptr null, i64 [[TMP5]] +; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i64> [[TMP4]], i32 1 +; CHECK-NEXT: [[GETELEMENTPTR6:%.*]] = getelementptr i32, ptr null, i64 [[TMP6]] +; CHECK-NEXT: ret void +; CHECK: bb7: +; CHECK-NEXT: [[PHI8:%.*]] = phi i64 [ [[TMP2]], [[BB3:%.*]] ], [ [[TMP2]], [[BB3]] ] +; CHECK-NEXT: br label [[BB9]] +; CHECK: bb9: +; CHECK-NEXT: ret void +; CHECK: bb10: +; CHECK-NEXT: ret void +; +bb: + %zext = zext i32 %arg to i64 + %zext1 = zext i32 0 to i64 + br label %bb2 + +bb2: + switch i32 0, label %bb10 [ + i32 0, label %bb9 + i32 11, label %bb9 + i32 1, label %bb4 + ] + +bb3: + switch i32 0, label %bb10 [ + i32 18, label %bb7 + i32 1, label %bb7 + i32 0, label %bb10 + ] + +bb4: + %phi = phi i64 [ %zext, %bb2 ] + %phi5 = phi i64 [ %zext1, %bb2 ] + %getelementptr = getelementptr i32, ptr null, i64 %phi + %getelementptr6 = getelementptr i32, ptr null, i64 %phi5 + ret void + +bb7: + %phi8 = phi i64 [ %zext, %bb3 ], [ %zext, %bb3 ] + br label %bb9 + +bb9: + ret void + +bb10: + ret void +} -- GitLab From 03e50c451427d908bbf8cf2d455de3ebba49fe4f Mon Sep 17 00:00:00 2001 From: Peter Klausler <35819229+klausler@users.noreply.github.com> Date: Wed, 13 Mar 2024 14:11:45 -0700 Subject: [PATCH 442/953] [flang] Emit warning when Hollerith actual passed to CLASS(*) (#84084) When a Hollerith actual argument is associated with an unlimited polymorphic dummy argument, it's treated as if it were CHARACTER. Some other compilers treat it as if it had been BOZ, so emit a portability warning. Resolves https://github.com/llvm/llvm-project/issues/83548. --- flang/include/flang/Evaluate/constant.h | 3 +++ flang/lib/Semantics/check-call.cpp | 10 +++++++++- flang/lib/Semantics/expression.cpp | 7 +++++-- flang/test/Semantics/call41.f90 | 12 ++++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 flang/test/Semantics/call41.f90 diff --git a/flang/include/flang/Evaluate/constant.h b/flang/include/flang/Evaluate/constant.h index ee83d9fc04f3..71be7906d2fe 100644 --- a/flang/include/flang/Evaluate/constant.h +++ b/flang/include/flang/Evaluate/constant.h @@ -186,6 +186,8 @@ public: const Scalar &values() const { return values_; } ConstantSubscript LEN() const { return length_; } + bool wasHollerith() const { return wasHollerith_; } + void set_wasHollerith(bool yes = true) { wasHollerith_ = yes; } std::optional> GetScalarValue() const { if (Rank() == 0) { @@ -210,6 +212,7 @@ public: private: Scalar values_; // one contiguous string ConstantSubscript length_; + bool wasHollerith_{false}; }; class StructureConstructor; diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp index 3adbd7cc4177..d625f8c2f7fc 100644 --- a/flang/lib/Semantics/check-call.cpp +++ b/flang/lib/Semantics/check-call.cpp @@ -332,7 +332,15 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, bool typesCompatible{typesCompatibleWithIgnoreTKR || dummy.type.type().IsTkCompatibleWith(actualType.type())}; int dummyRank{dummy.type.Rank()}; - if (!typesCompatible && dummyRank == 0 && allowActualArgumentConversions) { + if (typesCompatible) { + if (const auto *constantChar{ + evaluate::UnwrapConstantValue(actual)}; + constantChar && constantChar->wasHollerith() && + dummy.type.type().IsUnlimitedPolymorphic()) { + messages.Say( + "passing Hollerith to unlimited polymorphic as if it were CHARACTER"_port_en_US); + } + } else if (dummyRank == 0 && allowActualArgumentConversions) { // Extension: pass Hollerith literal to scalar as if it had been BOZ if (auto converted{evaluate::HollerithToBOZ( foldingContext, actual, dummy.type.type())}) { diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index 54bfe0f2e156..1015a9e6efce 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -875,8 +875,11 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::CharLiteralConstant &x) { MaybeExpr ExpressionAnalyzer::Analyze( const parser::HollerithLiteralConstant &x) { int kind{GetDefaultKind(TypeCategory::Character)}; - auto value{x.v}; - return AnalyzeString(std::move(value), kind); + auto result{AnalyzeString(std::string{x.v}, kind)}; + if (auto *constant{UnwrapConstantValue(result)}) { + constant->set_wasHollerith(true); + } + return result; } // .TRUE. and .FALSE. of various kinds diff --git a/flang/test/Semantics/call41.f90 b/flang/test/Semantics/call41.f90 new file mode 100644 index 000000000000..a4c7514d99ba --- /dev/null +++ b/flang/test/Semantics/call41.f90 @@ -0,0 +1,12 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 -Werror +module m + contains + subroutine unlimited(x) + class(*), intent(in) :: x + end + subroutine test + !PORTABILITY: passing Hollerith to unlimited polymorphic as if it were CHARACTER + call unlimited(6HHERMAN) + call unlimited('abc') ! ok + end +end -- GitLab From b49d741c0c3bb21b40c925b4c1a717470181eb8d Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Wed, 13 Mar 2024 14:15:41 -0700 Subject: [PATCH 443/953] [lldb] Skip TestIndirectSymbols (#85133) Correction to e2b8cc11b307aaf2717c344cbaa1d3eb5a4e0401 --- lldb/test/API/macosx/indirect_symbol/TestIndirectSymbols.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/test/API/macosx/indirect_symbol/TestIndirectSymbols.py b/lldb/test/API/macosx/indirect_symbol/TestIndirectSymbols.py index ad4cb4b12c79..c4bbedc92891 100644 --- a/lldb/test/API/macosx/indirect_symbol/TestIndirectSymbols.py +++ b/lldb/test/API/macosx/indirect_symbol/TestIndirectSymbols.py @@ -16,7 +16,7 @@ class TestIndirectFunctions(TestBase): @skipUnlessDarwin @add_test_categories(["pyapi"]) - @expectedFailureDarwin("rdar://120796553") + @skipIf(bugnumber="rdar://120796553") def test_with_python_api(self): """Test stepping and setting breakpoints in indirect and re-exported symbols.""" self.build() -- GitLab From ea848d0a6d5c17af3eb1a4e39dc712606ac684f6 Mon Sep 17 00:00:00 2001 From: MessyHack Date: Wed, 13 Mar 2024 14:22:23 -0700 Subject: [PATCH 444/953] [OpenMP] Sort topology after adding processor group layer. (#83943) Various behavior around creating affinity masks and detecting uniform topology depends on the topology being sorted. resort topology after adding processor group layer to ensure that the updated topology reflects the newly added processor group info. Observed that the topology was not sorted correctly on high core count AMD Epyc Genoa (2 sockets, 96 cores, 2 threads) using NUMA (NPS 2+). --- openmp/runtime/src/kmp_affinity.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openmp/runtime/src/kmp_affinity.cpp b/openmp/runtime/src/kmp_affinity.cpp index c3ee4de75a23..048bd174fc95 100644 --- a/openmp/runtime/src/kmp_affinity.cpp +++ b/openmp/runtime/src/kmp_affinity.cpp @@ -327,6 +327,9 @@ void kmp_topology_t::_insert_windows_proc_groups() { KMP_CPU_FREE(mask); _insert_layer(KMP_HW_PROC_GROUP, ids); __kmp_free(ids); + + // sort topology after adding proc groups + __kmp_topology->sort_ids(); } #endif -- GitLab From ccfb9e6eb7429885e6d09e99cf89bce41f1ca3cc Mon Sep 17 00:00:00 2001 From: Peter Klausler <35819229+klausler@users.noreply.github.com> Date: Wed, 13 Mar 2024 14:30:04 -0700 Subject: [PATCH 445/953] [flang] Omit parent components for references to bindings (#84836) https://github.com/llvm/llvm-project/pull/78593 changed expression semantics to always include the names of parent components that were necessary to access an inherited component. This turns out to have broken calls to inherited NOPASS procedure bindings. Update the patch to omit explicit parent components when accessing bindings, while retaining them for component accesses (including procedure components). --- flang/lib/Semantics/expression.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index 1015a9e6efce..6af86de9dd81 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -1302,7 +1302,8 @@ static NamedEntity IgnoreAnySubscripts(Designator &&designator) { std::move(designator.u)); } -// Components of parent derived types are explicitly represented as such. +// Components, but not bindings, of parent derived types are explicitly +// represented as such. std::optional ExpressionAnalyzer::CreateComponent(DataRef &&base, const Symbol &component, const semantics::Scope &scope, bool C919bAlreadyEnforced) { @@ -1310,7 +1311,8 @@ std::optional ExpressionAnalyzer::CreateComponent(DataRef &&base, base.Rank() > 0) { // C919b Say("An allocatable or pointer component reference must be applied to a scalar base"_err_en_US); } - if (&component.owner() == &scope) { + if (&component.owner() == &scope || + component.has()) { return Component{std::move(base), component}; } if (const Symbol *typeSymbol{scope.GetSymbol()}) { -- GitLab From af61b8e8f18df2545017ade74baee7a8a8ca99f8 Mon Sep 17 00:00:00 2001 From: Justice Adams <107649528+justice-adams-apple@users.noreply.github.com> Date: Wed, 13 Mar 2024 14:42:04 -0700 Subject: [PATCH 446/953] [cmake] Add check_linker_flag import (#85128) Fixing ``` CMake Error at cmake/llvm/AddLLVM.cmake:266 (check_linker_flag): Unknown CMake command "check_linker_flag". ``` --- llvm/cmake/modules/AddLLVM.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake index eb9e6101bdce..f6fb56eb51e8 100644 --- a/llvm/cmake/modules/AddLLVM.cmake +++ b/llvm/cmake/modules/AddLLVM.cmake @@ -263,6 +263,7 @@ if (NOT DEFINED LLVM_LINKER_DETECTED AND NOT WIN32) # -no_warn_duplicate_libraries, but only in versions of the linker that # support that flag. if(NOT LLVM_USE_LINKER AND ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + include(CheckLinkerFlag) check_linker_flag(C "-Wl,-no_warn_duplicate_libraries" LLVM_LINKER_SUPPORTS_NO_WARN_DUPLICATE_LIBRARIES) else() set(LLVM_LINKER_SUPPORTS_NO_WARN_DUPLICATE_LIBRARIES OFF CACHE INTERNAL "") -- GitLab From 5661188c5766c3136d1954d769825261715b1f9a Mon Sep 17 00:00:00 2001 From: Peter Klausler <35819229+klausler@users.noreply.github.com> Date: Wed, 13 Mar 2024 14:42:40 -0700 Subject: [PATCH 447/953] =?UTF-8?q?[flang]=20Support=20multiple=20distinct?= =?UTF-8?q?=20module=20files=20with=20same=20name=20in=20one=20=E2=80=A6?= =?UTF-8?q?=20(#84838)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …compilation Allow multiple module files with the same module name to exist in one compilation; distinct modules are distinguished by their hashes. --- .../flang/Semantics/module-dependences.h | 4 +- flang/include/flang/Semantics/symbol.h | 3 + flang/lib/Semantics/mod-file.cpp | 85 +++++++++---------- flang/test/Semantics/modfile63.f90 | 7 +- 4 files changed, 46 insertions(+), 53 deletions(-) diff --git a/flang/include/flang/Semantics/module-dependences.h b/flang/include/flang/Semantics/module-dependences.h index 29813a19a4b1..3401d64c9593 100644 --- a/flang/include/flang/Semantics/module-dependences.h +++ b/flang/include/flang/Semantics/module-dependences.h @@ -23,9 +23,9 @@ public: void AddDependence( std::string &&name, bool intrinsic, ModuleCheckSumType hash) { if (intrinsic) { - intrinsicMap_.emplace(std::move(name), hash); + intrinsicMap_.insert_or_assign(std::move(name), hash); } else { - nonIntrinsicMap_.emplace(std::move(name), hash); + nonIntrinsicMap_.insert_or_assign(std::move(name), hash); } } std::optional GetRequiredHash( diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index c3175a5d1a11..67153ffb3be9 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -91,12 +91,15 @@ public: return moduleFileHash_; } void set_moduleFileHash(ModuleCheckSumType x) { moduleFileHash_ = x; } + const Symbol *previous() const { return previous_; } + void set_previous(const Symbol *p) { previous_ = p; } private: bool isSubmodule_; bool isDefaultPrivate_{false}; const Scope *scope_{nullptr}; std::optional moduleFileHash_; + const Symbol *previous_{nullptr}; // same name, different module file hash }; class MainProgramDetails : public WithOmpDeclarative { diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index b4df7216a33e..5d0d210fa348 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -1242,7 +1242,7 @@ static void GetModuleDependences( std::size_t limit{content.size()}; std::string_view str{content.data(), limit}; for (std::size_t j{ModHeader::len}; - str.substr(j, ModHeader::needLen) == ModHeader::need;) { + str.substr(j, ModHeader::needLen) == ModHeader::need; ++j) { j += 7; auto checkSum{ExtractCheckSum(str.substr(j, ModHeader::sumLen))}; if (!checkSum) { @@ -1260,8 +1260,8 @@ static void GetModuleDependences( for (; j < limit && str.at(j) != '\n'; ++j) { } if (j > start && j < limit && str.at(j) == '\n') { - dependences.AddDependence( - std::string{str.substr(start, j - start)}, intrinsic, *checkSum); + std::string depModName{str.substr(start, j - start)}; + dependences.AddDependence(std::move(depModName), intrinsic, *checkSum); } else { break; } @@ -1271,7 +1271,7 @@ static void GetModuleDependences( Scope *ModFileReader::Read(SourceName name, std::optional isIntrinsic, Scope *ancestor, bool silent) { std::string ancestorName; // empty for module - Symbol *notAModule{nullptr}; + const Symbol *notAModule{nullptr}; bool fatalError{false}; if (ancestor) { if (auto *scope{ancestor->FindSubmodule(name)}) { @@ -1287,26 +1287,28 @@ Scope *ModFileReader::Read(SourceName name, std::optional isIntrinsic, if (it != context_.globalScope().end()) { Scope *scope{it->second->scope()}; if (scope->kind() == Scope::Kind::Module) { - if (requiredHash) { - if (const Symbol * foundModule{scope->symbol()}) { - if (const auto *module{foundModule->detailsIf()}; - module && module->moduleFileHash() && - *requiredHash != *module->moduleFileHash()) { - Say(name, ancestorName, - "Multiple versions of the module '%s' cannot be required by the same compilation"_err_en_US, - name.ToString()); - return nullptr; + for (const Symbol *found{scope->symbol()}; found;) { + if (const auto *module{found->detailsIf()}) { + if (!requiredHash || + *requiredHash == + module->moduleFileHash().value_or(*requiredHash)) { + return const_cast(found->scope()); } + found = module->previous(); // same name, distinct hash + } else { + notAModule = found; + break; } } - return scope; } else { notAModule = scope->symbol(); - // USE, NON_INTRINSIC global name isn't a module? - fatalError = isIntrinsic.has_value(); } } } + if (notAModule) { + // USE, NON_INTRINSIC global name isn't a module? + fatalError = isIntrinsic.has_value(); + } auto path{ModFileName(name, ancestorName, context_.moduleFileSuffix())}; parser::Parsing parsing{context_.allCookedSources()}; parser::Options options; @@ -1360,42 +1362,18 @@ Scope *ModFileReader::Read(SourceName name, std::optional isIntrinsic, // Look for the right module file if its hash is known if (requiredHash && !fatalError) { - std::vector misses; for (const std::string &maybe : parser::LocateSourceFileAll(path, options.searchDirectories)) { if (const auto *srcFile{context_.allCookedSources().allSources().OpenPath( maybe, llvm::errs())}) { - if (auto checkSum{VerifyHeader(srcFile->content())}) { - if (*checkSum == *requiredHash) { - path = maybe; - if (!misses.empty()) { - auto &msg{context_.Say(name, - "Module file for '%s' appears later in the module search path than conflicting modules with different checksums"_warn_en_US, - name.ToString())}; - for (const std::string &m : misses) { - msg.Attach( - name, "Module file with a conflicting name: '%s'"_en_US, m); - } - } - misses.clear(); - break; - } else { - misses.emplace_back(maybe); - } + if (auto checkSum{VerifyHeader(srcFile->content())}; + checkSum && *checkSum == *requiredHash) { + path = maybe; + break; } } } - if (!misses.empty()) { - auto &msg{Say(name, ancestorName, - "Could not find a module file for '%s' in the module search path with the expected checksum"_err_en_US, - name.ToString())}; - for (const std::string &m : misses) { - msg.Attach(name, "Module file with different checksum: '%s'"_en_US, m); - } - return nullptr; - } } - const auto *sourceFile{fatalError ? nullptr : parsing.Prescan(path, options)}; if (fatalError || parsing.messages().AnyFatalError()) { if (!silent) { @@ -1451,11 +1429,24 @@ Scope *ModFileReader::Read(SourceName name, std::optional isIntrinsic, Scope &topScope{isIntrinsic.value_or(false) ? context_.intrinsicModulesScope() : context_.globalScope()}; Symbol *moduleSymbol{nullptr}; + const Symbol *previousModuleSymbol{nullptr}; if (!ancestor) { // module, not submodule parentScope = &topScope; auto pair{parentScope->try_emplace(name, UnknownDetails{})}; if (!pair.second) { - return nullptr; + // There is already a global symbol or intrinsic module of the same name. + previousModuleSymbol = &*pair.first->second; + if (const auto *details{ + previousModuleSymbol->detailsIf()}) { + if (!details->moduleFileHash().has_value()) { + return nullptr; + } + } else { + return nullptr; + } + CHECK(parentScope->erase(name) != 0); + pair = parentScope->try_emplace(name, UnknownDetails{}); + CHECK(pair.second); } moduleSymbol = &*pair.first->second; moduleSymbol->set(Symbol::Flag::ModFile); @@ -1486,7 +1477,9 @@ Scope *ModFileReader::Read(SourceName name, std::optional isIntrinsic, } if (moduleSymbol) { CHECK(moduleSymbol->test(Symbol::Flag::ModFile)); - moduleSymbol->get().set_moduleFileHash(checkSum.value()); + auto &details{moduleSymbol->get()}; + details.set_moduleFileHash(checkSum.value()); + details.set_previous(previousModuleSymbol); if (isIntrinsic.value_or(false)) { moduleSymbol->attrs().set(Attr::INTRINSIC); } diff --git a/flang/test/Semantics/modfile63.f90 b/flang/test/Semantics/modfile63.f90 index aaf1f7beaa48..078312101724 100644 --- a/flang/test/Semantics/modfile63.f90 +++ b/flang/test/Semantics/modfile63.f90 @@ -1,12 +1,10 @@ ! RUN: %flang_fc1 -fsyntax-only -I%S/Inputs/dir1 %s ! RUN: not %flang_fc1 -fsyntax-only -I%S/Inputs/dir2 %s 2>&1 | FileCheck --check-prefix=ERROR %s ! RUN: %flang_fc1 -Werror -fsyntax-only -I%S/Inputs/dir1 -I%S/Inputs/dir2 %s -! RUN: not %flang_fc1 -Werror -fsyntax-only -I%S/Inputs/dir2 -I%S/Inputs/dir1 %s 2>&1 | FileCheck --check-prefix=WARNING %s ! Inputs/dir1 and Inputs/dir2 each have identical copies of modfile63b.mod. ! modfile63b.mod depends on Inputs/dir1/modfile63a.mod - the version in -! Inputs/dir2/modfile63a.mod has a distinct checksum and should be -! ignored with a warning. +! Inputs/dir2/modfile63a.mod has a distinct checksum. ! If it becomes necessary to recompile those modules, just use the ! module files as Fortran source. @@ -15,5 +13,4 @@ use modfile63b call s2 end -! ERROR: Could not find a module file for 'modfile63a' in the module search path with the expected checksum -! WARNING: Module file for 'modfile63a' appears later in the module search path than conflicting modules with different checksums +! ERROR: Cannot read module file for module 'modfile63a': File is not the right module file for 'modfile63a': -- GitLab From af964c7e31f0728e84c97b734933fcb9a1912bce Mon Sep 17 00:00:00 2001 From: Peter Klausler <35819229+klausler@users.noreply.github.com> Date: Wed, 13 Mar 2024 14:52:25 -0700 Subject: [PATCH 448/953] =?UTF-8?q?[flang][runtime]=20Let=20FORT=5FCHECK?= =?UTF-8?q?=5FPOINTER=5FDEALLOCATION=3D0=20disable=20runtime=20=E2=80=A6?= =?UTF-8?q?=20(#84956)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …check Add an environment variable by which a user can disable the pointer validation check in DEALLOCATE statement handling. This is not safe, but it can help make a code work that allocates a pointer with an extended derived type, associates its target with a pointer to one of its ancestor types, and then deallocates that pointer. --- flang/docs/RuntimeEnvironment.md | 57 ++++++++++++++++++++++++++++++++ flang/docs/index.md | 1 + flang/runtime/environment.cpp | 13 ++++++++ flang/runtime/environment.h | 1 + flang/runtime/pointer.cpp | 26 +++++++++------ 5 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 flang/docs/RuntimeEnvironment.md diff --git a/flang/docs/RuntimeEnvironment.md b/flang/docs/RuntimeEnvironment.md new file mode 100644 index 000000000000..c7a3dfbb2af1 --- /dev/null +++ b/flang/docs/RuntimeEnvironment.md @@ -0,0 +1,57 @@ + + +```{contents} +--- +local: +--- +``` + +# Environment variables of significance to Fortran execution + +A few environment variables are queried by the Fortran runtime support +library. + +The following environment variables can affect the behavior of +Fortran programs during execution. + +## `DEFAULT_UTF8=1` + +Set `DEFAULT_UTF8` to cause formatted external input to assume UTF-8 +encoding on input and use UTF-8 encoding on formatted external output. + +## `FORT_CONVERT` + +Determines data conversions applied to unformatted I/O. + +* `NATIVE`: no conversions (default) +* `LITTLE_ENDIAN`: assume input is little-endian; emit little-endian output +* `BIG_ENDIAN`: assume input is big-endian; emit big-endian output +* `SWAP`: reverse endianness (always convert) + +## `FORT_CHECK_POINTER_DEALLOCATION` + +Fortran requires that a pointer that appears in a `DEALLOCATE` statement +must have been allocated in an `ALLOCATE` statement with the same declared +type. +The runtime support library validates this requirement by checking the +size of the allocated data, and will fail with an error message if +the deallocated pointer is not valid. +Set `FORT_CHECK_POINTER_DEALLOCATION=0` to disable this check. + +## `FORT_FMT_RECL` + +Set to an integer value to specify the record length for list-directed +and `NAMELIST` output. +The default is 72. + +## `NO_STOP_MESSAGE` + +Set `NO_STOP_MESSAGE=1` to disable the extra information about +IEEE floating-point exception flags that the Fortran language +standard requires for `STOP` and `ERROR STOP` statements. diff --git a/flang/docs/index.md b/flang/docs/index.md index b4dbdc87fdf6..ed749f565ff1 100644 --- a/flang/docs/index.md +++ b/flang/docs/index.md @@ -80,6 +80,7 @@ on how to get in touch with us and to learn more about the current status. Preprocessing ProcedurePointer RuntimeDescriptor + RuntimeEnvironment RuntimeTypeInfo Semantics f2018-grammar.md diff --git a/flang/runtime/environment.cpp b/flang/runtime/environment.cpp index 62d9ee2afd1c..29196ae8f310 100644 --- a/flang/runtime/environment.cpp +++ b/flang/runtime/environment.cpp @@ -123,6 +123,19 @@ void ExecutionEnvironment::Configure(int ac, const char *av[], } } + if (auto *x{std::getenv("FORT_CHECK_POINTER_DEALLOCATION")}) { + char *end; + auto n{std::strtol(x, &end, 10)}; + if (n >= 0 && n <= 1 && *end == '\0') { + checkPointerDeallocation = n != 0; + } else { + std::fprintf(stderr, + "Fortran runtime: FORT_CHECK_POINTER_DEALLOCATION=%s is invalid; " + "ignored\n", + x); + } + } + // TODO: Set RP/ROUND='PROCESSOR_DEFINED' from environment } diff --git a/flang/runtime/environment.h b/flang/runtime/environment.h index 82a5ec8f4ebf..6da2c7bb3cf7 100644 --- a/flang/runtime/environment.h +++ b/flang/runtime/environment.h @@ -48,6 +48,7 @@ struct ExecutionEnvironment { Convert conversion{Convert::Unknown}; // FORT_CONVERT bool noStopMessage{false}; // NO_STOP_MESSAGE=1 inhibits "Fortran STOP" bool defaultUTF8{false}; // DEFAULT_UTF8 + bool checkPointerDeallocation{true}; // FORT_CHECK_POINTER_DEALLOCATION }; extern ExecutionEnvironment executionEnvironment; diff --git a/flang/runtime/pointer.cpp b/flang/runtime/pointer.cpp index fc9e0eeb7dac..08a1223764f3 100644 --- a/flang/runtime/pointer.cpp +++ b/flang/runtime/pointer.cpp @@ -9,6 +9,7 @@ #include "flang/Runtime/pointer.h" #include "assign-impl.h" #include "derived.h" +#include "environment.h" #include "stat.h" #include "terminator.h" #include "tools.h" @@ -184,17 +185,20 @@ int RTDEF(PointerDeallocate)(Descriptor &pointer, bool hasStat, if (!pointer.IsAllocated()) { return ReturnError(terminator, StatBaseNull, errMsg, hasStat); } - // Validate the footer. This should fail if the pointer doesn't - // span the entire object, or the object was not allocated as a - // pointer. - std::size_t byteSize{pointer.Elements() * pointer.ElementBytes()}; - constexpr std::size_t align{sizeof(std::uintptr_t)}; - byteSize = ((byteSize + align - 1) / align) * align; - void *p{pointer.raw().base_addr}; - std::uintptr_t *footer{ - reinterpret_cast(static_cast(p) + byteSize)}; - if (*footer != ~reinterpret_cast(p)) { - return ReturnError(terminator, StatBadPointerDeallocation, errMsg, hasStat); + if (executionEnvironment.checkPointerDeallocation) { + // Validate the footer. This should fail if the pointer doesn't + // span the entire object, or the object was not allocated as a + // pointer. + std::size_t byteSize{pointer.Elements() * pointer.ElementBytes()}; + constexpr std::size_t align{sizeof(std::uintptr_t)}; + byteSize = ((byteSize + align - 1) / align) * align; + void *p{pointer.raw().base_addr}; + std::uintptr_t *footer{ + reinterpret_cast(static_cast(p) + byteSize)}; + if (*footer != ~reinterpret_cast(p)) { + return ReturnError( + terminator, StatBadPointerDeallocation, errMsg, hasStat); + } } return ReturnError(terminator, pointer.Destroy(/*finalize=*/true, /*destroyPointers=*/true, &terminator), -- GitLab From 003e292f9895a9cf4e30688269efa668d1fcbb09 Mon Sep 17 00:00:00 2001 From: Amy Huang Date: Wed, 13 Mar 2024 21:53:38 +0000 Subject: [PATCH 449/953] Revert "[Clang][C++23] Implement P2448R2 ..." (#85136) Revert "[Clang][C++23] Implement P2448R2: Relaxing some constexpr restrictions (#77753)" This reverts commit 99500e8c08a4d941acb8a7eb00523296fb2acf7a because it causes a behavior change for std=c++20. See https://github.com/llvm/llvm-project/pull/77753. --- clang/docs/ReleaseNotes.rst | 2 - .../clang/Basic/DiagnosticSemaKinds.td | 26 ++- clang/lib/AST/DeclCXX.cpp | 13 +- clang/lib/Sema/SemaDeclCXX.cpp | 93 +++++----- clang/test/AST/Interp/cxx23.cpp | 59 +++++-- .../class.compare.default/p3.cpp | 40 +++-- .../class.compare.default/p4.cpp | 20 +-- .../dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp | 8 +- .../dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp | 10 +- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp | 18 +- .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp | 8 +- .../dcl.fct.def/dcl.fct.def.default/p2.cpp | 6 +- clang/test/CXX/drs/dr13xx.cpp | 22 +-- clang/test/CXX/drs/dr14xx.cpp | 6 +- clang/test/CXX/drs/dr15xx.cpp | 21 +-- clang/test/CXX/drs/dr16xx.cpp | 20 +-- clang/test/CXX/drs/dr6xx.cpp | 24 +-- clang/test/CXX/expr/expr.const/p5-26.cpp | 4 +- clang/test/CXX/special/class.copy/p13-0x.cpp | 2 +- .../SemaCXX/constant-expression-cxx11.cpp | 38 ++--- .../SemaCXX/constant-expression-cxx14.cpp | 33 ++-- .../SemaCXX/constant-expression-cxx2b.cpp | 24 +-- .../test/SemaCXX/cxx23-invalid-constexpr.cpp | 159 ------------------ clang/test/SemaCXX/cxx2a-consteval.cpp | 2 +- .../SemaCXX/deduced-return-type-cxx14.cpp | 8 +- .../addrspace-constructors.clcpp | 2 +- clang/www/cxx_status.html | 9 +- 27 files changed, 269 insertions(+), 408 deletions(-) delete mode 100644 clang/test/SemaCXX/cxx23-invalid-constexpr.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5fe3fd066df2..e018d3835594 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -102,8 +102,6 @@ C++23 Feature Support materialize temporary object which is a prvalue in discarded-value expression. - Implemented `P1774R8: Portable assumptions `_. -- Implemented `P2448R2: Relaxing some constexpr restrictions `_. - C++2c Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d7ab1635cf12..605fbc52701d 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9617,10 +9617,13 @@ def err_defaulted_copy_assign_not_ref : Error< "the parameter for an explicitly-defaulted copy assignment operator must be an " "lvalue reference type">; def err_incorrect_defaulted_constexpr : Error< - "defaulted definition of %sub{select_special_member_kind}0 cannot be marked %select{constexpr|consteval}1 " - "before C++23">; + "defaulted definition of %sub{select_special_member_kind}0 " + "is not constexpr">; def err_incorrect_defaulted_constexpr_with_vb: Error< "%sub{select_special_member_kind}0 cannot be 'constexpr' in a class with virtual base class">; +def err_incorrect_defaulted_consteval : Error< + "defaulted declaration of %sub{select_special_member_kind}0 " + "cannot be consteval because implicit definition is not constexpr">; def warn_defaulted_method_deleted : Warning< "explicitly defaulted %sub{select_special_member_kind}0 is implicitly " "deleted">, InGroup; @@ -9731,12 +9734,21 @@ def note_defaulted_comparison_cannot_deduce_undeduced_auto : Note< "%select{|member|base class}0 %1 declared here">; def note_defaulted_comparison_cannot_deduce_callee : Note< "selected 'operator<=>' for %select{|member|base class}0 %1 declared here">; -def err_defaulted_comparison_constexpr_mismatch : Error< +def ext_defaulted_comparison_constexpr_mismatch : Extension< "defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|" - "three-way comparison operator}0 cannot be " - "declared %select{constexpr|consteval}2 because " - "%select{it|for which the corresponding implicit 'operator==' }0 " - "invokes a non-constexpr comparison function ">; + "three-way comparison operator}0 that is " + "declared %select{constexpr|consteval}2 but" + "%select{|for which the corresponding implicit 'operator==' }0 " + "invokes a non-constexpr comparison function is a C++23 extension">, + InGroup>; +def warn_cxx23_compat_defaulted_comparison_constexpr_mismatch : Warning< + "defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|" + "three-way comparison operator}0 that is " + "declared %select{constexpr|consteval}2 but" + "%select{|for which the corresponding implicit 'operator==' }0 " + "invokes a non-constexpr comparison function is incompatible with C++ " + "standards before C++23">, + InGroup, DefaultIgnore; def note_defaulted_comparison_not_constexpr : Note< "non-constexpr comparison function would be used to compare " "%select{|member %1|base class %1}0">; diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 1c3dcf63465c..b4f2327d9c56 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -400,11 +400,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // C++11 [class.ctor]p6: // If that user-written default constructor would satisfy the - // requirements of a constexpr constructor/function(C++23), the - // implicitly-defined default constructor is constexpr. + // requirements of a constexpr constructor, the implicitly-defined + // default constructor is constexpr. if (!BaseClassDecl->hasConstexprDefaultConstructor()) - data().DefaultedDefaultConstructorIsConstexpr = - C.getLangOpts().CPlusPlus23; + data().DefaultedDefaultConstructorIsConstexpr = false; // C++1z [class.copy]p8: // The implicitly-declared copy constructor for a class X will have @@ -549,8 +548,7 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { // -- for every subobject of class type or (possibly multi-dimensional) // array thereof, that class type shall have a constexpr destructor if (!Subobj->hasConstexprDestructor()) - data().DefaultedDestructorIsConstexpr = - getASTContext().getLangOpts().CPlusPlus23; + data().DefaultedDestructorIsConstexpr = false; // C++20 [temp.param]p7: // A structural type is [...] a literal class type [for which] the types @@ -1299,8 +1297,7 @@ void CXXRecordDecl::addedMember(Decl *D) { !FieldRec->hasConstexprDefaultConstructor() && !isUnion()) // The standard requires any in-class initializer to be a constant // expression. We consider this to be a defect. - data().DefaultedDefaultConstructorIsConstexpr = - Context.getLangOpts().CPlusPlus23; + data().DefaultedDefaultConstructorIsConstexpr = false; // C++11 [class.copy]p8: // The implicitly-declared copy constructor for a class X will have diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e258a4f7c894..199f2523cfb5 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1715,8 +1715,6 @@ static bool CheckLiteralType(Sema &SemaRef, Sema::CheckConstexprKind Kind, static bool CheckConstexprDestructorSubobjects(Sema &SemaRef, const CXXDestructorDecl *DD, Sema::CheckConstexprKind Kind) { - assert(!SemaRef.getLangOpts().CPlusPlus23 && - "this check is obsolete for C++23"); auto Check = [&](SourceLocation Loc, QualType T, const FieldDecl *FD) { const CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); @@ -1748,8 +1746,6 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef, static bool CheckConstexprParameterTypes(Sema &SemaRef, const FunctionDecl *FD, Sema::CheckConstexprKind Kind) { - assert(!SemaRef.getLangOpts().CPlusPlus23 && - "this check is obsolete for C++23"); unsigned ArgIndex = 0; const auto *FT = FD->getType()->castAs(); for (FunctionProtoType::param_type_iterator i = FT->param_type_begin(), @@ -1771,8 +1767,6 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef, /// true. If not, produce a suitable diagnostic and return false. static bool CheckConstexprReturnType(Sema &SemaRef, const FunctionDecl *FD, Sema::CheckConstexprKind Kind) { - assert(!SemaRef.getLangOpts().CPlusPlus23 && - "this check is obsolete for C++23"); if (CheckLiteralType(SemaRef, Kind, FD->getLocation(), FD->getReturnType(), diag::err_constexpr_non_literal_return, FD->isConsteval())) @@ -1862,18 +1856,16 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD, } } - // - its return type shall be a literal type; (removed in C++23) - if (!getLangOpts().CPlusPlus23 && - !CheckConstexprReturnType(*this, NewFD, Kind)) + // - its return type shall be a literal type; + if (!CheckConstexprReturnType(*this, NewFD, Kind)) return false; } if (auto *Dtor = dyn_cast(NewFD)) { // A destructor can be constexpr only if the defaulted destructor could be; // we don't need to check the members and bases if we already know they all - // have constexpr destructors. (removed in C++23) - if (!getLangOpts().CPlusPlus23 && - !Dtor->getParent()->defaultedDestructorIsConstexpr()) { + // have constexpr destructors. + if (!Dtor->getParent()->defaultedDestructorIsConstexpr()) { if (Kind == CheckConstexprKind::CheckValid) return false; if (!CheckConstexprDestructorSubobjects(*this, Dtor, Kind)) @@ -1881,9 +1873,8 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD, } } - // - each of its parameter types shall be a literal type; (removed in C++23) - if (!getLangOpts().CPlusPlus23 && - !CheckConstexprParameterTypes(*this, NewFD, Kind)) + // - each of its parameter types shall be a literal type; + if (!CheckConstexprParameterTypes(*this, NewFD, Kind)) return false; Stmt *Body = NewFD->getBody(); @@ -2466,8 +2457,7 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, // function", so is not checked in CheckValid mode. SmallVector Diags; if (Kind == Sema::CheckConstexprKind::Diagnose && - !Expr::isPotentialConstantExpr(Dcl, Diags) && - !SemaRef.getLangOpts().CPlusPlus23) { + !Expr::isPotentialConstantExpr(Dcl, Diags)) { SemaRef.Diag(Dcl->getLocation(), diag::ext_constexpr_function_never_constant_expr) << isa(Dcl) << Dcl->isConsteval() @@ -7545,23 +7535,21 @@ static bool defaultedSpecialMemberIsConstexpr( // C++1y [class.copy]p26: // -- [the class] is a literal type, and - if (!Ctor && !ClassDecl->isLiteral() && !S.getLangOpts().CPlusPlus23) + if (!Ctor && !ClassDecl->isLiteral()) return false; // -- every constructor involved in initializing [...] base class // sub-objects shall be a constexpr constructor; // -- the assignment operator selected to copy/move each direct base // class is a constexpr function, and - if (!S.getLangOpts().CPlusPlus23) { - for (const auto &B : ClassDecl->bases()) { - const RecordType *BaseType = B.getType()->getAs(); - if (!BaseType) - continue; - CXXRecordDecl *BaseClassDecl = cast(BaseType->getDecl()); - if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg, - InheritedCtor, Inherited)) - return false; - } + for (const auto &B : ClassDecl->bases()) { + const RecordType *BaseType = B.getType()->getAs(); + if (!BaseType) + continue; + CXXRecordDecl *BaseClassDecl = cast(BaseType->getDecl()); + if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg, + InheritedCtor, Inherited)) + return false; } // -- every constructor involved in initializing non-static data members @@ -7571,22 +7559,20 @@ static bool defaultedSpecialMemberIsConstexpr( // -- for each non-static data member of X that is of class type (or array // thereof), the assignment operator selected to copy/move that member is // a constexpr function - if (!S.getLangOpts().CPlusPlus23) { - for (const auto *F : ClassDecl->fields()) { - if (F->isInvalidDecl()) - continue; - if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer()) - continue; - QualType BaseType = S.Context.getBaseElementType(F->getType()); - if (const RecordType *RecordTy = BaseType->getAs()) { - CXXRecordDecl *FieldRecDecl = cast(RecordTy->getDecl()); - if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM, - BaseType.getCVRQualifiers(), - ConstArg && !F->isMutable())) - return false; - } else if (CSM == Sema::CXXDefaultConstructor) { + for (const auto *F : ClassDecl->fields()) { + if (F->isInvalidDecl()) + continue; + if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer()) + continue; + QualType BaseType = S.Context.getBaseElementType(F->getType()); + if (const RecordType *RecordTy = BaseType->getAs()) { + CXXRecordDecl *FieldRecDecl = cast(RecordTy->getDecl()); + if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM, + BaseType.getCVRQualifiers(), + ConstArg && !F->isMutable())) return false; - } + } else if (CSM == Sema::CXXDefaultConstructor) { + return false; } } @@ -7872,17 +7858,18 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, MD->isConstexpr() && !Constexpr && MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { if (!MD->isConsteval() && RD->getNumVBases()) { - Diag(MD->getBeginLoc(), - diag::err_incorrect_defaulted_constexpr_with_vb) + Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr_with_vb) << CSM; for (const auto &I : RD->vbases()) Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here); } else { - Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr) - << CSM << MD->isConsteval(); + Diag(MD->getBeginLoc(), MD->isConsteval() + ? diag::err_incorrect_defaulted_consteval + : diag::err_incorrect_defaulted_constexpr) + << CSM; } - HadError = true; - // FIXME: Explain why the special member can't be constexpr. + // FIXME: Explain why the special member can't be constexpr. + HadError = true; } if (First) { @@ -9114,11 +9101,13 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, // - if the function is a constructor or destructor, its class does not // have any virtual base classes. if (FD->isConstexpr()) { - if (!getLangOpts().CPlusPlus23 && - CheckConstexprReturnType(*this, FD, CheckConstexprKind::Diagnose) && + if (CheckConstexprReturnType(*this, FD, CheckConstexprKind::Diagnose) && CheckConstexprParameterTypes(*this, FD, CheckConstexprKind::Diagnose) && !Info.Constexpr) { - Diag(FD->getBeginLoc(), diag::err_defaulted_comparison_constexpr_mismatch) + Diag(FD->getBeginLoc(), + getLangOpts().CPlusPlus23 + ? diag::warn_cxx23_compat_defaulted_comparison_constexpr_mismatch + : diag::ext_defaulted_comparison_constexpr_mismatch) << FD->isImplicit() << (int)DCK << FD->isConsteval(); DefaultedComparisonAnalyzer(*this, RD, FD, DCK, DefaultedComparisonAnalyzer::ExplainConstexpr) diff --git a/clang/test/AST/Interp/cxx23.cpp b/clang/test/AST/Interp/cxx23.cpp index 127b58915127..f1df936a5abe 100644 --- a/clang/test/AST/Interp/cxx23.cpp +++ b/clang/test/AST/Interp/cxx23.cpp @@ -1,58 +1,82 @@ -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref20,all,all-20 %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref20,all %s // RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=ref23,all %s -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20,all,all-20 %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20,all %s -fexperimental-new-constant-interpreter // RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=expected23,all %s -fexperimental-new-constant-interpreter /// FIXME: The new interpreter is missing all the 'control flows through...' diagnostics. constexpr int f(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ - // expected20-error {{constexpr function never produces a constant expression}} + // ref23-error {{constexpr function never produces a constant expression}} \ + // expected20-error {{constexpr function never produces a constant expression}} \ + // expected23-error {{constexpr function never produces a constant expression}} static const int m = n; // ref20-note {{control flows through the definition of a static variable}} \ // ref20-warning {{is a C++23 extension}} \ + // ref23-note {{control flows through the definition of a static variable}} \ // expected20-warning {{is a C++23 extension}} \ // expected20-note {{declared here}} \ + // expected23-note {{declared here}} - return m; // expected20-note {{initializer of 'm' is not a constant expression}} + return m; // expected20-note {{initializer of 'm' is not a constant expression}} \ + // expected23-note {{initializer of 'm' is not a constant expression}} } constexpr int g(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ - // expected20-error {{constexpr function never produces a constant expression}} + // ref23-error {{constexpr function never produces a constant expression}} \ + // expected20-error {{constexpr function never produces a constant expression}} \ + // expected23-error {{constexpr function never produces a constant expression}} thread_local const int m = n; // ref20-note {{control flows through the definition of a thread_local variable}} \ // ref20-warning {{is a C++23 extension}} \ + // ref23-note {{control flows through the definition of a thread_local variable}} \ // expected20-warning {{is a C++23 extension}} \ - // expected20-note {{declared here}} - return m; // expected20-note {{initializer of 'm' is not a constant expression}} + // expected20-note {{declared here}} \ + // expected23-note {{declared here}} + return m; // expected20-note {{initializer of 'm' is not a constant expression}} \ + // expected23-note {{initializer of 'm' is not a constant expression}} } constexpr int c_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ - // expected20-error {{constexpr function never produces a constant expression}} + // ref23-error {{constexpr function never produces a constant expression}} \ + // expected20-error {{constexpr function never produces a constant expression}} \ + // expected23-error {{constexpr function never produces a constant expression}} static _Thread_local int m = 0; // ref20-note {{control flows through the definition of a thread_local variable}} \ // ref20-warning {{is a C++23 extension}} \ + // ref23-note {{control flows through the definition of a thread_local variable}} \ // expected20-warning {{is a C++23 extension}} \ - // expected20-note {{declared here}} - return m; // expected20-note {{read of non-const variable}} + // expected20-note {{declared here}} \ + // expected23-note {{declared here}} + return m; // expected20-note {{read of non-const variable}} \ + // expected23-note {{read of non-const variable}} } constexpr int gnu_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ - // expected20-error {{constexpr function never produces a constant expression}} + // ref23-error {{constexpr function never produces a constant expression}} \ + // expected20-error {{constexpr function never produces a constant expression}} \ + // expected23-error {{constexpr function never produces a constant expression}} static __thread int m = 0; // ref20-note {{control flows through the definition of a thread_local variable}} \ // ref20-warning {{is a C++23 extension}} \ + // ref23-note {{control flows through the definition of a thread_local variable}} \ // expected20-warning {{is a C++23 extension}} \ - // expected20-note {{declared here}} - return m; // expected20-note {{read of non-const variable}} + // expected20-note {{declared here}} \ + // expected23-note {{declared here}} + return m; // expected20-note {{read of non-const variable}} \ + // expected23-note {{read of non-const variable}} } -constexpr int h(int n) { // ref20-error {{constexpr function never produces a constant expression}} +constexpr int h(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ + // ref23-error {{constexpr function never produces a constant expression}} static const int m = n; // ref20-note {{control flows through the definition of a static variable}} \ // ref20-warning {{is a C++23 extension}} \ + // ref23-note {{control flows through the definition of a static variable}} \ // expected20-warning {{is a C++23 extension}} return &m - &m; } -constexpr int i(int n) { // ref20-error {{constexpr function never produces a constant expression}} +constexpr int i(int n) { // ref20-error {{constexpr function never produces a constant expression}} \ + // ref23-error {{constexpr function never produces a constant expression}} thread_local const int m = n; // ref20-note {{control flows through the definition of a thread_local variable}} \ // ref20-warning {{is a C++23 extension}} \ + // ref23-note {{control flows through the definition of a thread_local variable}} \ // expected20-warning {{is a C++23 extension}} return &m - &m; } @@ -108,9 +132,8 @@ namespace StaticOperators { static_assert(f2() == 3); struct S1 { - constexpr S1() { // all-20-error {{never produces a constant expression}} - throw; // all-note {{not valid in a constant expression}} \ - // all-20-note {{not valid in a constant expression}} + constexpr S1() { // all-error {{never produces a constant expression}} + throw; // all-note 2{{not valid in a constant expression}} } static constexpr int operator()() { return 3; } // ref20-warning {{C++23 extension}} \ // expected20-warning {{C++23 extension}} diff --git a/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp b/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp index c73eb0dee995..166bd97e2731 100644 --- a/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp +++ b/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp @@ -1,8 +1,8 @@ // This test is for the [class.compare.default]p3 added by P2002R0 -// Also covers modifications made by P2448R2 +// Also covers modifications made by P2448R2 and extension warnings -// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx2a %s -// RUN: %clang_cc1 -std=c++23 -verify=expected %s +// RUN: %clang_cc1 -std=c++2a -verify %s +// RUN: %clang_cc1 -std=c++2a -Wc++23-default-comp-relaxed-constexpr -verify=expected,extension %s namespace std { struct strong_ordering { @@ -82,12 +82,10 @@ struct TestB { }; struct C { - friend bool operator==(const C&, const C&); // expected-note {{previous}} \ - // cxx2a-note 2{{declared here}} + friend bool operator==(const C&, const C&); // expected-note {{previous}} extension-note 2{{non-constexpr comparison function declared here}} friend bool operator!=(const C&, const C&) = default; // expected-note {{previous}} - friend std::strong_ordering operator<=>(const C&, const C&); // expected-note {{previous}} \ - // cxx2a-note 2{{declared here}} + friend std::strong_ordering operator<=>(const C&, const C&); // expected-note {{previous}} extension-note 2{{non-constexpr comparison function declared here}} friend bool operator<(const C&, const C&) = default; // expected-note {{previous}} friend bool operator<=(const C&, const C&) = default; // expected-note {{previous}} friend bool operator>(const C&, const C&) = default; // expected-note {{previous}} @@ -131,23 +129,23 @@ struct TestD { struct E { A a; - C c; // cxx2a-note 2{{non-constexpr comparison function would be used to compare member 'c'}} + C c; // extension-note 2{{non-constexpr comparison function would be used to compare member 'c'}} A b; - friend constexpr bool operator==(const E&, const E&) = default; // cxx2a-error {{cannot be declared constexpr}} + friend constexpr bool operator==(const E&, const E&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} friend constexpr bool operator!=(const E&, const E&) = default; - friend constexpr std::strong_ordering operator<=>(const E&, const E&) = default; // cxx2a-error {{cannot be declared constexpr}} + friend constexpr std::strong_ordering operator<=>(const E&, const E&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} friend constexpr bool operator<(const E&, const E&) = default; friend constexpr bool operator<=(const E&, const E&) = default; friend constexpr bool operator>(const E&, const E&) = default; friend constexpr bool operator>=(const E&, const E&) = default; }; -struct E2 : A, C { // cxx2a-note 2{{non-constexpr comparison function would be used to compare base class 'C'}} - friend constexpr bool operator==(const E2&, const E2&) = default; // cxx2a-error {{cannot be declared constexpr}} +struct E2 : A, C { // extension-note 2{{non-constexpr comparison function would be used to compare base class 'C'}} + friend constexpr bool operator==(const E2&, const E2&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} friend constexpr bool operator!=(const E2&, const E2&) = default; - friend constexpr std::strong_ordering operator<=>(const E2&, const E2&) = default; // cxx2a-error {{cannot be declared constexpr}} + friend constexpr std::strong_ordering operator<=>(const E2&, const E2&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} friend constexpr bool operator<(const E2&, const E2&) = default; friend constexpr bool operator<=(const E2&, const E2&) = default; friend constexpr bool operator>(const E2&, const E2&) = default; @@ -155,14 +153,14 @@ struct E2 : A, C { // cxx2a-note 2{{non-constexpr comparison function would be u }; struct F { - friend bool operator==(const F&, const F&); // cxx2a-note {{declared here}} - friend constexpr bool operator!=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} - - friend std::strong_ordering operator<=>(const F&, const F&); // cxx2a-note 4{{non-constexpr comparison function declared here}} - friend constexpr bool operator<(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} - friend constexpr bool operator<=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} - friend constexpr bool operator>(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} - friend constexpr bool operator>=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}} + friend bool operator==(const F&, const F&); // extension-note {{non-constexpr comparison function declared here}} + friend constexpr bool operator!=(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} + + friend std::strong_ordering operator<=>(const F&, const F&); // extension-note 4{{non-constexpr comparison function declared here}} + friend constexpr bool operator<(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} + friend constexpr bool operator<=(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} + friend constexpr bool operator>(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} + friend constexpr bool operator>=(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} }; // No implicit 'constexpr' if it's not the first declaration. diff --git a/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp b/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp index 534c3b34d883..02cdd7f85aeb 100644 --- a/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp +++ b/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx2a %s -// RUN: %clang_cc1 -std=c++23 -verify=expected %s +// RUN: %clang_cc1 -std=c++2a -verify %s +// RUN: %clang_cc1 -std=c++2a -Wc++23-default-comp-relaxed-constexpr -verify=expected,extension %s // This test is for [class.compare.default]p3 as modified and renumbered to p4 // by P2002R0. -// Also covers modifications made by P2448R2 +// Also covers modifications made by P2448R2 and extension warnings namespace std { struct strong_ordering { @@ -78,13 +78,13 @@ void use_g(G g) { } struct H { - bool operator==(const H&) const; // cxx2a-note {{non-constexpr comparison function declared here}} + bool operator==(const H&) const; // extension-note {{non-constexpr comparison function declared here}} constexpr std::strong_ordering operator<=>(const H&) const { return std::strong_ordering::equal; } }; struct I { - H h; // cxx2a-note {{non-constexpr comparison function would be used to compare member 'h'}} - constexpr std::strong_ordering operator<=>(const I&) const = default; // cxx2a-error {{cannot be declared constexpr}} + H h; // extension-note {{non-constexpr comparison function would be used to compare member 'h'}} + constexpr std::strong_ordering operator<=>(const I&) const = default; // extension-warning {{implicit 'operator==' invokes a non-constexpr comparison function is a C++23 extension}} }; struct J { @@ -148,16 +148,16 @@ namespace NoInjectionIfOperatorEqualsDeclared { namespace GH61238 { template struct my_struct { - A value; // cxx2a-note {{non-constexpr comparison function would be used to compare member 'value'}} + A value; // extension-note {{non-constexpr comparison function would be used to compare member 'value'}} - constexpr friend bool operator==(const my_struct &, const my_struct &) noexcept = default; // cxx2a-error {{cannot be declared constexpr}} + constexpr friend bool operator==(const my_struct &, const my_struct &) noexcept = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}} }; struct non_constexpr_type { - friend bool operator==(non_constexpr_type, non_constexpr_type) noexcept { // cxx2a-note {{non-constexpr comparison function declared here}} + friend bool operator==(non_constexpr_type, non_constexpr_type) noexcept { // extension-note {{non-constexpr comparison function declared here}} return false; } }; -my_struct obj; // cxx2a-note {{in instantiation of template class 'GH61238::my_struct' requested here}} +my_struct obj; // extension-note {{in instantiation of template class 'GH61238::my_struct' requested here}} } diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp index 48bc8fb426bc..7ad2e582a812 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp @@ -58,12 +58,12 @@ namespace subobject { struct A { ~A(); }; - struct B : A { // cxx2a-note {{here}} - constexpr ~B() {} // cxx2a-error {{destructor cannot be declared constexpr because base class 'A' does not have a constexpr destructor}} + struct B : A { // expected-note {{here}} + constexpr ~B() {} // expected-error {{destructor cannot be declared constexpr because base class 'A' does not have a constexpr destructor}} }; struct C { - A a; // cxx2a-note {{here}} - constexpr ~C() {} // cxx2a-error {{destructor cannot be declared constexpr because data member 'a' does not have a constexpr destructor}} + A a; // expected-note {{here}} + constexpr ~C() {} // expected-error {{destructor cannot be declared constexpr because data member 'a' does not have a constexpr destructor}} }; struct D : A { A a; diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp index 8cb37ae6d1cd..c07502c0555b 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp @@ -14,8 +14,9 @@ constexpr int i(int n) { return m; } -constexpr int g() { - goto test; // expected-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++23}} +constexpr int g() { // expected-error {{constexpr function never produces a constant expression}} + goto test; // expected-note {{subexpression not valid in a constant expression}} \ + // expected-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++23}} test: return 0; } @@ -28,8 +29,9 @@ struct NonLiteral { // expected-note 2 {{'NonLiteral' is not literal}} NonLiteral() {} }; -constexpr void non_literal() { - NonLiteral n; // expected-warning {{definition of a variable of non-literal type in a constexpr function is incompatible with C++ standards before C++23}} +constexpr void non_literal() { // expected-error {{constexpr function never produces a constant expression}} + NonLiteral n; // expected-note {{non-literal type 'NonLiteral' cannot be used in a constant expression}} \ + // expected-warning {{definition of a variable of non-literal type in a constexpr function is incompatible with C++ standards before C++23}} } constexpr void non_literal2(bool b) { diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp index 4416c8252264..6214ff8006d6 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fcxx-exceptions -verify=expected,beforecxx14,beforecxx20,beforecxx23 -std=c++11 %s -// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,beforecxx20,beforecxx23,cxx14_20 -std=c++14 %s -// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20,beforecxx23,cxx14_20 -std=c++20 %s +// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,beforecxx20,beforecxx23 -std=c++14 %s +// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20,beforecxx23 -std=c++20 %s // RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20 -std=c++23 %s namespace N { @@ -11,7 +11,7 @@ namespace M { typedef double D; } -struct NonLiteral { // beforecxx23-note 2{{no constexpr constructors}} +struct NonLiteral { // expected-note 2{{no constexpr constructors}} NonLiteral() {} NonLiteral(int) {} }; @@ -43,7 +43,7 @@ struct T : SS, NonLiteral { // - its return type shall be a literal type; // Once we support P2448R2 constexpr functions will be allowd to return non-literal types // The destructor will also be allowed - constexpr NonLiteral NonLiteralReturn() const { return {}; } // beforecxx23-error {{constexpr function's return type 'NonLiteral' is not a literal type}} + constexpr NonLiteral NonLiteralReturn() const { return {}; } // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}} constexpr void VoidReturn() const { return; } // beforecxx14-error {{constexpr function's return type 'void' is not a literal type}} constexpr ~T(); // beforecxx20-error {{destructor cannot be declared constexpr}} @@ -52,7 +52,7 @@ struct T : SS, NonLiteral { // - each of its parameter types shall be a literal type; // Once we support P2448R2 constexpr functions will be allowd to have parameters of non-literal types - constexpr int NonLiteralParam(NonLiteral) const { return 0; } // beforecxx23-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} + constexpr int NonLiteralParam(NonLiteral) const { return 0; } // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} typedef int G(NonLiteral) const; constexpr G NonLiteralParam2; // ok until definition @@ -66,7 +66,7 @@ struct T : SS, NonLiteral { // constexpr since they can't be const. constexpr T &operator=(const T &) = default; // beforecxx14-error {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} \ // beforecxx14-warning {{C++14}} \ - // cxx14_20-error{{defaulted definition of copy assignment operator cannot be marked constexpr}} + // aftercxx14-error{{defaulted definition of copy assignment operator is not constexpr}} }; constexpr int T::OutOfLineVirtual() const { return 0; } @@ -229,9 +229,9 @@ namespace DR1364 { return k; // ok, even though lvalue-to-rvalue conversion of a function // parameter is not allowed in a constant expression. } - int kGlobal; // beforecxx23-note {{here}} - constexpr int f() { // beforecxx23-error {{constexpr function never produces a constant expression}} - return kGlobal; // beforecxx23-note {{read of non-const}} + int kGlobal; // expected-note {{here}} + constexpr int f() { // expected-error {{constexpr function never produces a constant expression}} + return kGlobal; // expected-note {{read of non-const}} } } diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp index 92698ec1c738..f1f677ebfcd3 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp @@ -272,7 +272,7 @@ struct X { union XU1 { int a; constexpr XU1() = default; }; #ifndef CXX2A -// expected-error@-2{{cannot be marked constexpr}} +// expected-error@-2{{not constexpr}} #endif union XU2 { int a = 1; constexpr XU2() = default; }; @@ -282,7 +282,7 @@ struct XU3 { }; constexpr XU3() = default; #ifndef CXX2A - // expected-error@-2{{cannot be marked constexpr}} + // expected-error@-2{{not constexpr}} #endif }; struct XU4 { @@ -333,7 +333,7 @@ namespace CtorLookup { constexpr B(B&); }; constexpr B::B(const B&) = default; - constexpr B::B(B&) = default; // expected-error {{cannot be marked constexpr}} + constexpr B::B(B&) = default; // expected-error {{not constexpr}} struct C { A a; @@ -342,7 +342,7 @@ namespace CtorLookup { constexpr C(C&); }; constexpr C::C(const C&) = default; - constexpr C::C(C&) = default; // expected-error {{cannot be marked constexpr}} + constexpr C::C(C&) = default; // expected-error {{not constexpr}} } namespace PR14503 { diff --git a/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp index 849594307390..5b525fc91aba 100644 --- a/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp +++ b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp @@ -3,7 +3,7 @@ // An explicitly-defaulted function may be declared constexpr only if it would // have been implicitly declared as constexpr. struct S1 { - constexpr S1() = default; // expected-error {{defaulted definition of default constructor cannot be marked constexpr}} + constexpr S1() = default; // expected-error {{defaulted definition of default constructor is not constexpr}} constexpr S1(const S1&) = default; constexpr S1(S1&&) = default; constexpr S1 &operator=(const S1&) const = default; // expected-error {{explicitly-defaulted copy assignment operator may not have}} @@ -18,8 +18,8 @@ struct NoCopyMove { }; struct S2 { constexpr S2() = default; - constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor cannot be marked constexpr}} - constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor cannot be marked}} + constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor is not constexpr}} + constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor is not constexpr}} NoCopyMove ncm; }; diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp index d8e3b5d87bd1..effdc53040d0 100644 --- a/clang/test/CXX/drs/dr13xx.cpp +++ b/clang/test/CXX/drs/dr13xx.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-20,cxx11-17,cxx11-14,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-20,cxx11-17,cxx11-14,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-20,cxx11-17,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 %s -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-17,cxx11-14,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-17,cxx11-14,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-17,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors @@ -485,11 +485,11 @@ namespace dr1358 { // dr1358: 3.1 struct B : Virt { int member; constexpr B(NonLit u) : member(u) {} - // cxx11-20-error@-1 {{constexpr constructor's 1st parameter type 'NonLit' is not a literal type}} - // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + // since-cxx11-error@-1 {{constexpr constructor's 1st parameter type 'NonLit' is not a literal type}} + // since-cxx11-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} constexpr NonLit f(NonLit u) const { return NonLit(); } - // cxx11-20-error@-1 {{constexpr function's return type 'NonLit' is not a literal type}} - // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + // since-cxx11-error@-1 {{constexpr function's return type 'NonLit' is not a literal type}} + // since-cxx11-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} }; #endif } @@ -498,13 +498,13 @@ namespace dr1359 { // dr1359: 3.5 #if __cplusplus >= 201103L union A { constexpr A() = default; }; union B { constexpr B() = default; int a; }; // #dr1359-B - // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr before C++23}} + // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} union C { constexpr C() = default; int a, b; }; // #dr1359-C - // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} + // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} struct X { constexpr X() = default; union {}; }; // since-cxx11-error@-1 {{declaration does not declare anything}} struct Y { constexpr Y() = default; union { int a; }; }; // #dr1359-Y - // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} + // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} constexpr A a = A(); constexpr B b = B(); diff --git a/clang/test/CXX/drs/dr14xx.cpp b/clang/test/CXX/drs/dr14xx.cpp index ed6dda731fd5..58a2b3a0d027 100644 --- a/clang/test/CXX/drs/dr14xx.cpp +++ b/clang/test/CXX/drs/dr14xx.cpp @@ -153,16 +153,16 @@ namespace dr1460 { // dr1460: 3.5 namespace Defaulted { union A { constexpr A() = default; }; union B { int n; constexpr B() = default; }; - // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} + // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} union C { int n = 0; constexpr C() = default; }; struct D { union {}; constexpr D() = default; }; // expected-error@-1 {{declaration does not declare anything}} struct E { union { int n; }; constexpr E() = default; }; - // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} + // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} struct F { union { int n = 0; }; constexpr F() = default; }; struct G { union { int n = 0; }; union { int m; }; constexpr G() = default; }; - // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} + // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} struct H { union { int n = 0; diff --git a/clang/test/CXX/drs/dr15xx.cpp b/clang/test/CXX/drs/dr15xx.cpp index 195c0fa610d5..ac503db625ba 100644 --- a/clang/test/CXX/drs/dr15xx.cpp +++ b/clang/test/CXX/drs/dr15xx.cpp @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,cxx11-14,cxx14-17 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11-14,cxx14-17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors namespace dr1512 { // dr1512: 4 void f(char *p) { @@ -407,7 +407,7 @@ namespace dr1573 { // dr1573: 3.9 B b(1, 'x', 4.0, "hello"); // ok // inherited constructor is effectively constexpr if the user-written constructor would be - struct C { C(); constexpr C(int) {} }; // #dr1573-C + struct C { C(); constexpr C(int) {} }; struct D : C { using C::C; }; constexpr D d = D(0); // ok struct E : C { using C::C; A a; }; // #dr1573-E @@ -420,11 +420,8 @@ namespace dr1573 { // dr1573: 3.9 struct F : C { using C::C; C c; }; // #dr1573-F constexpr F f = F(0); // since-cxx11-error@-1 {{constexpr variable 'f' must be initialized by a constant expression}} - // cxx11-20-note@-2 {{constructor inherited from base class 'C' cannot be used in a constant expression; derived class cannot be implicitly initialized}} - // since-cxx23-note@-3 {{in implicit initialization for inherited constructor of 'F'}} - // since-cxx23-note@#dr1573-F {{non-constexpr constructor 'C' cannot be used in a constant expression}} - // cxx11-20-note@#dr1573-F {{declared here}} - // since-cxx23-note@#dr1573-C {{declared here}} + // since-cxx11-note@-2 {{constructor inherited from base class 'C' cannot be used in a constant expression; derived class cannot be implicitly initialized}} + // since-cxx11-note@#dr1573-F {{declared here}} // inherited constructor is effectively deleted if the user-written constructor would be struct G { G(int); }; diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp index 766c90d3bc7b..2dd7d1502e59 100644 --- a/clang/test/CXX/drs/dr16xx.cpp +++ b/clang/test/CXX/drs/dr16xx.cpp @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors #if __cplusplus == 199711L #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__) @@ -256,12 +256,12 @@ namespace dr1658 { // dr1658: 5 struct A { A(A&); }; struct B : virtual A { virtual void f() = 0; }; struct C : virtual A { virtual void f(); }; - struct D : A { virtual void f() = 0; }; // since-cxx23-note {{previous declaration is here}} + struct D : A { virtual void f() = 0; }; struct X { friend B::B(const B&) throw(); friend C::C(C&); - friend D::D(D&); // since-cxx23-error {{non-constexpr declaration of 'D' follows constexpr declaration}} + friend D::D(D&); }; } @@ -350,8 +350,8 @@ namespace dr1684 { // dr1684: 3.6 }; constexpr int f(NonLiteral &) { return 0; } constexpr int f(NonLiteral) { return 0; } - // cxx11-20-error@-1 {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} - // cxx11-20-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + // since-cxx11-error@-1 {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} + // since-cxx11-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} #endif } diff --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp index 190e05784f32..b35d3051ab55 100644 --- a/clang/test/CXX/drs/dr6xx.cpp +++ b/clang/test/CXX/drs/dr6xx.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-17,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -// RUN: %clang_cc1 -std=c++20 %s -verify=expected,cxx11-20,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx98-17,cxx11-17,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking +// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx98-17,cxx11-17,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking +// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx98-17,cxx11-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking +// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking namespace dr600 { // dr600: 2.8 @@ -584,8 +584,8 @@ namespace dr647 { // dr647: 3.1 struct C { constexpr C(NonLiteral); constexpr C(NonLiteral, int) {} - // cxx11-20-error@-1 {{constexpr constructor's 1st parameter type 'NonLiteral' is not a literal type}} - // cxx11-20-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + // since-cxx11-error@-1 {{constexpr constructor's 1st parameter type 'NonLiteral' is not a literal type}} + // since-cxx11-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} constexpr C() try {} catch (...) {} // cxx11-17-error@-1 {{function try block in constexpr constructor is a C++20 extension}} // cxx11-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}} @@ -609,15 +609,15 @@ namespace dr647 { // dr647: 3.1 d(0) {} constexpr E(int) - // cxx11-20-error@-1 {{constexpr constructor never produces a constant expression}} - // cxx11-20-note@#dr647-int-d {{non-constexpr constructor 'D' cannot be used in a constant expression}} - // cxx11-20-note@#dr647-D-float-ctor {{declared here}} + // since-cxx11-error@-1 {{constexpr constructor never produces a constant expression}} + // since-cxx11-note@#dr647-int-d {{non-constexpr constructor 'D' cannot be used in a constant expression}} + // since-cxx11-note@#dr647-D-float-ctor {{declared here}} : n(0), d(0.0f) {} // #dr647-int-d constexpr E(float f) - // cxx11-20-error@-1 {{never produces a constant expression}} - // cxx11-20-note@#dr647-float-d {{non-constexpr constructor}} - // cxx11-20-note@#dr647-D-float-ctor {{declared here}} + // since-cxx11-error@-1 {{never produces a constant expression}} + // since-cxx11-note@#dr647-float-d {{non-constexpr constructor}} + // since-cxx11-note@#dr647-D-float-ctor {{declared here}} : n(get()), d(D(0) + f) {} // #dr647-float-d }; diff --git a/clang/test/CXX/expr/expr.const/p5-26.cpp b/clang/test/CXX/expr/expr.const/p5-26.cpp index 3624b1e5a3e3..de2afa71b426 100644 --- a/clang/test/CXX/expr/expr.const/p5-26.cpp +++ b/clang/test/CXX/expr/expr.const/p5-26.cpp @@ -5,11 +5,11 @@ struct S {}; struct T : S {} t; -consteval void test() { +consteval void test() { // cxx23-error{{consteval function never produces a constant expression}} void* a = &t; const void* b = &t; volatile void* c = &t; - (void)static_cast(a); + (void)static_cast(a); //cxx23-note {{cast from 'void *' is not allowed in a constant expression in C++ standards before C++2c}} (void)static_cast(a); (void)static_cast(a); diff --git a/clang/test/CXX/special/class.copy/p13-0x.cpp b/clang/test/CXX/special/class.copy/p13-0x.cpp index 013d5b565823..16c8a4029cba 100644 --- a/clang/test/CXX/special/class.copy/p13-0x.cpp +++ b/clang/test/CXX/special/class.copy/p13-0x.cpp @@ -125,7 +125,7 @@ namespace Mutable { mutable A a; }; struct C { - constexpr C(const C &) = default; // expected-error {{cannot be marked constexpr}} + constexpr C(const C &) = default; // expected-error {{not constexpr}} A a; }; } diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index efb391ba0922..9e2ae07cbe4c 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -1273,8 +1273,8 @@ namespace PR11595 { struct B { B(); A& x; }; static_assert(B().x == 3, ""); // expected-error {{constant expression}} expected-note {{non-literal type 'B' cannot be used in a constant expression}} - constexpr bool f(int k) { // cxx11_20-error {{constexpr function never produces a constant expression}} - return B().x == k; // cxx11_20-note {{non-literal type 'B' cannot be used in a constant expression}} + constexpr bool f(int k) { // expected-error {{constexpr function never produces a constant expression}} + return B().x == k; // expected-note {{non-literal type 'B' cannot be used in a constant expression}} } } @@ -1326,8 +1326,8 @@ namespace ExternConstexpr { constexpr int g() { return q; } // expected-note {{outside its lifetime}} constexpr int q = g(); // expected-error {{constant expression}} expected-note {{in call}} - extern int r; // cxx11_20-note {{here}} - constexpr int h() { return r; } // cxx11_20-error {{never produces a constant}} cxx11_20-note {{read of non-const}} + extern int r; // expected-note {{here}} + constexpr int h() { return r; } // expected-error {{never produces a constant}} expected-note {{read of non-const}} struct S { int n; }; extern const S s; @@ -1678,7 +1678,7 @@ namespace ImplicitConstexpr { struct R { constexpr R() noexcept; constexpr R(const R&) noexcept; constexpr R(R&&) noexcept; ~R() noexcept; }; struct S { R r; }; // expected-note 3{{here}} struct T { T(const T&) noexcept; T(T &&) noexcept; ~T() noexcept; }; - struct U { T t; }; // cxx11_20-note 3{{here}} + struct U { T t; }; // expected-note 3{{here}} static_assert(!__is_literal_type(Q), ""); static_assert(!__is_literal_type(R), ""); static_assert(!__is_literal_type(S), ""); @@ -1691,9 +1691,9 @@ namespace ImplicitConstexpr { friend S::S() noexcept; // expected-error {{follows constexpr}} friend S::S(S&&) noexcept; // expected-error {{follows constexpr}} friend S::S(const S&) noexcept; // expected-error {{follows constexpr}} - friend constexpr U::U() noexcept; // cxx11_20-error {{follows non-constexpr}} - friend constexpr U::U(U&&) noexcept; // cxx11_20-error {{follows non-constexpr}} - friend constexpr U::U(const U&) noexcept; // cxx11_20-error {{follows non-constexpr}} + friend constexpr U::U() noexcept; // expected-error {{follows non-constexpr}} + friend constexpr U::U(U&&) noexcept; // expected-error {{follows non-constexpr}} + friend constexpr U::U(const U&) noexcept; // expected-error {{follows non-constexpr}} }; } @@ -1906,9 +1906,9 @@ namespace StmtExpr { }); } static_assert(g(123) == 15129, ""); - constexpr int h() { // cxx11_20-error {{never produces a constant}} + constexpr int h() { // expected-error {{never produces a constant}} return ({ // expected-warning {{extension}} - return 0; // cxx11_20-note {{not supported}} + return 0; // expected-note {{not supported}} 1; }); } @@ -2093,8 +2093,8 @@ namespace ZeroSizeTypes { // expected-note@-2 {{subtraction of pointers to type 'int[0]' of zero size}} int arr[5][0]; - constexpr int f() { // cxx11_20-error {{never produces a constant expression}} - return &arr[3] - &arr[0]; // cxx11_20-note {{subtraction of pointers to type 'int[0]' of zero size}} + constexpr int f() { // expected-error {{never produces a constant expression}} + return &arr[3] - &arr[0]; // expected-note {{subtraction of pointers to type 'int[0]' of zero size}} } } @@ -2118,8 +2118,8 @@ namespace NeverConstantTwoWays { // If we see something non-constant but foldable followed by something // non-constant and not foldable, we want the first diagnostic, not the // second. - constexpr int f(int n) { // cxx11_20-error {{never produces a constant expression}} - return (int *)(long)&n == &n ? // cxx11_20-note {{reinterpret_cast}} + constexpr int f(int n) { // expected-error {{never produces a constant expression}} + return (int *)(long)&n == &n ? // expected-note {{reinterpret_cast}} 1 / 0 : // expected-warning {{division by zero}} 0; } @@ -2277,8 +2277,7 @@ namespace InheritedCtor { struct A { constexpr A(int) {} }; struct B : A { int n; using A::A; }; // expected-note {{here}} - constexpr B b(0); // expected-error {{constant expression}} cxx11_20-note {{derived class}}\ - // cxx23-note {{not initialized}} + constexpr B b(0); // expected-error {{constant expression}} expected-note {{derived class}} struct C : A { using A::A; struct { union { int n, m = 0; }; union { int a = 0; }; int k = 0; }; struct {}; union {}; }; // expected-warning 6{{}} constexpr C c(0); @@ -2317,11 +2316,10 @@ namespace InheritedCtor { namespace PR28366 { namespace ns1 { -void f(char c) { //expected-note{{declared here}} - //cxx11_20-note@-1{{declared here}} +void f(char c) { //expected-note2{{declared here}} struct X { - static constexpr char f() { // cxx11_20-error {{never produces a constant expression}} - return c; //expected-error{{reference to local}} cxx11_20-note{{function parameter}} + static constexpr char f() { //expected-error{{never produces a constant expression}} + return c; //expected-error{{reference to local}} expected-note{{function parameter}} } }; int I = X::f(); diff --git a/clang/test/SemaCXX/constant-expression-cxx14.cpp b/clang/test/SemaCXX/constant-expression-cxx14.cpp index 80a7a2dd3153..273d7ff3a208 100644 --- a/clang/test/SemaCXX/constant-expression-cxx14.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp @@ -44,13 +44,13 @@ constexpr int g(int k) { return 3 * k3 + 5 * k2 + n * k - 20; } static_assert(g(2) == 42, ""); -constexpr int h(int n) { // cxx14_20-error {{constexpr function never produces a constant expression}} - static const int m = n; // cxx14_20-note {{control flows through the definition of a static variable}} \ +constexpr int h(int n) { // expected-error {{constexpr function never produces a constant expression}} + static const int m = n; // expected-note {{control flows through the definition of a static variable}} \ // cxx14_20-warning {{definition of a static variable in a constexpr function is a C++23 extension}} return m; } -constexpr int i(int n) { // cxx14_20-error {{constexpr function never produces a constant expression}} - thread_local const int m = n; // cxx14_20-note {{control flows through the definition of a thread_local variable}} \ +constexpr int i(int n) { // expected-error {{constexpr function never produces a constant expression}} + thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \ // cxx14_20-warning {{definition of a thread_local variable in a constexpr function is a C++23 extension}} return m; } @@ -68,7 +68,6 @@ constexpr int j(int k) { } } } // expected-note 2{{control reached end of constexpr function}} - // cxx23-warning@-1 {{does not return a value in all control paths}} static_assert(j(0) == -3, ""); static_assert(j(1) == 5, ""); static_assert(j(2), ""); // expected-error {{constant expression}} expected-note {{in call to 'j(2)'}} @@ -105,10 +104,10 @@ static_assert(l(false) == 5, ""); static_assert(l(true), ""); // expected-error {{constant expression}} expected-note {{in call to 'l(true)'}} // Potential constant expression checking is still applied where possible. -constexpr int htonl(int x) { // cxx14_20-error {{never produces a constant expression}} +constexpr int htonl(int x) { // expected-error {{never produces a constant expression}} typedef unsigned char uchar; uchar arr[4] = { uchar(x >> 24), uchar(x >> 16), uchar(x >> 8), uchar(x) }; - return *reinterpret_cast(arr); // cxx14_20-note {{reinterpret_cast is not allowed in a constant expression}} + return *reinterpret_cast(arr); // expected-note {{reinterpret_cast is not allowed in a constant expression}} } constexpr int maybe_htonl(bool isBigEndian, int x) { @@ -184,7 +183,7 @@ namespace string_assign { static_assert(!test1(100), ""); static_assert(!test1(101), ""); // expected-error {{constant expression}} expected-note {{in call to 'test1(101)'}} - constexpr void f() { // cxx14_20-error{{constexpr function never produces a constant expression}} cxx14_20-note@+2{{assignment to dereferenced one-past-the-end pointer is not allowed in a constant expression}} + constexpr void f() { // expected-error{{constexpr function never produces a constant expression}} expected-note@+2{{assignment to dereferenced one-past-the-end pointer is not allowed in a constant expression}} char foo[10] = { "z" }; // expected-note {{here}} foo[10] = 'x'; // expected-warning {{past the end}} } @@ -208,14 +207,14 @@ namespace array_resize { namespace potential_const_expr { constexpr void set(int &n) { n = 1; } constexpr int div_zero_1() { int z = 0; set(z); return 100 / z; } // no error - constexpr int div_zero_2() { // cxx14_20-error {{never produces a constant expression}} + constexpr int div_zero_2() { // expected-error {{never produces a constant expression}} int z = 0; - return 100 / (set(z), 0); // cxx14_20-note {{division by zero}} + return 100 / (set(z), 0); // expected-note {{division by zero}} } - int n; // cxx14_20-note {{declared here}} - constexpr int ref() { // cxx14_20-error {{never produces a constant expression}} + int n; // expected-note {{declared here}} + constexpr int ref() { // expected-error {{never produces a constant expression}} int &r = n; - return r; // cxx14_20-note {{read of non-const variable 'n'}} + return r; // expected-note {{read of non-const variable 'n'}} } } @@ -847,8 +846,8 @@ namespace StmtExpr { static_assert(g() == 0, ""); // expected-error {{constant expression}} expected-note {{in call}} // FIXME: We should handle the void statement expression case. - constexpr int h() { // cxx14_20-error {{never produces a constant}} - ({ if (true) {} }); // cxx14_20-note {{not supported}} + constexpr int h() { // expected-error {{never produces a constant}} + ({ if (true) {} }); // expected-note {{not supported}} return 0; } } @@ -1044,9 +1043,9 @@ static_assert(sum(Cs) == 'a' + 'b', ""); // expected-error{{not an integral cons constexpr int S = sum(Cs); // expected-error{{must be initialized by a constant expression}} expected-note{{in call}} } -constexpr void PR28739(int n) { // cxx14_20-error {{never produces a constant}} +constexpr void PR28739(int n) { // expected-error {{never produces a constant}} int *p = &n; // expected-note {{array 'p' declared here}} - p += (__int128)(unsigned long)-1; // cxx14_20-note {{cannot refer to element 18446744073709551615 of non-array object in a constant expression}} + p += (__int128)(unsigned long)-1; // expected-note {{cannot refer to element 18446744073709551615 of non-array object in a constant expression}} // expected-warning@-1 {{the pointer incremented by 18446744073709551615 refers past the last possible element for an array in 64-bit address space containing 32-bit (4-byte) elements (max possible 4611686018427387904 elements)}} } diff --git a/clang/test/SemaCXX/constant-expression-cxx2b.cpp b/clang/test/SemaCXX/constant-expression-cxx2b.cpp index 2519839b7ac5..2ee1d48d1cd6 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2b.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2b.cpp @@ -10,36 +10,36 @@ struct Constexpr{}; #if __cplusplus > 202002L -constexpr int f(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} - static const int m = n; // cxx2a-note {{control flows through the definition of a static variable}} \ +constexpr int f(int n) { // expected-error {{constexpr function never produces a constant expression}} + static const int m = n; // expected-note {{control flows through the definition of a static variable}} \ // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} return m; } -constexpr int g(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} - thread_local const int m = n; // cxx2a-note {{control flows through the definition of a thread_local variable}} \ +constexpr int g(int n) { // expected-error {{constexpr function never produces a constant expression}} + thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \ // cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}} return m; } -constexpr int c_thread_local(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} - static _Thread_local int m = 0; // cxx2a-note {{control flows through the definition of a thread_local variable}} \ +constexpr int c_thread_local(int n) { // expected-error {{constexpr function never produces a constant expression}} + static _Thread_local int m = 0; // expected-note {{control flows through the definition of a thread_local variable}} \ // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} return m; } -constexpr int gnu_thread_local(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} - static __thread int m = 0; // cxx2a-note {{control flows through the definition of a thread_local variable}} \ +constexpr int gnu_thread_local(int n) { // expected-error {{constexpr function never produces a constant expression}} + static __thread int m = 0; // expected-note {{control flows through the definition of a thread_local variable}} \ // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} return m; } -constexpr int h(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} - static const int m = n; // cxx2a-note {{control flows through the definition of a static variable}} \ +constexpr int h(int n) { // expected-error {{constexpr function never produces a constant expression}} + static const int m = n; // expected-note {{control flows through the definition of a static variable}} \ // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}} return &m - &m; } -constexpr int i(int n) { // cxx2a-error {{constexpr function never produces a constant expression}} - thread_local const int m = n; // cxx2a-note {{control flows through the definition of a thread_local variable}} \ +constexpr int i(int n) { // expected-error {{constexpr function never produces a constant expression}} + thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \ // cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}} return &m - &m; } diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp deleted file mode 100644 index 4dc16c59d805..000000000000 --- a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++23 %s - -// This test covers modifications made by P2448R2. - -// Check that there is no error when a constexpr function that never produces a -// constant expression, but still an error if such function is called from -// constexpr context. -constexpr int F(int N) { - double D = 2.0 / 0.0; // expected-note {{division by zero}} - return 1; -} - -constexpr int F0(int N) { - if (N == 0) - double d2 = 2.0 / 0.0; // expected-note {{division by zero}} - return 1; -} - -template -constexpr int FT(T N) { - double D = 2.0 / 0.0; // expected-note {{division by zero}} - return 1; -} - -class NonLiteral { // expected-note {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors}} -public: - NonLiteral() {} - ~NonLiteral() {} -}; - -constexpr NonLiteral F1() { - return NonLiteral{}; -} - -constexpr int F2(NonLiteral N) { - return 8; -} - -class Derived : public NonLiteral { - constexpr ~Derived() {}; -}; - -class Derived1 : public NonLiteral { - constexpr Derived1() : NonLiteral () {} -}; - - -struct X { - X(); - X(const X&); - X(X&&); - X& operator=(X&); - X& operator=(X&& other); - bool operator==(X const&) const; -}; - -template -struct Wrapper { - constexpr Wrapper() = default; - constexpr Wrapper(Wrapper const&) = default; - constexpr Wrapper(T const& t) : t(t) { } - constexpr Wrapper(Wrapper &&) = default; - constexpr X get() const { return t; } - constexpr bool operator==(Wrapper const&) const = default; - private: - T t; -}; - -struct WrapperNonT { - constexpr WrapperNonT() = default; - constexpr WrapperNonT(WrapperNonT const&) = default; - constexpr WrapperNonT(X const& t) : t(t) { } - constexpr WrapperNonT(WrapperNonT &&) = default; - constexpr WrapperNonT& operator=(WrapperNonT &) = default; - constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; - constexpr X get() const { return t; } - constexpr bool operator==(WrapperNonT const&) const = default; - private: - X t; -}; - -struct NonDefaultMembers { - constexpr NonDefaultMembers() {}; // expected-note {{non-literal type 'X' cannot be used in a constant expression}} - constexpr NonDefaultMembers(NonDefaultMembers const&) {}; - constexpr NonDefaultMembers(NonDefaultMembers &&) {}; - constexpr NonDefaultMembers& operator=(NonDefaultMembers &other) {this->t = other.t; return *this;} - constexpr NonDefaultMembers& operator=(NonDefaultMembers&& other) {this->t = other.t; return *this;} - constexpr bool operator==(NonDefaultMembers const& other) const {return this->t == other.t;} - X t; -}; - -int Glob = 0; -class C1 { -public: - constexpr C1() : D(Glob) {}; -private: - int D; -}; - -void test() { - - constexpr int A = F(3); // expected-error {{constexpr variable 'A' must be initialized by a constant expression}} - // expected-note@-1 {{in call}} - F(3); - constexpr int B = F0(0); // expected-error {{constexpr variable 'B' must be initialized by a constant expression}} - // expected-note@-1 {{in call}} - F0(0); - constexpr auto C = F1(); // expected-error {{constexpr variable cannot have non-literal type 'const NonLiteral'}} - F1(); - NonLiteral L; - constexpr auto D = F2(L); // expected-error {{constexpr variable 'D' must be initialized by a constant expression}} - // expected-note@-1 {{non-literal type 'NonLiteral' cannot be used in a constant expression}} - - constexpr auto E = FT(1); // expected-error {{constexpr variable 'E' must be initialized by a constant expression}} - // expected-note@-1 {{in call}} - F2(L); - - Wrapper x; - WrapperNonT x1; - NonDefaultMembers x2; - - // TODO these produce notes with an invalid source location. - // static_assert((Wrapper(), true)); - // static_assert((WrapperNonT(), true),""); - - static_assert((NonDefaultMembers(), true),""); // expected-error{{expression is not an integral constant expression}} \ - // expected-note {{in call to}} - constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error{{must be initialized by a constant expression}} \ - // expected-note{{non-literal}} -} - -struct A { - A (); - ~A(); -}; - -template -struct opt -{ - union { - char c; - T data; - }; - - constexpr opt() {} - - constexpr ~opt() { - if (engaged) - data.~T(); - } - - bool engaged = false; -}; - -consteval void foo() { - opt a; -} - -void bar() { foo(); } diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp index 192621225a54..d8482ec53f0e 100644 --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -54,7 +54,7 @@ struct C { struct D { C c; - consteval D() = default; // expected-error {{cannot be marked consteval}} + consteval D() = default; // expected-error {{cannot be consteval}} consteval ~D() = default; // expected-error {{destructor cannot be declared consteval}} }; diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp index 431d77ca785b..415bbbf1a0bc 100644 --- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp +++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx20_23,cxx23 %s // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx20_23,cxx23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,since-cxx14,cxx14_20,cxx14 %s // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,since-cxx14,cxx14_20,cxx14 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING @@ -299,8 +299,8 @@ namespace Constexpr { constexpr int q = Y().f(); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Y().f()'}} } struct NonLiteral { ~NonLiteral(); } nl; // cxx14-note {{user-provided destructor}} - // cxx20-note@-1 {{'NonLiteral' is not literal because its destructor is not constexpr}} - constexpr auto f2(int n) { return nl; } // cxx14_20-error {{constexpr function's return type 'struct NonLiteral' is not a literal type}} + // cxx20_23-note@-1 {{'NonLiteral' is not literal because its destructor is not constexpr}} + constexpr auto f2(int n) { return nl; } // expected-error {{return type 'struct NonLiteral' is not a literal type}} } // It's not really clear whether these are valid, but this matches g++. diff --git a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp index 067a404c489a..1b97484767b1 100644 --- a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp +++ b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp @@ -54,5 +54,5 @@ struct Z { struct W { int w; - constexpr W() __constant = default; // expected-error {{defaulted definition of default constructor cannot be marked constexpr}} + constexpr W() __constant = default; // expected-error {{defaulted definition of default constructor is not constexpr}} }; diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 1e36b90356c3..fe3fc0926e49 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -356,7 +356,14 @@ C++23, informally referred to as C++26.

Relaxing some constexpr restrictions
P2448R2 - Clang 19 + +
Clang 17 (Partial) + We do not support outside of defaulted special memeber functions the change that constexpr functions no + longer have to be constexpr compatible but rather support a less restricted requirements for constexpr + functions. Which include allowing non-literal types as return values and parameters, allow calling of + non-constexpr functions and constructors. +
+ Using unknown pointers and references in constant expressions -- GitLab From 207e45fb67ee3dbec9590d9303eebf4f720c8a40 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 13 Mar 2024 14:56:25 -0700 Subject: [PATCH 450/953] [RISCV] Add back SiFive's cdiscard.d.l1, cflush.d.l1, and cease instructions. (#83896) These were in LLVM 17 but removed from LLVM 18 due to an incorrect extension name being used. This restores them with new extension names that match SiFive's downstream compiler. The extension name has been used internally for some time. It uses XSiFive instead of XSf like the newer extensions. `cease` did not have an internal extension name so its using the `XSf` convention. The spec for the instructions is here https://sifive.cdn.prismic.io/sifive/767804da-53b2-4893-97d5-b7c030ae0a94_s76mc_core_complex_manual_21G3.pdf though the extension name is not listed. Column width in the extension printing had to be changed to accommodate a longer extension name. --- .../test/Preprocessor/riscv-target-features.c | 27 ++ llvm/docs/RISCVUsage.rst | 9 + llvm/lib/Support/RISCVISAInfo.cpp | 5 +- .../RISCV/Disassembler/RISCVDisassembler.cpp | 8 + llvm/lib/Target/RISCV/RISCVFeatures.td | 24 ++ llvm/lib/Target/RISCV/RISCVInstrInfoXSf.td | 32 ++ llvm/test/MC/RISCV/xsifive-invalid.s | 20 ++ llvm/test/MC/RISCV/xsifive-valid.s | 36 ++ llvm/unittests/Support/RISCVISAInfoTest.cpp | 327 +++++++++--------- 9 files changed, 325 insertions(+), 163 deletions(-) create mode 100644 llvm/test/MC/RISCV/xsifive-invalid.s create mode 100644 llvm/test/MC/RISCV/xsifive-valid.s diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 1a15be1c6e4d..b2cad622610b 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -56,11 +56,14 @@ // CHECK-NOT: __riscv_xcvmac {{.*$}} // CHECK-NOT: __riscv_xcvmem {{.*$}} // CHECK-NOT: __riscv_xcvsimd {{.*$}} +// CHECK-NOT: __riscv_xsfcease {{.*$}} // CHECK-NOT: __riscv_xsfvcp {{.*$}} // CHECK-NOT: __riscv_xsfvfnrclipxfqf {{.*$}} // CHECK-NOT: __riscv_xsfvfwmaccqqq {{.*$}} // CHECK-NOT: __riscv_xsfqmaccdod {{.*$}} // CHECK-NOT: __riscv_xsfvqmaccqoq {{.*$}} +// CHECK-NOT: __riscv_xsifivecdiscarddlone {{.*$}} +// CHECK-NOT: __riscv_xsifivecflushdlone {{.*$}} // CHECK-NOT: __riscv_xtheadba {{.*$}} // CHECK-NOT: __riscv_xtheadbb {{.*$}} // CHECK-NOT: __riscv_xtheadbs {{.*$}} @@ -517,6 +520,14 @@ // RUN: -o - | FileCheck --check-prefix=CHECK-XCVSIMD-EXT %s // CHECK-XCVSIMD-EXT: __riscv_xcvsimd 1000000{{$}} +// RUN: %clang --target=riscv32-unknown-linux-gnu \ +// RUN: -march=rv32ixsfcease -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-XSFCEASE-EXT %s +// RUN: %clang --target=riscv64-unknown-linux-gnu \ +// RUN: -march=rv64ixsfcease -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-XSFCEASE-EXT %s +// CHECK-XSFCEASE-EXT: __riscv_xsfcease 1000000{{$}} + // RUN: %clang --target=riscv32-unknown-linux-gnu \ // RUN: -march=rv32ixsfvcp -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-XSFVCP-EXT %s @@ -557,6 +568,22 @@ // RUN: -o - | FileCheck --check-prefix=CHECK-XSFVQMACCQOQ-EXT %s // CHECK-XSFVQMACCQOQ-EXT: __riscv_xsfvqmaccqoq 1000000{{$}} +// RUN: %clang --target=riscv32-unknown-linux-gnu \ +// RUN: -march=rv32ixsifivecdiscarddlone -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-XSIFIVECDISCARDDLONE-EXT %s +// RUN: %clang --target=riscv64-unknown-linux-gnu \ +// RUN: -march=rv64ixsifivecdiscarddlone -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-XSIFIVECDISCARDDLONE-EXT %s +// CHECK-XSIFIVECDISCARDDLONE-EXT: __riscv_xsifivecdiscarddlone 1000000{{$}} + +// RUN: %clang --target=riscv32-unknown-linux-gnu \ +// RUN: -march=rv32ixsifivecflushdlone -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-XSIFIVECFLUSHDLONE-EXT %s +// RUN: %clang --target=riscv64-unknown-linux-gnu \ +// RUN: -march=rv64ixsifivecflushdlone -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-XSIFIVECFLUSHDLONE-EXT %s +// CHECK-XSIFIVECFLUSHDLONE-EXT: __riscv_xsifivecflushdlone 1000000{{$}} + // RUN: %clang --target=riscv32-unknown-linux-gnu \ // RUN: -march=rv32ixtheadba -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-XTHEADBA-EXT %s diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst index a1de8596480d..2f17c9d7dda0 100644 --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -362,6 +362,15 @@ The current vendor extensions supported are: ``XCVbi`` LLVM implements `version 1.0.0 of the CORE-V immediate branching custom instructions specification `__ by OpenHW Group. All instructions are prefixed with `cv.` as described in the specification. These instructions are only available for riscv32 at this time. +``XSiFivecdiscarddlone`` + LLVM implements `the SiFive sf.cdiscard.d.l1 instruction specified in `_ by SiFive. + +``XSiFivecflushdlone`` + LLVM implements `the SiFive sf.cflush.d.l1 instruction specified in `_ by SiFive. + +``XSfcease`` + LLVM implements `the SiFive sf.cease instruction specified in `_ by SiFive. + Experimental C Intrinsics ========================= diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp index 6eec03fd6f70..39235ace4724 100644 --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -90,11 +90,14 @@ static const RISCVSupportedExtension SupportedExtensions[] = { {"xcvmac", {1, 0}}, {"xcvmem", {1, 0}}, {"xcvsimd", {1, 0}}, + {"xsfcease", {1, 0}}, {"xsfvcp", {1, 0}}, {"xsfvfnrclipxfqf", {1, 0}}, {"xsfvfwmaccqqq", {1, 0}}, {"xsfvqmaccdod", {1, 0}}, {"xsfvqmaccqoq", {1, 0}}, + {"xsifivecdiscarddlone", {1, 0}}, + {"xsifivecflushdlone", {1, 0}}, {"xtheadba", {1, 0}}, {"xtheadbb", {1, 0}}, {"xtheadbs", {1, 0}}, @@ -258,7 +261,7 @@ static void PrintExtension(StringRef Name, StringRef Version, StringRef Description) { outs().indent(4); unsigned VersionWidth = Description.empty() ? 0 : 10; - outs() << left_justify(Name, 20) << left_justify(Version, VersionWidth) + outs() << left_justify(Name, 21) << left_justify(Version, VersionWidth) << Description << "\n"; } diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp index f1ca1212ec37..6aadabdf1bc6 100644 --- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -595,6 +595,14 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size, TRY_TO_DECODE_FEATURE( RISCV::FeatureVendorXSfvfnrclipxfqf, DecoderTableXSfvfnrclipxfqf32, "SiFive FP32-to-int8 Ranged Clip Instructions opcode table"); + TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXSiFivecdiscarddlone, + DecoderTableXSiFivecdiscarddlone32, + "SiFive sf.cdiscard.d.l1 custom opcode table"); + TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXSiFivecflushdlone, + DecoderTableXSiFivecflushdlone32, + "SiFive sf.cflush.d.l1 custom opcode table"); + TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXSfcease, DecoderTableXSfcease32, + "SiFive sf.cease custom opcode table"); TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXCVbitmanip, DecoderTableXCVbitmanip32, "CORE-V Bit Manipulation custom opcode table"); diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index 83619ccb24ba..f3e641e25018 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -1058,6 +1058,30 @@ def HasVendorXSfvfnrclipxfqf AssemblerPredicate<(all_of FeatureVendorXSfvfnrclipxfqf), "'XSfvfnrclipxfqf' (SiFive FP32-to-int8 Ranged Clip Instructions)">; +def FeatureVendorXSiFivecdiscarddlone + : SubtargetFeature<"xsifivecdiscarddlone", "HasVendorXSiFivecdiscarddlone", "true", + "'XSiFivecdiscarddlone' (SiFive sf.cdiscard.d.l1 Instruction)", []>; +def HasVendorXSiFivecdiscarddlone + : Predicate<"Subtarget->hasVendorXSiFivecdiscarddlone()">, + AssemblerPredicate<(all_of FeatureVendorXSiFivecdiscarddlone), + "'XSiFivecdiscarddlone' (SiFive sf.cdiscard.d.l1 Instruction)">; + +def FeatureVendorXSiFivecflushdlone + : SubtargetFeature<"xsifivecflushdlone", "HasVendorXSiFivecflushdlone", "true", + "'XSiFivecflushdlone' (SiFive sf.cflush.d.l1 Instruction)", []>; +def HasVendorXSiFivecflushdlone + : Predicate<"Subtarget->hasVendorXSiFivecflushdlone()">, + AssemblerPredicate<(all_of FeatureVendorXSiFivecflushdlone), + "'XSiFivecflushdlone' (SiFive sf.cflush.d.l1 Instruction)">; + +def FeatureVendorXSfcease + : SubtargetFeature<"xsfcease", "HasVendorXSfcease", "true", + "'XSfcease' (SiFive sf.cease Instruction)", []>; +def HasVendorXSfcease + : Predicate<"Subtarget->hasVendorXSfcease()">, + AssemblerPredicate<(all_of FeatureVendorXSfcease), + "'XSfcease' (SiFive sf.cease Instruction)">; + // Core-V Extensions def FeatureVendorXCVelw diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXSf.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXSf.td index b4130e3805a1..9a6818c99af2 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoXSf.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXSf.td @@ -808,3 +808,35 @@ let Predicates = [HasVendorXSfvfnrclipxfqf] in { defm : VPatVFNRCLIP<"vfnrclip_xu_f_qf", "VFNRCLIP_XU_F_QF">; defm : VPatVFNRCLIP<"vfnrclip_x_f_qf", "VFNRCLIP_X_F_QF">; } + +let Predicates = [HasVendorXSiFivecdiscarddlone] in { + let hasNoSchedulingInfo = 1, hasSideEffects = 1, mayLoad = 0, mayStore = 0, + DecoderNamespace = "XSiFivecdiscarddlone" in + def SF_CDISCARD_D_L1 + : RVInstIUnary<0b111111000010, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1), + "sf.cdiscard.d.l1", "$rs1">, Sched<[]> { + let rd = 0; + } + def : InstAlias<"sf.cdiscard.d.l1", (SF_CDISCARD_D_L1 X0)>; +} // Predicates = [HasVendorXSifivecdiscarddlone] + +let Predicates = [HasVendorXSiFivecflushdlone] in { + let hasNoSchedulingInfo = 1, hasSideEffects = 1, mayLoad = 0, mayStore = 0, + DecoderNamespace = "XSiFivecflushdlone" in + def SF_CFLUSH_D_L1 + : RVInstIUnary<0b111111000000, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1), + "sf.cflush.d.l1", "$rs1">, Sched<[]> { + let rd = 0; + } + def : InstAlias<"sf.cflush.d.l1", (SF_CFLUSH_D_L1 X0)>; +} // Predicates = [HasVendorXSifivecflushdlone] + +let Predicates = [HasVendorXSfcease] in { + let hasNoSchedulingInfo = 1, hasSideEffects = 1, mayLoad = 0, mayStore = 0, + DecoderNamespace = "XSfcease" in + def SF_CEASE : RVInstIUnary<0b001100000101, 0b000, OPC_SYSTEM, (outs), (ins), + "sf.cease", "">, Sched<[]> { + let rs1 = 0b00000; + let rd = 0b00000; +} +} diff --git a/llvm/test/MC/RISCV/xsifive-invalid.s b/llvm/test/MC/RISCV/xsifive-invalid.s new file mode 100644 index 000000000000..5210d29f9d36 --- /dev/null +++ b/llvm/test/MC/RISCV/xsifive-invalid.s @@ -0,0 +1,20 @@ +# RUN: not llvm-mc -triple riscv32 < %s 2>&1 | FileCheck %s +# RUN: not llvm-mc -triple riscv64 < %s 2>&1 | FileCheck %s + +sf.cflush.d.l1 0x10 # CHECK: :[[@LINE]]:16: error: invalid operand for instruction + +sf.cdiscard.d.l1 0x10 # CHECK: :[[@LINE]]:18: error: invalid operand for instruction + +sf.cflush.d.l1 x0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'XSiFivecflushdlone' (SiFive sf.cflush.d.l1 Instruction){{$}} + +sf.cflush.d.l1 x7 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'XSiFivecflushdlone' (SiFive sf.cflush.d.l1 Instruction){{$}} + +sf.cdiscard.d.l1 x0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'XSiFivecdiscarddlone' (SiFive sf.cdiscard.d.l1 Instruction){{$}} + +sf.cdiscard.d.l1 x7 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'XSiFivecdiscarddlone' (SiFive sf.cdiscard.d.l1 Instruction){{$}} + +sf.cease x1 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + +sf.cease 0x10 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + +sf.cease # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'XSfcease' (SiFive sf.cease Instruction){{$}} diff --git a/llvm/test/MC/RISCV/xsifive-valid.s b/llvm/test/MC/RISCV/xsifive-valid.s new file mode 100644 index 000000000000..8aa0ab1bd8ba --- /dev/null +++ b/llvm/test/MC/RISCV/xsifive-valid.s @@ -0,0 +1,36 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+xsifivecdiscarddlone,+xsifivecflushdlone,+xsfcease -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+xsifivecdiscarddlone,+xsifivecflushdlone,+xsfcease -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+xsifivecdiscarddlone,+xsifivecflushdlone,+xsfcease < %s \ +# RUN: | llvm-objdump --mattr=+xsifivecdiscarddlone,+xsifivecflushdlone,+xsfcease -M no-aliases -d - \ +# RUN: | FileCheck -check-prefix=CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+xsifivecdiscarddlone,+xsifivecflushdlone,+xsfcease < %s \ +# RUN: | llvm-objdump --mattr=+xsifivecdiscarddlone,+xsifivecflushdlone,+xsfcease -M no-aliases -d - \ +# RUN: | FileCheck -check-prefix=CHECK-INST %s + +# CHECK-INST: sf.cflush.d.l1 zero +# CHECK-ENC: encoding: [0x73,0x00,0x00,0xfc] +sf.cflush.d.l1 x0 +# CHECK-INST: sf.cflush.d.l1 zero +# CHECK-ENC: encoding: [0x73,0x00,0x00,0xfc] +sf.cflush.d.l1 + +# CHECK-INST: sf.cflush.d.l1 t2 +# CHECK-ENC: encoding: [0x73,0x80,0x03,0xfc] +sf.cflush.d.l1 x7 + +# CHECK-INST: sf.cdiscard.d.l1 zero +# CHECK-ENC: encoding: [0x73,0x00,0x20,0xfc] +sf.cdiscard.d.l1 x0 +# CHECK-INST: sf.cdiscard.d.l1 zero +# CHECK-ENC: encoding: [0x73,0x00,0x20,0xfc] +sf.cdiscard.d.l1 + +# CHECK-INST: sf.cdiscard.d.l1 t2 +# CHECK-ENC: encoding: [0x73,0x80,0x23,0xfc] +sf.cdiscard.d.l1 x7 + +# CHECK-INST: sf.cease +# CHECK-ENC: encoding: [0x73,0x00,0x50,0x30] +sf.cease diff --git a/llvm/unittests/Support/RISCVISAInfoTest.cpp b/llvm/unittests/Support/RISCVISAInfoTest.cpp index 82cf4c639b61..a331e6a74ceb 100644 --- a/llvm/unittests/Support/RISCVISAInfoTest.cpp +++ b/llvm/unittests/Support/RISCVISAInfoTest.cpp @@ -739,170 +739,173 @@ TEST(RiscvExtensionsHelp, CheckExtensions) { std::string ExpectedOutput = R"(All available -march extensions for RISC-V - Name Version Description - i 2.1 This is a long dummy description - e 2.0 - m 2.0 - a 2.1 - f 2.2 - d 2.2 - c 2.0 - v 1.0 - h 1.0 - zic64b 1.0 - zicbom 1.0 - zicbop 1.0 - zicboz 1.0 - ziccamoa 1.0 - ziccif 1.0 - zicclsm 1.0 - ziccrse 1.0 - zicntr 2.0 - zicond 1.0 - zicsr 2.0 - zifencei 2.0 - zihintntl 1.0 - zihintpause 2.0 - zihpm 2.0 - zmmul 1.0 - za128rs 1.0 - za64rs 1.0 - zacas 1.0 - zawrs 1.0 - zfa 1.0 - zfh 1.0 - zfhmin 1.0 - zfinx 1.0 - zdinx 1.0 - zca 1.0 - zcb 1.0 - zcd 1.0 - zce 1.0 - zcf 1.0 - zcmp 1.0 - zcmt 1.0 - zba 1.0 - zbb 1.0 - zbc 1.0 - zbkb 1.0 - zbkc 1.0 - zbkx 1.0 - zbs 1.0 - zk 1.0 - zkn 1.0 - zknd 1.0 - zkne 1.0 - zknh 1.0 - zkr 1.0 - zks 1.0 - zksed 1.0 - zksh 1.0 - zkt 1.0 - zvbb 1.0 - zvbc 1.0 - zve32f 1.0 - zve32x 1.0 - zve64d 1.0 - zve64f 1.0 - zve64x 1.0 - zvfh 1.0 - zvfhmin 1.0 - zvkb 1.0 - zvkg 1.0 - zvkn 1.0 - zvknc 1.0 - zvkned 1.0 - zvkng 1.0 - zvknha 1.0 - zvknhb 1.0 - zvks 1.0 - zvksc 1.0 - zvksed 1.0 - zvksg 1.0 - zvksh 1.0 - zvkt 1.0 - zvl1024b 1.0 - zvl128b 1.0 - zvl16384b 1.0 - zvl2048b 1.0 - zvl256b 1.0 - zvl32768b 1.0 - zvl32b 1.0 - zvl4096b 1.0 - zvl512b 1.0 - zvl64b 1.0 - zvl65536b 1.0 - zvl8192b 1.0 - zhinx 1.0 - zhinxmin 1.0 - shcounterenw 1.0 - shgatpa 1.0 - shtvala 1.0 - shvsatpa 1.0 - shvstvala 1.0 - shvstvecd 1.0 - smaia 1.0 - smepmp 1.0 - ssaia 1.0 - ssccptr 1.0 - sscofpmf 1.0 - sscounterenw 1.0 - ssstateen 1.0 - ssstrict 1.0 - sstc 1.0 - sstvala 1.0 - sstvecd 1.0 - ssu64xl 1.0 - svade 1.0 - svadu 1.0 - svbare 1.0 - svinval 1.0 - svnapot 1.0 - svpbmt 1.0 - xcvalu 1.0 - xcvbi 1.0 - xcvbitmanip 1.0 - xcvelw 1.0 - xcvmac 1.0 - xcvmem 1.0 - xcvsimd 1.0 - xsfvcp 1.0 - xsfvfnrclipxfqf 1.0 - xsfvfwmaccqqq 1.0 - xsfvqmaccdod 1.0 - xsfvqmaccqoq 1.0 - xtheadba 1.0 - xtheadbb 1.0 - xtheadbs 1.0 - xtheadcmo 1.0 - xtheadcondmov 1.0 - xtheadfmemidx 1.0 - xtheadmac 1.0 - xtheadmemidx 1.0 - xtheadmempair 1.0 - xtheadsync 1.0 - xtheadvdot 1.0 - xventanacondops 1.0 + Name Version Description + i 2.1 This is a long dummy description + e 2.0 + m 2.0 + a 2.1 + f 2.2 + d 2.2 + c 2.0 + v 1.0 + h 1.0 + zic64b 1.0 + zicbom 1.0 + zicbop 1.0 + zicboz 1.0 + ziccamoa 1.0 + ziccif 1.0 + zicclsm 1.0 + ziccrse 1.0 + zicntr 2.0 + zicond 1.0 + zicsr 2.0 + zifencei 2.0 + zihintntl 1.0 + zihintpause 2.0 + zihpm 2.0 + zmmul 1.0 + za128rs 1.0 + za64rs 1.0 + zacas 1.0 + zawrs 1.0 + zfa 1.0 + zfh 1.0 + zfhmin 1.0 + zfinx 1.0 + zdinx 1.0 + zca 1.0 + zcb 1.0 + zcd 1.0 + zce 1.0 + zcf 1.0 + zcmp 1.0 + zcmt 1.0 + zba 1.0 + zbb 1.0 + zbc 1.0 + zbkb 1.0 + zbkc 1.0 + zbkx 1.0 + zbs 1.0 + zk 1.0 + zkn 1.0 + zknd 1.0 + zkne 1.0 + zknh 1.0 + zkr 1.0 + zks 1.0 + zksed 1.0 + zksh 1.0 + zkt 1.0 + zvbb 1.0 + zvbc 1.0 + zve32f 1.0 + zve32x 1.0 + zve64d 1.0 + zve64f 1.0 + zve64x 1.0 + zvfh 1.0 + zvfhmin 1.0 + zvkb 1.0 + zvkg 1.0 + zvkn 1.0 + zvknc 1.0 + zvkned 1.0 + zvkng 1.0 + zvknha 1.0 + zvknhb 1.0 + zvks 1.0 + zvksc 1.0 + zvksed 1.0 + zvksg 1.0 + zvksh 1.0 + zvkt 1.0 + zvl1024b 1.0 + zvl128b 1.0 + zvl16384b 1.0 + zvl2048b 1.0 + zvl256b 1.0 + zvl32768b 1.0 + zvl32b 1.0 + zvl4096b 1.0 + zvl512b 1.0 + zvl64b 1.0 + zvl65536b 1.0 + zvl8192b 1.0 + zhinx 1.0 + zhinxmin 1.0 + shcounterenw 1.0 + shgatpa 1.0 + shtvala 1.0 + shvsatpa 1.0 + shvstvala 1.0 + shvstvecd 1.0 + smaia 1.0 + smepmp 1.0 + ssaia 1.0 + ssccptr 1.0 + sscofpmf 1.0 + sscounterenw 1.0 + ssstateen 1.0 + ssstrict 1.0 + sstc 1.0 + sstvala 1.0 + sstvecd 1.0 + ssu64xl 1.0 + svade 1.0 + svadu 1.0 + svbare 1.0 + svinval 1.0 + svnapot 1.0 + svpbmt 1.0 + xcvalu 1.0 + xcvbi 1.0 + xcvbitmanip 1.0 + xcvelw 1.0 + xcvmac 1.0 + xcvmem 1.0 + xcvsimd 1.0 + xsfcease 1.0 + xsfvcp 1.0 + xsfvfnrclipxfqf 1.0 + xsfvfwmaccqqq 1.0 + xsfvqmaccdod 1.0 + xsfvqmaccqoq 1.0 + xsifivecdiscarddlone 1.0 + xsifivecflushdlone 1.0 + xtheadba 1.0 + xtheadbb 1.0 + xtheadbs 1.0 + xtheadcmo 1.0 + xtheadcondmov 1.0 + xtheadfmemidx 1.0 + xtheadmac 1.0 + xtheadmemidx 1.0 + xtheadmempair 1.0 + xtheadsync 1.0 + xtheadvdot 1.0 + xventanacondops 1.0 Experimental extensions - zicfilp 0.4 This is a long dummy description - zicfiss 0.4 - zimop 0.1 - zaamo 0.2 - zabha 1.0 - zalasr 0.1 - zalrsc 0.2 - zfbfmin 1.0 - zcmop 0.2 - ztso 0.1 - zvfbfmin 1.0 - zvfbfwma 1.0 - smmpm 0.8 - smnpm 0.8 - ssnpm 0.8 - sspm 0.8 - ssqosid 1.0 - supm 0.8 + zicfilp 0.4 This is a long dummy description + zicfiss 0.4 + zimop 0.1 + zaamo 0.2 + zabha 1.0 + zalasr 0.1 + zalrsc 0.2 + zfbfmin 1.0 + zcmop 0.2 + ztso 0.1 + zvfbfmin 1.0 + zvfbfwma 1.0 + smmpm 0.8 + smnpm 0.8 + ssnpm 0.8 + sspm 0.8 + ssqosid 1.0 + supm 0.8 Use -march to specify the target's extension. For example, clang -march=rv32i_v1p0)"; -- GitLab From 7bdba956efae81f111f0cc6c7aaa92f9712444ba Mon Sep 17 00:00:00 2001 From: Fehr Mathieu Date: Wed, 13 Mar 2024 21:59:34 +0000 Subject: [PATCH 451/953] [mlir][arith] Fix `arith.select` canonicalization patterns (#84685) Because `arith.select` does not propagate poison of the second or third operand depending on the condition, some canonicalization patterns are currently incorrect. This patch removes these incorrect patterns, and adds a new pattern to fix the case of `i1` select with constants. Patterns that are removed: * select(predA, select(predB, x, y), y) => select(and(predA, predB), x, y) * select(predA, select(predB, y, x), y) => select(and(predA, not(predB)), x, y) * select(predA, x, select(predB, x, y)) => select(or(predA, predB), x, y) * select(predA, x, select(predB, y, x)) => select(or(predA, not(predB)), x, y) * arith.select %arg, %x, %y : i1 => and(%arg, %x) or and(!%arg, %y) Pattern that is added: * select(pred, false, true) => not(pred) for i1 The first two patterns are incorrect when `predB` is poison and `predA` is false, as a non-poison `y` gets compiled to `poison`. The next two patterns are incorrect when `predB` is poison and `predA` is true, as a non-poison `x` gets compiled to `poison`. The last pattern is incorrect as it propagates poison from all operands afer compilation. --- .../Dialect/Arith/IR/ArithCanonicalization.td | 34 ++------ mlir/lib/Dialect/Arith/IR/ArithOps.cpp | 35 +------- mlir/test/Dialect/Arith/canonicalize.mlir | 80 ------------------- 3 files changed, 8 insertions(+), 141 deletions(-) diff --git a/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td b/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td index 11c4a29718e1..caca2ff81964 100644 --- a/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td +++ b/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td @@ -253,9 +253,6 @@ def CmpIExtUI : // SelectOp //===----------------------------------------------------------------------===// -def GetScalarOrVectorTrueAttribute : - NativeCodeCall<"cast(getBoolAttribute($0.getType(), true))">; - // select(not(pred), a, b) => select(pred, b, a) def SelectNotCond : Pat<(SelectOp (Arith_XOrIOp $pred, (ConstantLikeMatcher APIntAttr:$ones)), $a, $b), @@ -272,31 +269,12 @@ def RedundantSelectFalse : Pat<(SelectOp $pred, $a, (SelectOp $pred, $b, $c)), (SelectOp $pred, $a, $c)>; -// select(predA, select(predB, x, y), y) => select(and(predA, predB), x, y) -def SelectAndCond : - Pat<(SelectOp $predA, (SelectOp $predB, $x, $y), $y), - (SelectOp (Arith_AndIOp $predA, $predB), $x, $y)>; - -// select(predA, select(predB, y, x), y) => select(and(predA, not(predB)), x, y) -def SelectAndNotCond : - Pat<(SelectOp $predA, (SelectOp $predB, $y, $x), $y), - (SelectOp (Arith_AndIOp $predA, - (Arith_XOrIOp $predB, - (Arith_ConstantOp (GetScalarOrVectorTrueAttribute $predB)))), - $x, $y)>; - -// select(predA, x, select(predB, x, y)) => select(or(predA, predB), x, y) -def SelectOrCond : - Pat<(SelectOp $predA, $x, (SelectOp $predB, $x, $y)), - (SelectOp (Arith_OrIOp $predA, $predB), $x, $y)>; - -// select(predA, x, select(predB, y, x)) => select(or(predA, not(predB)), x, y) -def SelectOrNotCond : - Pat<(SelectOp $predA, $x, (SelectOp $predB, $y, $x)), - (SelectOp (Arith_OrIOp $predA, - (Arith_XOrIOp $predB, - (Arith_ConstantOp (GetScalarOrVectorTrueAttribute $predB)))), - $x, $y)>; +// select(pred, false, true) => not(pred) +def SelectI1ToNot : + Pat<(SelectOp $pred, + (ConstantLikeMatcher ConstantAttr), + (ConstantLikeMatcher ConstantAttr)), + (Arith_XOrIOp $pred, (Arith_ConstantOp ConstantAttr))>; //===----------------------------------------------------------------------===// // IndexCastOp diff --git a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp index 0f71c19c23b6..9f64a07f31e3 100644 --- a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp +++ b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp @@ -969,7 +969,6 @@ OpFoldResult arith::MaxNumFOp::fold(FoldAdaptor adaptor) { [](const APFloat &a, const APFloat &b) { return llvm::maximum(a, b); }); } - //===----------------------------------------------------------------------===// // MaxSIOp //===----------------------------------------------------------------------===// @@ -2173,35 +2172,6 @@ void arith::CmpFOp::getCanonicalizationPatterns(RewritePatternSet &patterns, // SelectOp //===----------------------------------------------------------------------===// -// Transforms a select of a boolean to arithmetic operations -// -// arith.select %arg, %x, %y : i1 -// -// becomes -// -// and(%arg, %x) or and(!%arg, %y) -struct SelectI1Simplify : public OpRewritePattern { - using OpRewritePattern::OpRewritePattern; - - LogicalResult matchAndRewrite(arith::SelectOp op, - PatternRewriter &rewriter) const override { - if (!op.getType().isInteger(1)) - return failure(); - - Value falseConstant = - rewriter.create(op.getLoc(), true, 1); - Value notCondition = rewriter.create( - op.getLoc(), op.getCondition(), falseConstant); - - Value trueVal = rewriter.create( - op.getLoc(), op.getCondition(), op.getTrueValue()); - Value falseVal = rewriter.create(op.getLoc(), notCondition, - op.getFalseValue()); - rewriter.replaceOpWithNewOp(op, trueVal, falseVal); - return success(); - } -}; - // select %arg, %c1, %c0 => extui %arg struct SelectToExtUI : public OpRewritePattern { using OpRewritePattern::OpRewritePattern; @@ -2238,9 +2208,8 @@ struct SelectToExtUI : public OpRewritePattern { void arith::SelectOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { - results.add(context); + results.add(context); } OpFoldResult arith::SelectOp::fold(FoldAdaptor adaptor) { diff --git a/mlir/test/Dialect/Arith/canonicalize.mlir b/mlir/test/Dialect/Arith/canonicalize.mlir index cb98a10048a3..bdc6c91d9267 100644 --- a/mlir/test/Dialect/Arith/canonicalize.mlir +++ b/mlir/test/Dialect/Arith/canonicalize.mlir @@ -116,18 +116,6 @@ func.func @selToNot(%arg0: i1) -> i1 { return %res : i1 } -// CHECK-LABEL: @selToArith -// CHECK-NEXT: %[[trueval:.+]] = arith.constant true -// CHECK-NEXT: %[[notcmp:.+]] = arith.xori %arg0, %[[trueval]] : i1 -// CHECK-NEXT: %[[condtrue:.+]] = arith.andi %arg0, %arg1 : i1 -// CHECK-NEXT: %[[condfalse:.+]] = arith.andi %[[notcmp]], %arg2 : i1 -// CHECK-NEXT: %[[res:.+]] = arith.ori %[[condtrue]], %[[condfalse]] : i1 -// CHECK: return %[[res]] -func.func @selToArith(%arg0: i1, %arg1 : i1, %arg2 : i1) -> i1 { - %res = arith.select %arg0, %arg1, %arg2 : i1 - return %res : i1 -} - // CHECK-LABEL: @redundantSelectTrue // CHECK-NEXT: %[[res:.+]] = arith.select %arg0, %arg1, %arg3 // CHECK-NEXT: return %[[res]] @@ -160,74 +148,6 @@ func.func @selNotCond(%arg0: i1, %arg1 : i32, %arg2 : i32, %arg3 : i32, %arg4 : return %res1, %res2 : i32, i32 } -// CHECK-LABEL: @selAndCond -// CHECK-NEXT: %[[and:.+]] = arith.andi %arg1, %arg0 -// CHECK-NEXT: %[[res:.+]] = arith.select %[[and]], %arg2, %arg3 -// CHECK-NEXT: return %[[res]] -func.func @selAndCond(%arg0: i1, %arg1: i1, %arg2 : i32, %arg3 : i32) -> i32 { - %sel = arith.select %arg0, %arg2, %arg3 : i32 - %res = arith.select %arg1, %sel, %arg3 : i32 - return %res : i32 -} - -// CHECK-LABEL: @selAndNotCond -// CHECK-NEXT: %[[one:.+]] = arith.constant true -// CHECK-NEXT: %[[not:.+]] = arith.xori %arg0, %[[one]] -// CHECK-NEXT: %[[and:.+]] = arith.andi %arg1, %[[not]] -// CHECK-NEXT: %[[res:.+]] = arith.select %[[and]], %arg3, %arg2 -// CHECK-NEXT: return %[[res]] -func.func @selAndNotCond(%arg0: i1, %arg1: i1, %arg2 : i32, %arg3 : i32) -> i32 { - %sel = arith.select %arg0, %arg2, %arg3 : i32 - %res = arith.select %arg1, %sel, %arg2 : i32 - return %res : i32 -} - -// CHECK-LABEL: @selAndNotCondVec -// CHECK-NEXT: %[[one:.+]] = arith.constant dense : vector<4xi1> -// CHECK-NEXT: %[[not:.+]] = arith.xori %arg0, %[[one]] -// CHECK-NEXT: %[[and:.+]] = arith.andi %arg1, %[[not]] -// CHECK-NEXT: %[[res:.+]] = arith.select %[[and]], %arg3, %arg2 -// CHECK-NEXT: return %[[res]] -func.func @selAndNotCondVec(%arg0: vector<4xi1>, %arg1: vector<4xi1>, %arg2 : vector<4xi32>, %arg3 : vector<4xi32>) -> vector<4xi32> { - %sel = arith.select %arg0, %arg2, %arg3 : vector<4xi1>, vector<4xi32> - %res = arith.select %arg1, %sel, %arg2 : vector<4xi1>, vector<4xi32> - return %res : vector<4xi32> -} - -// CHECK-LABEL: @selOrCond -// CHECK-NEXT: %[[or:.+]] = arith.ori %arg1, %arg0 -// CHECK-NEXT: %[[res:.+]] = arith.select %[[or]], %arg2, %arg3 -// CHECK-NEXT: return %[[res]] -func.func @selOrCond(%arg0: i1, %arg1: i1, %arg2 : i32, %arg3 : i32) -> i32 { - %sel = arith.select %arg0, %arg2, %arg3 : i32 - %res = arith.select %arg1, %arg2, %sel : i32 - return %res : i32 -} - -// CHECK-LABEL: @selOrNotCond -// CHECK-NEXT: %[[one:.+]] = arith.constant true -// CHECK-NEXT: %[[not:.+]] = arith.xori %arg0, %[[one]] -// CHECK-NEXT: %[[or:.+]] = arith.ori %arg1, %[[not]] -// CHECK-NEXT: %[[res:.+]] = arith.select %[[or]], %arg3, %arg2 -// CHECK-NEXT: return %[[res]] -func.func @selOrNotCond(%arg0: i1, %arg1: i1, %arg2 : i32, %arg3 : i32) -> i32 { - %sel = arith.select %arg0, %arg2, %arg3 : i32 - %res = arith.select %arg1, %arg3, %sel : i32 - return %res : i32 -} - -// CHECK-LABEL: @selOrNotCondVec -// CHECK-NEXT: %[[one:.+]] = arith.constant dense : vector<4xi1> -// CHECK-NEXT: %[[not:.+]] = arith.xori %arg0, %[[one]] -// CHECK-NEXT: %[[or:.+]] = arith.ori %arg1, %[[not]] -// CHECK-NEXT: %[[res:.+]] = arith.select %[[or]], %arg3, %arg2 -// CHECK-NEXT: return %[[res]] -func.func @selOrNotCondVec(%arg0: vector<4xi1>, %arg1: vector<4xi1>, %arg2 : vector<4xi32>, %arg3 : vector<4xi32>) -> vector<4xi32> { - %sel = arith.select %arg0, %arg2, %arg3 : vector<4xi1>, vector<4xi32> - %res = arith.select %arg1, %arg3, %sel : vector<4xi1>, vector<4xi32> - return %res : vector<4xi32> -} - // Test case: Folding of comparisons with equal operands. // CHECK-LABEL: @cmpi_equal_operands // CHECK-DAG: %[[T:.*]] = arith.constant true -- GitLab From fc71a49eca630a0f201261b89c5c9b0252ddb48b Mon Sep 17 00:00:00 2001 From: Peter Klausler <35819229+klausler@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:02:00 -0700 Subject: [PATCH 452/953] [flang][runtime] Handle end of internal output correctly (#84994) At the end of an internal output statement, be sure to finish any following control edit descriptors in the format (if any), and (for output) advance to the next record. Return the right I/O error status code if output overruns the buffer. --- flang/runtime/format-implementation.h | 27 +++++++++++++++++---------- flang/runtime/internal-unit.cpp | 16 +++++----------- flang/runtime/internal-unit.h | 1 - flang/runtime/io-stmt.cpp | 19 +++++++++++++++---- flang/runtime/io-stmt.h | 1 + 5 files changed, 38 insertions(+), 26 deletions(-) diff --git a/flang/runtime/format-implementation.h b/flang/runtime/format-implementation.h index 9c342db2e19a..f554f740573f 100644 --- a/flang/runtime/format-implementation.h +++ b/flang/runtime/format-implementation.h @@ -66,15 +66,6 @@ template int FormatControl::GetIntField( IoErrorHandler &handler, CharType firstCh, bool *hadError) { CharType ch{firstCh ? firstCh : PeekNext()}; - if (ch != '-' && ch != '+' && (ch < '0' || ch > '9')) { - handler.SignalError(IostatErrorInFormat, - "Invalid FORMAT: integer expected at '%c'", static_cast(ch)); - if (hadError) { - *hadError = true; - } - return 0; - } - int result{0}; bool negate{ch == '-'}; if (negate || ch == '+') { if (firstCh) { @@ -84,6 +75,15 @@ int FormatControl::GetIntField( } ch = PeekNext(); } + if (ch < '0' || ch > '9') { + handler.SignalError(IostatErrorInFormat, + "Invalid FORMAT: integer expected at '%c'", static_cast(ch)); + if (hadError) { + *hadError = true; + } + return 0; + } + int result{0}; while (ch >= '0' && ch <= '9') { constexpr int tenth{std::numeric_limits::max() / 10}; if (result > tenth || @@ -246,8 +246,15 @@ int FormatControl::CueUpNextDataEdit(Context &context, bool stop) { ch = GetNextChar(context); } if (ch == '-' || ch == '+' || (ch >= '0' && ch <= '9')) { + bool hadSign{ch == '-' || ch == '+'}; repeat = GetIntField(context, ch); ch = GetNextChar(context); + if (hadSign && ch != 'p' && ch != 'P') { + ReportBadFormat(context, + "Invalid FORMAT: signed integer may appear only before 'P", + maybeReversionPoint); + return 0; + } } else if (ch == '*') { unlimited = true; ch = GetNextChar(context); @@ -297,11 +304,11 @@ int FormatControl::CueUpNextDataEdit(Context &context, bool stop) { return 0; } else if (ch == ')') { if (height_ == 1) { + hitEnd_ = true; if (stop) { return 0; // end of FORMAT and no data items remain } context.AdvanceRecord(); // implied / before rightmost ) - hitEnd_ = true; } auto restart{stack_[height_ - 1].start}; if (format_[restart] == '(') { diff --git a/flang/runtime/internal-unit.cpp b/flang/runtime/internal-unit.cpp index e3fffaa6f378..66140e005887 100644 --- a/flang/runtime/internal-unit.cpp +++ b/flang/runtime/internal-unit.cpp @@ -41,16 +41,6 @@ InternalDescriptorUnit::InternalDescriptorUnit( endfileRecordNumber = d.Elements() + 1; } -template void InternalDescriptorUnit::EndIoStatement() { - if constexpr (DIR == Direction::Output) { - // Clear the remainder of the current record. - auto end{endfileRecordNumber.value_or(0)}; - if (currentRecordNumber < end) { - BlankFillOutputRecord(); - } - } -} - template bool InternalDescriptorUnit::Emit( const char *data, std::size_t bytes, IoErrorHandler &handler) { @@ -109,7 +99,11 @@ std::size_t InternalDescriptorUnit::GetNextInputBytes( template bool InternalDescriptorUnit::AdvanceRecord(IoErrorHandler &handler) { if (currentRecordNumber >= endfileRecordNumber.value_or(0)) { - handler.SignalEnd(); + if constexpr (DIR == Direction::Input) { + handler.SignalEnd(); + } else { + handler.SignalError(IostatInternalWriteOverrun); + } return false; } if constexpr (DIR == Direction::Output) { diff --git a/flang/runtime/internal-unit.h b/flang/runtime/internal-unit.h index f0c50aac9887..b536ffb831d5 100644 --- a/flang/runtime/internal-unit.h +++ b/flang/runtime/internal-unit.h @@ -28,7 +28,6 @@ public: std::conditional_t; InternalDescriptorUnit(Scalar, std::size_t chars, int kind); InternalDescriptorUnit(const Descriptor &, const Terminator &); - void EndIoStatement(); bool Emit(const char *, std::size_t, IoErrorHandler &); std::size_t GetNextInputBytes(const char *&, IoErrorHandler &); diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp index 3ec01ffba9bf..153195fd9656 100644 --- a/flang/runtime/io-stmt.cpp +++ b/flang/runtime/io-stmt.cpp @@ -119,9 +119,6 @@ template void InternalIoStatementState::BackspaceRecord() { } template int InternalIoStatementState::EndIoStatement() { - if constexpr (DIR == Direction::Output) { - unit_.EndIoStatement(); // fill - } auto result{IoStatementBase::EndIoStatement()}; if (free_) { FreeMemory(this); @@ -165,7 +162,8 @@ template void InternalFormattedIoStatementState::CompleteOperation() { if (!this->completedOperation()) { if constexpr (DIR == Direction::Output) { - format_.Finish(*this); // ignore any remaining input positioning actions + format_.Finish(*this); + unit_.AdvanceRecord(*this); } IoStatementBase::CompleteOperation(); } @@ -189,8 +187,21 @@ InternalListIoStatementState::InternalListIoStatementState( : InternalIoStatementState{d, sourceFile, sourceLine}, ioStatementState_{*this} {} +template +void InternalListIoStatementState::CompleteOperation() { + if (!this->completedOperation()) { + if constexpr (DIR == Direction::Output) { + if (unit_.furthestPositionInRecord > 0) { + unit_.AdvanceRecord(*this); + } + } + IoStatementBase::CompleteOperation(); + } +} + template int InternalListIoStatementState::EndIoStatement() { + CompleteOperation(); if constexpr (DIR == Direction::Input) { if (int status{ListDirectedStatementState::EndIoStatement()}; status != IostatOk) { diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h index 0b6bcbd9af02..dcee7f936569 100644 --- a/flang/runtime/io-stmt.h +++ b/flang/runtime/io-stmt.h @@ -403,6 +403,7 @@ public: const Descriptor &, const char *sourceFile = nullptr, int sourceLine = 0); IoStatementState &ioStatementState() { return ioStatementState_; } using ListDirectedStatementState::GetNextDataEdit; + void CompleteOperation(); int EndIoStatement(); private: -- GitLab From 605abe0689dfd28aadc9413306f33a4494cf3fb8 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 13 Mar 2024 15:06:55 -0700 Subject: [PATCH 453/953] [clang] Initialize AllTocData after #67999 --- clang/include/clang/Basic/CodeGenOptions.def | 1 + clang/include/clang/Basic/CodeGenOptions.h | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 6ad050319625..340b08dd7e2a 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -59,6 +59,7 @@ CODEGENOPT(UniqueBasicBlockSectionNames, 1, 1) ///< Set for -funique-basic-block ///< basic block sections. CODEGENOPT(EnableAIXExtendedAltivecABI, 1, 0) ///< Set for -mabi=vec-extabi. Enables the extended Altivec ABI on AIX. CODEGENOPT(XCOFFReadOnlyPointers, 1, 0) ///< Set for -mxcoff-roptr. +CODEGENOPT(AllTocData, 1, 0) ///< AIX -mtocdata ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None) /// frame-pointer: all,non-leaf,none CODEGENOPT(ClearASTBeforeBackend , 1, 0) ///< Free the AST before running backend code generation. Only works with -disable-free. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index cf29e576ef32..9469a424045b 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -410,9 +410,6 @@ public: /// List of global variables that over-ride the toc-data default. std::vector NoTocDataVars; - /// Flag for all global variables to be treated as toc-data. - bool AllTocData; - /// Path to allowlist file specifying which objects /// (files, functions) should exclusively be instrumented /// by sanitizer coverage pass. -- GitLab From 702a86a8f1e4d96c62574fc8d7dd9ccea243517a Mon Sep 17 00:00:00 2001 From: Peter Klausler <35819229+klausler@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:13:56 -0700 Subject: [PATCH 454/953] =?UTF-8?q?[flang]=20Correct=20accessibility=20of?= =?UTF-8?q?=20name=20that=20is=20both=20generic=20and=20derive=E2=80=A6=20?= =?UTF-8?q?(#85098)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …d type When the same name is used for a derived type and generic interface in a module, and no explicit PUBLIC or PRIVATE statement appears for the name but the derived type definition does have an explicit accessibility, that accessibility must also apply to the generic interface. --- flang/lib/Semantics/resolve-names.cpp | 19 +++++++++++--- flang/test/Semantics/resolve11.f90 | 37 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 67392a02cf18..b13674573fe0 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -3391,12 +3391,25 @@ void ModuleVisitor::ApplyDefaultAccess() { const auto *moduleDetails{ DEREF(currScope().symbol()).detailsIf()}; CHECK(moduleDetails); + Attr defaultAttr{ + DEREF(moduleDetails).isDefaultPrivate() ? Attr::PRIVATE : Attr::PUBLIC}; for (auto &pair : currScope()) { Symbol &symbol{*pair.second}; if (!symbol.attrs().HasAny({Attr::PUBLIC, Attr::PRIVATE})) { - SetImplicitAttr(symbol, - DEREF(moduleDetails).isDefaultPrivate() ? Attr::PRIVATE - : Attr::PUBLIC); + Attr attr{defaultAttr}; + if (auto *generic{symbol.detailsIf()}) { + if (generic->derivedType()) { + // If a generic interface has a derived type of the same + // name that has an explicit accessibility attribute, then + // the generic must have the same accessibility. + if (generic->derivedType()->attrs().test(Attr::PUBLIC)) { + attr = Attr::PUBLIC; + } else if (generic->derivedType()->attrs().test(Attr::PRIVATE)) { + attr = Attr::PRIVATE; + } + } + } + SetImplicitAttr(symbol, attr); } } } diff --git a/flang/test/Semantics/resolve11.f90 b/flang/test/Semantics/resolve11.f90 index 33ce88342b49..db508f062d1d 100644 --- a/flang/test/Semantics/resolve11.f90 +++ b/flang/test/Semantics/resolve11.f90 @@ -49,3 +49,40 @@ module m3 !ERROR: The accessibility of 'OPERATOR(.GT.)' has already been specified as PUBLIC private :: operator(.gt.) end + +module m4 + private + type, public :: foo + end type + interface foo + procedure fun + end interface + contains + function fun + end +end + +subroutine s4 + !ERROR: 'fun' is PRIVATE in 'm4' + use m4, only: foo, fun + type(foo) x ! ok + print *, foo() ! ok +end + +module m5 + public + type, private :: foo + end type + interface foo + procedure fun + end interface + contains + function fun + end +end + +subroutine s5 + !ERROR: 'foo' is PRIVATE in 'm5' + use m5, only: foo, fun + print *, fun() ! ok +end -- GitLab From 35db929b50af51e18c75da74b23caa6c14beeaf6 Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Wed, 13 Mar 2024 15:13:46 -0700 Subject: [PATCH 456/953] [RISCV] Add cost model coverage for fixed vector insert with known VLEN --- .../RISCV/shuffle-insert_subvector.ll | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/llvm/test/Analysis/CostModel/RISCV/shuffle-insert_subvector.ll b/llvm/test/Analysis/CostModel/RISCV/shuffle-insert_subvector.ll index 9a333dc8b8dd..a91d562b3f6f 100644 --- a/llvm/test/Analysis/CostModel/RISCV/shuffle-insert_subvector.ll +++ b/llvm/test/Analysis/CostModel/RISCV/shuffle-insert_subvector.ll @@ -520,3 +520,69 @@ define void @test_vXi8(<2 x i8> %src16, <4 x i8> %src32, <8 x i8> %src64, <16x i ret void } + +define void @fixed_m1_in_m2_notail(<8 x i32> %src, <8 x i32> %passthru) vscale_range(2) { +; CHECK-LABEL: 'fixed_m1_in_m2_notail' +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %1 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %2 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %3 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %4 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %5 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +; SIZE-LABEL: 'fixed_m1_in_m2_notail' +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %1 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> +; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> +; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> +; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> +; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> +; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void +; + shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> + shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> + shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> + shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> + shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> + ret void +} + +define void @fixed_m2_in_m4_notail(<8 x i64> %src, <8 x i64> %passthru) vscale_range(2) { +; CHECK-LABEL: 'fixed_m2_in_m4_notail' +; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %1 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 41 for instruction: %2 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 41 for instruction: %3 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 41 for instruction: %4 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 41 for instruction: %5 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +; SIZE-LABEL: 'fixed_m2_in_m4_notail' +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %1 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> +; SIZE-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %2 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> +; SIZE-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %3 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> +; SIZE-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %4 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> +; SIZE-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %5 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> +; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void +; + shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> + shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> + shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> + shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> + shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> + ret void +} + +define void @fixed_m1_in_m2_tail(<8 x i32> %src, <8 x i32> %passthru) vscale_range(2) { +; CHECK-LABEL: 'fixed_m1_in_m2_tail' +; CHECK-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %1 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %2 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +; SIZE-LABEL: 'fixed_m1_in_m2_tail' +; SIZE-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %1 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> +; SIZE-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %2 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> +; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void +; + shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> + shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> + ret void +} -- GitLab From 6885810e7de283ee8d3c8fc328a98544970b3db6 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Wed, 13 Mar 2024 15:33:11 -0700 Subject: [PATCH 457/953] [llvm] Include LLVM_REPOSITORY and LLVM_REVISION in tool version (#84990) Include the `LLVM_REPOSITORY` and `LLVM_REVISION` in the version output of tools using `cl::PrintVersionMessage()` such as dwarfdump and dsymutil. Before: ``` $ llvm-dwarfdump --version LLVM (http://llvm.org/): LLVM version 19.0.0git Optimized build with assertions. ``` After: ``` $ llvm-dwarfdump --version LLVM (http://llvm.org/): LLVM version 19.0.0git (git@github.com:llvm/llvm-project.git 8467457afc61d70e881c9817ace26356ef757733) Optimized build with assertions. ``` rdar://121526866 --- llvm/lib/Support/CMakeLists.txt | 3 +++ llvm/lib/Support/CommandLine.cpp | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt index 1f2d82427552..b9c13c43e9a7 100644 --- a/llvm/lib/Support/CMakeLists.txt +++ b/llvm/lib/Support/CMakeLists.txt @@ -286,6 +286,9 @@ add_llvm_component_library(LLVMSupport ${LLVM_MAIN_INCLUDE_DIR}/llvm/Support ${Backtrace_INCLUDE_DIRS} + DEPENDS + llvm_vcsrevision_h + LINK_LIBS ${system_libs} ${imported_libs} ${delayload_flags} diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp index c076ae8b8431..42dbc4de2003 100644 --- a/llvm/lib/Support/CommandLine.cpp +++ b/llvm/lib/Support/CommandLine.cpp @@ -39,6 +39,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/StringSaver.h" +#include "llvm/Support/VCSRevision.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" #include @@ -2538,7 +2539,15 @@ public: #else OS << "LLVM (http://llvm.org/):\n "; #endif - OS << PACKAGE_NAME << " version " << PACKAGE_VERSION << "\n "; + OS << PACKAGE_NAME << " version " << PACKAGE_VERSION; +#ifdef LLVM_REPOSITORY + OS << " (" << LLVM_REPOSITORY; +#ifdef LLVM_REVISION + OS << ' ' << LLVM_REVISION; +#endif + OS << ')'; +#endif + OS << "\n "; #if LLVM_IS_DEBUG_BUILD OS << "DEBUG build"; #else -- GitLab From db058b954a32dfb164926e407dfcf49bec054216 Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Wed, 13 Mar 2024 15:34:12 -0700 Subject: [PATCH 458/953] [asan][windows] fix issue64990 test (#85137) This was broken by https://github.com/llvm/llvm-project/pull/84971 --- compiler-rt/test/asan/TestCases/Windows/issue64990.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp b/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp index aab66502bd16..b1b6e42148cb 100644 --- a/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp @@ -16,5 +16,5 @@ int main(int argc, char **argv) { } return 0; } - -// CHECK: SUMMARY: AddressSanitizer: global-buffer-overflow {{.*}} in __asan_memcpy +// CHECK: #0 {{.*}} in __asan_memcpy +// CHECK: SUMMARY: AddressSanitizer: global-buffer-overflow {{.*}} in main -- GitLab From b87db5b6c28f1b5b2358213351d837bc72777cd5 Mon Sep 17 00:00:00 2001 From: Slava Zakharin Date: Wed, 13 Mar 2024 16:04:16 -0700 Subject: [PATCH 459/953] [flang][runtime] Fixed flang-runtime-cuda-gcc builder after af964c7. (#85144) --- flang/include/flang/Runtime/api-attrs.h | 12 ++++++++++++ flang/runtime/environment.cpp | 4 +++- flang/runtime/environment.h | 12 ++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/flang/include/flang/Runtime/api-attrs.h b/flang/include/flang/Runtime/api-attrs.h index 9c8a67ffc34a..fc3eb42e1b73 100644 --- a/flang/include/flang/Runtime/api-attrs.h +++ b/flang/include/flang/Runtime/api-attrs.h @@ -109,6 +109,18 @@ #endif #endif /* !defined(RT_CONST_VAR_ATTRS) */ +/* + * RT_VAR_ATTRS is marking non-const/constexpr module scope variables + * referenced by Flang runtime. + */ +#ifndef RT_VAR_ATTRS +#if (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) +#define RT_VAR_ATTRS __device__ +#else +#define RT_VAR_ATTRS +#endif +#endif /* !defined(RT_VAR_ATTRS) */ + /* * RT_DEVICE_COMPILATION is defined for any device compilation. * Note that it can only be used reliably with compilers that perform diff --git a/flang/runtime/environment.cpp b/flang/runtime/environment.cpp index 29196ae8f310..fe6701d72c9f 100644 --- a/flang/runtime/environment.cpp +++ b/flang/runtime/environment.cpp @@ -23,7 +23,9 @@ extern char **environ; namespace Fortran::runtime { -ExecutionEnvironment executionEnvironment; +RT_OFFLOAD_VAR_GROUP_BEGIN +RT_VAR_ATTRS ExecutionEnvironment executionEnvironment; +RT_OFFLOAD_VAR_GROUP_END static void SetEnvironmentDefaults(const EnvironmentDefaultList *envDefaults) { if (!envDefaults) { diff --git a/flang/runtime/environment.h b/flang/runtime/environment.h index 6da2c7bb3cf7..49c7dbd2940f 100644 --- a/flang/runtime/environment.h +++ b/flang/runtime/environment.h @@ -10,6 +10,7 @@ #define FORTRAN_RUNTIME_ENVIRONMENT_H_ #include "flang/Decimal/decimal.h" +#include "flang/Runtime/api-attrs.h" #include struct EnvironmentDefaultList; @@ -32,7 +33,11 @@ enum class Convert { Unknown, Native, LittleEndian, BigEndian, Swap }; std::optional GetConvertFromString(const char *, std::size_t); struct ExecutionEnvironment { - constexpr ExecutionEnvironment(){}; +#if !defined(_OPENMP) + // FIXME: https://github.com/llvm/llvm-project/issues/84942 + constexpr +#endif + ExecutionEnvironment(){}; void Configure(int argc, const char *argv[], const char *envp[], const EnvironmentDefaultList *envDefaults); const char *GetEnv( @@ -51,7 +56,10 @@ struct ExecutionEnvironment { bool checkPointerDeallocation{true}; // FORT_CHECK_POINTER_DEALLOCATION }; -extern ExecutionEnvironment executionEnvironment; +RT_OFFLOAD_VAR_GROUP_BEGIN +extern RT_VAR_ATTRS ExecutionEnvironment executionEnvironment; +RT_OFFLOAD_VAR_GROUP_END + } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_ENVIRONMENT_H_ -- GitLab From 2dc9ec47fb16a01c8f7cbb76fba4ad00ac4cb81b Mon Sep 17 00:00:00 2001 From: ChiaHungDuan Date: Wed, 13 Mar 2024 16:05:24 -0700 Subject: [PATCH 460/953] [scudo] Refactor allocator config to support optional flags (#81805) Instead of explicitly disabling a feature by declaring the variable and set it to false, this change supports the optional flags. I.e., you can skip certain flags if you are not using it. This optional feature supports both forms, 1. Value: A parameter for a feature. E.g., EnableRandomOffset 2. Type: A C++ type implementing a feature. E.g., ConditionVariableT On the other hand, to access the flags will be through one of the wrappers, BaseConfig/PrimaryConfig/SecondaryConfig/CacheConfig (CacheConfig is embedded in SecondaryConfig). These wrappers have the getters to access the value and the type. When adding a new feature, we need to add it to `allocator_config.def` and mark the new variable with either *_REQUIRED_* or *_OPTIONAL_* macro so that the accessor will be generated properly. In addition, also remove the need of `UseConditionVariable` to flip on/off of condition variable. Now we only need to define the type of condition variable. --- .../lib/scudo/standalone/CMakeLists.txt | 1 + .../lib/scudo/standalone/allocator_config.def | 124 ++++++++++++++++ .../lib/scudo/standalone/allocator_config.h | 78 +--------- .../standalone/allocator_config_wrapper.h | 135 ++++++++++++++++++ compiler-rt/lib/scudo/standalone/combined.h | 54 +++---- .../lib/scudo/standalone/condition_variable.h | 16 --- compiler-rt/lib/scudo/standalone/memtag.h | 2 +- compiler-rt/lib/scudo/standalone/primary32.h | 25 ++-- compiler-rt/lib/scudo/standalone/primary64.h | 25 ++-- compiler-rt/lib/scudo/standalone/secondary.h | 36 +++-- .../lib/scudo/standalone/tests/CMakeLists.txt | 1 + .../tests/allocator_config_test.cpp | 119 +++++++++++++++ .../scudo/standalone/tests/combined_test.cpp | 1 - .../scudo/standalone/tests/primary_test.cpp | 29 +++- .../scudo/standalone/tests/secondary_test.cpp | 22 ++- 15 files changed, 498 insertions(+), 170 deletions(-) create mode 100644 compiler-rt/lib/scudo/standalone/allocator_config.def create mode 100644 compiler-rt/lib/scudo/standalone/allocator_config_wrapper.h create mode 100644 compiler-rt/lib/scudo/standalone/tests/allocator_config_test.cpp diff --git a/compiler-rt/lib/scudo/standalone/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/CMakeLists.txt index 60092005cc33..6fb4e88de315 100644 --- a/compiler-rt/lib/scudo/standalone/CMakeLists.txt +++ b/compiler-rt/lib/scudo/standalone/CMakeLists.txt @@ -58,6 +58,7 @@ endif() set(SCUDO_HEADERS allocator_common.h allocator_config.h + allocator_config_wrapper.h atomic_helpers.h bytemap.h checksum.h diff --git a/compiler-rt/lib/scudo/standalone/allocator_config.def b/compiler-rt/lib/scudo/standalone/allocator_config.def new file mode 100644 index 000000000000..92f4e39872d4 --- /dev/null +++ b/compiler-rt/lib/scudo/standalone/allocator_config.def @@ -0,0 +1,124 @@ +//===-- allocator_config.def ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines all the flags and types supported in Scudo. For optional +// flags and types, only explicitly define them when interested (i.e., unused +// optional flags or types can be skipped). + +#ifndef BASE_REQUIRED_TEMPLATE_TYPE +#define BASE_REQUIRED_TEMPLATE_TYPE(...) +#endif +#ifndef BASE_OPTIONAL +#define BASE_OPTIONAL(...) +#endif +#ifndef PRIMARY_REQUIRED_TYPE +#define PRIMARY_REQUIRED_TYPE(...) +#endif +#ifndef PRIMARY_REQUIRED +#define PRIMARY_REQUIRED(...) +#endif +#ifndef PRIMARY_OPTIONAL +#define PRIMARY_OPTIONAL(...) +#endif +#ifndef PRIMARY_OPTIONAL_TYPE +#define PRIMARY_OPTIONAL_TYPE(...) +#endif +#ifndef SECONDARY_REQUIRED_TEMPLATE_TYPE +#define SECONDARY_REQUIRED_TEMPLATE_TYPE(...) +#endif +#ifndef SECONDARY_CACHE_OPTIONAL +#define SECONDARY_CACHE_OPTIONAL(...) +#endif + +// BASE_REQUIRED_TEMPLATE_TYPE(NAME) +// +// Thread-Specific Data Registry used, shared or exclusive. +BASE_REQUIRED_TEMPLATE_TYPE(TSDRegistryT) + +// Defines the type of Primary allocator to use. +BASE_REQUIRED_TEMPLATE_TYPE(PrimaryT) + +// Defines the type of Secondary allocator to use. +BASE_REQUIRED_TEMPLATE_TYPE(SecondaryT) + +// BASE_OPTIONAL(TYPE, NAME, DEFAULT) +// +// Indicates possible support for Memory Tagging. +BASE_OPTIONAL(const bool, MaySupportMemoryTagging, false) + +// PRIMARY_REQUIRED_TYPE(NAME) +// +// SizeClassMap to use with the Primary. +PRIMARY_REQUIRED_TYPE(SizeClassMap) + +// Defines the type and scale of a compact pointer. A compact pointer can +// be understood as the offset of a pointer within the region it belongs +// to, in increments of a power-of-2 scale. See `CompactPtrScale` also. +PRIMARY_REQUIRED_TYPE(CompactPtrT) + +// PRIMARY_REQUIRED(TYPE, NAME) +// +// The scale of a compact pointer. E.g., Ptr = Base + (CompactPtr << Scale). +PRIMARY_REQUIRED(const uptr, CompactPtrScale) + +// Log2 of the size of a size class region, as used by the Primary. +PRIMARY_REQUIRED(const uptr, RegionSizeLog) + +// Conceptually, a region will be divided into groups based on the address +// range. Each allocation consumes blocks in the same group until exhaustion +// then it pops out blocks in a new group. Therefore, `GroupSizeLog` is always +// smaller or equal to `RegionSizeLog`. Note that `GroupSizeLog` needs to be +// equal to `RegionSizeLog` for SizeClassAllocator32 because of certain +// constraints. +PRIMARY_REQUIRED(const uptr, GroupSizeLog) + +// Call map for user memory with at least this size. Only used with primary64. +PRIMARY_REQUIRED(const uptr, MapSizeIncrement) + +// Defines the minimal & maximal release interval that can be set. +PRIMARY_REQUIRED(const s32, MinReleaseToOsIntervalMs) +PRIMARY_REQUIRED(const s32, MaxReleaseToOsIntervalMs) + +// PRIMARY_OPTIONAL(TYPE, NAME, DEFAULT) +// +// Indicates support for offsetting the start of a region by a random number of +// pages. Only used with primary64. +PRIMARY_OPTIONAL(const bool, EnableRandomOffset, false) + +// PRIMARY_OPTIONAL_TYPE(NAME, DEFAULT) +// +// Use condition variable to shorten the waiting time of refillment of +// freelist. Note that this depends on the implementation of condition +// variable on each platform and the performance may vary so that it does not +// guarantee a performance benefit. +PRIMARY_OPTIONAL_TYPE(ConditionVariableT, ConditionVariableDummy) + +// SECONDARY_REQUIRED_TEMPLATE_TYPE(NAME) +// +// Defines the type of Secondary Cache to use. +SECONDARY_REQUIRED_TEMPLATE_TYPE(CacheT) + +// SECONDARY_CACHE_OPTIONAL(TYPE, NAME, DEFAULT) +// +// Defines the type of cache used by the Secondary. Some additional +// configuration entries can be necessary depending on the Cache. +SECONDARY_CACHE_OPTIONAL(const u32, EntriesArraySize, 0) +SECONDARY_CACHE_OPTIONAL(const u32, QuarantineSize, 0) +SECONDARY_CACHE_OPTIONAL(const u32, DefaultMaxEntriesCount, 0) +SECONDARY_CACHE_OPTIONAL(const u32, DefaultMaxEntrySize, 0) +SECONDARY_CACHE_OPTIONAL(const s32, MinReleaseToOsIntervalMs, INT32_MIN) +SECONDARY_CACHE_OPTIONAL(const s32, MaxReleaseToOsIntervalMs, INT32_MAX) + +#undef SECONDARY_CACHE_OPTIONAL +#undef SECONDARY_REQUIRED_TEMPLATE_TYPE +#undef PRIMARY_OPTIONAL_TYPE +#undef PRIMARY_OPTIONAL +#undef PRIMARY_REQUIRED +#undef PRIMARY_REQUIRED_TYPE +#undef BASE_OPTIONAL +#undef BASE_REQUIRED_TEMPLATE_TYPE diff --git a/compiler-rt/lib/scudo/standalone/allocator_config.h b/compiler-rt/lib/scudo/standalone/allocator_config.h index 3c6aa3acb0e4..1e0cf1015ba6 100644 --- a/compiler-rt/lib/scudo/standalone/allocator_config.h +++ b/compiler-rt/lib/scudo/standalone/allocator_config.h @@ -38,80 +38,10 @@ namespace scudo { -// The combined allocator uses a structure as a template argument that -// specifies the configuration options for the various subcomponents of the -// allocator. -// -// struct ExampleConfig { -// // Indicates possible support for Memory Tagging. -// static const bool MaySupportMemoryTagging = false; -// -// // Thread-Specific Data Registry used, shared or exclusive. -// template using TSDRegistryT = TSDRegistrySharedT; -// -// struct Primary { -// // SizeClassMap to use with the Primary. -// using SizeClassMap = DefaultSizeClassMap; -// -// // Log2 of the size of a size class region, as used by the Primary. -// static const uptr RegionSizeLog = 30U; -// -// // Log2 of the size of block group, as used by the Primary. Each group -// // contains a range of memory addresses, blocks in the range will belong -// // to the same group. In general, single region may have 1 or 2MB group -// // size. Multiple regions will have the group size equal to the region -// // size because the region size is usually smaller than 1 MB. -// // Smaller value gives fine-grained control of memory usage but the -// // trade-off is that it may take longer time of deallocation. -// static const uptr GroupSizeLog = 20U; -// -// // Defines the type and scale of a compact pointer. A compact pointer can -// // be understood as the offset of a pointer within the region it belongs -// // to, in increments of a power-of-2 scale. -// // eg: Ptr = Base + (CompactPtr << Scale). -// typedef u32 CompactPtrT; -// static const uptr CompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG; -// -// // Indicates support for offsetting the start of a region by -// // a random number of pages. Only used with primary64. -// static const bool EnableRandomOffset = true; -// -// // Call map for user memory with at least this size. Only used with -// // primary64. -// static const uptr MapSizeIncrement = 1UL << 18; -// -// // Defines the minimal & maximal release interval that can be set. -// static const s32 MinReleaseToOsIntervalMs = INT32_MIN; -// static const s32 MaxReleaseToOsIntervalMs = INT32_MAX; -// -// // Use condition variable to shorten the waiting time of refillment of -// // freelist. Note that this depends on the implementation of condition -// // variable on each platform and the performance may vary so that it -// // doesn't guarantee a performance benefit. -// // Note that both variables have to be defined to enable it. -// static const bool UseConditionVariable = true; -// using ConditionVariableT = ConditionVariableLinux; -// }; -// // Defines the type of Primary allocator to use. -// template using PrimaryT = SizeClassAllocator64; -// -// // Defines the type of cache used by the Secondary. Some additional -// // configuration entries can be necessary depending on the Cache. -// struct Secondary { -// struct Cache { -// static const u32 EntriesArraySize = 32U; -// static const u32 QuarantineSize = 0U; -// static const u32 DefaultMaxEntriesCount = 32U; -// static const uptr DefaultMaxEntrySize = 1UL << 19; -// static const s32 MinReleaseToOsIntervalMs = INT32_MIN; -// static const s32 MaxReleaseToOsIntervalMs = INT32_MAX; -// }; -// // Defines the type of Secondary Cache to use. -// template using CacheT = MapAllocatorCache; -// }; -// // Defines the type of Secondary allocator to use. -// template using SecondaryT = MapAllocator; -// }; +// Scudo uses a structure as a template argument that specifies the +// configuration options for the various subcomponents of the allocator. See the +// following configs as examples and check `allocator_config.def` for all the +// available options. #ifndef SCUDO_USE_CUSTOM_CONFIG diff --git a/compiler-rt/lib/scudo/standalone/allocator_config_wrapper.h b/compiler-rt/lib/scudo/standalone/allocator_config_wrapper.h new file mode 100644 index 000000000000..a51d770b4664 --- /dev/null +++ b/compiler-rt/lib/scudo/standalone/allocator_config_wrapper.h @@ -0,0 +1,135 @@ +//===-- allocator_config_wrapper.h ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_ +#define SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_ + +#include "condition_variable.h" +#include "internal_defs.h" +#include "secondary.h" + +namespace { + +template struct removeConst { + using type = T; +}; +template struct removeConst { + using type = T; +}; + +// This is only used for SFINAE when detecting if a type is defined. +template struct voidAdaptor { + using type = void; +}; + +} // namespace + +namespace scudo { + +#define OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, MEMBER) \ + template struct NAME##State { \ + static constexpr removeConst::type getValue() { return DEFAULT; } \ + }; \ + template \ + struct NAME##State { \ + static constexpr removeConst::type getValue() { \ + return Config::MEMBER; \ + } \ + }; + +#define OPTIONAL_TYPE_TEMPLATE(NAME, DEFAULT, MEMBER) \ + template struct NAME##Type { \ + static constexpr bool enabled() { return false; } \ + using NAME = DEFAULT; \ + }; \ + template \ + struct NAME##Type::type> { \ + static constexpr bool enabled() { return true; } \ + using NAME = typename Config::MEMBER; \ + }; + +template struct BaseConfig { +#define BASE_REQUIRED_TEMPLATE_TYPE(NAME) \ + template using NAME = typename AllocatorConfig::template NAME; + +#define BASE_OPTIONAL(TYPE, NAME, DEFAULT) \ + OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME) \ + static constexpr removeConst::type get##NAME() { \ + return NAME##State::getValue(); \ + } + +#include "allocator_config.def" +}; // BaseConfig + +template struct PrimaryConfig { + // TODO: Pass this flag through template argument to remove this hard-coded + // function. + static constexpr bool getMaySupportMemoryTagging() { + return BaseConfig::getMaySupportMemoryTagging(); + } + +#define PRIMARY_REQUIRED_TYPE(NAME) \ + using NAME = typename AllocatorConfig::Primary::NAME; + +#define PRIMARY_REQUIRED(TYPE, NAME) \ + static constexpr removeConst::type get##NAME() { \ + return AllocatorConfig::Primary::NAME; \ + } + +#define PRIMARY_OPTIONAL(TYPE, NAME, DEFAULT) \ + OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME) \ + static constexpr removeConst::type get##NAME() { \ + return NAME##State::getValue(); \ + } + +#define PRIMARY_OPTIONAL_TYPE(NAME, DEFAULT) \ + OPTIONAL_TYPE_TEMPLATE(NAME, DEFAULT, NAME) \ + static constexpr bool has##NAME() { \ + return NAME##Type::enabled(); \ + } \ + using NAME = typename NAME##Type::NAME; + +#include "allocator_config.def" + +}; // PrimaryConfig + +template struct SecondaryConfig { + // TODO: Pass this flag through template argument to remove this hard-coded + // function. + static constexpr bool getMaySupportMemoryTagging() { + return BaseConfig::getMaySupportMemoryTagging(); + } + +#define SECONDARY_REQUIRED_TEMPLATE_TYPE(NAME) \ + template \ + using NAME = typename AllocatorConfig::Secondary::template NAME; +#include "allocator_config.def" + + struct CacheConfig { + // TODO: Pass this flag through template argument to remove this hard-coded + // function. + static constexpr bool getMaySupportMemoryTagging() { + return BaseConfig::getMaySupportMemoryTagging(); + } + +#define SECONDARY_CACHE_OPTIONAL(TYPE, NAME, DEFAULT) \ + OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, Cache::NAME) \ + static constexpr removeConst::type get##NAME() { \ + return NAME##State::getValue(); \ + } +#include "allocator_config.def" + }; // CacheConfig +}; // SecondaryConfig + +#undef OPTIONAL_TEMPLATE +#undef OPTIONAL_TEMPLATE_TYPE + +} // namespace scudo + +#endif // SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_ diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h index 9e1fd6d6dca3..f4dd90aac665 100644 --- a/compiler-rt/lib/scudo/standalone/combined.h +++ b/compiler-rt/lib/scudo/standalone/combined.h @@ -9,6 +9,7 @@ #ifndef SCUDO_COMBINED_H_ #define SCUDO_COMBINED_H_ +#include "allocator_config_wrapper.h" #include "atomic_helpers.h" #include "chunk.h" #include "common.h" @@ -47,11 +48,14 @@ namespace scudo { template class Allocator { public: - using PrimaryT = typename Config::template PrimaryT; - using SecondaryT = typename Config::template SecondaryT; + using AllocatorConfig = BaseConfig; + using PrimaryT = + typename AllocatorConfig::template PrimaryT>; + using SecondaryT = + typename AllocatorConfig::template SecondaryT>; using CacheT = typename PrimaryT::CacheT; typedef Allocator ThisT; - typedef typename Config::template TSDRegistryT TSDRegistryT; + typedef typename AllocatorConfig::template TSDRegistryT TSDRegistryT; void callPostInitCallback() { pthread_once(&PostInitNonce, PostInitCallback); @@ -72,7 +76,7 @@ public: Header.State = Chunk::State::Available; Chunk::storeHeader(Allocator.Cookie, Ptr, &Header); - if (allocatorSupportsMemoryTagging()) + if (allocatorSupportsMemoryTagging()) Ptr = untagPointer(Ptr); void *BlockBegin = Allocator::getBlockBegin(Ptr, &Header); Cache.deallocate(Header.ClassId, BlockBegin); @@ -99,7 +103,8 @@ public: // Reset tag to 0 as this chunk may have been previously used for a tagged // user allocation. - if (UNLIKELY(useMemoryTagging(Allocator.Primary.Options.load()))) + if (UNLIKELY(useMemoryTagging( + Allocator.Primary.Options.load()))) storeTags(reinterpret_cast(Ptr), reinterpret_cast(Ptr) + sizeof(QuarantineBatch)); @@ -159,7 +164,7 @@ public: Primary.Options.set(OptionBit::DeallocTypeMismatch); if (getFlags()->delete_size_mismatch) Primary.Options.set(OptionBit::DeleteSizeMismatch); - if (allocatorSupportsMemoryTagging() && + if (allocatorSupportsMemoryTagging() && systemSupportsMemoryTagging()) Primary.Options.set(OptionBit::UseMemoryTagging); @@ -274,7 +279,7 @@ public: void drainCaches() { TSDRegistry.drainCaches(this); } ALWAYS_INLINE void *getHeaderTaggedPointer(void *Ptr) { - if (!allocatorSupportsMemoryTagging()) + if (!allocatorSupportsMemoryTagging()) return Ptr; auto UntaggedPtr = untagPointer(Ptr); if (UntaggedPtr != Ptr) @@ -286,7 +291,7 @@ public: } ALWAYS_INLINE uptr addHeaderTag(uptr Ptr) { - if (!allocatorSupportsMemoryTagging()) + if (!allocatorSupportsMemoryTagging()) return Ptr; return addFixedTag(Ptr, 2); } @@ -419,7 +424,7 @@ public: // // When memory tagging is enabled, zeroing the contents is done as part of // setting the tag. - if (UNLIKELY(useMemoryTagging(Options))) { + if (UNLIKELY(useMemoryTagging(Options))) { uptr PrevUserPtr; Chunk::UnpackedHeader Header; const uptr BlockSize = PrimaryT::getSizeByClassId(ClassId); @@ -501,7 +506,7 @@ public: } else { Block = addHeaderTag(Block); Ptr = addHeaderTag(Ptr); - if (UNLIKELY(useMemoryTagging(Options))) { + if (UNLIKELY(useMemoryTagging(Options))) { storeTags(reinterpret_cast(Block), reinterpret_cast(Ptr)); storeSecondaryAllocationStackMaybe(Options, Ptr, Size); } @@ -661,7 +666,7 @@ public: (reinterpret_cast(OldTaggedPtr) + NewSize)) & Chunk::SizeOrUnusedBytesMask; Chunk::storeHeader(Cookie, OldPtr, &Header); - if (UNLIKELY(useMemoryTagging(Options))) { + if (UNLIKELY(useMemoryTagging(Options))) { if (ClassId) { resizeTaggedChunk(reinterpret_cast(OldTaggedPtr) + OldSize, reinterpret_cast(OldTaggedPtr) + NewSize, @@ -764,8 +769,9 @@ public: Base = untagPointer(Base); const uptr From = Base; const uptr To = Base + Size; - bool MayHaveTaggedPrimary = allocatorSupportsMemoryTagging() && - systemSupportsMemoryTagging(); + bool MayHaveTaggedPrimary = + allocatorSupportsMemoryTagging() && + systemSupportsMemoryTagging(); auto Lambda = [this, From, To, MayHaveTaggedPrimary, Callback, Arg](uptr Block) { if (Block < From || Block >= To) @@ -786,9 +792,9 @@ public: } if (Header.State == Chunk::State::Allocated) { uptr TaggedChunk = Chunk; - if (allocatorSupportsMemoryTagging()) + if (allocatorSupportsMemoryTagging()) TaggedChunk = untagPointer(TaggedChunk); - if (useMemoryTagging(Primary.Options.load())) + if (useMemoryTagging(Primary.Options.load())) TaggedChunk = loadTag(Chunk); Callback(TaggedChunk, getSize(reinterpret_cast(Chunk), &Header), Arg); @@ -887,7 +893,7 @@ public: } bool useMemoryTaggingTestOnly() const { - return useMemoryTagging(Primary.Options.load()); + return useMemoryTagging(Primary.Options.load()); } void disableMemoryTagging() { // If we haven't been initialized yet, we need to initialize now in order to @@ -897,7 +903,7 @@ public: // callback), which may cause mappings to be created with memory tagging // enabled. TSDRegistry.initOnceMaybe(this); - if (allocatorSupportsMemoryTagging()) { + if (allocatorSupportsMemoryTagging()) { Secondary.disableMemoryTagging(); Primary.Options.clear(OptionBit::UseMemoryTagging); } @@ -983,7 +989,7 @@ public: // should not be able to crash the crash dumper (crash_dump on Android). // See also the get_error_info_fuzzer. *ErrorInfo = {}; - if (!allocatorSupportsMemoryTagging() || + if (!allocatorSupportsMemoryTagging() || MemoryAddr + MemorySize < MemoryAddr) return; @@ -1032,7 +1038,7 @@ private: static_assert(MinAlignment >= sizeof(Chunk::PackedHeader), "Minimal alignment must at least cover a chunk header."); - static_assert(!allocatorSupportsMemoryTagging() || + static_assert(!allocatorSupportsMemoryTagging() || MinAlignment >= archMemoryTagGranuleSize(), ""); @@ -1142,7 +1148,7 @@ private: const uptr SizeOrUnusedBytes = Header->SizeOrUnusedBytes; if (LIKELY(Header->ClassId)) return SizeOrUnusedBytes; - if (allocatorSupportsMemoryTagging()) + if (allocatorSupportsMemoryTagging()) Ptr = untagPointer(const_cast(Ptr)); return SecondaryT::getBlockEnd(getBlockBegin(Ptr, Header)) - reinterpret_cast(Ptr) - SizeOrUnusedBytes; @@ -1162,12 +1168,12 @@ private: Header->State = Chunk::State::Available; else Header->State = Chunk::State::Quarantined; - Header->OriginOrWasZeroed = useMemoryTagging(Options) && + Header->OriginOrWasZeroed = useMemoryTagging(Options) && Header->ClassId && !TSDRegistry.getDisableMemInit(); Chunk::storeHeader(Cookie, Ptr, Header); - if (UNLIKELY(useMemoryTagging(Options))) { + if (UNLIKELY(useMemoryTagging(Options))) { u8 PrevTag = extractTag(reinterpret_cast(TaggedPtr)); storeDeallocationStackMaybe(Options, Ptr, PrevTag, Size); if (Header->ClassId) { @@ -1184,7 +1190,7 @@ private: } } if (BypassQuarantine) { - if (allocatorSupportsMemoryTagging()) + if (allocatorSupportsMemoryTagging()) Ptr = untagPointer(Ptr); void *BlockBegin = getBlockBegin(Ptr, Header); const uptr ClassId = Header->ClassId; @@ -1201,7 +1207,7 @@ private: if (CacheDrained) Primary.tryReleaseToOS(ClassId, ReleaseToOS::Normal); } else { - if (UNLIKELY(useMemoryTagging(Options))) + if (UNLIKELY(useMemoryTagging(Options))) storeTags(reinterpret_cast(BlockBegin), reinterpret_cast(Ptr)); Secondary.deallocate(Options, BlockBegin); diff --git a/compiler-rt/lib/scudo/standalone/condition_variable.h b/compiler-rt/lib/scudo/standalone/condition_variable.h index 4afebdc9d04c..3f16c86651e7 100644 --- a/compiler-rt/lib/scudo/standalone/condition_variable.h +++ b/compiler-rt/lib/scudo/standalone/condition_variable.h @@ -39,22 +39,6 @@ public: } }; -template -struct ConditionVariableState { - static constexpr bool enabled() { return false; } - // This is only used for compilation purpose so that we won't end up having - // many conditional compilations. If you want to use `ConditionVariableDummy`, - // define `ConditionVariableT` in your allocator configuration. See - // allocator_config.h for more details. - using ConditionVariableT = ConditionVariableDummy; -}; - -template -struct ConditionVariableState { - static constexpr bool enabled() { return Config::UseConditionVariable; } - using ConditionVariableT = typename Config::ConditionVariableT; -}; - } // namespace scudo #endif // SCUDO_CONDITION_VARIABLE_H_ diff --git a/compiler-rt/lib/scudo/standalone/memtag.h b/compiler-rt/lib/scudo/standalone/memtag.h index aaed2192ad75..1f6983e99404 100644 --- a/compiler-rt/lib/scudo/standalone/memtag.h +++ b/compiler-rt/lib/scudo/standalone/memtag.h @@ -326,7 +326,7 @@ inline void *addFixedTag(void *Ptr, uptr Tag) { template inline constexpr bool allocatorSupportsMemoryTagging() { - return archSupportsMemoryTagging() && Config::MaySupportMemoryTagging && + return archSupportsMemoryTagging() && Config::getMaySupportMemoryTagging() && (1 << SCUDO_MIN_ALIGNMENT_LOG) >= archMemoryTagGranuleSize(); } diff --git a/compiler-rt/lib/scudo/standalone/primary32.h b/compiler-rt/lib/scudo/standalone/primary32.h index c86e75b8fd66..1d8a77b73e5c 100644 --- a/compiler-rt/lib/scudo/standalone/primary32.h +++ b/compiler-rt/lib/scudo/standalone/primary32.h @@ -43,14 +43,13 @@ namespace scudo { template class SizeClassAllocator32 { public: - typedef typename Config::Primary::CompactPtrT CompactPtrT; - typedef typename Config::Primary::SizeClassMap SizeClassMap; - static const uptr GroupSizeLog = Config::Primary::GroupSizeLog; + typedef typename Config::CompactPtrT CompactPtrT; + typedef typename Config::SizeClassMap SizeClassMap; + static const uptr GroupSizeLog = Config::getGroupSizeLog(); // The bytemap can only track UINT8_MAX - 1 classes. static_assert(SizeClassMap::LargestClassId <= (UINT8_MAX - 1), ""); // Regions should be large enough to hold the largest Block. - static_assert((1UL << Config::Primary::RegionSizeLog) >= - SizeClassMap::MaxSize, + static_assert((1UL << Config::getRegionSizeLog()) >= SizeClassMap::MaxSize, ""); typedef SizeClassAllocator32 ThisT; typedef SizeClassAllocatorLocalCache CacheT; @@ -331,9 +330,9 @@ public: bool setOption(Option O, sptr Value) { if (O == Option::ReleaseInterval) { - const s32 Interval = Max(Min(static_cast(Value), - Config::Primary::MaxReleaseToOsIntervalMs), - Config::Primary::MinReleaseToOsIntervalMs); + const s32 Interval = Max( + Min(static_cast(Value), Config::getMaxReleaseToOsIntervalMs()), + Config::getMinReleaseToOsIntervalMs()); atomic_store_relaxed(&ReleaseToOsIntervalMs, Interval); return true; } @@ -373,9 +372,9 @@ public: private: static const uptr NumClasses = SizeClassMap::NumClasses; - static const uptr RegionSize = 1UL << Config::Primary::RegionSizeLog; - static const uptr NumRegions = - SCUDO_MMAP_RANGE_SIZE >> Config::Primary::RegionSizeLog; + static const uptr RegionSize = 1UL << Config::getRegionSizeLog(); + static const uptr NumRegions = SCUDO_MMAP_RANGE_SIZE >> + Config::getRegionSizeLog(); static const u32 MaxNumBatches = SCUDO_ANDROID ? 4U : 8U; typedef FlatByteMap ByteMap; @@ -408,7 +407,7 @@ private: static_assert(sizeof(SizeClassInfo) % SCUDO_CACHE_LINE_SIZE == 0, ""); uptr computeRegionId(uptr Mem) { - const uptr Id = Mem >> Config::Primary::RegionSizeLog; + const uptr Id = Mem >> Config::getRegionSizeLog(); CHECK_LT(Id, NumRegions); return Id; } @@ -437,7 +436,7 @@ private: unmap(reinterpret_cast(End), MapEnd - End); DCHECK_EQ(Region % RegionSize, 0U); - static_assert(Config::Primary::RegionSizeLog == GroupSizeLog, + static_assert(Config::getRegionSizeLog() == GroupSizeLog, "Memory group should be the same size as Region"); return Region; diff --git a/compiler-rt/lib/scudo/standalone/primary64.h b/compiler-rt/lib/scudo/standalone/primary64.h index d89a2e6a4e5c..f5e4ab57b4df 100644 --- a/compiler-rt/lib/scudo/standalone/primary64.h +++ b/compiler-rt/lib/scudo/standalone/primary64.h @@ -47,13 +47,12 @@ namespace scudo { template class SizeClassAllocator64 { public: - typedef typename Config::Primary::CompactPtrT CompactPtrT; - typedef typename Config::Primary::SizeClassMap SizeClassMap; - typedef typename ConditionVariableState< - typename Config::Primary>::ConditionVariableT ConditionVariableT; - static const uptr CompactPtrScale = Config::Primary::CompactPtrScale; - static const uptr RegionSizeLog = Config::Primary::RegionSizeLog; - static const uptr GroupSizeLog = Config::Primary::GroupSizeLog; + typedef typename Config::CompactPtrT CompactPtrT; + typedef typename Config::SizeClassMap SizeClassMap; + typedef typename Config::ConditionVariableT ConditionVariableT; + static const uptr CompactPtrScale = Config::getCompactPtrScale(); + static const uptr RegionSizeLog = Config::getRegionSizeLog(); + static const uptr GroupSizeLog = Config::getGroupSizeLog(); static_assert(RegionSizeLog >= GroupSizeLog, "Group size shouldn't be greater than the region size"); static const uptr GroupScale = GroupSizeLog - CompactPtrScale; @@ -74,7 +73,7 @@ public: static bool canAllocate(uptr Size) { return Size <= SizeClassMap::MaxSize; } static bool conditionVariableEnabled() { - return ConditionVariableState::enabled(); + return Config::hasConditionVariableT(); } void init(s32 ReleaseToOsInterval) NO_THREAD_SAFETY_ANALYSIS { @@ -135,7 +134,7 @@ public: // The actual start of a region is offset by a random number of pages // when PrimaryEnableRandomOffset is set. Region->RegionBeg = (PrimaryBase + (I << RegionSizeLog)) + - (Config::Primary::EnableRandomOffset + (Config::getEnableRandomOffset() ? ((getRandomModN(&Seed, 16) + 1) * PageSize) : 0); Region->RandState = getRandomU32(&Seed); @@ -400,9 +399,9 @@ public: bool setOption(Option O, sptr Value) { if (O == Option::ReleaseInterval) { - const s32 Interval = Max(Min(static_cast(Value), - Config::Primary::MaxReleaseToOsIntervalMs), - Config::Primary::MinReleaseToOsIntervalMs); + const s32 Interval = Max( + Min(static_cast(Value), Config::getMaxReleaseToOsIntervalMs()), + Config::getMinReleaseToOsIntervalMs()); atomic_store_relaxed(&ReleaseToOsIntervalMs, Interval); return true; } @@ -516,7 +515,7 @@ private: static const uptr NumClasses = SizeClassMap::NumClasses; static const uptr PrimarySize = RegionSize * NumClasses; - static const uptr MapSizeIncrement = Config::Primary::MapSizeIncrement; + static const uptr MapSizeIncrement = Config::getMapSizeIncrement(); // Fill at most this number of batches from the newly map'd memory. static const u32 MaxNumBatches = SCUDO_ANDROID ? 4U : 8U; diff --git a/compiler-rt/lib/scudo/standalone/secondary.h b/compiler-rt/lib/scudo/standalone/secondary.h index 732fd307ed2f..202c55cc1a92 100644 --- a/compiler-rt/lib/scudo/standalone/secondary.h +++ b/compiler-rt/lib/scudo/standalone/secondary.h @@ -173,8 +173,6 @@ public: template class MapAllocatorCache { public: - using CacheConfig = typename Config::Secondary::Cache; - void getStats(ScopedString *Str) { ScopedLock L(Mutex); uptr Integral; @@ -199,16 +197,16 @@ public: } // Ensure the default maximum specified fits the array. - static_assert(CacheConfig::DefaultMaxEntriesCount <= - CacheConfig::EntriesArraySize, + static_assert(Config::getDefaultMaxEntriesCount() <= + Config::getEntriesArraySize(), ""); void init(s32 ReleaseToOsInterval) NO_THREAD_SAFETY_ANALYSIS { DCHECK_EQ(EntriesCount, 0U); setOption(Option::MaxCacheEntriesCount, - static_cast(CacheConfig::DefaultMaxEntriesCount)); + static_cast(Config::getDefaultMaxEntriesCount())); setOption(Option::MaxCacheEntrySize, - static_cast(CacheConfig::DefaultMaxEntrySize)); + static_cast(Config::getDefaultMaxEntrySize())); setOption(Option::ReleaseInterval, static_cast(ReleaseToOsInterval)); } @@ -253,9 +251,9 @@ public: // just unmap it. break; } - if (CacheConfig::QuarantineSize && useMemoryTagging(Options)) { + if (Config::getQuarantineSize() && useMemoryTagging(Options)) { QuarantinePos = - (QuarantinePos + 1) % Max(CacheConfig::QuarantineSize, 1u); + (QuarantinePos + 1) % Max(Config::getQuarantineSize(), 1u); if (!Quarantine[QuarantinePos].isValid()) { Quarantine[QuarantinePos] = Entry; return; @@ -382,14 +380,14 @@ public: bool setOption(Option O, sptr Value) { if (O == Option::ReleaseInterval) { const s32 Interval = Max( - Min(static_cast(Value), CacheConfig::MaxReleaseToOsIntervalMs), - CacheConfig::MinReleaseToOsIntervalMs); + Min(static_cast(Value), Config::getMaxReleaseToOsIntervalMs()), + Config::getMinReleaseToOsIntervalMs()); atomic_store_relaxed(&ReleaseToOsIntervalMs, Interval); return true; } if (O == Option::MaxCacheEntriesCount) { const u32 MaxCount = static_cast(Value); - if (MaxCount > CacheConfig::EntriesArraySize) + if (MaxCount > Config::getEntriesArraySize()) return false; atomic_store_relaxed(&MaxEntriesCount, MaxCount); return true; @@ -406,7 +404,7 @@ public: void disableMemoryTagging() EXCLUDES(Mutex) { ScopedLock L(Mutex); - for (u32 I = 0; I != CacheConfig::QuarantineSize; ++I) { + for (u32 I = 0; I != Config::getQuarantineSize(); ++I) { if (Quarantine[I].isValid()) { MemMapT &MemMap = Quarantine[I].MemMap; MemMap.unmap(MemMap.getBase(), MemMap.getCapacity()); @@ -431,11 +429,11 @@ public: private: void empty() { - MemMapT MapInfo[CacheConfig::EntriesArraySize]; + MemMapT MapInfo[Config::getEntriesArraySize()]; uptr N = 0; { ScopedLock L(Mutex); - for (uptr I = 0; I < CacheConfig::EntriesArraySize; I++) { + for (uptr I = 0; I < Config::getEntriesArraySize(); I++) { if (!Entries[I].isValid()) continue; MapInfo[N] = Entries[I].MemMap; @@ -468,9 +466,9 @@ private: if (!EntriesCount || OldestTime == 0 || OldestTime > Time) return; OldestTime = 0; - for (uptr I = 0; I < CacheConfig::QuarantineSize; I++) + for (uptr I = 0; I < Config::getQuarantineSize(); I++) releaseIfOlderThan(Quarantine[I], Time); - for (uptr I = 0; I < CacheConfig::EntriesArraySize; I++) + for (uptr I = 0; I < Config::getEntriesArraySize(); I++) releaseIfOlderThan(Entries[I], Time); } @@ -485,8 +483,8 @@ private: u32 CallsToRetrieve GUARDED_BY(Mutex) = 0; u32 SuccessfulRetrieves GUARDED_BY(Mutex) = 0; - CachedBlock Entries[CacheConfig::EntriesArraySize] GUARDED_BY(Mutex) = {}; - NonZeroLengthArray + CachedBlock Entries[Config::getEntriesArraySize()] GUARDED_BY(Mutex) = {}; + NonZeroLengthArray Quarantine GUARDED_BY(Mutex) = {}; }; @@ -555,7 +553,7 @@ public: void getStats(ScopedString *Str); private: - typename Config::Secondary::template CacheT Cache; + typename Config::template CacheT Cache; mutable HybridMutex Mutex; DoublyLinkedList InUseBlocks GUARDED_BY(Mutex); diff --git a/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt index ac92805872f9..1786756fa5ea 100644 --- a/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt +++ b/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt @@ -90,6 +90,7 @@ macro(add_scudo_unittest testname) endmacro() set(SCUDO_UNIT_TEST_SOURCES + allocator_config_test.cpp atomic_test.cpp bytemap_test.cpp checksum_test.cpp diff --git a/compiler-rt/lib/scudo/standalone/tests/allocator_config_test.cpp b/compiler-rt/lib/scudo/standalone/tests/allocator_config_test.cpp new file mode 100644 index 000000000000..4c4ceb832e27 --- /dev/null +++ b/compiler-rt/lib/scudo/standalone/tests/allocator_config_test.cpp @@ -0,0 +1,119 @@ +//===-- allocator_config_test.cpp -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "tests/scudo_unit_test.h" + +#include "allocator_config.h" +#include "allocator_config_wrapper.h" +#include "common.h" +#include "secondary.h" + +#include + +struct TestBaseConfig { + template using TSDRegistryT = void; + template using PrimaryT = void; + template using SecondaryT = void; +}; + +struct TestBaseConfigEnableOptionalFlag : public TestBaseConfig { + static const bool MaySupportMemoryTagging = true; + // Use the getter to avoid the test to `use` the address of static const + // variable (which requires additional explicit definition). + static bool getMaySupportMemoryTagging() { return MaySupportMemoryTagging; } +}; + +struct TestBasePrimaryConfig { + using SizeClassMap = void; + static const scudo::uptr RegionSizeLog = 18U; + static const scudo::uptr GroupSizeLog = 18U; + static const scudo::s32 MinReleaseToOsIntervalMs = INT32_MIN; + static const scudo::s32 MaxReleaseToOsIntervalMs = INT32_MAX; + typedef scudo::uptr CompactPtrT; + static const scudo::uptr CompactPtrScale = 0; + static const scudo::uptr MapSizeIncrement = 1UL << 18; +}; + +struct TestPrimaryConfig : public TestBaseConfig { + struct Primary : TestBasePrimaryConfig {}; +}; + +struct TestPrimaryConfigEnableOptionalFlag : public TestBaseConfig { + struct Primary : TestBasePrimaryConfig { + static const bool EnableRandomOffset = true; + static bool getEnableRandomOffset() { return EnableRandomOffset; } + }; +}; + +struct TestPrimaryConfigEnableOptionalType : public TestBaseConfig { + struct DummyConditionVariable {}; + + struct Primary : TestBasePrimaryConfig { + using ConditionVariableT = DummyConditionVariable; + }; +}; + +struct TestSecondaryConfig : public TestPrimaryConfig { + struct Secondary { + template + using CacheT = scudo::MapAllocatorNoCache; + }; +}; + +struct TestSecondaryCacheConfigEnableOptionalFlag : public TestPrimaryConfig { + struct Secondary { + struct Cache { + static const scudo::u32 EntriesArraySize = 256U; + static scudo::u32 getEntriesArraySize() { return EntriesArraySize; } + }; + template using CacheT = scudo::MapAllocatorCache; + }; +}; + +TEST(ScudoAllocatorConfigTest, VerifyOptionalFlags) { + // Test the top level allocator optional config. + // + // `MaySupportMemoryTagging` is default off. + EXPECT_FALSE(scudo::BaseConfig::getMaySupportMemoryTagging()); + EXPECT_EQ(scudo::BaseConfig< + TestBaseConfigEnableOptionalFlag>::getMaySupportMemoryTagging(), + TestBaseConfigEnableOptionalFlag::getMaySupportMemoryTagging()); + + // Test primary optional config. + // + // `EnableRandomeOffset` is default off. + EXPECT_FALSE( + scudo::PrimaryConfig::getEnableRandomOffset()); + EXPECT_EQ( + scudo::PrimaryConfig< + TestPrimaryConfigEnableOptionalFlag>::getEnableRandomOffset(), + TestPrimaryConfigEnableOptionalFlag::Primary::getEnableRandomOffset()); + + // `ConditionVariableT` is default off. + EXPECT_FALSE( + scudo::PrimaryConfig::hasConditionVariableT()); + EXPECT_TRUE(scudo::PrimaryConfig< + TestPrimaryConfigEnableOptionalType>::hasConditionVariableT()); + EXPECT_TRUE((std::is_same_v< + typename scudo::PrimaryConfig< + TestPrimaryConfigEnableOptionalType>::ConditionVariableT, + typename TestPrimaryConfigEnableOptionalType::Primary:: + ConditionVariableT>)); + + // Test secondary cache optional config. + using NoCacheConfig = + scudo::SecondaryConfig::CacheConfig; + // `EntriesArraySize` is default 0. + EXPECT_EQ(NoCacheConfig::getEntriesArraySize(), 0U); + + using CacheConfig = scudo::SecondaryConfig< + TestSecondaryCacheConfigEnableOptionalFlag>::CacheConfig; + EXPECT_EQ(CacheConfig::getEntriesArraySize(), + TestSecondaryCacheConfigEnableOptionalFlag::Secondary::Cache:: + getEntriesArraySize()); +} diff --git a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp index 13d627b11680..6a311adc55e4 100644 --- a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp @@ -190,7 +190,6 @@ struct TestConditionVariableConfig { #endif static const scudo::s32 MinReleaseToOsIntervalMs = 1000; static const scudo::s32 MaxReleaseToOsIntervalMs = 1000; - static const bool UseConditionVariable = true; #if SCUDO_LINUX using ConditionVariableT = scudo::ConditionVariableLinux; #else diff --git a/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp b/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp index f64a5143b30d..683ce3e59659 100644 --- a/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp @@ -9,6 +9,7 @@ #include "tests/scudo_unit_test.h" #include "allocator_config.h" +#include "allocator_config_wrapper.h" #include "condition_variable.h" #include "primary32.h" #include "primary64.h" @@ -29,6 +30,9 @@ template struct TestConfig1 { static const bool MaySupportMemoryTagging = false; + template using TSDRegistryT = void; + template using PrimaryT = void; + template using SecondaryT = void; struct Primary { using SizeClassMap = SizeClassMapT; @@ -45,6 +49,9 @@ template struct TestConfig1 { template struct TestConfig2 { static const bool MaySupportMemoryTagging = false; + template using TSDRegistryT = void; + template using PrimaryT = void; + template using SecondaryT = void; struct Primary { using SizeClassMap = SizeClassMapT; @@ -66,6 +73,9 @@ template struct TestConfig2 { template struct TestConfig3 { static const bool MaySupportMemoryTagging = true; + template using TSDRegistryT = void; + template using PrimaryT = void; + template using SecondaryT = void; struct Primary { using SizeClassMap = SizeClassMapT; @@ -87,6 +97,9 @@ template struct TestConfig3 { template struct TestConfig4 { static const bool MaySupportMemoryTagging = true; + template using TSDRegistryT = void; + template using PrimaryT = void; + template using SecondaryT = void; struct Primary { using SizeClassMap = SizeClassMapT; @@ -109,6 +122,9 @@ template struct TestConfig4 { // This is the only test config that enables the condition variable. template struct TestConfig5 { static const bool MaySupportMemoryTagging = true; + template using TSDRegistryT = void; + template using PrimaryT = void; + template using SecondaryT = void; struct Primary { using SizeClassMap = SizeClassMapT; @@ -125,7 +141,6 @@ template struct TestConfig5 { typedef scudo::u32 CompactPtrT; static const bool EnableRandomOffset = true; static const scudo::uptr MapSizeIncrement = 1UL << 18; - static const bool UseConditionVariable = true; #if SCUDO_LINUX using ConditionVariableT = scudo::ConditionVariableLinux; #else @@ -139,10 +154,12 @@ struct Config : public BaseConfig {}; template