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